add the ToCLong, ToCULong and ToCDouble functions, with docs and test units
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59645 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -2202,24 +2202,33 @@ public:
|
||||
// check if the string contents matches a mask containing '*' and '?'
|
||||
bool Matches(const wxString& mask) const;
|
||||
|
||||
// conversion to numbers: all functions return true only if the whole
|
||||
// string is a number and put the value of this number into the pointer
|
||||
// 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
|
||||
bool ToLong(long *val, int base = 10) const;
|
||||
// convert to an unsigned integer
|
||||
bool ToULong(unsigned long *val, int base = 10) const;
|
||||
// convert to wxLongLong
|
||||
// conversion to numbers: all functions return true only if the whole
|
||||
// string is a number and put the value of this number into the pointer
|
||||
// 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
|
||||
bool ToLong(long *val, int base = 10) const;
|
||||
// convert to an unsigned integer
|
||||
bool ToULong(unsigned long *val, int base = 10) const;
|
||||
// convert to wxLongLong
|
||||
#if defined(wxLongLong_t)
|
||||
bool ToLongLong(wxLongLong_t *val, int base = 10) const;
|
||||
// convert to wxULongLong
|
||||
bool ToULongLong(wxULongLong_t *val, int base = 10) const;
|
||||
bool ToLongLong(wxLongLong_t *val, int base = 10) const;
|
||||
// convert to wxULongLong
|
||||
bool ToULongLong(wxULongLong_t *val, int base = 10) const;
|
||||
#endif // wxLongLong_t
|
||||
// convert to a double
|
||||
bool ToDouble(double *val) const;
|
||||
// convert to a double
|
||||
bool ToDouble(double *val) const;
|
||||
|
||||
#if wxUSE_XLOCALE
|
||||
// conversions to numbers using C locale
|
||||
// convert to a signed integer
|
||||
bool ToCLong(long *val, int base = 10) const;
|
||||
// convert to an unsigned integer
|
||||
bool ToCULong(unsigned long *val, int base = 10) const;
|
||||
// convert to a double
|
||||
bool ToCDouble(double *val) const;
|
||||
#endif
|
||||
|
||||
#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
|
||||
// formatted input/output
|
||||
|
@@ -894,21 +894,43 @@ public:
|
||||
//@{
|
||||
|
||||
/**
|
||||
Attempts to convert the string to a floating point number. Returns @true on
|
||||
success (the number is stored in the location pointed to by @e val) or @false
|
||||
if the string does not represent such number (the value of @a val is not
|
||||
modified in this case).
|
||||
Attempts to convert the string to a floating point number.
|
||||
|
||||
@see ToLong(), ToULong()
|
||||
Returns @true on success (the number is stored in the location pointed to by
|
||||
@a val) or @false if the string does not represent such number (the value of
|
||||
@a val is not modified in this case).
|
||||
|
||||
Note that unlike ToCDouble() this function uses a localized version of
|
||||
@c wxStrtod() and thus needs as decimal point (and thousands separator) the
|
||||
locale-specific decimal point. Thus you should use this function only when
|
||||
you are sure that this string contains a floating point number formatted with
|
||||
the rules of the locale currently in use (see wxLocale).
|
||||
|
||||
Refer to the docs of the standard function @c strtod() for more details about
|
||||
the supported syntax.
|
||||
|
||||
@see ToCDouble(), ToLong(), ToULong()
|
||||
*/
|
||||
bool ToDouble(double* val) const;
|
||||
|
||||
/**
|
||||
Attempts to convert the string to a signed integer in base @e base. Returns
|
||||
@true on success in which case the number is stored in the location
|
||||
Works like ToDouble() but unlike it this function expects the floating point
|
||||
number to be formatted always with the rules dictated by the "C" locale
|
||||
(in particular, the decimal point must be a dot), independently from the
|
||||
current application-wide locale (see wxLocale).
|
||||
|
||||
@see ToDouble(), ToLong(), ToULong()
|
||||
*/
|
||||
bool ToCDouble(double* val) const;
|
||||
|
||||
/**
|
||||
Attempts to convert the string to a signed integer in base @a base.
|
||||
|
||||
Returns @true on success in which case the number is stored in the location
|
||||
pointed to by @a val or @false if the string does not represent a
|
||||
valid number in the given base (the value of @a val is not modified
|
||||
in this case).
|
||||
|
||||
The value of @a base must be comprised between 2 and 36, inclusive, or
|
||||
be a special value 0 which means that the usual rules of @c C numbers are
|
||||
applied: if the number starts with @c 0x it is considered to be in base
|
||||
@@ -917,13 +939,30 @@ public:
|
||||
which may have leading zeroes as they can yield unexpected (to the user not
|
||||
familiar with C) results.
|
||||
|
||||
@see ToDouble(), ToULong()
|
||||
Note that unlike ToCLong() this function uses a localized version of
|
||||
@c wxStrtol(). Thus you should use this function only when you are sure
|
||||
that this string contains an integer number formatted with
|
||||
the rules of the locale currently in use (see wxLocale).
|
||||
|
||||
Refer to the docs of the standard function @c strtol() for more details about
|
||||
the supported syntax.
|
||||
|
||||
@see ToCDouble(), ToDouble(), ToULong()
|
||||
*/
|
||||
bool ToLong(long* val, int base = 10) const;
|
||||
|
||||
/**
|
||||
This is exactly the same as ToLong() but works with 64
|
||||
bit integer numbers.
|
||||
Works like ToLong() but unlike it this function expects the integer
|
||||
number to be formatted always with the rules dictated by the "C" locale,
|
||||
independently from the current application-wide locale (see wxLocale).
|
||||
|
||||
@see ToDouble(), ToLong(), ToULong()
|
||||
*/
|
||||
bool ToCLong(long* val, int base = 10) const;
|
||||
|
||||
/**
|
||||
This is exactly the same as ToLong() but works with 64 bit integer numbers.
|
||||
|
||||
Notice that currently it doesn't work (always returns @false) if parsing of 64
|
||||
bit numbers is not supported by the underlying C run-time library. Compilers
|
||||
with C99 support and Microsoft Visual C++ version 7 and higher do support this.
|
||||
@@ -933,7 +972,8 @@ public:
|
||||
bool ToLongLong(wxLongLong_t* val, int base = 10) const;
|
||||
|
||||
/**
|
||||
Attempts to convert the string to an unsigned integer in base @e base.
|
||||
Attempts to convert the string to an unsigned integer in base @a base.
|
||||
|
||||
Returns @true on success in which case the number is stored in the
|
||||
location pointed to by @a val or @false if the string does not
|
||||
represent a valid number in the given base (the value of @a val is not
|
||||
@@ -943,12 +983,22 @@ public:
|
||||
@c strtoul() and so it simply converts negative numbers to unsigned
|
||||
representation instead of rejecting them (e.g. -1 is returned as @c ULONG_MAX).
|
||||
|
||||
See ToLong() for the more detailed description of the @a base parameter.
|
||||
See ToLong() for the more detailed description of the @a base parameter
|
||||
(and of the locale-specific behaviour of this function).
|
||||
|
||||
@see ToDouble(), ToLong()
|
||||
@see ToCULong(), ToDouble(), ToLong()
|
||||
*/
|
||||
bool ToULong(unsigned long* val, int base = 10) const;
|
||||
|
||||
/**
|
||||
Works like ToULong() but unlike it this function expects the integer
|
||||
number to be formatted always with the rules dictated by the "C" locale,
|
||||
independently from the current application-wide locale (see wxLocale).
|
||||
|
||||
@see ToDouble(), ToLong(), ToULong()
|
||||
*/
|
||||
bool ToCULong(unsigned long* val, int base = 10) const;
|
||||
|
||||
/**
|
||||
This is exactly the same as ToULong() but works with 64
|
||||
bit integer numbers.
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "wx/hashmap.h"
|
||||
#include "wx/vector.h"
|
||||
#include "wx/xlocale.h"
|
||||
|
||||
// string handling functions used by wxString:
|
||||
#if wxUSE_UNICODE_UTF8
|
||||
@@ -1644,64 +1645,105 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const
|
||||
#define DO_IF_NOT_WINCE(x)
|
||||
#endif
|
||||
|
||||
#define WX_STRING_TO_INT_TYPE(out, base, func, T) \
|
||||
wxCHECK_MSG( out, false, _T("NULL output pointer") ); \
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); \
|
||||
\
|
||||
#define WX_STRING_TO_X_TYPE_START \
|
||||
wxCHECK_MSG( pVal, false, _T("NULL output pointer") ); \
|
||||
DO_IF_NOT_WINCE( errno = 0; ) \
|
||||
\
|
||||
const wxStringCharType *start = wx_str(); \
|
||||
wxStringCharType *end; \
|
||||
T val = func(start, &end, base); \
|
||||
\
|
||||
wxStringCharType *end;
|
||||
|
||||
#define WX_STRING_TO_X_TYPE_END \
|
||||
/* return true only if scan was stopped by the terminating NUL and */ \
|
||||
/* if the string was not empty to start with and no under/overflow */ \
|
||||
/* occurred: */ \
|
||||
if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) \
|
||||
return false; \
|
||||
*out = val; \
|
||||
return true
|
||||
*pVal = val; \
|
||||
return true;
|
||||
|
||||
bool wxString::ToLong(long *pVal, int base) const
|
||||
{
|
||||
WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long);
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
long val = wxStrtol(start, &end, base);
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToULong(unsigned long *pVal, int base) const
|
||||
{
|
||||
WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long);
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
unsigned long val = wxStrtoul(start, &end, base);
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const
|
||||
{
|
||||
WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t);
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
wxLongLong_t val = wxStrtoll(start, &end, base);
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const
|
||||
{
|
||||
WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t);
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
wxULongLong_t val = wxStrtoull(start, &end, base);
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToDouble(double *pVal) const
|
||||
{
|
||||
wxCHECK_MSG( pVal, false, _T("NULL output pointer") );
|
||||
|
||||
DO_IF_NOT_WINCE( errno = 0; )
|
||||
|
||||
const wxChar *start = c_str();
|
||||
wxChar *end;
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
double val = wxStrtod(start, &end);
|
||||
|
||||
// return true only if scan was stopped by the terminating NUL and if the
|
||||
// string was not empty to start with and no under/overflow occurred
|
||||
if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )
|
||||
return false;
|
||||
|
||||
*pVal = val;
|
||||
|
||||
return true;
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
#if wxUSE_XLOCALE
|
||||
|
||||
bool wxString::ToCLong(long *pVal, int base) const
|
||||
{
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
|
||||
long val = wxStrtol_lA(start, &end, base, wxCLocale);
|
||||
#else
|
||||
long val = wxStrtol_l(start, &end, base, wxCLocale);
|
||||
#endif
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToCULong(unsigned long *pVal, int base) const
|
||||
{
|
||||
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
|
||||
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
|
||||
unsigned long val = wxStrtoul_lA(start, &end, base, wxCLocale);
|
||||
#else
|
||||
unsigned long val = wxStrtoul_l(start, &end, base, wxCLocale);
|
||||
#endif
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
bool wxString::ToCDouble(double *pVal) const
|
||||
{
|
||||
WX_STRING_TO_X_TYPE_START
|
||||
#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
|
||||
double val = wxStrtod_lA(start, &end, wxCLocale);
|
||||
#else
|
||||
double val = wxStrtod_l(start, &end, wxCLocale);
|
||||
#endif
|
||||
WX_STRING_TO_X_TYPE_END
|
||||
}
|
||||
|
||||
#endif // wxUSE_XLOCALE
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// formatted output
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@@ -589,6 +589,13 @@ void StringTestCase::ToLong()
|
||||
if ( ld.flags & (Number_LongLong | Number_Unsigned) )
|
||||
continue;
|
||||
|
||||
// NOTE: unless you're using some exotic locale, ToCLong and ToLong
|
||||
// should behave the same for our test data set:
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToCLong(&l) );
|
||||
if ( ld.IsOk() )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.LValue(), l );
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToLong(&l) );
|
||||
if ( ld.IsOk() )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.LValue(), l );
|
||||
@@ -605,6 +612,13 @@ void StringTestCase::ToULong()
|
||||
if ( ld.flags & (Number_LongLong | Number_Signed) )
|
||||
continue;
|
||||
|
||||
// NOTE: unless you're using some exotic locale, ToCLong and ToLong
|
||||
// should behave the same for our test data set:
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToCULong(&ul) );
|
||||
if ( ld.IsOk() )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul );
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToULong(&ul) );
|
||||
if ( ld.IsOk() )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul );
|
||||
@@ -667,20 +681,59 @@ void StringTestCase::ToDouble()
|
||||
{ _T("12345"), 12345, true },
|
||||
{ _T("-1"), -1, true },
|
||||
{ _T("--1"), 0, false },
|
||||
{ _T("-3E-5"), -3E-5, true },
|
||||
{ _T("-3E-abcde5"), 0, false },
|
||||
};
|
||||
|
||||
// we need to use decimal point, not comma or whatever is its value for the
|
||||
// current locale
|
||||
wxSetlocale(LC_ALL, "C");
|
||||
// test ToCDouble() first:
|
||||
|
||||
size_t n;
|
||||
for ( n = 0; n < WXSIZEOF(doubleData); n++ )
|
||||
{
|
||||
const ToDoubleData& ld = doubleData[n];
|
||||
CPPUNIT_ASSERT_EQUAL( ld.ok, wxString(ld.str).ToCDouble(&d) );
|
||||
if ( ld.ok )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.value, d );
|
||||
}
|
||||
|
||||
|
||||
// test ToDouble() now:
|
||||
// NOTE: for the test to be reliable, we need to set the locale explicitely
|
||||
// so that we know the decimal point character to use
|
||||
|
||||
if (!wxLocale::IsAvailable(wxLANGUAGE_FRENCH))
|
||||
return; // you should have french support installed to continue this test!
|
||||
|
||||
wxLocale *locale = new wxLocale;
|
||||
|
||||
// don't load default catalog, it may be unavailable:
|
||||
CPPUNIT_ASSERT( locale->Init(wxLANGUAGE_FRENCH, wxLOCALE_CONV_ENCODING) );
|
||||
|
||||
static const struct ToDoubleData doubleData2[] =
|
||||
{
|
||||
{ _T("1"), 1, true },
|
||||
{ _T("1,23"), 1.23, true },
|
||||
{ _T(",1"), .1, true },
|
||||
{ _T("1,"), 1, true },
|
||||
{ _T("1,,"), 0, false },
|
||||
{ _T("0"), 0, true },
|
||||
{ _T("a"), 0, false },
|
||||
{ _T("12345"), 12345, true },
|
||||
{ _T("-1"), -1, true },
|
||||
{ _T("--1"), 0, false },
|
||||
{ _T("-3E-5"), -3E-5, true },
|
||||
{ _T("-3E-abcde5"), 0, false },
|
||||
};
|
||||
|
||||
for ( n = 0; n < WXSIZEOF(doubleData2); n++ )
|
||||
{
|
||||
const ToDoubleData& ld = doubleData2[n];
|
||||
CPPUNIT_ASSERT_EQUAL( ld.ok, wxString(ld.str).ToDouble(&d) );
|
||||
if ( ld.ok )
|
||||
CPPUNIT_ASSERT_EQUAL( ld.value, d );
|
||||
}
|
||||
|
||||
delete locale;
|
||||
}
|
||||
|
||||
void StringTestCase::StringBuf()
|
||||
|
Reference in New Issue
Block a user