1
0
Fork 0

added optimized StringUtils::uint64_trusted()

This commit is contained in:
jsteemann 2016-05-30 22:11:13 +02:00
parent d6db132b94
commit db00e46772
3 changed files with 138 additions and 1 deletions

View File

@ -192,6 +192,100 @@ BOOST_AUTO_TEST_CASE (test_convertUTF16ToUTF8) {
BOOST_CHECK(result.empty());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test_uint64
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (test_uint64) {
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64("abc"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64("ABC"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64(" foo"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64(""));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64(" "));
BOOST_CHECK_EQUAL(12ULL, StringUtils::uint64(" 012"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64("1234a"));
BOOST_CHECK_EQUAL(18446744073709551615ULL, StringUtils::uint64("-1"));
BOOST_CHECK_EQUAL(18446744073709539271ULL, StringUtils::uint64("-12345"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64("1234.56"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64("1234567890123456789012345678901234567890"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64("@"));
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64("0"));
BOOST_CHECK_EQUAL(1ULL, StringUtils::uint64("1"));
BOOST_CHECK_EQUAL(12ULL, StringUtils::uint64("12"));
BOOST_CHECK_EQUAL(123ULL, StringUtils::uint64("123"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64("1234"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64("01234"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64("9"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64(" 9"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64("0009"));
BOOST_CHECK_EQUAL(12345678ULL, StringUtils::uint64("12345678"));
BOOST_CHECK_EQUAL(1234567800ULL, StringUtils::uint64("1234567800"));
BOOST_CHECK_EQUAL(1234567890123456ULL, StringUtils::uint64("1234567890123456"));
BOOST_CHECK_EQUAL(UINT64_MAX, StringUtils::uint64(std::to_string(UINT64_MAX)));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test_uint64_check
////////////////////////////////////////////////////////////////////////////////
static bool InvalidArgument(std::invalid_argument const& ex) {
return true;
}
static bool OutOfRange(std::out_of_range const& ex) {
return true;
}
BOOST_AUTO_TEST_CASE (test_uint64_check) {
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("abc"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("ABC"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check(" foo"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check(""), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check(" "), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EQUAL(12ULL, StringUtils::uint64_check(" 012"));
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("1234a"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EQUAL(18446744073709551615ULL, StringUtils::uint64_check("-1"));
BOOST_CHECK_EQUAL(18446744073709539271ULL, StringUtils::uint64_check("-12345"));
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("1234."), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("1234.56"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("1234567889123456789012345678901234567890"), std::out_of_range, OutOfRange);
BOOST_CHECK_EXCEPTION(StringUtils::uint64_check("@"), std::invalid_argument, InvalidArgument);
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64_check("0"));
BOOST_CHECK_EQUAL(1ULL, StringUtils::uint64_check("1"));
BOOST_CHECK_EQUAL(12ULL, StringUtils::uint64_check("12"));
BOOST_CHECK_EQUAL(123ULL, StringUtils::uint64_check("123"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64_check("1234"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64_check("01234"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64_check("9"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64_check(" 9"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64_check("0009"));
BOOST_CHECK_EQUAL(12345678ULL, StringUtils::uint64_check("12345678"));
BOOST_CHECK_EQUAL(1234567800ULL, StringUtils::uint64_check("1234567800"));
BOOST_CHECK_EQUAL(1234567890123456ULL, StringUtils::uint64_check("1234567890123456"));
BOOST_CHECK_EQUAL(UINT64_MAX, StringUtils::uint64_check(std::to_string(UINT64_MAX)));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test_uint64_trusted
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (test_uint64_trusted) {
BOOST_CHECK_EQUAL(0ULL, StringUtils::uint64_trusted("0"));
BOOST_CHECK_EQUAL(1ULL, StringUtils::uint64_trusted("1"));
BOOST_CHECK_EQUAL(12ULL, StringUtils::uint64_trusted("12"));
BOOST_CHECK_EQUAL(123ULL, StringUtils::uint64_trusted("123"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64_trusted("1234"));
BOOST_CHECK_EQUAL(1234ULL, StringUtils::uint64_trusted("01234"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64_trusted("9"));
BOOST_CHECK_EQUAL(9ULL, StringUtils::uint64_trusted("0009"));
BOOST_CHECK_EQUAL(12345678ULL, StringUtils::uint64_trusted("12345678"));
BOOST_CHECK_EQUAL(1234567800ULL, StringUtils::uint64_trusted("1234567800"));
BOOST_CHECK_EQUAL(1234567890123456ULL, StringUtils::uint64_trusted("1234567890123456"));
BOOST_CHECK_EQUAL(UINT64_MAX, StringUtils::uint64_trusted(std::to_string(UINT64_MAX)));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

View File

@ -1586,12 +1586,41 @@ uint64_t uint64_check(std::string const& str) {
int64_t value = std::stoull(str, &n, 10);
if (n < str.size()) {
throw std::invalid_argument("cannot convert '" + str + "' to int64");
throw std::invalid_argument("cannot convert '" + str + "' to uint64");
}
return value;
}
uint64_t uint64_trusted(char const* value, size_t length) {
uint64_t result = 0;
switch (length) {
case 20: result += (value[length - 20] - '0') * 10000000000000000000ULL;
case 19: result += (value[length - 19] - '0') * 1000000000000000000ULL;
case 18: result += (value[length - 18] - '0') * 100000000000000000ULL;
case 17: result += (value[length - 17] - '0') * 10000000000000000ULL;
case 16: result += (value[length - 16] - '0') * 1000000000000000ULL;
case 15: result += (value[length - 15] - '0') * 100000000000000ULL;
case 14: result += (value[length - 14] - '0') * 10000000000000ULL;
case 13: result += (value[length - 13] - '0') * 1000000000000ULL;
case 12: result += (value[length - 12] - '0') * 100000000000ULL;
case 11: result += (value[length - 11] - '0') * 10000000000ULL;
case 10: result += (value[length - 10] - '0') * 1000000000ULL;
case 9: result += (value[length - 9] - '0') * 100000000ULL;
case 8: result += (value[length - 8] - '0') * 10000000ULL;
case 7: result += (value[length - 7] - '0') * 1000000ULL;
case 6: result += (value[length - 6] - '0') * 100000ULL;
case 5: result += (value[length - 5] - '0') * 10000ULL;
case 4: result += (value[length - 4] - '0') * 1000ULL;
case 3: result += (value[length - 3] - '0') * 100ULL;
case 2: result += (value[length - 2] - '0') * 10ULL;
case 1: result += (value[length - 1] - '0');
}
return result;
}
int32_t int32(std::string const& str) {
#ifdef TRI_HAVE_STRTOL_R
struct reent buffer;

View File

@ -451,6 +451,20 @@ inline uint64_t uint64_check(char const* value, size_t size) {
return StringUtils::uint64_check(std::string(value, size));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parses an unsigned integer
/// the caller must make sure that the input buffer only contains valid
/// numeric characters - otherwise the uint64_t result will be wrong.
/// because the input is restricted to some valid characters, this function
/// is highly optimized
////////////////////////////////////////////////////////////////////////////////
uint64_t uint64_trusted(char const* value, size_t length);
inline uint64_t uint64_trusted(std::string const& value) {
return uint64_trusted(value.c_str(), value.size());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parses an integer
////////////////////////////////////////////////////////////////////////////////