Skip to content

Commit d8a3948

Browse files
authored
Merge pull request #518 from scratchcpp/hex_oct_bin_conversion
Fix #462: Implement hex, octal and bin conversion
2 parents f2965e9 + 2136523 commit d8a3948

File tree

2 files changed

+296
-0
lines changed

2 files changed

+296
-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: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,61 @@ 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 = "0x0afe";
770+
ASSERT_TRUE(v.isString());
771+
ASSERT_EQ(v.toInt(), 2814);
772+
773+
v = "0xBaCD";
774+
ASSERT_TRUE(v.isString());
775+
ASSERT_EQ(v.toInt(), 47821);
776+
777+
v = "0XBaCD";
778+
ASSERT_TRUE(v.isString());
779+
ASSERT_EQ(v.toInt(), 47821);
780+
781+
v = "0xAbG";
782+
ASSERT_TRUE(v.isString());
783+
ASSERT_EQ(v.toInt(), 0);
784+
785+
// Octal
786+
v = "0o506";
787+
ASSERT_TRUE(v.isString());
788+
ASSERT_EQ(v.toInt(), 326);
789+
790+
v = "0o0506";
791+
ASSERT_TRUE(v.isString());
792+
ASSERT_EQ(v.toInt(), 326);
793+
794+
v = "0O17206";
795+
ASSERT_TRUE(v.isString());
796+
ASSERT_EQ(v.toInt(), 7814);
797+
798+
v = "0o5783";
799+
ASSERT_TRUE(v.isString());
800+
ASSERT_EQ(v.toInt(), 0);
801+
802+
// Binary
803+
v = "0b101101";
804+
ASSERT_TRUE(v.isString());
805+
ASSERT_EQ(v.toInt(), 45);
806+
807+
v = "0b0101101";
808+
ASSERT_TRUE(v.isString());
809+
ASSERT_EQ(v.toInt(), 45);
810+
811+
v = "0B1110100110";
812+
ASSERT_TRUE(v.isString());
813+
ASSERT_EQ(v.toInt(), 934);
814+
815+
v = "0b100112001";
816+
ASSERT_TRUE(v.isString());
817+
ASSERT_EQ(v.toInt(), 0);
763818
}
764819

765820
TEST(ValueTest, ToLong)
@@ -808,6 +863,61 @@ TEST(ValueTest, ToLong)
808863

809864
v = "something";
810865
ASSERT_EQ(v.toLong(), 0);
866+
867+
// Hex
868+
v = "0xafe";
869+
ASSERT_TRUE(v.isString());
870+
ASSERT_EQ(v.toLong(), 2814);
871+
872+
v = "0x0afe";
873+
ASSERT_TRUE(v.isString());
874+
ASSERT_EQ(v.toLong(), 2814);
875+
876+
v = "0xBaCD";
877+
ASSERT_TRUE(v.isString());
878+
ASSERT_EQ(v.toLong(), 47821);
879+
880+
v = "0XBaCD";
881+
ASSERT_TRUE(v.isString());
882+
ASSERT_EQ(v.toLong(), 47821);
883+
884+
v = "0xAbG";
885+
ASSERT_TRUE(v.isString());
886+
ASSERT_EQ(v.toLong(), 0);
887+
888+
// Octal
889+
v = "0o506";
890+
ASSERT_TRUE(v.isString());
891+
ASSERT_EQ(v.toLong(), 326);
892+
893+
v = "0o0506";
894+
ASSERT_TRUE(v.isString());
895+
ASSERT_EQ(v.toLong(), 326);
896+
897+
v = "0O17206";
898+
ASSERT_TRUE(v.isString());
899+
ASSERT_EQ(v.toLong(), 7814);
900+
901+
v = "0o5783";
902+
ASSERT_TRUE(v.isString());
903+
ASSERT_EQ(v.toLong(), 0);
904+
905+
// Binary
906+
v = "0b101101";
907+
ASSERT_TRUE(v.isString());
908+
ASSERT_EQ(v.toLong(), 45);
909+
910+
v = "0b0101101";
911+
ASSERT_TRUE(v.isString());
912+
ASSERT_EQ(v.toLong(), 45);
913+
914+
v = "0B1110100110";
915+
ASSERT_TRUE(v.isString());
916+
ASSERT_EQ(v.toLong(), 934);
917+
918+
v = "0b100112001";
919+
ASSERT_TRUE(v.isString());
920+
ASSERT_EQ(v.toLong(), 0);
811921
}
812922

813923
TEST(ValueTest, ToDouble)
@@ -866,6 +976,61 @@ TEST(ValueTest, ToDouble)
866976

867977
v = "something";
868978
ASSERT_EQ(v.toDouble(), 0.0);
979+
980+
// Hex
981+
v = "0xafe";
982+
ASSERT_TRUE(v.isString());
983+
ASSERT_EQ(v.toDouble(), 2814);
984+
985+
v = "0x0afe";
986+
ASSERT_TRUE(v.isString());
987+
ASSERT_EQ(v.toDouble(), 2814);
988+
989+
v = "0xBaCD";
990+
ASSERT_TRUE(v.isString());
991+
ASSERT_EQ(v.toDouble(), 47821);
992+
993+
v = "0XBaCD";
994+
ASSERT_TRUE(v.isString());
995+
ASSERT_EQ(v.toDouble(), 47821);
996+
997+
v = "0xAbG";
998+
ASSERT_TRUE(v.isString());
999+
ASSERT_EQ(v.toDouble(), 0);
1000+
1001+
// Octal
1002+
v = "0o506";
1003+
ASSERT_TRUE(v.isString());
1004+
ASSERT_EQ(v.toDouble(), 326);
1005+
1006+
v = "0o0506";
1007+
ASSERT_TRUE(v.isString());
1008+
ASSERT_EQ(v.toDouble(), 326);
1009+
1010+
v = "0O17206";
1011+
ASSERT_TRUE(v.isString());
1012+
ASSERT_EQ(v.toDouble(), 7814);
1013+
1014+
v = "0o5783";
1015+
ASSERT_TRUE(v.isString());
1016+
ASSERT_EQ(v.toDouble(), 0);
1017+
1018+
// Binary
1019+
v = "0b101101";
1020+
ASSERT_TRUE(v.isString());
1021+
ASSERT_EQ(v.toDouble(), 45);
1022+
1023+
v = "0b0101101";
1024+
ASSERT_TRUE(v.isString());
1025+
ASSERT_EQ(v.toDouble(), 45);
1026+
1027+
v = "0B1110100110";
1028+
ASSERT_TRUE(v.isString());
1029+
ASSERT_EQ(v.toDouble(), 934);
1030+
1031+
v = "0b100112001";
1032+
ASSERT_TRUE(v.isString());
1033+
ASSERT_EQ(v.toDouble(), 0);
8691034
}
8701035

8711036
TEST(ValueTest, ToBool)
@@ -921,6 +1086,66 @@ TEST(ValueTest, ToBool)
9211086

9221087
v = "something";
9231088
ASSERT_EQ(v.toBool(), false);
1089+
1090+
// TODO: Uncomment this (#517)
1091+
// Hex
1092+
/*v = "0xafe";
1093+
ASSERT_TRUE(v.isString());
1094+
ASSERT_TRUE(v.toBool());
1095+
1096+
v = "0x0afe";
1097+
ASSERT_TRUE(v.isString());
1098+
ASSERT_TRUE(v.toBool());
1099+
1100+
v = "0xBaCD";
1101+
ASSERT_TRUE(v.isString());
1102+
ASSERT_TRUE(v.toBool());
1103+
1104+
v = "0x0";
1105+
ASSERT_TRUE(v.isString());
1106+
ASSERT_FALSE(v.toBool());
1107+
1108+
v = "0XBaCD";
1109+
ASSERT_TRUE(v.isString());
1110+
ASSERT_TRUE(v.toBool());
1111+
1112+
v = "0xAbG";
1113+
ASSERT_TRUE(v.isString());
1114+
ASSERT_FALSE(v.toBool());
1115+
1116+
// Octal
1117+
v = "0o506";
1118+
ASSERT_TRUE(v.isString());
1119+
ASSERT_TRUE(v.toBool());
1120+
1121+
v = "0o0506";
1122+
ASSERT_TRUE(v.isString());
1123+
ASSERT_TRUE(v.toBool());
1124+
1125+
v = "0O17206";
1126+
ASSERT_TRUE(v.isString());
1127+
ASSERT_TRUE(v.toBool());
1128+
1129+
v = "0o5783";
1130+
ASSERT_TRUE(v.isString());
1131+
ASSERT_FALSE(v.toBool());
1132+
1133+
// Binary
1134+
v = "0b101101";
1135+
ASSERT_TRUE(v.isString());
1136+
ASSERT_TRUE(v.toBool());
1137+
1138+
v = "0b0101101";
1139+
ASSERT_TRUE(v.isString());
1140+
ASSERT_TRUE(v.toBool());
1141+
1142+
v = "0B1110100110";
1143+
ASSERT_TRUE(v.isString());
1144+
ASSERT_TRUE(v.toBool());
1145+
1146+
v = "0b100112001";
1147+
ASSERT_TRUE(v.isString());
1148+
ASSERT_FALSE(v.toBool());*/
9241149
}
9251150

9261151
TEST(ValueTest, ToString)

0 commit comments

Comments
 (0)