Skip to content

Commit 6980325

Browse files
committed
Added support for the "%n" sscanf format specifier
1 parent e6a24fc commit 6980325

File tree

2 files changed

+61
-20
lines changed

2 files changed

+61
-20
lines changed

src/stdlib/SDL_string.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,7 @@ static bool CharacterMatchesSet(char c, const char *set, size_t set_len)
14481448
// NOLINTNEXTLINE(readability-non-const-parameter)
14491449
int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap)
14501450
{
1451+
const char *start = text;
14511452
int result = 0;
14521453

14531454
if (!text || !*text) {
@@ -1718,6 +1719,36 @@ int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_li
17181719
}
17191720
done = true;
17201721
break;
1722+
case 'n':
1723+
switch (inttype) {
1724+
case DO_SHORT:
1725+
{
1726+
short *valuep = va_arg(ap, short *);
1727+
*valuep = (short)(text - start);
1728+
} break;
1729+
case DO_INT:
1730+
{
1731+
int *valuep = va_arg(ap, int *);
1732+
*valuep = (int)(text - start);
1733+
} break;
1734+
case DO_LONG:
1735+
{
1736+
long *valuep = va_arg(ap, long *);
1737+
*valuep = (long)(text - start);
1738+
} break;
1739+
case DO_LONGLONG:
1740+
{
1741+
long long *valuep = va_arg(ap, long long *);
1742+
*valuep = (long long)(text - start);
1743+
} break;
1744+
case DO_SIZE_T:
1745+
{
1746+
size_t *valuep = va_arg(ap, size_t *);
1747+
*valuep = (size_t)(text - start);
1748+
} break;
1749+
}
1750+
done = true;
1751+
break;
17211752
case '[':
17221753
{
17231754
const char *set = fmt + 1;

test/testautomation_stdlib.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ static int SDLCALL stdlib_getsetenv(void *arg)
731731
#endif
732732

733733
#define FMT_PRILLd "%" SDL_PRILLd
734+
#define FMT_PRILLdn "%" SDL_PRILLd "%" SDL_PRILL_PREFIX "n"
734735
#define FMT_PRILLu "%" SDL_PRILLu
735736

736737
/**
@@ -740,11 +741,12 @@ static int SDLCALL stdlib_sscanf(void *arg)
740741
{
741742
int output;
742743
int result;
744+
int length;
743745
int expected_output;
744746
int expected_result;
745-
short short_output, expected_short_output;
746-
long long_output, expected_long_output;
747-
long long long_long_output, expected_long_long_output;
747+
short short_output, expected_short_output, short_length;
748+
long long_output, expected_long_output, long_length;
749+
long long long_long_output, expected_long_long_output, long_long_length;
748750
size_t size_output, expected_size_output;
749751
void *ptr_output, *expected_ptr_output;
750752
char text[128], text2[128];
@@ -764,43 +766,51 @@ static int SDLCALL stdlib_sscanf(void *arg)
764766
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
765767

766768
output = 123;
769+
length = 0;
767770
expected_output = 2;
768771
expected_result = 1;
769-
result = SDL_sscanf("2", "%i", &output);
770-
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i\", &output)");
772+
result = SDL_sscanf("2", "%i%n", &output, &length);
773+
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i%%n\", &output, &length)");
771774
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
772775
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
776+
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
773777

774778
output = 123;
779+
length = 0;
775780
expected_output = 0xa;
776781
expected_result = 1;
777-
result = SDL_sscanf("aa", "%1x", &output);
778-
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x\", &output)");
782+
result = SDL_sscanf("aa", "%1x%n", &output, &length);
783+
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x%%n\", &output, &length)");
779784
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
780785
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
786+
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
781787

782-
#define SIZED_TEST_CASE(type, var, format_specifier) \
788+
#define SIZED_TEST_CASE(type, var, printf_specifier, scanf_specifier) \
783789
var##_output = 123; \
790+
var##_length = 0; \
784791
expected_##var##_output = (type)(((unsigned type)(~0)) >> 1); \
785792
expected_result = 1; \
786-
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
787-
result = SDL_sscanf(text, format_specifier, &var##_output); \
788-
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
789-
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
793+
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
794+
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
795+
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
796+
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
790797
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
798+
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
791799
\
792800
var##_output = 123; \
801+
var##_length = 0; \
793802
expected_##var##_output = ~(type)(((unsigned type)(~0)) >> 1); \
794803
expected_result = 1; \
795-
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
796-
result = SDL_sscanf(text, format_specifier, &var##_output); \
797-
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
798-
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
799-
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
804+
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
805+
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
806+
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
807+
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
808+
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
809+
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
800810

801-
SIZED_TEST_CASE(short, short, "%hd")
802-
SIZED_TEST_CASE(long, long, "%ld")
803-
SIZED_TEST_CASE(long long, long_long, FMT_PRILLd)
811+
SIZED_TEST_CASE(short, short, "%hd", "%hd%hn")
812+
SIZED_TEST_CASE(long, long, "%ld", "%ld%ln")
813+
SIZED_TEST_CASE(long long, long_long, FMT_PRILLd, FMT_PRILLdn)
804814

805815
size_output = 123;
806816
expected_size_output = ~((size_t)0);

0 commit comments

Comments
 (0)