mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-31 14:39:53 +01:00
- strToInt benchmark and more optimization
- warnmsg macro in CppUnit
This commit is contained in:
parent
bf74a4be8b
commit
8a4eafd05a
@ -1,7 +1,7 @@
|
|||||||
This is the changelog file for the POCO C++ Libraries.
|
This is the changelog file for the POCO C++ Libraries.
|
||||||
|
|
||||||
|
|
||||||
Release 1.5.0 (2012-09-??)
|
Release 1.5.0 (2012-10-01)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
- added JSON
|
- added JSON
|
||||||
@ -43,6 +43,8 @@ Release 1.5.0 (2012-09-??)
|
|||||||
- fixed SF#307 Detect the SQL driver type at run time
|
- fixed SF#307 Detect the SQL driver type at run time
|
||||||
- added VS 2012 Projects/Solutions
|
- added VS 2012 Projects/Solutions
|
||||||
- enhanced and accelerated numeric parsing for integers and floats
|
- enhanced and accelerated numeric parsing for integers and floats
|
||||||
|
- fixed SF#590 Segfault on FreeBSD when stack size not rounded
|
||||||
|
- added warn function and warnmsg macro in CppUnit
|
||||||
|
|
||||||
Release 1.4.4p1 (2012-??-??)
|
Release 1.4.4p1 (2012-??-??)
|
||||||
============================
|
============================
|
||||||
|
@ -162,9 +162,9 @@ protected:
|
|||||||
long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER,
|
long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER,
|
||||||
const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME);
|
const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME);
|
||||||
|
|
||||||
void warn(const std::string& message = "",
|
void warn(const std::string& message = "",
|
||||||
long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER,
|
long lineNumber = CppUnitException::CPPUNIT_UNKNOWNLINENUMBER,
|
||||||
const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME);
|
const std::string& fileName = CppUnitException::CPPUNIT_UNKNOWNFILENAME);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -247,6 +247,9 @@ inline std::string TestCase::toString()
|
|||||||
#define failmsg(msg) \
|
#define failmsg(msg) \
|
||||||
(this->fail(msg, __LINE__, __FILE__))
|
(this->fail(msg, __LINE__, __FILE__))
|
||||||
|
|
||||||
|
#define warnmsg(msg) \
|
||||||
|
(this->fail(msg, __LINE__, __FILE__))
|
||||||
|
|
||||||
|
|
||||||
} // namespace CppUnit
|
} // namespace CppUnit
|
||||||
|
|
||||||
|
@ -57,138 +57,106 @@ namespace Poco {
|
|||||||
|
|
||||||
|
|
||||||
inline char decimalSeparator()
|
inline char decimalSeparator()
|
||||||
/// Returns decimal separator from global locale or
|
/// Returns decimal separator from global locale or
|
||||||
/// default '.' for platforms where locale is unavailable.
|
/// default '.' for platforms where locale is unavailable.
|
||||||
{
|
{
|
||||||
#if !defined(POCO_NO_LOCALE)
|
#if !defined(POCO_NO_LOCALE)
|
||||||
return std::use_facet<std::numpunct<char> >(std::locale()).decimal_point();
|
return std::use_facet<std::numpunct<char> >(std::locale()).decimal_point();
|
||||||
#else
|
#else
|
||||||
return '.';
|
return '.';
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline char thousandSeparator()
|
inline char thousandSeparator()
|
||||||
/// Returns thousand separator from global locale or
|
/// Returns thousand separator from global locale or
|
||||||
/// default ',' for platforms where locale is unavailable.
|
/// default ',' for platforms where locale is unavailable.
|
||||||
{
|
{
|
||||||
#if !defined(POCO_NO_LOCALE)
|
#if !defined(POCO_NO_LOCALE)
|
||||||
return std::use_facet<std::numpunct<char> >(std::locale()).thousands_sep();
|
return std::use_facet<std::numpunct<char> >(std::locale()).thousands_sep();
|
||||||
#else
|
#else
|
||||||
return ',';
|
return ',';
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
bool strToInt(const char* pStr, I& result, short base = -1)
|
bool strToInt(const char* pStr, I& result, short base)
|
||||||
/// Converts zero-terminated array to integer number;
|
/// Converts zero-terminated character array to integer number;
|
||||||
/// If base is equal to -1, this functin will try to determine
|
/// Thousand separators are recognized for base10 and current locale;
|
||||||
/// the numeric base (using '0' prefix for octal, '0x' for
|
/// it is silently skipped but not verified for correct positioning.
|
||||||
/// hexadecimal and no prefix for decimal).
|
/// Function returns true if succesful. If parsing was unsuccesful,
|
||||||
/// Thousand separators are recognized for base10 and the locale
|
/// the return value is false with the result value undetermined.
|
||||||
/// and silently skipped but not verified for correct positioning.
|
|
||||||
/// Returns true if succesful. If parsing was unsuccesful,
|
|
||||||
/// the return value is false with result value undetermined.
|
|
||||||
{
|
{
|
||||||
if (!std::numeric_limits<I>::is_integer) return false;
|
if (!pStr) return false;
|
||||||
|
while (*pStr == ' ') ++pStr;
|
||||||
if (!pStr || (pStr && *pStr == '\0')) return false;
|
|
||||||
while ((*pStr != '\0') && (*pStr == ' ')) ++pStr;
|
|
||||||
if (*pStr == '\0') return false;
|
if (*pStr == '\0') return false;
|
||||||
|
I sign = 1;
|
||||||
char sign = 1;
|
if ((base == 10) && (*pStr == '-'))
|
||||||
|
|
||||||
if (*pStr == '-')
|
|
||||||
{
|
{
|
||||||
++pStr;
|
|
||||||
sign = -1;
|
sign = -1;
|
||||||
|
++pStr;
|
||||||
}
|
}
|
||||||
else if (*pStr == '+') ++pStr;
|
else if (*pStr == '+') ++pStr;
|
||||||
if (*pStr == '\0') return false;
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
|
|
||||||
if (*pStr == '0')
|
|
||||||
{
|
|
||||||
while ((*pStr != '\0') && (*pStr == '0')) ++pStr;
|
|
||||||
if (*pStr == '\0')
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*pStr == 'x') || (*pStr == 'X'))
|
|
||||||
{
|
|
||||||
base = 0x10;
|
|
||||||
++pStr;
|
|
||||||
if (*pStr == '\0') return false;
|
|
||||||
}
|
|
||||||
else if (base == -1) base = 010;
|
|
||||||
}
|
|
||||||
else if (base == -1) base = 10;
|
|
||||||
|
|
||||||
while ((*pStr == '0'))
|
|
||||||
{
|
|
||||||
if (*pStr != '\0')
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
++pStr;
|
|
||||||
}
|
|
||||||
if (*pStr == '\0') return false;
|
|
||||||
|
|
||||||
|
// parser states:
|
||||||
|
const char STATE_SIGNIFICANT_DIGITS = 1;
|
||||||
|
char state = 0;
|
||||||
const char thSep = thousandSeparator();
|
const char thSep = thousandSeparator();
|
||||||
bool allowDigits = true;
|
|
||||||
|
result = 0;
|
||||||
|
I limitCheck = std::numeric_limits<I>::max() / base;
|
||||||
for (; *pStr != '\0'; ++pStr)
|
for (; *pStr != '\0'; ++pStr)
|
||||||
{
|
{
|
||||||
switch (*pStr)
|
switch (*pStr)
|
||||||
{
|
{
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case 'x': case 'X':
|
||||||
|
if (base != 0x10) return false;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
if (state < STATE_SIGNIFICANT_DIGITS) break;
|
||||||
|
|
||||||
|
case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7':
|
case '5': case '6': case '7':
|
||||||
if (allowDigits)
|
if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
|
||||||
{
|
if (result > limitCheck) return false;
|
||||||
if (result > (std::numeric_limits<I>::max() / base)) return false;
|
result = result * base + (*pStr - '0');
|
||||||
result = result * base + (*pStr - '0');
|
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '8': case '9':
|
case '8': case '9':
|
||||||
if (allowDigits && (base == 10 || base == 16))
|
if ((base == 10) || (base == 0x10))
|
||||||
{
|
{
|
||||||
if (result > (std::numeric_limits<I>::max() / base)) return false;
|
if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
|
||||||
|
if (result > limitCheck) return false;
|
||||||
result = result * base + (*pStr - '0');
|
result = result * base + (*pStr - '0');
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||||
if (allowDigits && base == 16)
|
if (base != 0x10) return false;
|
||||||
{
|
if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
|
||||||
if (result > (std::numeric_limits<I>::max() / base)) return false;
|
if (result > limitCheck) return false;
|
||||||
result = result * base + (10 + *pStr - 'a');
|
result = result * base + (10 + *pStr - 'a');
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||||
if (allowDigits && base == 16)
|
if (base != 0x10) return false;
|
||||||
{
|
|
||||||
if (result > (std::numeric_limits<I>::max() / base)) return false;
|
if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
|
||||||
result = result * base + (10 + *pStr - 'A');
|
if (result > limitCheck) return false;
|
||||||
}
|
result = result * base + (10 + *pStr - 'A');
|
||||||
else
|
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'l':
|
case 'l':
|
||||||
allowDigits = false;
|
goto done;
|
||||||
break;
|
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
if ((base == 10) && (thSep == '.')) break;
|
if ((base == 10) && (thSep == '.')) break;
|
||||||
@ -199,23 +167,23 @@ bool strToInt(const char* pStr, I& result, short base = -1)
|
|||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
case ' ':
|
case ' ':
|
||||||
if (base == 10) break;
|
if ((base == 10) && (thSep == ' ')) break;
|
||||||
else return false;
|
goto done;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((base == 10) && (std::numeric_limits<I>::is_signed))
|
done:
|
||||||
result *= sign;
|
if ((sign < 0) && (base == 10)) result *= sign;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
bool strToInt(const std::string& str, I& result, short base = -1)
|
bool strToInt(const std::string& str, I& result, short base)
|
||||||
/// Converts string to integer number;
|
/// Converts string to integer number;
|
||||||
/// This is a wrapper function, for details see see the
|
/// This is a wrapper function, for details see see the
|
||||||
/// bool strToInt(const char*, I&, short&) implementation.
|
/// bool strToInt(const char*, I&, short&) implementation.
|
||||||
|
@ -564,24 +564,63 @@ void StringTest::testNumericLocale()
|
|||||||
} catch (std::runtime_error& ex)
|
} catch (std::runtime_error& ex)
|
||||||
{
|
{
|
||||||
std::cout << ex.what() << std::endl;
|
std::cout << ex.what() << std::endl;
|
||||||
warn ("Locale not found, skipping test");
|
warnmsg ("Locale not found, skipping test");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool parseStream(const std::string& s, double& value)
|
void StringTest::benchmarkStrToInt()
|
||||||
{
|
{
|
||||||
MemoryInputStream istr(s.data(), s.size());
|
Poco::Stopwatch sw;
|
||||||
#if !defined(POCO_NO_LOCALE)
|
int number = 123456789;
|
||||||
istr.imbue(std::locale::classic());
|
std::string num = "123456789";
|
||||||
#endif
|
int res;
|
||||||
istr >> value;
|
sw.start();
|
||||||
return istr.eof() && !istr.fail();
|
for (int i = 0; i < 1000000; ++i) parseStream(num, res);
|
||||||
|
sw.stop();
|
||||||
|
std::cout << "parseStream Number: " << res << std::endl;
|
||||||
|
double timeStream = sw.elapsed() / 1000.0;
|
||||||
|
|
||||||
|
char* pC = 0;
|
||||||
|
sw.restart();
|
||||||
|
for (int i = 0; i < 1000000; ++i) res = std::strtol(num.c_str(), &pC, 10);
|
||||||
|
sw.stop();
|
||||||
|
std::cout << "std::strtol Number: " << res << std::endl;
|
||||||
|
double timeStrtol = sw.elapsed() / 1000.0;
|
||||||
|
|
||||||
|
sw.restart();
|
||||||
|
for (int i = 0; i < 1000000; ++i) strToInt(num.c_str(), res, 10);
|
||||||
|
sw.stop();
|
||||||
|
std::cout << "strToInt Number: " << res << std::endl;
|
||||||
|
double timeStrToInt = sw.elapsed() / 1000.0;
|
||||||
|
|
||||||
|
sw.restart();
|
||||||
|
for (int i = 0; i < 1000000; ++i) std::sscanf(num.c_str(), "%d%c", &res);
|
||||||
|
sw.stop();
|
||||||
|
std::cout << "sscanf Number: " << res << std::endl;
|
||||||
|
double timeScanf = sw.elapsed() / 1000.0;
|
||||||
|
|
||||||
|
int graph;
|
||||||
|
std::cout << std::endl << "Timing and speedup relative to I/O stream:" << std::endl << std::endl;
|
||||||
|
std::cout << std::setw(14) << "Stream:\t" << std::setw(10) << std::setfill(' ') << timeStream << "[ms]" << std::endl;
|
||||||
|
|
||||||
|
std::cout << std::setw(14) << "std::strtol:\t" << std::setw(10) << std::setfill(' ') << timeStrtol << "[ms]" <<
|
||||||
|
std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrtol) << '\t' ;
|
||||||
|
graph = (int) (timeStream / timeStrtol); for (int i = 0; i < graph; ++i) std::cout << '|';
|
||||||
|
|
||||||
|
std::cout << std::endl << std::setw(14) << "strToInt:\t" << std::setw(10) << std::setfill(' ') << timeStrToInt << "[ms]" <<
|
||||||
|
std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrToInt) << '\t' ;
|
||||||
|
graph = (int) (timeStream / timeStrToInt); for (int i = 0; i < graph; ++i) std::cout << '|';
|
||||||
|
|
||||||
|
std::cout << std::endl << std::setw(14) << "std::sscanf:\t" << std::setw(10) << std::setfill(' ') << timeScanf << "[ms]" <<
|
||||||
|
std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeScanf) << '\t' ;
|
||||||
|
graph = (int) (timeStream / timeScanf); for (int i = 0; i < graph; ++i) std::cout << '|';
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringTest::benchmark()
|
void StringTest::benchmarkStrToFloat()
|
||||||
{
|
{
|
||||||
Poco::Stopwatch sw;
|
Poco::Stopwatch sw;
|
||||||
double number = 1.23456e-123;
|
double number = 1.23456e-123;
|
||||||
@ -599,7 +638,7 @@ void StringTest::benchmark()
|
|||||||
sw.stop();
|
sw.stop();
|
||||||
std::cout << "std::strtod Number: " << res << std::endl;
|
std::cout << "std::strtod Number: " << res << std::endl;
|
||||||
double timeStrtod = sw.elapsed() / 1000.0;
|
double timeStrtod = sw.elapsed() / 1000.0;
|
||||||
|
|
||||||
sw.restart();
|
sw.restart();
|
||||||
char ou = 0;
|
char ou = 0;
|
||||||
for (int i = 0; i < 1000000; ++i) strToFloat(num.c_str(), res, ou);
|
for (int i = 0; i < 1000000; ++i) strToFloat(num.c_str(), res, ou);
|
||||||
@ -662,7 +701,8 @@ CppUnit::Test* StringTest::suite()
|
|||||||
CppUnit_addTest(pSuite, StringTest, testStringToFloat);
|
CppUnit_addTest(pSuite, StringTest, testStringToFloat);
|
||||||
CppUnit_addTest(pSuite, StringTest, testStringToFloatError);
|
CppUnit_addTest(pSuite, StringTest, testStringToFloatError);
|
||||||
CppUnit_addTest(pSuite, StringTest, testNumericLocale);
|
CppUnit_addTest(pSuite, StringTest, testNumericLocale);
|
||||||
CppUnit_addTest(pSuite, StringTest, benchmark);
|
//CppUnit_addTest(pSuite, StringTest, benchmarkStrToFloat);
|
||||||
|
//CppUnit_addTest(pSuite, StringTest, benchmarkStrToInt);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,8 @@ public:
|
|||||||
void testStringToFloat();
|
void testStringToFloat();
|
||||||
void testStringToFloatError();
|
void testStringToFloatError();
|
||||||
void testNumericLocale();
|
void testNumericLocale();
|
||||||
void benchmark();
|
void benchmarkStrToFloat();
|
||||||
|
void benchmarkStrToInt();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
@ -80,43 +81,55 @@ private:
|
|||||||
{
|
{
|
||||||
T result = 0;
|
T result = 0;
|
||||||
if (123 <= std::numeric_limits<T>::max())
|
if (123 <= std::numeric_limits<T>::max())
|
||||||
assert(strToInt("123", result)); assert(result == 123);
|
assert(strToInt("123", result, 10)); assert(result == 123);
|
||||||
|
|
||||||
assert(strToInt("0", result)); assert(result == 0);
|
assert(strToInt("0", result, 10)); assert(result == 0);
|
||||||
assert(strToInt("000", result)); assert(result == 0);
|
assert(strToInt("000", result, 10)); assert(result == 0);
|
||||||
|
|
||||||
if (123 < std::numeric_limits<T>::max())
|
if (123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt(" 123 ", result)); assert(result == 123); }
|
{ assert(strToInt(" 123 ", result, 10)); assert(result == 123); }
|
||||||
if (123 < std::numeric_limits<T>::max())
|
if (123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt(" 123", result)); assert(result == 123); }
|
{ assert(strToInt(" 123", result, 10)); assert(result == 123); }
|
||||||
if (123 < std::numeric_limits<T>::max())
|
if (123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("123 ", result)); assert(result == 123); }
|
{ assert(strToInt("123 ", result, 10)); assert(result == 123); }
|
||||||
if (std::numeric_limits<T>::is_signed && (-123 > std::numeric_limits<T>::min()))
|
if (std::numeric_limits<T>::is_signed && (-123 > std::numeric_limits<T>::min()))
|
||||||
{ assert(strToInt("-123", result)); assert(result == -123); }
|
{ assert(strToInt("-123", result, 10)); assert(result == -123); }
|
||||||
if (0x123 < std::numeric_limits<T>::max())
|
if (0x123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("123", result, 0x10)); assert(result == 0x123); }
|
{ assert(strToInt("123", result, 0x10)); assert(result == 0x123); }
|
||||||
if (0x12ab < std::numeric_limits<T>::max())
|
if (0x12ab < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("12AB", result, 0x10)); assert(result == 0x12ab); }
|
{ assert(strToInt("12AB", result, 0x10)); assert(result == 0x12ab); }
|
||||||
if (0x12ab < std::numeric_limits<T>::max())
|
if (0x12ab < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0X12AB", result)); assert(result == 0x12ab); }
|
{ assert(strToInt("0X12AB", result, 0x10)); assert(result == 0x12ab); }
|
||||||
if (0x12ab < std::numeric_limits<T>::max())
|
if (0x12ab < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0x12AB", result)); assert(result == 0x12ab); }
|
{ assert(strToInt("0x12AB", result, 0x10)); assert(result == 0x12ab); }
|
||||||
if (0x12ab < std::numeric_limits<T>::max())
|
if (0x12ab < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0x12aB", result)); assert(result == 0x12ab); }
|
{ assert(strToInt("0x12aB", result, 0x10)); assert(result == 0x12ab); }
|
||||||
if (0x98fe < std::numeric_limits<T>::max())
|
if (0x98fe < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0X98Fe", result)); assert(result == 0x98fe); }
|
{ assert(strToInt("0X98Fe", result, 0x10)); assert(result == 0x98fe); }
|
||||||
if (123 < std::numeric_limits<T>::max())
|
if (123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0x0", result)); assert(result == 0); }
|
{ assert(strToInt("0x0", result, 0x10)); assert(result == 0); }
|
||||||
if (123 < std::numeric_limits<T>::max())
|
if (123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("00", result, 0x10)); assert(result == 0); }
|
{ assert(strToInt("00", result, 0x10)); assert(result == 0); }
|
||||||
if (0123 < std::numeric_limits<T>::max())
|
if (0123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("123", result, 010)); assert(result == 0123); }
|
{ assert(strToInt("123", result, 010)); assert(result == 0123); }
|
||||||
if (0123 < std::numeric_limits<T>::max())
|
if (0123 < std::numeric_limits<T>::max())
|
||||||
{ assert(strToInt("0123", result)); assert(result == 0123); }
|
{ assert(strToInt("0123", result, 010)); assert(result == 0123); }
|
||||||
|
|
||||||
assert(strToInt("0", result, 010)); assert(result == 0);
|
assert(strToInt("0", result, 010)); assert(result == 0);
|
||||||
assert(strToInt("000", result)); assert(result == 0);
|
assert(strToInt("000", result, 010)); assert(result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool parseStream(const std::string& s, T& value)
|
||||||
|
{
|
||||||
|
MemoryInputStream istr(s.data(), s.size());
|
||||||
|
#if !defined(POCO_NO_LOCALE)
|
||||||
|
istr.imbue(std::locale::classic());
|
||||||
|
#endif
|
||||||
|
istr >> value;
|
||||||
|
return istr.eof() && !istr.fail();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user