scan fixed-width integers in vcscanf

when a format string like %2x is provided, the width parameter was read
correctly as 2, but it was not used when decoding the number from the
input string (ie instead of reading 2 characters from the input string,
vcscanf read all the characters).

this change uses the value of width within the number decoding loop to
read fixed number of digits correctly. if width is zero (not provided),
the default of width is set as bits.

also added a test for this specific use case.
This commit is contained in:
ahgamut 2022-06-16 09:12:33 +05:30
parent e466dd0553
commit c8f573b3ac
2 changed files with 11 additions and 1 deletions

View file

@ -177,9 +177,11 @@ int vcscanf(int callback(void *), int unget(int, void *), void *arg,
DecodeNumber:
if (c != -1) {
number = 0;
width = !width ? bits : width;
do {
diglet = kBase36[(unsigned char)c];
if (1 <= diglet && diglet <= base) {
width -= 1;
number *= base;
number += diglet - 1;
} else if (thousands && diglet == ',') {
@ -187,7 +189,7 @@ int vcscanf(int callback(void *), int unget(int, void *), void *arg,
} else {
break;
}
} while ((c = callback(arg)) != -1);
} while ((c = callback(arg)) != -1 && width > 0);
if (!discard) {
uint128_t bane = (uint128_t)1 << (bits - 1);
if (!(number & ~((bane - 1) | (issigned ? 0 : bane))) ||

View file

@ -141,3 +141,11 @@ TEST(sscanf, testDiscard_notIncludedInCount) {
ASSERT_EQ(1, sscanf("hello there", "%*s %8s", buf));
EXPECT_STREQ("there", buf);
}
TEST(sscanf, testFixedWidthFormat_Integer) {
int r, g, b;
ASSERT_EQ(3, sscanf("#321030", "#%2x%2b%2d", &r, &g, &b));
ASSERT_EQ(0x32, r);
ASSERT_EQ(2, g);
ASSERT_EQ(30, b);
}