Fix C++17 implementation of wxString::ToCULong()

Do use std::from_chars<unsigned long>() in it as otherwise values
greater than LONG_MAX failed to parse.

Handle negative numbers explicitly to still parse them in this function
as well, as needs to be done for compatibility.

Add a test case for the previously failing numbers.

Closes #23957.
This commit is contained in:
Vadim Zeitlin 2023-10-30 23:56:53 +01:00
parent 9a620bf920
commit 8d6a722ed8
2 changed files with 34 additions and 9 deletions

View file

@ -1633,20 +1633,34 @@ bool wxString::ToCLong(long *pVal, int base) const
bool wxString::ToCULong(unsigned long *pVal, int base) const
{
// We intentionally don't use std::from_chars() here because this function
// is supposed to be compatible with strtoul() and so _succeed_ for "-1",
// for example, instead of returning an error as from_chars() (much more
// logically) does.
wxCHECK_MSG( pVal, false, "null output pointer" );
long l;
if ( !ToCLong(&l, base) )
const wxScopedCharBuffer& buf = utf8_str();
auto start = buf.data();
const auto end = start + buf.length();
if ( !SetBaseAndSkipPrefix(base, start, end) )
return false;
*pVal = static_cast<unsigned long>(l);
// Extra complication: for compatibility reasons, this function does accept
// "-1" as valid input (as strtoul() does!), but from_chars() doesn't, for
// unsigned values, so check for this separately.
if ( *start == '-' )
{
long l;
const auto res = std::from_chars(start, end, l, base);
return true;
if ( res.ec != std::errc{} || res.ptr != end )
return false;
*pVal = static_cast<unsigned long>(l);
return true;
}
const auto res = std::from_chars(start, end, *pVal, base);
return res.ec == std::errc{} && res.ptr == end;
}
bool wxString::ToCDouble(double *pVal) const

View file

@ -607,6 +607,17 @@ static const struct ToLongData
{ wxT("0x11"), 17, Number_Ok, 0 },
{ wxT("0x11"), 0, Number_Invalid, 8 },
{ wxT("0x11"), 17, Number_Ok, 16 },
{
#if SIZEOF_LONG == 4
wxT("0xffffffff"),
#elif SIZEOF_LONG == 8
wxT("0xffffffffffffffff"),
#else
#error "Unknown sizeof(long)"
#endif
(TestValue_t)ULONG_MAX, Number_Unsigned, 0
},
};
wxGCC_WARNING_RESTORE(missing-field-initializers)