Skip to content

Commit 024c276

Browse files
committed
Added support for the "%n" sscanf format specifier
(cherry picked from commit 6980325) (cherry picked from commit ab44451)
1 parent c2047f0 commit 024c276

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
@@ -1113,6 +1113,7 @@ static SDL_bool CharacterMatchesSet(char c, const char *set, size_t set_len)
11131113
/* NOLINTNEXTLINE(readability-non-const-parameter) */
11141114
int SDL_vsscanf(const char *text, const char *fmt, va_list ap)
11151115
{
1116+
const char *start = text;
11161117
int retval = 0;
11171118

11181119
if (!text || !*text) {
@@ -1383,6 +1384,36 @@ int SDL_vsscanf(const char *text, const char *fmt, va_list ap)
13831384
}
13841385
done = SDL_TRUE;
13851386
break;
1387+
case 'n':
1388+
switch (inttype) {
1389+
case DO_SHORT:
1390+
{
1391+
short *valuep = va_arg(ap, short *);
1392+
*valuep = (short)(text - start);
1393+
} break;
1394+
case DO_INT:
1395+
{
1396+
int *valuep = va_arg(ap, int *);
1397+
*valuep = (int)(text - start);
1398+
} break;
1399+
case DO_LONG:
1400+
{
1401+
long *valuep = va_arg(ap, long *);
1402+
*valuep = (long)(text - start);
1403+
} break;
1404+
case DO_LONGLONG:
1405+
{
1406+
long long *valuep = va_arg(ap, long long *);
1407+
*valuep = (long long)(text - start);
1408+
} break;
1409+
case DO_SIZE_T:
1410+
{
1411+
size_t *valuep = va_arg(ap, size_t *);
1412+
*valuep = (size_t)(text - start);
1413+
} break;
1414+
}
1415+
done = SDL_TRUE;
1416+
break;
13861417
case '[':
13871418
{
13881419
const char *set = fmt + 1;

test/testautomation_stdlib.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ int stdlib_getsetenv(void *arg)
393393
#endif
394394

395395
#define FMT_PRILLd "%lld"
396+
#define FMT_PRILLdn "%lld%lln"
396397
#define FMT_PRILLu "%llu"
397398

398399
/**
@@ -403,11 +404,12 @@ int stdlib_sscanf(void *arg)
403404
{
404405
int output;
405406
int result;
407+
int length;
406408
int expected_output;
407409
int expected_result;
408-
short short_output, expected_short_output;
409-
long long_output, expected_long_output;
410-
long long long_long_output, expected_long_long_output;
410+
short short_output, expected_short_output, short_length;
411+
long long_output, expected_long_output, long_length;
412+
long long long_long_output, expected_long_long_output, long_long_length;
411413
size_t size_output, expected_size_output;
412414
char text[128], text2[128];
413415

@@ -426,43 +428,51 @@ int stdlib_sscanf(void *arg)
426428
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
427429

428430
output = 123;
431+
length = 0;
429432
expected_output = 2;
430433
expected_result = 1;
431-
result = SDL_sscanf("2", "%i", &output);
432-
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i\", &output)");
434+
result = SDL_sscanf("2", "%i%n", &output, &length);
435+
SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i%%n\", &output, &length)");
433436
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
434437
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
438+
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
435439

436440
output = 123;
441+
length = 0;
437442
expected_output = 0xa;
438443
expected_result = 1;
439-
result = SDL_sscanf("aa", "%1x", &output);
440-
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x\", &output)");
444+
result = SDL_sscanf("aa", "%1x%n", &output, &length);
445+
SDLTest_AssertPass("Call to SDL_sscanf(\"aa\", \"%%1x%%n\", &output, &length)");
441446
SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
442447
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
448+
SDLTest_AssertCheck(length == 1, "Check length, expected: 1, got: %i", length);
443449

444-
#define SIZED_TEST_CASE(type, var, format_specifier) \
450+
#define SIZED_TEST_CASE(type, var, printf_specifier, scanf_specifier) \
445451
var##_output = 123; \
452+
var##_length = 0; \
446453
expected_##var##_output = (type)(((unsigned type)(~0)) >> 1); \
447454
expected_result = 1; \
448-
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
449-
result = SDL_sscanf(text, format_specifier, &var##_output); \
450-
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
451-
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
455+
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
456+
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
457+
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
458+
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
452459
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
460+
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
453461
\
454462
var##_output = 123; \
463+
var##_length = 0; \
455464
expected_##var##_output = ~(type)(((unsigned type)(~0)) >> 1); \
456465
expected_result = 1; \
457-
result = SDL_snprintf(text, sizeof(text), format_specifier, expected_##var##_output); \
458-
result = SDL_sscanf(text, format_specifier, &var##_output); \
459-
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%s\", &output)", text, #format_specifier); \
460-
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " format_specifier ", got: " format_specifier, expected_##var##_output, var##_output); \
461-
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
466+
result = SDL_snprintf(text, sizeof(text), printf_specifier, expected_##var##_output); \
467+
result = SDL_sscanf(text, scanf_specifier, &var##_output, &var##_length); \
468+
SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", %s, &output, &length)", text, #scanf_specifier); \
469+
SDLTest_AssertCheck(expected_##var##_output == var##_output, "Check output, expected: " printf_specifier ", got: " printf_specifier, expected_##var##_output, var##_output); \
470+
SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); \
471+
SDLTest_AssertCheck(var##_length == (type)SDL_strlen(text), "Check length, expected: %i, got: %i", (int)SDL_strlen(text), (int)var##_length); \
462472

463-
SIZED_TEST_CASE(short, short, "%hd")
464-
SIZED_TEST_CASE(long, long, "%ld")
465-
SIZED_TEST_CASE(long long, long_long, "%lld")
473+
SIZED_TEST_CASE(short, short, "%hd", "%hd%hn")
474+
SIZED_TEST_CASE(long, long, "%ld", "%ld%ln")
475+
SIZED_TEST_CASE(long long, long_long, FMT_PRILLd, FMT_PRILLdn)
466476

467477
size_output = 123;
468478
expected_size_output = ~((size_t)0);

0 commit comments

Comments
 (0)