Add conversion to signed/unsigned int to wxString

Add wxString::ToInt() and ToUInt() for convenience and consistency with
the existing ToLong() and ToULong().

Closes #22068.
This commit is contained in:
Gerhard Gruber
2022-01-28 11:27:29 +01:00
committed by Vadim Zeitlin
parent c10a70be67
commit 9dc7248b1d
4 changed files with 148 additions and 4 deletions

View File

@@ -2310,9 +2310,14 @@ public:
// provided, the base is the numeric base in which the conversion should be
// done and must be comprised between 2 and 36 or be 0 in which case the
// standard C rules apply (leading '0' => octal, "0x" => hex)
// convert to a signed integer
// convert to a signed integer
bool ToInt(int *val, int base = 10) const;
// convert to an unsigned integer
bool ToUInt(unsigned int *val, int base = 10) const;
// convert to a signed long
bool ToLong(long *val, int base = 10) const;
// convert to an unsigned integer
// convert to an unsigned long
bool ToULong(unsigned long *val, int base = 10) const;
// convert to wxLongLong
#if defined(wxLongLong_t)

View File

@@ -1266,6 +1266,24 @@ public:
*/
bool ToCDouble(double* val) const;
/**
Works like ToLong() but for signed integers.
@see ToLong(), ToUInt(), ToDouble()
@since 3.1.6
*/
bool ToInt(int *val, int base = 10) const;
/**
Works like ToULong() but for unsigned integers.
@see ToInt(), ToULong(), ToDouble()
@since 3.1.6
*/
bool ToUInt(unsigned int *val, int base = 10) const;
/**
Attempts to convert the string to a signed integer in base @a base.
@@ -1294,7 +1312,7 @@ public:
Please refer to the documentation of the standard function @c strtol()
for more details about the supported syntax.
@see ToCDouble(), ToDouble(), ToULong()
@see ToCDouble(), ToDouble(), ToULong(), ToInt()
*/
bool ToLong(long* val, int base = 10) const;

View File

@@ -1677,6 +1677,32 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const
*pVal = val; \
return !*end;
bool wxString::ToInt(int *pVal, int base) const
{
wxASSERT_MSG(!base || (base > 1 && base <= 36), wxT("invalid base"));
WX_STRING_TO_X_TYPE_START
wxLongLong_t lval = wxStrtoll(start, &end, base);
if (lval < INT_MIN || lval > INT_MAX)
return false;
int val = (int)lval;
WX_STRING_TO_X_TYPE_END
}
bool wxString::ToUInt(unsigned int *pVal, int base) const
{
wxASSERT_MSG(!base || (base > 1 && base <= 36), wxT("invalid base"));
WX_STRING_TO_X_TYPE_START
wxULongLong_t lval = wxStrtoull(start, &end, base);
if (lval > UINT_MAX)
return false;
unsigned int val = (unsigned int)lval;
WX_STRING_TO_X_TYPE_END
}
bool wxString::ToLong(long *pVal, int base) const
{
wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );

View File

@@ -43,6 +43,8 @@ private:
CPPUNIT_TEST( Compare );
CPPUNIT_TEST( CompareNoCase );
CPPUNIT_TEST( Contains );
CPPUNIT_TEST( ToInt );
CPPUNIT_TEST( ToUInt );
CPPUNIT_TEST( ToLong );
CPPUNIT_TEST( ToULong );
#ifdef wxLongLong_t
@@ -78,6 +80,8 @@ private:
void Compare();
void CompareNoCase();
void Contains();
void ToInt();
void ToUInt();
void ToLong();
void ToULong();
#ifdef wxLongLong_t
@@ -602,7 +606,8 @@ enum
Number_Unsigned = 2, // if not specified, works for signed conversion
Number_Signed = 4, // if not specified, works for unsigned
Number_LongLong = 8, // only for long long tests
Number_Long = 16 // only for long tests
Number_Long = 16, // only for long tests
Number_Int = 32 // only for int tests
};
#ifdef wxLongLong_t
@@ -613,6 +618,38 @@ typedef long TestValue_t;
wxGCC_WARNING_SUPPRESS(missing-field-initializers)
static const struct ToIntData
{
const wxChar *str;
TestValue_t value;
int flags;
int base;
int IValue() const { return value; }
unsigned int UIValue() const { return value; }
bool IsOk() const { return !(flags & Number_Invalid); }
} intData[] =
{
{ wxT("1"), 1, Number_Ok },
{ wxT("0"), 0, Number_Ok },
{ wxT("a"), 0, Number_Invalid },
{ wxT("12345"), 12345, Number_Ok },
{ wxT("--1"), 0, Number_Invalid },
{ wxT("-1"), -1, Number_Signed | Number_Int },
{ wxT("-1"), (TestValue_t)UINT_MAX, Number_Unsigned | Number_Int | Number_Invalid },
{ wxT("2147483647"), (TestValue_t)INT_MAX, Number_Int | Number_Signed },
{ wxT("2147483648"), (TestValue_t)INT_MAX, Number_Int | Number_Signed | Number_Invalid },
{ wxT("-2147483648"), (TestValue_t)INT_MIN, Number_Int | Number_Signed },
{ wxT("-2147483649"), (TestValue_t)INT_MIN, Number_Int | Number_Signed | Number_Invalid },
{ wxT("4294967295"), (TestValue_t)UINT_MAX, Number_Int | Number_Unsigned },
{ wxT("4294967296"), (TestValue_t)UINT_MAX, Number_Int | Number_Unsigned | Number_Invalid },
};
static const struct ToLongData
{
const wxChar *str;
@@ -670,6 +707,64 @@ static const struct ToLongData
wxGCC_WARNING_RESTORE(missing-field-initializers)
void StringTestCase::ToInt()
{
int i;
for (size_t n = 0; n < WXSIZEOF(intData); n++)
{
const ToIntData &id = intData[n];
if (id.flags & (Number_Unsigned))
continue;
CPPUNIT_ASSERT_EQUAL(id.IsOk(),
wxString(id.str).ToInt(&i, id.base));
if (id.IsOk())
CPPUNIT_ASSERT_EQUAL(id.IValue(), i);
}
// special case: check that the output is not modified if the parsing
// failed completely
i = 17;
CPPUNIT_ASSERT(!wxString("foo").ToInt(&i));
CPPUNIT_ASSERT_EQUAL(17, i);
// also check that it is modified if we did parse something successfully in
// the beginning of the string
CPPUNIT_ASSERT(!wxString("9 cats").ToInt(&i));
CPPUNIT_ASSERT_EQUAL(9, i);
}
void StringTestCase::ToUInt()
{
unsigned int i;
for (size_t n = 0; n < WXSIZEOF(intData); n++)
{
const ToIntData &id = intData[n];
if (id.flags & (Number_Signed))
continue;
CPPUNIT_ASSERT_EQUAL(id.IsOk(),
wxString(id.str).ToUInt(&i, id.base));
if (id.IsOk())
CPPUNIT_ASSERT_EQUAL(id.UIValue(), i);
}
// special case: check that the output is not modified if the parsing
// failed completely
i = 17;
CPPUNIT_ASSERT(!wxString("foo").ToUInt(&i));
CPPUNIT_ASSERT_EQUAL(17, i);
// also check that it is modified if we did parse something successfully in
// the beginning of the string
CPPUNIT_ASSERT(!wxString("9 cats").ToUInt(&i));
CPPUNIT_ASSERT_EQUAL(9, i);
}
void StringTestCase::ToLong()
{
long l;