diff --git a/common/network/MACAddress.cpp b/common/network/MACAddress.cpp index 028f11f52a..4259f3e087 100644 --- a/common/network/MACAddress.cpp +++ b/common/network/MACAddress.cpp @@ -150,7 +150,7 @@ bool StringToEther(const string &address, ether_addr *target) { } for (unsigned int i = 0; i < MACAddress::LENGTH; i++) { - if (!ola::HexStringToInt(tokens[i], target->ether_addr_octet + i)) { + if (!ola::StringToInt(tokens[i], target->ether_addr_octet + i, true, 16)) { return false; } } diff --git a/common/rdm/UID.cpp b/common/rdm/UID.cpp index eed7e24f03..07e0698f4d 100644 --- a/common/rdm/UID.cpp +++ b/common/rdm/UID.cpp @@ -39,10 +39,10 @@ UID* UID::FromString(const string &uid) { uint16_t esta_id; unsigned int device_id; - if (!ola::HexStringToInt(tokens[0], &esta_id)) { + if (!ola::StringToInt(tokens[0], &esta_id, true, 16)) { return NULL; } - if (!ola::HexStringToInt(tokens[1], &device_id)) { + if (!ola::StringToInt(tokens[1], &device_id, true, 16)) { return NULL; } diff --git a/common/utils/StringUtils.cpp b/common/utils/StringUtils.cpp index c777bd016f..8d8bee7c51 100644 --- a/common/utils/StringUtils.cpp +++ b/common/utils/StringUtils.cpp @@ -152,14 +152,17 @@ bool StringToBoolTolerant(const string &value, bool *output) { return false; } -bool StringToInt(const string &value, unsigned int *output, bool strict) { +bool StringToInt(const string &value, + uint32_t *output, + bool strict, + uint8_t base) { if (value.empty()) { return false; } char *end_ptr; errno = 0; - long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) - if (l < 0 || (l == 0 && errno != 0)) { + unsigned long l = strtoul(value.data(), &end_ptr, base); // NOLINT(runtime/int) + if (l == 0 && errno != 0) { return false; } if (value == end_ptr) { @@ -168,44 +171,56 @@ bool StringToInt(const string &value, unsigned int *output, bool strict) { if (strict && *end_ptr != 0) { return false; } - if (l > static_cast(UINT32_MAX)) { // NOLINT(runtime/int) + if (l != static_cast(l)) { // NOLINT(runtime/int) return false; } - *output = static_cast(l); + *output = static_cast(l); return true; } -bool StringToInt(const string &value, uint16_t *output, bool strict) { - unsigned int v; - if (!StringToInt(value, &v, strict)) { +bool StringToInt(const string &value, + uint16_t *output, + bool strict, + uint8_t base) { + uint32_t v; + if (!StringToInt(value, &v, strict, base)) { return false; } - if (v > UINT16_MAX) { + if (v != static_cast(v)) { return false; } *output = static_cast(v); return true; } -bool StringToInt(const string &value, uint8_t *output, bool strict) { - unsigned int v; - if (!StringToInt(value, &v, strict)) { +bool StringToInt(const string &value, + uint8_t *output, + bool strict, + uint8_t base) { + uint32_t v; + if (!StringToInt(value, &v, strict, base)) { return false; } - if (v > UINT8_MAX) { + if (v != static_cast(v)) { return false; } *output = static_cast(v); return true; } -bool StringToInt(const string &value, int *output, bool strict) { +bool StringToInt(const string &value, + int32_t *output, + bool strict, + uint8_t base) { if (value.empty()) { return false; } char *end_ptr; errno = 0; - long long l = strtoll(value.data(), &end_ptr, 10); // NOLINT(runtime/int) + + long l = strtol(value.data(), &end_ptr, base); // NOLINT(runtime/int) + int32_t i = static_cast(l); + if (l == 0 && errno != 0) { return false; } @@ -215,34 +230,69 @@ bool StringToInt(const string &value, int *output, bool strict) { if (strict && *end_ptr != 0) { return false; } - if (l < INT32_MIN || l > INT32_MAX) { + if (i < 0 && base != 10) { + if (l > 0 && l != static_cast(l)) { + return false; + } else if(l < 0 && i != l) { + return false; + } + } else if (l != static_cast(l)) { return false; } - *output = static_cast(l); + + *output = static_cast(l); return true; } -bool StringToInt(const string &value, int16_t *output, bool strict) { - int v; - if (!StringToInt(value, &v, strict)) { +bool StringToInt(const string &value, + int16_t *output, + bool strict, + uint8_t base) { + int32_t v; + int16_t i; + + if (!StringToInt(value, &v, strict, base)) { return false; } - if (v < INT16_MIN || v > INT16_MAX) { + i = static_cast(v); + + if (i < 0 && base != 10) { + if (v > 0 && v != static_cast(v)) { + return false; + } else if(v < 0 && i != v) { + return false; + } + } else if (v != i) { return false; } - *output = static_cast(v); + + *output = i; return true; } -bool StringToInt(const string &value, int8_t *output, bool strict) { - int v; - if (!StringToInt(value, &v, strict)) { +bool StringToInt(const string &value, + int8_t *output, + bool strict, + uint8_t base) { + int32_t v; + int8_t i; + + if (!StringToInt(value, &v, strict, base)) { return false; } - if (v < INT8_MIN || v > INT8_MAX) { + i = static_cast(v); + + if (i < 0 && base != 10) { + if (v > 0 && v != static_cast(v)) { + return false; + } else if(v < 0 && i != v) { + return false; + } + } else if (v != i) { return false; } - *output = static_cast(v); + + *output = i; return true; } @@ -327,80 +377,6 @@ void ReplaceAll(string *original, const string &find, const string &replace) { } } -bool HexStringToInt(const string &value, uint8_t *output) { - uint32_t temp; - if (!HexStringToInt(value, &temp)) { - return false; - } - if (temp > UINT8_MAX) { - return false; - } - *output = static_cast(temp); - return true; -} - -bool HexStringToInt(const string &value, uint16_t *output) { - uint32_t temp; - if (!HexStringToInt(value, &temp)) { - return false; - } - if (temp > UINT16_MAX) { - return false; - } - *output = static_cast(temp); - return true; -} - -bool HexStringToInt(const string &value, uint32_t *output) { - if (value.empty()) { - return false; - } - - size_t found = value.find_first_not_of("ABCDEFabcdef0123456789"); - if (found != string::npos) { - return false; - } - *output = strtoul(value.data(), NULL, 16); - return true; -} - -bool HexStringToInt(const string &value, int8_t *output) { - int32_t temp; - if (!HexStringToInt(value, &temp)) { - return false; - } - if (temp < 0 || temp > static_cast(UINT8_MAX)) { - return false; - } - *output = static_cast(temp); - return true; -} - -bool HexStringToInt(const string &value, int16_t *output) { - int32_t temp; - if (!HexStringToInt(value, &temp)) { - return false; - } - if (temp < 0 || temp > static_cast(UINT16_MAX)) { - return false; - } - *output = static_cast(temp); - return true; -} - -bool HexStringToInt(const string &value, int32_t *output) { - if (value.empty()) { - return false; - } - - size_t found = value.find_first_not_of("ABCDEFabcdef0123456789"); - if (found != string::npos) { - return false; - } - *output = strtoll(value.data(), NULL, 16); - return true; -} - void ToLower(string *s) { std::transform(s->begin(), s->end(), s->begin(), std::ptr_fun(std::tolower)); diff --git a/common/utils/StringUtilsTest.cpp b/common/utils/StringUtilsTest.cpp index 189427dacd..e46be5a9cd 100644 --- a/common/utils/StringUtilsTest.cpp +++ b/common/utils/StringUtilsTest.cpp @@ -34,7 +34,6 @@ using ola::EncodeString; using ola::Escape; using ola::EscapeString; using ola::FormatData; -using ola::HexStringToInt; using ola::IntToHexString; using ola::IntToString; using ola::PrefixedHexStringToInt; @@ -85,7 +84,6 @@ class StringUtilsTest: public CppUnit::TestFixture { CPPUNIT_TEST(testStringToInt16OrDefault); CPPUNIT_TEST(testStringToInt8); CPPUNIT_TEST(testStringToInt8OrDefault); - CPPUNIT_TEST(testHexStringToInt); CPPUNIT_TEST(testPrefixedHexStringToInt); CPPUNIT_TEST(testToLower); CPPUNIT_TEST(testToUpper); @@ -123,7 +121,6 @@ class StringUtilsTest: public CppUnit::TestFixture { void testStringToInt16OrDefault(); void testStringToInt8(); void testStringToInt8OrDefault(); - void testHexStringToInt(); void testPrefixedHexStringToInt(); void testToLower(); void testToUpper(); @@ -539,7 +536,7 @@ void StringUtilsTest::testStringToBoolTolerant() { void StringUtilsTest::testStringToUInt() { - unsigned int value; + unsigned int value, value2; OLA_ASSERT_FALSE(StringToInt("", &value)); OLA_ASSERT_FALSE(StringToInt("-1", &value)); OLA_ASSERT_TRUE(StringToInt("0", &value)); @@ -561,186 +558,79 @@ void StringUtilsTest::testStringToUInt() { OLA_ASSERT_FALSE(StringToInt("1 bar baz", &value, true)); OLA_ASSERT_FALSE(StringToInt("65537cat", &value, true)); OLA_ASSERT_FALSE(StringToInt("4294967295bat bar", &value, true)); -} -void StringUtilsTest::testStringToUIntOrDefault() { - OLA_ASSERT_EQ(42u, StringToIntOrDefault("", 42u)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1", 42u)); - OLA_ASSERT_EQ(0u, StringToIntOrDefault("0", 42u)); - OLA_ASSERT_EQ(1u, StringToIntOrDefault("1", 42u)); - OLA_ASSERT_EQ(65537u, StringToIntOrDefault("65537", 42u)); - OLA_ASSERT_EQ(4294967295U, StringToIntOrDefault("4294967295", 42u)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967296", 42u)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("foo", 42u)); + // Base8 test + OLA_ASSERT_TRUE(StringToInt("377", &value, false, 8)); + OLA_ASSERT_EQ(value, 255u); - // same tests with strict mode on - OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1 foo", 42u, true)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("0 ", 42u, true)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("1 bar baz", 42u, true)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("65537cat", 42u, true)); - OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967295bat bar", 42u, true)); -} + OLA_ASSERT_FALSE(StringToInt("999", &value, false, 8)); + + // Base16 test + OLA_ASSERT_TRUE(StringToInt("ff00", &value, false, 16)); + OLA_ASSERT_EQ(value, 65280u); -void StringUtilsTest::testHexStringToInt() { - unsigned int value; - OLA_ASSERT_FALSE(HexStringToInt("", &value)); - OLA_ASSERT_FALSE(HexStringToInt("-1", &value)); + OLA_ASSERT_FALSE(StringToInt("gg00", &value, false, 16)); - OLA_ASSERT_TRUE(HexStringToInt("0", &value)); + OLA_ASSERT_TRUE(StringToInt("0", &value, true, 16)); OLA_ASSERT_EQ(0u, value); - OLA_ASSERT_TRUE(HexStringToInt("1", &value)); + OLA_ASSERT_TRUE(StringToInt("1", &value, true, 16)); OLA_ASSERT_EQ(1u, value); - OLA_ASSERT_TRUE(HexStringToInt("a", &value)); + OLA_ASSERT_TRUE(StringToInt("a", &value, true, 16)); OLA_ASSERT_EQ(10u, value); - OLA_ASSERT_TRUE(HexStringToInt("f", &value)); + OLA_ASSERT_TRUE(StringToInt("f", &value, true, 16)); OLA_ASSERT_EQ(15u, value); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value)); + OLA_ASSERT_TRUE(StringToInt("a1", &value, true, 16)); OLA_ASSERT_EQ(161u, value); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value)); + OLA_ASSERT_TRUE(StringToInt("ff", &value, true, 16)); OLA_ASSERT_EQ(255u, value); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value)); + OLA_ASSERT_TRUE(StringToInt("a1", &value, true, 16)); OLA_ASSERT_EQ(161u, value); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value)); + OLA_ASSERT_TRUE(StringToInt("ff", &value, true, 16)); OLA_ASSERT_EQ(255u, value); - OLA_ASSERT_TRUE(HexStringToInt("ffff", &value)); + OLA_ASSERT_TRUE(StringToInt("ffff", &value, true, 16)); OLA_ASSERT_EQ(65535u, value); - OLA_ASSERT_TRUE(HexStringToInt("ffffff", &value)); + OLA_ASSERT_TRUE(StringToInt("ffffff", &value, true, 16)); OLA_ASSERT_EQ((unsigned int) 16777215, value); - OLA_ASSERT_TRUE(HexStringToInt("ffffffff", &value)); + OLA_ASSERT_TRUE(StringToInt("ffffffff", &value, true, 16)); OLA_ASSERT_EQ((unsigned int) 4294967295UL, value); - OLA_ASSERT_TRUE(HexStringToInt("ef123456", &value)); + OLA_ASSERT_TRUE(StringToInt("ef123456", &value, true, 16)); OLA_ASSERT_EQ((unsigned int) 4010947670UL, value); - OLA_ASSERT_FALSE(HexStringToInt("fz", &value)); - OLA_ASSERT_FALSE(HexStringToInt("zfff", &value)); - OLA_ASSERT_FALSE(HexStringToInt("0xf", &value)); - - // uint16_t - uint16_t value2; - OLA_ASSERT_FALSE(HexStringToInt("", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("-1", &value2)); - - OLA_ASSERT_TRUE(HexStringToInt("0", &value2)); - OLA_ASSERT_EQ((uint16_t) 0, value2); - OLA_ASSERT_TRUE(HexStringToInt("1", &value2)); - OLA_ASSERT_EQ((uint16_t) 1, value2); - OLA_ASSERT_TRUE(HexStringToInt("a", &value2)); - OLA_ASSERT_EQ((uint16_t) 10, value2); - OLA_ASSERT_TRUE(HexStringToInt("f", &value2)); - OLA_ASSERT_EQ((uint16_t) 15, value2); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value2)); - OLA_ASSERT_EQ((uint16_t) 161, value2); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value2)); - OLA_ASSERT_EQ((uint16_t) 255, value2); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value2)); - OLA_ASSERT_EQ((uint16_t) 161, value2); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value2)); - OLA_ASSERT_EQ((uint16_t) 255, value2); - OLA_ASSERT_TRUE(HexStringToInt("400", &value2)); - OLA_ASSERT_EQ((uint16_t) 1024, value2); - OLA_ASSERT_TRUE(HexStringToInt("ffff", &value2)); - OLA_ASSERT_EQ((uint16_t) 65535, value2); - - OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("fz", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("zfff", &value2)); - OLA_ASSERT_FALSE(HexStringToInt("0xf", &value2)); - - // int8_t - int8_t value3; - OLA_ASSERT_FALSE(HexStringToInt("", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("-1", &value3)); - - OLA_ASSERT_TRUE(HexStringToInt("0", &value3)); - OLA_ASSERT_EQ((int8_t) 0, value3); - OLA_ASSERT_TRUE(HexStringToInt("1", &value3)); - OLA_ASSERT_EQ((int8_t) 1, value3); - OLA_ASSERT_TRUE(HexStringToInt("a", &value3)); - OLA_ASSERT_EQ((int8_t) 10, value3); - OLA_ASSERT_TRUE(HexStringToInt("f", &value3)); - OLA_ASSERT_EQ((int8_t) 15, value3); - OLA_ASSERT_TRUE(HexStringToInt("7f", &value3)); - OLA_ASSERT_EQ((int8_t) 127, value3); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value3)); - OLA_ASSERT_EQ((int8_t) -95, value3); - OLA_ASSERT_TRUE(HexStringToInt("80", &value3)); - OLA_ASSERT_EQ((int8_t) -128, value3); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value3)); - OLA_ASSERT_EQ((int8_t) -1, value3); - - OLA_ASSERT_FALSE(HexStringToInt("ffff", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("fff0", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("fz", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("zfff", &value3)); - OLA_ASSERT_FALSE(HexStringToInt("0xf", &value3)); - - // int16_t - int16_t value4; - OLA_ASSERT_FALSE(HexStringToInt("", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("-1", &value4)); - - OLA_ASSERT_TRUE(HexStringToInt("0", &value4)); - OLA_ASSERT_EQ((int16_t) 0, value4); - OLA_ASSERT_TRUE(HexStringToInt("1", &value4)); - OLA_ASSERT_EQ((int16_t) 1, value4); - OLA_ASSERT_TRUE(HexStringToInt("a", &value4)); - OLA_ASSERT_EQ((int16_t) 10, value4); - OLA_ASSERT_TRUE(HexStringToInt("f", &value4)); - OLA_ASSERT_EQ((int16_t) 15, value4); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value4)); - OLA_ASSERT_EQ((int16_t) 161, value4); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value4)); - OLA_ASSERT_EQ((int16_t) 255, value4); - OLA_ASSERT_TRUE(HexStringToInt("7fff", &value4)); - OLA_ASSERT_EQ((int16_t) 32767, value4); - OLA_ASSERT_TRUE(HexStringToInt("ffff", &value4)); - OLA_ASSERT_EQ((int16_t) -1, value4); - OLA_ASSERT_TRUE(HexStringToInt("fff0", &value4)); - OLA_ASSERT_EQ((int16_t) -16, value4); - OLA_ASSERT_TRUE(HexStringToInt("8000", &value4)); - OLA_ASSERT_EQ((int16_t) -32768, value4); - - OLA_ASSERT_FALSE(HexStringToInt("ffffff", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("ffffffff", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("ef123456", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("fz", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("zfff", &value4)); - OLA_ASSERT_FALSE(HexStringToInt("0xf", &value4)); - - // int32 - int32_t value5; - OLA_ASSERT_FALSE(HexStringToInt("", &value5)); - OLA_ASSERT_FALSE(HexStringToInt("-1", &value5)); - - OLA_ASSERT_TRUE(HexStringToInt("0", &value5)); - OLA_ASSERT_EQ((int32_t) 0, value5); - OLA_ASSERT_TRUE(HexStringToInt("1", &value5)); - OLA_ASSERT_EQ((int32_t) 1, value5); - OLA_ASSERT_TRUE(HexStringToInt("a", &value5)); - OLA_ASSERT_EQ((int32_t) 10, value5); - OLA_ASSERT_TRUE(HexStringToInt("f", &value5)); - OLA_ASSERT_EQ((int32_t) 15, value5); - OLA_ASSERT_TRUE(HexStringToInt("a1", &value5)); - OLA_ASSERT_EQ((int32_t) 161, value5); - OLA_ASSERT_TRUE(HexStringToInt("ff", &value5)); - OLA_ASSERT_EQ((int32_t) 255, value5); - OLA_ASSERT_TRUE(HexStringToInt("7fff", &value5)); - OLA_ASSERT_EQ((int32_t) 32767, value5); - OLA_ASSERT_TRUE(HexStringToInt("ffff", &value5)); - OLA_ASSERT_EQ((int32_t) 65535, value5); - OLA_ASSERT_TRUE(HexStringToInt("ffffffff", &value5)); - OLA_ASSERT_EQ((int32_t) -1, value5); - OLA_ASSERT_TRUE(HexStringToInt("fffffff0", &value5)); - OLA_ASSERT_EQ((int32_t) -16, value5); - OLA_ASSERT_TRUE(HexStringToInt("80000000", &value5)); - OLA_ASSERT_EQ((int32_t) -2147483647 - 1, value5); + OLA_ASSERT_FALSE(StringToInt("fz", &value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("zfff", &value, true, 16)); + OLA_ASSERT_TRUE(StringToInt("0xf", &value, true, 16)); + + // Base36 test + OLA_ASSERT_TRUE(StringToInt("12FZ9A", &value, false, 36)); + OLA_ASSERT_TRUE(StringToInt("12fz9a", &value2, false, 36)); + OLA_ASSERT_EQ(value, value2); + OLA_ASSERT_EQ(value, 64570942u); + + OLA_ASSERT_TRUE(StringToInt("STRIC7", &value, true, 36)); + OLA_ASSERT_TRUE(StringToInt("stric7", &value2, true, 36)); + OLA_ASSERT_EQ(value, value2); + OLA_ASSERT_EQ(value, 1743045271u); + + OLA_ASSERT_FALSE(StringToInt("STRICT1", &value, true, 36)); } +void StringUtilsTest::testStringToUIntOrDefault() { + OLA_ASSERT_EQ(42u, StringToIntOrDefault("", 42u)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1", 42u)); + OLA_ASSERT_EQ(0u, StringToIntOrDefault("0", 42u)); + OLA_ASSERT_EQ(1u, StringToIntOrDefault("1", 42u)); + OLA_ASSERT_EQ(65537u, StringToIntOrDefault("65537", 42u)); + OLA_ASSERT_EQ(4294967295U, StringToIntOrDefault("4294967295", 42u)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967296", 42u)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("foo", 42u)); + + // same tests with strict mode on + OLA_ASSERT_EQ(42u, StringToIntOrDefault("-1 foo", 42u, true)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("0 ", 42u, true)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("1 bar baz", 42u, true)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("65537cat", 42u, true)); + OLA_ASSERT_EQ(42u, StringToIntOrDefault("4294967295bat bar", 42u, true)); +} void StringUtilsTest::testPrefixedHexStringToInt() { int value; @@ -783,6 +673,41 @@ void StringUtilsTest::testStringToUInt16() { OLA_ASSERT_EQ((uint16_t) 143, value); OLA_ASSERT_TRUE(StringToInt("65535", &value)); OLA_ASSERT_EQ((uint16_t) 65535, value); + + // base16 - uint16_t + uint16_t uint16_value; + OLA_ASSERT_FALSE(StringToInt("", &uint16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("-1", &uint16_value, true, 16)); + + OLA_ASSERT_TRUE(StringToInt("0", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 0, uint16_value); + OLA_ASSERT_TRUE(StringToInt("1", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 1, uint16_value); + OLA_ASSERT_TRUE(StringToInt("a", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 10, uint16_value); + OLA_ASSERT_TRUE(StringToInt("f", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 15, uint16_value); + OLA_ASSERT_TRUE(StringToInt("a1", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 161, uint16_value); + OLA_ASSERT_TRUE(StringToInt("ff", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 255, uint16_value); + OLA_ASSERT_TRUE(StringToInt("a1", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 161, uint16_value); + OLA_ASSERT_TRUE(StringToInt("ff", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 255, uint16_value); + OLA_ASSERT_TRUE(StringToInt("400", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 1024, uint16_value); + OLA_ASSERT_TRUE(StringToInt("ffff", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 65535, uint16_value); + + OLA_ASSERT_FALSE(StringToInt("ffffff", &uint16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("ffffffff", &uint16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("ef123456", &uint16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("fz", &uint16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("zfff", &uint16_value, true, 16)); + + OLA_ASSERT_TRUE(StringToInt("0xf", &uint16_value, true, 16)); + OLA_ASSERT_EQ((uint16_t) 15, uint16_value); } @@ -861,6 +786,36 @@ void StringUtilsTest::testStringToInt() { OLA_ASSERT_FALSE(StringToInt("143car", &value, true)); OLA_ASSERT_FALSE(StringToInt("2147483647 !@#", &value, true)); OLA_ASSERT_FALSE(StringToInt("2147483648mm", &value, true)); + + // base16 - int32 + int32_t int32_value; + OLA_ASSERT_FALSE(StringToInt("", &int32_value, true, 16)); + + OLA_ASSERT_TRUE(StringToInt("-1", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) -1, int32_value); + + OLA_ASSERT_TRUE(StringToInt("0", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 0, int32_value); + OLA_ASSERT_TRUE(StringToInt("1", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 1, int32_value); + OLA_ASSERT_TRUE(StringToInt("a", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 10, int32_value); + OLA_ASSERT_TRUE(StringToInt("f", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 15, int32_value); + OLA_ASSERT_TRUE(StringToInt("a1", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 161, int32_value); + OLA_ASSERT_TRUE(StringToInt("ff", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 255, int32_value); + OLA_ASSERT_TRUE(StringToInt("7fff", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 32767, int32_value); + OLA_ASSERT_TRUE(StringToInt("ffff", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) 65535, int32_value); + OLA_ASSERT_TRUE(StringToInt("ffffffff", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) -1, int32_value); + OLA_ASSERT_TRUE(StringToInt("fffffff0", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) -16, int32_value); + OLA_ASSERT_TRUE(StringToInt("80000000", &int32_value, true, 16)); + OLA_ASSERT_EQ((int32_t) -2147483647 - 1, int32_value); } @@ -916,6 +871,42 @@ void StringUtilsTest::testStringToInt16() { OLA_ASSERT_TRUE(StringToInt("32767", &value)); OLA_ASSERT_EQ((int16_t) 32767, value); OLA_ASSERT_FALSE(StringToInt("32768", &value)); + + // base16 - int16_t + int16_t int16_value; + OLA_ASSERT_FALSE(StringToInt("", &int16_value, true, 16)); + + OLA_ASSERT_TRUE(StringToInt("-1", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) -1, int16_value); + + OLA_ASSERT_TRUE(StringToInt("0", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 0, int16_value); + OLA_ASSERT_TRUE(StringToInt("1", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 1, int16_value); + OLA_ASSERT_TRUE(StringToInt("a", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 10, int16_value); + OLA_ASSERT_TRUE(StringToInt("f", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 15, int16_value); + OLA_ASSERT_TRUE(StringToInt("a1", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 161, int16_value); + OLA_ASSERT_TRUE(StringToInt("ff", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 255, int16_value); + OLA_ASSERT_TRUE(StringToInt("7fff", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 32767, int16_value); + OLA_ASSERT_TRUE(StringToInt("ffff", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) -1, int16_value); + OLA_ASSERT_TRUE(StringToInt("fff0", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) -16, int16_value); + OLA_ASSERT_TRUE(StringToInt("8000", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) -32768, int16_value); + + OLA_ASSERT_FALSE(StringToInt("ffffff", &int16_value, true, 16)); + OLA_ASSERT_TRUE(StringToInt("ffffffff", &int16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("ef123456", &int16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("fz", &int16_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("zfff", &int16_value, true, 16)); + OLA_ASSERT_TRUE(StringToInt("0xf", &int16_value, true, 16)); + OLA_ASSERT_EQ((int16_t) 15, int16_value); } @@ -959,6 +950,40 @@ void StringUtilsTest::testStringToInt8() { OLA_ASSERT_EQ((int8_t) 127, value); OLA_ASSERT_FALSE(StringToInt("128", &value)); OLA_ASSERT_FALSE(StringToInt("129", &value)); + + // base16 - int8_t + int8_t int8_value; + OLA_ASSERT_FALSE(StringToInt("", &int8_value, true, 16)); + + OLA_ASSERT_TRUE(StringToInt("-1", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) -1, int8_value); + + OLA_ASSERT_TRUE(StringToInt("0", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 0, int8_value); + OLA_ASSERT_TRUE(StringToInt("1", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 1, int8_value); + OLA_ASSERT_TRUE(StringToInt("a", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 10, int8_value); + OLA_ASSERT_TRUE(StringToInt("f", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 15, int8_value); + OLA_ASSERT_TRUE(StringToInt("7f", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 127, int8_value); + OLA_ASSERT_TRUE(StringToInt("a1", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) -95, int8_value); + OLA_ASSERT_TRUE(StringToInt("80", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) -128, int8_value); + OLA_ASSERT_TRUE(StringToInt("ff", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) -1, int8_value); + + OLA_ASSERT_FALSE(StringToInt("ffff", &int8_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("fff0", &int8_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("ffffff", &int8_value, true, 16)); + OLA_ASSERT_TRUE(StringToInt("ffffffff", &int8_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("ef123456", &int8_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("fz", &int8_value, true, 16)); + OLA_ASSERT_FALSE(StringToInt("zfff", &int8_value, true, 16)); + OLA_ASSERT_TRUE(StringToInt("0xf", &int8_value, true, 16)); + OLA_ASSERT_EQ((int8_t) 15, int8_value); } diff --git a/include/ola/StringUtils.h b/include/ola/StringUtils.h index ff88dbdca8..c6e3002d5a 100644 --- a/include/ola/StringUtils.h +++ b/include/ola/StringUtils.h @@ -262,73 +262,89 @@ bool StringToBoolTolerant(const std::string &value, bool *output); * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. */ bool StringToInt(const std::string &value, unsigned int *output, - bool strict = false); + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a uint16_t. * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ bool StringToInt(const std::string &value, uint16_t *output, - bool strict = false); + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a uint8_t. * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ bool StringToInt(const std::string &value, uint8_t *output, - bool strict = false); + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a int. * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ -bool StringToInt(const std::string &value, int *output, bool strict = false); +bool StringToInt(const std::string &value, + int *output, + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a int16_t. * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ bool StringToInt(const std::string &value, int16_t *output, - bool strict = false); + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to a int8_t. * @param[in] value the string to convert * @param[out] output a pointer where the value will be stored. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns true if the value was converted, false if the string was not an int * or the value was too large / small for the type. * @sa StringToInt. */ -bool StringToInt(const std::string &value, int8_t *output, bool strict = false); +bool StringToInt(const std::string &value, + int8_t *output, + bool strict = false, + uint8_t base = 10); /** * @brief Convert a string to an int type or return a default if it failed. @@ -336,83 +352,19 @@ bool StringToInt(const std::string &value, int8_t *output, bool strict = false); * @param value the string to convert * @param alternative the default value to return if conversion failed. * @param[in] strict this controls if trailing characters produce an error. + * @param[in] base the base of the number being read * @returns the value if it converted successfully or the default if the string * was not an int or the value was too large / small for the type. */ template int_type StringToIntOrDefault(const std::string &value, int_type alternative, - bool strict = false) { + bool strict = false, + uint8_t base = 10) { int_type output; - return (StringToInt(value, &output, strict)) ? output : alternative; + return (StringToInt(value, &output, strict, base)) ? output : alternative; } -/** - * @brief Convert a hex string to a uint8_t. - * - * The string can contain upper or lower case hex characters. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - */ -bool HexStringToInt(const std::string &value, uint8_t *output); - -/** - * @brief Convert a hex string to a uint16_t. - * - * The string can contain upper or lower case hex characters. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - */ -bool HexStringToInt(const std::string &value, uint16_t *output); - -/** - * @brief Convert a hex string to a uint32_t. - * - * The string can contain upper or lower case hex characters. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - */ -bool HexStringToInt(const std::string &value, uint32_t *output); - -/** - * @brief Convert a hex string to a int8_t. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - * - * The string can contain upper or lower case hex characters. - */ -bool HexStringToInt(const std::string &value, int8_t *output); - -/** - * @brief Convert a hex string to a int16_t. - * - * The string can contain upper or lower case hex characters. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - */ -bool HexStringToInt(const std::string &value, int16_t *output); - -/** - * @brief Convert a hex string to a int32_t. - * - * The string can contain upper or lower case hex characters. - * @param[in] value the string to convert. - * @param[out] output a pointer to the store the converted value in. - * @returns true if the value was converted, false if the string was not an int - * or the value was too large / small for the type. - */ -bool HexStringToInt(const std::string &value, int32_t *output); - /** * @brief Convert a string to lower case. * @param s the string to convert to lower case. @@ -481,7 +433,7 @@ bool PrefixedHexStringToInt(const std::string &input, int_type *output) { if ((input.find("0x") != 0) && (input.find("0X") != 0)) return false; std::string modified_input = input.substr(2); - return HexStringToInt(modified_input, output); + return StringToInt(modified_input, output, true, 16); } /**