Browse Source

util: add parseint32 function with strict error reporting

None of the current integer parsing functions in util
check whether the result is valid and fits in the range
of the type. This is required for less sloppy error reporting.
0.10
Wladimir J. van der Laan 11 years ago
parent
commit
0d4ea1cf8a
  1. 22
      src/test/util_tests.cpp
  2. 14
      src/util.cpp
  3. 7
      src/util.h

22
src/test/util_tests.cpp

@ -342,4 +342,26 @@ BOOST_AUTO_TEST_CASE(gettime)
BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0); BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
} }
BOOST_AUTO_TEST_CASE(test_ParseInt32)
{
int32_t n;
// Valid values
BOOST_CHECK(ParseInt32("1234", NULL));
BOOST_CHECK(ParseInt32("0", &n) && n == 0);
BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648);
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
// Invalid values
BOOST_CHECK(!ParseInt32("1a", &n));
BOOST_CHECK(!ParseInt32("aap", &n));
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
// Overflow and underflow
BOOST_CHECK(!ParseInt32("-2147483649", NULL));
BOOST_CHECK(!ParseInt32("2147483648", NULL));
BOOST_CHECK(!ParseInt32("-32482348723847471234", NULL));
BOOST_CHECK(!ParseInt32("32482348723847471234", NULL));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

14
src/util.cpp

@ -1427,3 +1427,17 @@ void RenameThread(const char* name)
#endif #endif
} }
bool ParseInt32(const std::string& str, int32_t *out)
{
char *endp = NULL;
errno = 0; // strtol will not set errno if valid
long int n = strtol(str.c_str(), &endp, 10);
if(out) *out = (int)n;
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
return endp && *endp == 0 && !errno &&
n >= std::numeric_limits<int32_t>::min() &&
n <= std::numeric_limits<int32_t>::max();
}

7
src/util.h

@ -256,6 +256,13 @@ inline int atoi(const std::string& str)
return atoi(str.c_str()); return atoi(str.c_str());
} }
/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occured.
*/
bool ParseInt32(const std::string& str, int32_t *out);
inline int roundint(double d) inline int roundint(double d)
{ {
return (int)(d > 0 ? d + 0.5 : d - 0.5); return (int)(d > 0 ? d + 0.5 : d - 0.5);

Loading…
Cancel
Save