diff --git a/include/scratchcpp/value.h b/include/scratchcpp/value.h index 32180df0..7f872213 100644 --- a/include/scratchcpp/value.h +++ b/include/scratchcpp/value.h @@ -766,6 +766,51 @@ class LIBSCRATCHCPP_EXPORT Value return (s1.compare(s2) == 0); } + static long hexToDec(const std::string &s) + { + static const std::string digits = "0123456789abcdef"; + + for (char c : s) { + if (digits.find(c) == std::string::npos) { + return 0; + } + } + + std::istringstream stream(s); + long ret; + stream >> std::hex >> ret; + return ret; + } + + static long octToDec(const std::string &s) + { + static const std::string digits = "01234567"; + + for (char c : s) { + if (digits.find(c) == std::string::npos) { + return 0; + } + } + + std::istringstream stream(s); + long ret; + stream >> std::oct >> ret; + return ret; + } + + static double binToDec(const std::string &s) + { + static const std::string digits = "01"; + + for (char c : s) { + if (digits.find(c) == std::string::npos) { + return 0; + } + } + + return std::stoi(s, 0, 2); + } + static double stringToDouble(const std::string &s, bool *ok = nullptr) { if (ok) @@ -785,6 +830,19 @@ class LIBSCRATCHCPP_EXPORT Value return 0; } + if (s.size() >= 2 && s[0] == '0') { + std::string sub = s.substr(2, s.size() - 2); + std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); + + if (s[1] == 'x' || s[1] == 'X') { + return hexToDec(sub); + } else if (s[1] == 'o' || s[1] == 'O') { + return octToDec(sub); + } else if (s[1] == 'b' || s[1] == 'B') { + return binToDec(sub); + } + } + static const std::string digits = "0123456789.eE+-"; const std::string *stringPtr = &s; bool customStr = false; @@ -850,6 +908,19 @@ class LIBSCRATCHCPP_EXPORT Value return 0; } + if (s.size() >= 2 && s[0] == '0') { + std::string sub = s.substr(2, s.size() - 2); + std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); + + if (s[1] == 'x' || s[1] == 'X') { + return hexToDec(sub); + } else if (s[1] == 'o' || s[1] == 'O') { + return octToDec(sub); + } else if (s[1] == 'b' || s[1] == 'B') { + return binToDec(sub); + } + } + static const std::string digits = "0123456789+-"; for (char c : s) { diff --git a/test/scratch_classes/value_test.cpp b/test/scratch_classes/value_test.cpp index c46be444..de214c86 100644 --- a/test/scratch_classes/value_test.cpp +++ b/test/scratch_classes/value_test.cpp @@ -760,6 +760,61 @@ TEST(ValueTest, ToInt) v = "something"; ASSERT_EQ(v.toInt(), 0); + + // Hex + v = "0xafe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 2814); + + v = "0x0afe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 2814); + + v = "0xBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 47821); + + v = "0XBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 47821); + + v = "0xAbG"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 0); + + // Octal + v = "0o506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 326); + + v = "0o0506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 326); + + v = "0O17206"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 7814); + + v = "0o5783"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 0); + + // Binary + v = "0b101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 45); + + v = "0b0101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 45); + + v = "0B1110100110"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 934); + + v = "0b100112001"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toInt(), 0); } TEST(ValueTest, ToLong) @@ -808,6 +863,61 @@ TEST(ValueTest, ToLong) v = "something"; ASSERT_EQ(v.toLong(), 0); + + // Hex + v = "0xafe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 2814); + + v = "0x0afe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 2814); + + v = "0xBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 47821); + + v = "0XBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 47821); + + v = "0xAbG"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 0); + + // Octal + v = "0o506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 326); + + v = "0o0506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 326); + + v = "0O17206"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 7814); + + v = "0o5783"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 0); + + // Binary + v = "0b101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 45); + + v = "0b0101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 45); + + v = "0B1110100110"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 934); + + v = "0b100112001"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toLong(), 0); } TEST(ValueTest, ToDouble) @@ -866,6 +976,61 @@ TEST(ValueTest, ToDouble) v = "something"; ASSERT_EQ(v.toDouble(), 0.0); + + // Hex + v = "0xafe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 2814); + + v = "0x0afe"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 2814); + + v = "0xBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 47821); + + v = "0XBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 47821); + + v = "0xAbG"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 0); + + // Octal + v = "0o506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 326); + + v = "0o0506"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 326); + + v = "0O17206"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 7814); + + v = "0o5783"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 0); + + // Binary + v = "0b101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 45); + + v = "0b0101101"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 45); + + v = "0B1110100110"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 934); + + v = "0b100112001"; + ASSERT_TRUE(v.isString()); + ASSERT_EQ(v.toDouble(), 0); } TEST(ValueTest, ToBool) @@ -921,6 +1086,66 @@ TEST(ValueTest, ToBool) v = "something"; ASSERT_EQ(v.toBool(), false); + + // TODO: Uncomment this (#517) + // Hex + /*v = "0xafe"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0x0afe"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0xBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0x0"; + ASSERT_TRUE(v.isString()); + ASSERT_FALSE(v.toBool()); + + v = "0XBaCD"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0xAbG"; + ASSERT_TRUE(v.isString()); + ASSERT_FALSE(v.toBool()); + + // Octal + v = "0o506"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0o0506"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0O17206"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0o5783"; + ASSERT_TRUE(v.isString()); + ASSERT_FALSE(v.toBool()); + + // Binary + v = "0b101101"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0b0101101"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0B1110100110"; + ASSERT_TRUE(v.isString()); + ASSERT_TRUE(v.toBool()); + + v = "0b100112001"; + ASSERT_TRUE(v.isString()); + ASSERT_FALSE(v.toBool());*/ } TEST(ValueTest, ToString)