Skip to content

Commit 33a38a9

Browse files
committed
fix #462: Implement hex, octal and bin conversion
1 parent f2965e9 commit 33a38a9

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed

include/scratchcpp/value.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,51 @@ class LIBSCRATCHCPP_EXPORT Value
766766
return (s1.compare(s2) == 0);
767767
}
768768

769+
static long hexToDec(const std::string &s)
770+
{
771+
static const std::string digits = "0123456789abcdef";
772+
773+
for (char c : s) {
774+
if (digits.find(c) == std::string::npos) {
775+
return 0;
776+
}
777+
}
778+
779+
std::istringstream stream(s);
780+
long ret;
781+
stream >> std::hex >> ret;
782+
return ret;
783+
}
784+
785+
static long octToDec(const std::string &s)
786+
{
787+
static const std::string digits = "01234567";
788+
789+
for (char c : s) {
790+
if (digits.find(c) == std::string::npos) {
791+
return 0;
792+
}
793+
}
794+
795+
std::istringstream stream(s);
796+
long ret;
797+
stream >> std::oct >> ret;
798+
return ret;
799+
}
800+
801+
static double binToDec(const std::string &s)
802+
{
803+
static const std::string digits = "01";
804+
805+
for (char c : s) {
806+
if (digits.find(c) == std::string::npos) {
807+
return 0;
808+
}
809+
}
810+
811+
return std::stoi(s, 0, 2);
812+
}
813+
769814
static double stringToDouble(const std::string &s, bool *ok = nullptr)
770815
{
771816
if (ok)
@@ -785,6 +830,19 @@ class LIBSCRATCHCPP_EXPORT Value
785830
return 0;
786831
}
787832

833+
if (s.size() >= 2 && s[0] == '0') {
834+
std::string sub = s.substr(2, s.size() - 2);
835+
std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower);
836+
837+
if (s[1] == 'x' || s[1] == 'X') {
838+
return hexToDec(sub);
839+
} else if (s[1] == 'o' || s[1] == 'O') {
840+
return octToDec(sub);
841+
} else if (s[1] == 'b' || s[1] == 'B') {
842+
return binToDec(sub);
843+
}
844+
}
845+
788846
static const std::string digits = "0123456789.eE+-";
789847
const std::string *stringPtr = &s;
790848
bool customStr = false;
@@ -850,6 +908,19 @@ class LIBSCRATCHCPP_EXPORT Value
850908
return 0;
851909
}
852910

911+
if (s.size() >= 2 && s[0] == '0') {
912+
std::string sub = s.substr(2, s.size() - 2);
913+
std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower);
914+
915+
if (s[1] == 'x' || s[1] == 'X') {
916+
return hexToDec(sub);
917+
} else if (s[1] == 'o' || s[1] == 'O') {
918+
return octToDec(sub);
919+
} else if (s[1] == 'b' || s[1] == 'B') {
920+
return binToDec(sub);
921+
}
922+
}
923+
853924
static const std::string digits = "0123456789+-";
854925

855926
for (char c : s) {

test/scratch_classes/value_test.cpp

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,49 @@ TEST(ValueTest, ToInt)
760760

761761
v = "something";
762762
ASSERT_EQ(v.toInt(), 0);
763+
764+
// Hex
765+
v = "0xafe";
766+
ASSERT_TRUE(v.isString());
767+
ASSERT_EQ(v.toInt(), 2814);
768+
769+
v = "0xBaCD";
770+
ASSERT_TRUE(v.isString());
771+
ASSERT_EQ(v.toInt(), 47821);
772+
773+
v = "0XBaCD";
774+
ASSERT_TRUE(v.isString());
775+
ASSERT_EQ(v.toInt(), 47821);
776+
777+
v = "0xAbG";
778+
ASSERT_TRUE(v.isString());
779+
ASSERT_EQ(v.toInt(), 0);
780+
781+
// Octal
782+
v = "0o506";
783+
ASSERT_TRUE(v.isString());
784+
ASSERT_EQ(v.toInt(), 326);
785+
786+
v = "0O17206";
787+
ASSERT_TRUE(v.isString());
788+
ASSERT_EQ(v.toInt(), 7814);
789+
790+
v = "0o5783";
791+
ASSERT_TRUE(v.isString());
792+
ASSERT_EQ(v.toInt(), 0);
793+
794+
// Binary
795+
v = "0b101101";
796+
ASSERT_TRUE(v.isString());
797+
ASSERT_EQ(v.toInt(), 45);
798+
799+
v = "0B1110100110";
800+
ASSERT_TRUE(v.isString());
801+
ASSERT_EQ(v.toInt(), 934);
802+
803+
v = "0b100112001";
804+
ASSERT_TRUE(v.isString());
805+
ASSERT_EQ(v.toInt(), 0);
763806
}
764807

765808
TEST(ValueTest, ToLong)
@@ -808,6 +851,49 @@ TEST(ValueTest, ToLong)
808851

