1
0
mirror of synced 2025-01-30 19:43:43 +01:00

pattern: std::from_chars is not widely supported and doesn't support u128...

This commit is contained in:
WerWolv 2022-02-02 17:12:19 +01:00
parent 4c51efc5e0
commit c2bcbfb1e0
3 changed files with 37 additions and 33 deletions

View File

@ -38,11 +38,14 @@ namespace hex::pl {
} }
std::optional<Token::Literal> lexIntegerLiteral(std::string_view string) { std::optional<Token::Literal> lexIntegerLiteral(std::string_view string) {
bool hasFloatSuffix = string.ends_with('D') || string.ends_with('F') || string.ends_with('d') || string.ends_with('f');
bool isFloat = std::count(string.begin(), string.end(), '.') == 1 ||
!string.starts_with("0x") && hasFloatSuffix;
if (std::count(string.begin(), string.end(), '.') == 1) { if (isFloat) {
// Parse double // Parse double
char suffix = 0x00; char suffix = 0x00;
if (string.ends_with('D') || string.ends_with('F') || string.ends_with('d') || string.ends_with('f')) { if (hasFloatSuffix) {
suffix = string.back(); suffix = string.back();
string = string.substr(0, string.length() - 1); string = string.substr(0, string.length() - 1);
} }
@ -63,45 +66,46 @@ namespace hex::pl {
} }
} }
} else { } else {
bool unsignedNumber = false; bool isUnsigned = false;
if (string.ends_with('U') || string.ends_with('u')) { if (string.ends_with('U') || string.ends_with('u')) {
unsignedNumber = true; isUnsigned = true;
string = string.substr(0, string.length() - 1); string = string.substr(0, string.length() - 1);
} }
i128 value; u8 prefixOffset = 0;
u8 base = 10;
if (string.starts_with("0x") || string.starts_with("0X")) { if (string.starts_with("0x") || string.starts_with("0X")) {
// Parse hexadecimal // Parse hexadecimal
prefixOffset = 2;
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 16); base = 16;
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
} else if (string.starts_with("0o") || string.starts_with("0O")) { } else if (string.starts_with("0o") || string.starts_with("0O")) {
// Parse octal // Parse octal
prefixOffset = 2;
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 8); base = 8;
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
} else if (string.starts_with("0b") || string.starts_with("0B")) { } else if (string.starts_with("0b") || string.starts_with("0B")) {
// Parse binary // Parse binary
prefixOffset = 2;
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 2); base = 2;
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
} else { } else {
// Parse decimal // Parse decimal
prefixOffset = 0;
auto [p, error] = std::from_chars(string.begin(), string.end(), value, 10); base = 10;
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
} }
if (unsignedNumber) u128 value = 0x00;
return u128(value); for (char c : string.substr(prefixOffset)) {
value *= base;
value += [&] {
if (c >= '0' && c <= '9') return c - '0';
else if (c >= 'A' && c <= 'F') return 0xA + (c - 'A');
else if (c >= 'a' && c <= 'f') return 0xA + (c - 'a');
else return 0x00;
}();
}
if (isUnsigned)
return value;
else else
return i128(value); return i128(value);
} }

View File

@ -9,10 +9,10 @@ namespace hex::test {
TestPatternEnums() : TestPattern("Enums") { TestPatternEnums() : TestPattern("Enums") {
auto testEnum = create<PatternDataEnum>("TestEnum", "testEnum", 0x08, sizeof(u32)); auto testEnum = create<PatternDataEnum>("TestEnum", "testEnum", 0x08, sizeof(u32));
testEnum->setEnumValues({ testEnum->setEnumValues({
{u128(0x0000), "A"}, {u128(0x00), "A"},
{ i128(0x0C), "B"}, { i128(0x0C), "B"},
{ u128(0x0D), "C"}, { u128(0x0D), "C"},
{ u128(0x0E), "D"}, { u128(0x0E), "D"},
}); });
testEnum->setEndian(std::endian::big); testEnum->setEndian(std::endian::big);

View File

@ -31,7 +31,7 @@ namespace hex::test {
std::assert(0xFF00FF | 0x00AA00 == 0xFFAAFF, "| operator error"); std::assert(0xFF00FF | 0x00AA00 == 0xFFAAFF, "| operator error");
std::assert(0xFFFFFF & 0x00FF00 == 0x00FF00, "& operator error"); std::assert(0xFFFFFF & 0x00FF00 == 0x00FF00, "& operator error");
std::assert(0xFFFFFF ^ 0x00AA00 == 0xFF55FF, "^ operator error"); std::assert(0xFFFFFF ^ 0x00AA00 == 0xFF55FF, "^ operator error");
std::assert(~0x00 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "~ operator error"); std::assert(~0x00U == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, "~ operator error");
std::assert(0xAA >> 4 == 0x0A, ">> operator error"); std::assert(0xAA >> 4 == 0x0A, ">> operator error");
std::assert(0xAA << 4 == 0xAA0, "<< operator error"); std::assert(0xAA << 4 == 0xAA0, "<< operator error");