Make big_int_from_string return an error if not an integer.

This commit is contained in:
Jeroen van Rijn
2022-05-03 13:15:49 +02:00
parent 8bac82320f
commit 59f55a2119
3 changed files with 36 additions and 17 deletions
+27 -3
View File
@@ -40,7 +40,7 @@ typedef mp_int BigInt;
void big_int_from_u64(BigInt *dst, u64 x);
void big_int_from_i64(BigInt *dst, i64 x);
void big_int_init (BigInt *dst, BigInt const *src);
void big_int_from_string(BigInt *dst, String const &s);
void big_int_from_string(BigInt *dst, String const &s, bool &success);
void big_int_dealloc(BigInt *dst) {
mp_clear(dst);
@@ -84,7 +84,7 @@ void big_int_quo_eq(BigInt *dst, BigInt const *x);
void big_int_rem_eq(BigInt *dst, BigInt const *x);
bool big_int_is_neg(BigInt const *x);
void big_int_neg(BigInt *dst, BigInt const *x);
void big_int_add_eq(BigInt *dst, BigInt const *x) {
BigInt res = {};
@@ -169,7 +169,11 @@ BigInt big_int_make_i64(i64 x) {
}
void big_int_from_string(BigInt *dst, String const &s) {
void big_int_from_string(BigInt *dst, String const &s, bool *success) {
*success = true;
bool is_negative = false;
u64 base = 10;
bool has_prefix = false;
if (s.len > 2 && s[0] == '0') {
@@ -197,11 +201,26 @@ void big_int_from_string(BigInt *dst, String const &s) {
isize i = 0;
for (; i < len; i++) {
Rune r = cast(Rune)text[i];
if (r == '-') {
if (is_negative) {
// NOTE(Jeroen): Can't have a doubly negative number.
*success = false;
return;
}
is_negative = true;
continue;
}
if (r == '_') {
continue;
}
u64 v = u64_digit_value(r);
if (v >= base) {
// NOTE(Jeroen): Can still be a valid integer if the next character is an `e` or `E`.
if (r != 'e' && r != 'E') {
*success = false;
}
break;
}
BigInt val = big_int_make_u64(v);
@@ -225,6 +244,7 @@ void big_int_from_string(BigInt *dst, String const &s) {
if (gb_char_is_digit(r)) {
v = u64_digit_value(r);
} else {
*success = false;
break;
}
exp *= 10;
@@ -234,6 +254,10 @@ void big_int_from_string(BigInt *dst, String const &s) {
big_int_mul_eq(dst, &b);
}
}
if (is_negative) {
big_int_neg(dst, dst);
}
}
+5 -1
View File
@@ -177,7 +177,11 @@ ExactValue exact_value_typeid(Type *type) {
ExactValue exact_value_integer_from_string(String const &string) {
ExactValue result = {ExactValue_Integer};
big_int_from_string(&result.value_integer, string);
bool success;
big_int_from_string(&result.value_integer, string, &success);
if (!success) {
result = {ExactValue_Invalid};
}
return result;
}
+4 -13
View File
@@ -961,19 +961,10 @@ bool parse_build_flags(Array<String> args) {
bad_flags = true;
break;
}
// NOTE(Jeroen): We can't rely on `value.value_integer` here, because words will be returned as `0`.
// Meaning that -opt:speed will coerce to opt:0. That's not what the user intended.
// Instead we'll just compare 0..3 directly.
if (param == "0") {
build_context.optimization_level = 0;
} else if (param == "1") {
build_context.optimization_level = 1;
} else if (param == "2") {
build_context.optimization_level = 2;
} else if (param == "3") {
build_context.optimization_level = 3;
} else {
gb_printf_err("Invalid optimization level for -o:<integer>, got %.*s\n", LIT(param));
build_context.optimization_level = cast(i32)big_int_to_i64(&value.value_integer);
if (build_context.optimization_level < 0 || build_context.optimization_level > 3) {
gb_printf_err("Invalid optimization level for -o:<integer>, got %d\n", build_context.optimization_level);
gb_printf_err("Valid optimization levels:\n");
gb_printf_err("\t0\n");
gb_printf_err("\t1\n");