mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:08:12 +00:00
LibC: Use 'long long' specialisations of scanf's read_element_concrete
...for 'long long' and 'unsigned long long', instead of reading them as 'long's and 'unsigned long's. Also add a test for values that can only fit in (unsigned) long long. Fixes #6096.
This commit is contained in:
parent
f05cca7a9a
commit
143c68755b
2 changed files with 44 additions and 4 deletions
|
@ -163,6 +163,40 @@ struct read_element_concrete<unsigned, ApT, kind> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ApT, ReadKind kind>
|
||||||
|
struct read_element_concrete<long long, ApT, kind> {
|
||||||
|
bool operator()(GenericLexer& lexer, va_list* ap)
|
||||||
|
{
|
||||||
|
lexer.ignore_while(isspace);
|
||||||
|
|
||||||
|
auto* ptr = va_arg(*ap, ApT*);
|
||||||
|
long long value = 0;
|
||||||
|
char* endptr = nullptr;
|
||||||
|
auto nptr = lexer.remaining().characters_without_null_termination();
|
||||||
|
if constexpr (kind == ReadKind::Normal)
|
||||||
|
value = strtoll(nptr, &endptr, 10);
|
||||||
|
if constexpr (kind == ReadKind::Octal)
|
||||||
|
value = strtoll(nptr, &endptr, 8);
|
||||||
|
if constexpr (kind == ReadKind::Hex)
|
||||||
|
value = strtoll(nptr, &endptr, 16);
|
||||||
|
if constexpr (kind == ReadKind::Infer)
|
||||||
|
value = strtoll(nptr, &endptr, 0);
|
||||||
|
|
||||||
|
if (!endptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (endptr == nptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto diff = endptr - nptr;
|
||||||
|
VERIFY(diff > 0);
|
||||||
|
lexer.ignore((size_t)diff);
|
||||||
|
|
||||||
|
*ptr = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename ApT, ReadKind kind>
|
template<typename ApT, ReadKind kind>
|
||||||
struct read_element_concrete<unsigned long long, ApT, kind> {
|
struct read_element_concrete<unsigned long long, ApT, kind> {
|
||||||
bool operator()(GenericLexer& lexer, va_list* ap)
|
bool operator()(GenericLexer& lexer, va_list* ap)
|
||||||
|
@ -248,15 +282,15 @@ struct read_element {
|
||||||
if constexpr (IsSame<T, unsigned>::value)
|
if constexpr (IsSame<T, unsigned>::value)
|
||||||
return read_element_concrete<T, unsigned, kind> {}(input_lexer, ap);
|
return read_element_concrete<T, unsigned, kind> {}(input_lexer, ap);
|
||||||
if constexpr (IsSame<T, float>::value)
|
if constexpr (IsSame<T, float>::value)
|
||||||
return read_element_concrete<T, double, kind> {}(input_lexer, ap);
|
return read_element_concrete<int, double, kind> {}(input_lexer, ap);
|
||||||
return false;
|
return false;
|
||||||
case LongLong:
|
case LongLong:
|
||||||
if constexpr (IsSame<T, int>::value)
|
if constexpr (IsSame<T, int>::value)
|
||||||
return read_element_concrete<T, long long, kind> {}(input_lexer, ap);
|
return read_element_concrete<long long, long long, kind> {}(input_lexer, ap);
|
||||||
if constexpr (IsSame<T, unsigned>::value)
|
if constexpr (IsSame<T, unsigned>::value)
|
||||||
return read_element_concrete<T, unsigned long long, kind> {}(input_lexer, ap);
|
return read_element_concrete<unsigned long long, unsigned long long, kind> {}(input_lexer, ap);
|
||||||
if constexpr (IsSame<T, float>::value)
|
if constexpr (IsSame<T, float>::value)
|
||||||
return read_element_concrete<T, double, kind> {}(input_lexer, ap);
|
return read_element_concrete<long long, double, kind> {}(input_lexer, ap);
|
||||||
return false;
|
return false;
|
||||||
case IntMax:
|
case IntMax:
|
||||||
return read_element_concrete<T, intmax_t, kind> {}(input_lexer, ap);
|
return read_element_concrete<T, intmax_t, kind> {}(input_lexer, ap);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
typedef long double longdouble;
|
typedef long double longdouble;
|
||||||
typedef long long longlong;
|
typedef long long longlong;
|
||||||
|
typedef unsigned long long unsignedlonglong;
|
||||||
typedef unsigned long unsignedlong;
|
typedef unsigned long unsignedlong;
|
||||||
typedef char charstar[32];
|
typedef char charstar[32];
|
||||||
|
|
||||||
|
@ -145,6 +146,7 @@ DECL_WITH_TYPE(float);
|
||||||
DECL_WITH_TYPE(double);
|
DECL_WITH_TYPE(double);
|
||||||
DECL_WITH_TYPE(longdouble);
|
DECL_WITH_TYPE(longdouble);
|
||||||
DECL_WITH_TYPE(unsignedlong);
|
DECL_WITH_TYPE(unsignedlong);
|
||||||
|
DECL_WITH_TYPE(unsignedlonglong);
|
||||||
|
|
||||||
#undef DECL_WITH_TYPE
|
#undef DECL_WITH_TYPE
|
||||||
|
|
||||||
|
@ -184,6 +186,10 @@ const TestSuite test_suites[] {
|
||||||
// GCC failure tests
|
// GCC failure tests
|
||||||
{ "%d.%d.%d", "10.2.0", 3, 3, { intarg0, intarg1, intarg2 }, { to_value_t(10), to_value_t(2), to_value_t(0) } },
|
{ "%d.%d.%d", "10.2.0", 3, 3, { intarg0, intarg1, intarg2 }, { to_value_t(10), to_value_t(2), to_value_t(0) } },
|
||||||
{ "%lu", "3054 ", 1, 1, { unsignedlongarg0 }, { to_value_t(3054ul) } },
|
{ "%lu", "3054 ", 1, 1, { unsignedlongarg0 }, { to_value_t(3054ul) } },
|
||||||
|
// "actual" long long and unsigned long long, from #6096
|
||||||
|
// Note: '9223372036854775806' is the max value for 'long long'.
|
||||||
|
{ "%lld", "9223372036854775805", 1, 1, { longlongarg0 }, { to_value_t(9223372036854775805LL) } },
|
||||||
|
{ "%llu", "9223372036854775810", 1, 1, { unsignedlonglongarg0 }, { to_value_t(9223372036854775810ULL) } },
|
||||||
};
|
};
|
||||||
|
|
||||||
bool g_any_failed = false;
|
bool g_any_failed = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue