diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-16 17:21:01 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-16 17:21:01 -0400 |
| commit | c72b0406a32ffc3f04324f7b6c321486762fca41 (patch) | |
| tree | 244e51c858890ea2ffb8c74a2c33c81b79de376e /src/stdlib/integers.c | |
| parent | 849fd423a759edf1b58b548a6148c177a6f8cd71 (diff) | |
Improved parsing and prefix/suffix matching using a `remainder`
parameter
Diffstat (limited to 'src/stdlib/integers.c')
| -rw-r--r-- | src/stdlib/integers.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c index 018798ec..86be790d 100644 --- a/src/stdlib/integers.c +++ b/src/stdlib/integers.c @@ -424,8 +424,36 @@ public Int_t Int$from_str(const char *str) { return Int$from_mpz(i); } -public OptionalInt_t Int$parse(Text_t text) { - return Int$from_str(Text$as_c_string(text)); +public OptionalInt_t Int$parse(Text_t text, Text_t *remainder) { + const char *str = Text$as_c_string(text); + mpz_t i; + int result; + if (strncmp(str, "0x", 2) == 0) { + const char *end = str + 2 + strcspn(str + 2, "0123456789abcdefABCDEF"); + if (remainder) *remainder = Text$from_str(end); + else if (*end != '\0') return NONE_INT; + result = mpz_init_set_str(i, str + 2, 16); + } else if (strncmp(str, "0o", 2) == 0) { + const char *end = str + 2 + strcspn(str + 2, "01234567"); + if (remainder) *remainder = Text$from_str(end); + else if (*end != '\0') return NONE_INT; + result = mpz_init_set_str(i, str + 2, 8); + } else if (strncmp(str, "0b", 2) == 0) { + const char *end = str + 2 + strcspn(str + 2, "01"); + if (remainder) *remainder = Text$from_str(end); + else if (*end != '\0') return NONE_INT; + result = mpz_init_set_str(i, str + 2, 2); + } else { + const char *end = str + 2 + strcspn(str + 2, "0123456789"); + if (remainder) *remainder = Text$from_str(end); + else if (*end != '\0') return NONE_INT; + result = mpz_init_set_str(i, str, 10); + } + if (result != 0) { + if (remainder) *remainder = text; + return NONE_INT; + } + return Int$from_mpz(i); } public bool Int$is_prime(Int_t x, Int_t reps) @@ -670,8 +698,8 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty range->step = step; \ return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \ } \ - public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \ - OptionalInt_t full_int = Int$parse(text); \ + public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text, Text_t *remainder) { \ + OptionalInt_t full_int = Int$parse(text, remainder); \ if (full_int.small == 0L) return (Optional ## KindOfInt ## _t){.is_none=true}; \ if (Int$compare_value(full_int, I(min_val)) < 0) { \ return (Optional ## KindOfInt ## _t){.is_none=true}; \ |
