aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/test/util_tests.cpp22
-rw-r--r--src/util.cpp14
-rw-r--r--src/util.h7
3 files changed, 43 insertions, 0 deletions
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index b8f107f644..7e7c05a59d 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -342,4 +342,26 @@ BOOST_AUTO_TEST_CASE(gettime)
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()
diff --git a/src/util.cpp b/src/util.cpp
index a919b4b854..36ac23b1d5 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1427,3 +1427,17 @@ void RenameThread(const char* name)
#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();
+}
+
diff --git a/src/util.h b/src/util.h
index fbd841f7a8..fa1e664c92 100644
--- a/src/util.h
+++ b/src/util.h
@@ -256,6 +256,13 @@ inline int atoi(const std::string& 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)
{
return (int)(d > 0 ? d + 0.5 : d - 0.5);