809852
v = "something";
810853
ASSERT_EQ(v.toLong(), 0);
854+
855+
// Hex
856+
v = "0xafe";
857+
ASSERT_TRUE(v.isString());
858+
ASSERT_EQ(v.toLong(), 2814);
859+
860+
v = "0xBaCD";
861+
ASSERT_TRUE(v.isString());
862+
ASSERT_EQ(v.toLong(), 47821);
863+
864+
v = "0XBaCD";
865+
ASSERT_TRUE(v.isString());
866+
ASSERT_EQ(v.toLong(), 47821);
867+
868+
v = "0xAbG";
869+
ASSERT_TRUE(v.isString());
870+
ASSERT_EQ(v.toLong(), 0);
871+
872+
// Octal
873+
v = "0o506";
874+
ASSERT_TRUE(v.isString());
875+
ASSERT_EQ(v.toLong(), 326);
876+
877+
v = "0O17206";
878+
ASSERT_TRUE(v.isString());
879+
ASSERT_EQ(v.toLong(), 7814);
880+
881+
v = "0o5783";
882+
ASSERT_TRUE(v.isString());
883+
ASSERT_EQ(v.toLong(), 0);
884+
885+
// Binary
886+
v = "0b101101";
887+
ASSERT_TRUE(v.isString());
888+
ASSERT_EQ(v.toLong(), 45);
889+
890+
v = "0B1110100110";
891+
ASSERT_TRUE(v.isString());
892+
ASSERT_EQ(v.toLong(), 934);
893+
894+
v = "0b100112001";
895+
ASSERT_TRUE(v.isString());
896+
ASSERT_EQ(v.toLong(), 0);
811897
}
812898

813899
TEST(ValueTest, ToDouble)
@@ -866,6 +952,49 @@ TEST(ValueTest, ToDouble)
866952

867953
v = "something";
868954
ASSERT_EQ(v.toDouble(), 0.0);
955+
956+
// Hex
957+
v = "0xafe";
958+
ASSERT_TRUE(v.isString());
959+
ASSERT_EQ(v.toDouble(), 2814);
960+
961+
v = "0xBaCD";
962+
ASSERT_TRUE(v.isString());
963+
ASSERT_EQ(v.toDouble(), 47821);
964+
965+
v = "0XBaCD";
966+
ASSERT_TRUE(v.isString());
967+
ASSERT_EQ(v.toDouble(), 47821);
968+
969+
v = "0xAbG";
970+
ASSERT_TRUE(v.isString());
971+
ASSERT_EQ(v.toDouble(), 0);
972+
973+
// Octal
974+
v = "0o506";
975+
ASSERT_TRUE(v.isString());
976+
ASSERT_EQ(v.toDouble(), 326);
977+
978+
v = "0O17206";
979+
ASSERT_TRUE(v.isString());
980+
ASSERT_EQ(v.toDouble(), 7814);
981+
982+
v = "0o5783";
983+
ASSERT_TRUE(v.isString());
984+
ASSERT_EQ(v.toDouble(), 0);
985+
986+
// Binary
987+
v = "0b101101";
988+
ASSERT_TRUE(v.isString());
989+
ASSERT_EQ(v.toDouble(), 45);
990+
991+
v = "0B1110100110";
992+
ASSERT_TRUE(v.isString());
993+
ASSERT_EQ(v.toDouble(), 934);
994+
995+
v = "0b100112001";
996+
ASSERT_TRUE(v.isString());
997+
ASSERT_EQ(v.toDouble(), 0);
869998
}
870999

8711000
TEST(ValueTest, ToBool)
@@ -921,6 +1050,54 @@ TEST(ValueTest, ToBool)
9211050

9221051
v = "something";
9231052
ASSERT_EQ(v.toBool(), false);
1053+
1054+
// TODO: Uncomment this (#517)
1055+
// Hex
1056+
/*v = "0xafe";
1057+
ASSERT_TRUE(v.isString());
1058+
ASSERT_TRUE(v.toBool());
1059+
1060+
v = "0xBaCD";
1061+
ASSERT_TRUE(v.isString());
1062+
ASSERT_TRUE(v.toBool());
1063+
1064+
v = "0x0";
1065+
ASSERT_TRUE(v.isString());
1066+
ASSERT_FALSE(v.toBool());
1067+
1068+
v = "0XBaCD";
1069+
ASSERT_TRUE(v.isString());
1070+
ASSERT_TRUE(v.toBool());
1071+
1072+
v = "0xAbG";
1073+
ASSERT_TRUE(v.isString());
1074+
ASSERT_FALSE(v.toBool());
1075+
1076+
// Octal
1077+
v = "0o506";
1078+
ASSERT_TRUE(v.isString());
1079+
ASSERT_TRUE(v.toBool());
1080+
1081+
v = "0O17206";
1082+
ASSERT_TRUE(v.isString());
1083+
ASSERT_TRUE(v.toBool());
1084+
1085+
v = "0o5783";
1086+
ASSERT_TRUE(v.isString());
1087+
ASSERT_FALSE(v.toBool());
1088+
1089+
// Binary
1090+
v = "0b101101";
1091+
ASSERT_TRUE(v.isString());
1092+
ASSERT_TRUE(v.toBool());
1093+
1094+
v = "0B1110100110";
1095+
ASSERT_TRUE(v.isString());
1096+
ASSERT_TRUE(v.toBool());
1097+
1098+
v = "0b100112001";
1099+
ASSERT_TRUE(v.isString());
1100+
ASSERT_FALSE(v.toBool());*/
9241101
}
9251102

9261103
TEST(ValueTest, ToString)

0 commit comments

Comments
 (0)