1
0
mirror of synced 2025-01-29 19:17:28 +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) {
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
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();
string = string.substr(0, string.length() - 1);
}
@ -63,45 +66,46 @@ namespace hex::pl {
}
}
} else {
bool unsignedNumber = false;
bool isUnsigned = false;
if (string.ends_with('U') || string.ends_with('u')) {
unsignedNumber = true;
string = string.substr(0, string.length() - 1);
isUnsigned = true;
string = string.substr(0, string.length() - 1);
}
i128 value;
u8 prefixOffset = 0;
u8 base = 10;
if (string.starts_with("0x") || string.starts_with("0X")) {
// Parse hexadecimal
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 16);
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
prefixOffset = 2;
base = 16;
} else if (string.starts_with("0o") || string.starts_with("0O")) {
// Parse octal
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 8);
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
prefixOffset = 2;
base = 8;
} else if (string.starts_with("0b") || string.starts_with("0B")) {
// Parse binary
auto [p, error] = std::from_chars(string.begin() + 2, string.end(), value, 2);
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
prefixOffset = 2;
base = 2;
} else {
// Parse decimal
auto [p, error] = std::from_chars(string.begin(), string.end(), value, 10);
if (error == std::errc::invalid_argument || p != string.end())
return std::nullopt;
prefixOffset = 0;
base = 10;
}
if (unsignedNumber)
return u128(value);
u128 value = 0x00;
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
return i128(value);
}

View File

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

View File

@ -31,7 +31,7 @@ namespace hex::test {
std::assert(0xFF00FF | 0x00AA00 == 0xFFAAFF, "| operator error");
std::assert(0xFFFFFF & 0x00FF00 == 0x00FF00, "& 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 == 0xAA0, "<< operator error");