mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-26 18:18:26 +08:00
Merge branch 'cxx17-string-toculong'
Fixes for C++17 version of wxString::ToCULong(). See #24022.
This commit is contained in:
+59
-18
@@ -1577,18 +1577,29 @@ bool wxString::ToDouble(double *pVal) const
|
||||
// to if the compiler claims to support C++17, but it doesn't hurt to check).
|
||||
#ifdef __cpp_lib_to_chars
|
||||
|
||||
bool wxString::ToCLong(long *pVal, int base) const
|
||||
namespace
|
||||
{
|
||||
wxCHECK_MSG( pVal, false, "null output pointer" );
|
||||
|
||||
const wxScopedCharBuffer& buf = utf8_str();
|
||||
auto start = buf.data();
|
||||
const auto end = start + buf.length();
|
||||
// Helper of ToCLong() and ToCULong() taking care of prefix and base-related
|
||||
// stuff: because from_chars() doesn't skip leading whitespace and doesn't
|
||||
// recognize base==0 nor "0x" prefix even if base 16 is explicitly specified,
|
||||
// we need to skip the leading space and prefix indicating the base to use if
|
||||
// it's present and adjust "base" itself instead.
|
||||
//
|
||||
// Return false if base is already specified but is incompatible with the
|
||||
// prefix used.
|
||||
bool SkipOptPrefixAndSetBase(int& base, const char*& start, const char* end)
|
||||
{
|
||||
// Start by skipping whitespace.
|
||||
while ( wxSafeIsspace(*start) )
|
||||
++start;
|
||||
|
||||
// from_chars() doesn't recognize base==0 and doesn't recognize "0x" prefix
|
||||
// even if base 16 is explicitly specified, so adjust the input to use the
|
||||
// form it supports.
|
||||
if ( buf.length() > 1 && *start == '0' )
|
||||
// Also skip optional "+" which std::from_chars() doesn't accept neither.
|
||||
if ( *start == '+' )
|
||||
++start;
|
||||
|
||||
// Then check for the base prefix.
|
||||
if ( end - start > 1 && *start == '0' )
|
||||
{
|
||||
++start;
|
||||
if ( *start == 'x' || *start == 'X' )
|
||||
@@ -1609,6 +1620,22 @@ bool wxString::ToCLong(long *pVal, int base) const
|
||||
if ( base == 0 )
|
||||
base = 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool wxString::ToCLong(long *pVal, int base) const
|
||||
{
|
||||
wxCHECK_MSG( pVal, false, "null output pointer" );
|
||||
|
||||
const wxScopedCharBuffer& buf = utf8_str();
|
||||
auto start = buf.data();
|
||||
const auto end = start + buf.length();
|
||||
|
||||
if ( !SkipOptPrefixAndSetBase(base, start, end) )
|
||||
return false;
|
||||
|
||||
const auto res = std::from_chars(start, end, *pVal, base);
|
||||
|
||||
return res.ec == std::errc{} && res.ptr == end;
|
||||
@@ -1616,20 +1643,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 ( !SkipOptPrefixAndSetBase(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
|
||||
|
||||
@@ -580,6 +580,9 @@ static const struct ToLongData
|
||||
{ wxT("-1"), -1, Number_Signed | Number_Long },
|
||||
// this is surprising but consistent with strtoul() behaviour
|
||||
{ wxT("-1"), (TestValue_t)ULONG_MAX, Number_Unsigned | Number_Long },
|
||||
// a couple of edge cases
|
||||
{ wxT(" +1"), 1, Number_Ok },
|
||||
{ wxT(" -1"), (TestValue_t)ULONG_MAX, Number_Unsigned | Number_Long },
|
||||
|
||||
// this must overflow, even with 64 bit long
|
||||
{ wxT("922337203685477580711"), 0, Number_Invalid },
|
||||
@@ -607,6 +610,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)
|
||||
|
||||
Reference in New Issue
Block a user