diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-04-27 16:49:38 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-04-27 16:49:38 -0400 |
| commit | baf990e65c62f42e45fe25ac385db9536d3f1788 (patch) | |
| tree | 7b89cecde1d6cd3b600b9295e0ad22a702cd1065 /src/stdlib/integers.c | |
| parent | 1a8a8bc3e2ebd9c282db8131902f9bb5de8c03cb (diff) | |
Update stdlib to use `print` instead of `printf` in all cases. This
means bringing in fpconv to do float-to-string conversion and a few
updates to integer and number methods for string formatting.
Diffstat (limited to 'src/stdlib/integers.c')
| -rw-r--r-- | src/stdlib/integers.c | 76 |
1 files changed, 36 insertions, 40 deletions
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c index bb39d99c..86cdeb56 100644 --- a/src/stdlib/integers.c +++ b/src/stdlib/integers.c @@ -9,26 +9,44 @@ #include <stdio.h> #include <stdlib.h> -#include "lists.h" #include "datatypes.h" #include "integers.h" +#include "lists.h" #include "optionals.h" +#include "print.h" #include "siphash.h" #include "text.h" #include "types.h" public int Int$print(FILE *f, Int_t i) { if (likely(i.small & 1L)) { - return fprintf(f, "%ld", (i.small)>>2L); + return _print_int(f, (int64_t)((i.small)>>2L)); } else { - char *str = mpz_get_str(NULL, 10, *i.big); - return fputs(str, f); + return gmp_fprintf(f, "%Zd", *i.big); } } +static inline Text_t _int64_to_text(int64_t n) +{ + char buf[21] = {[20]=0}; // Big enough for INT64_MIN + '\0' + char *p = &buf[19]; + bool negative = n < 0; + + if (n == 0) + *(p--) = '0'; + + for (; n > 0; n /= 10) + *(p--) = '0' + (n % 10); + + if (negative) + *(p--) = '-'; + + return Text$from_strn(p + 1, (size_t)(&buf[19] - p)); +} + public Text_t Int$value_as_text(Int_t i) { if (likely(i.small & 1L)) { - return Text$format("%ld", i.small>>2L); + return _int64_to_text(i.small >> 2L); } else { char *str = mpz_get_str(NULL, 10, *i.big); return Text$from_str(str); @@ -96,40 +114,20 @@ public PUREFUNC uint64_t Int$hash(const void *vx, const TypeInfo_t *info) { } } -public Text_t Int$format(Int_t i, Int_t digits_int) { - int64_t digits = Int64$from_int(digits_int, false); - if (likely(i.small & 1L)) { - return Text$format("%0.*ld", digits, (int64_t)((i.small)>>2L)); - } else { - char *str = mpz_get_str(NULL, 10, *i.big); - bool negative = (str[0] == '-'); - int64_t needed_zeroes = digits - (int64_t)strlen(str); - if (needed_zeroes <= 0) - return Text$from_str(str); - - char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes)); - memset(zeroes, '0', (size_t)(needed_zeroes)); - if (negative) - return Text$concat(Text("-"), Text$from_str(zeroes), Text$from_str(str + 1)); - else - return Text$concat(Text$from_str(zeroes), Text$from_str(str)); - } -} - public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) { if (Int$is_negative(i)) return Text$concat(Text("-"), Int$hex(Int$negative(i), digits_int, uppercase, prefix)); - int64_t digits = Int64$from_int(digits_int, false); if (likely(i.small & 1L)) { - const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); - return Text$format(hex_fmt, digits, (i.small)>>2L); + uint64_t u64 = (uint64_t)(i.small >> 2); + return Text$from_str(String(hex(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false), .uppercase=uppercase))); } else { char *str = mpz_get_str(NULL, 16, *i.big); if (uppercase) { for (char *c = str; *c; c++) *c = (char)toupper(*c); } + int64_t digits = Int64$from_int(digits_int, false); int64_t needed_zeroes = digits - (int64_t)strlen(str); if (needed_zeroes <= 0) return prefix ? Text$concat(Text("0x"), Text$from_str(str)) : Text$from_str(str); @@ -147,11 +145,11 @@ public Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) { if (Int$is_negative(i)) return Text$concat(Text("-"), Int$octal(Int$negative(i), digits_int, prefix)); - int64_t digits = Int64$from_int(digits_int, false); if (likely(i.small & 1L)) { - const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; - return Text$format(octal_fmt, digits, (i.small)>>2L); + uint64_t u64 = (uint64_t)(i.small >> 2); + return Text$from_str(String(oct(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false)))); } else { + int64_t digits = Int64$from_int(digits_int, false); char *str = mpz_get_str(NULL, 8, *i.big); int64_t needed_zeroes = digits - (int64_t)strlen(str); if (needed_zeroes <= 0) @@ -581,11 +579,12 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty #define __builtin_add_overflow(x, y, result) ({ *(result) = (x) + (y); false; }) #endif -#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val, to_attr)\ +#define DEFINE_INT_TYPE(c_type, KindOfInt, min_val, max_val, to_attr)\ public Text_t KindOfInt ## $as_text(const void *i, bool colorize, const TypeInfo_t *info) { \ (void)info; \ if (!i) return Text(#KindOfInt); \ - return Text$format(colorize ? "\x1b[35m" fmt "\x1b[m" : fmt, *(c_type*)i); \ + Text_t text = _int64_to_text((int64_t)(*(c_type*)i)); \ + return colorize ? Texts(Text("\033[35m"), text, Text("\033[m")) : text; \ } \ public PUREFUNC int32_t KindOfInt ## $compare(const void *x, const void *y, const TypeInfo_t *info) { \ (void)info; \ @@ -601,9 +600,6 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty public CONSTFUNC c_type KindOfInt ## $clamped(c_type x, c_type min, c_type max) { \ return x < min ? min : (x > max ? max : x); \ } \ - public Text_t KindOfInt ## $format(c_type i, Int_t digits_int) { \ - return Text$format("%0*ld", Int32$from_int(digits_int, false), (int64_t)i); \ - } \ public Text_t KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \ Int_t as_int = Int$from_int64((int64_t)i); \ return Int$hex(as_int, digits_int, uppercase, prefix); \ @@ -685,10 +681,10 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty }, \ }; -DEFINE_INT_TYPE(int64_t, Int64, "%ld", INT64_MIN, INT64_MAX, __attribute__(())) -DEFINE_INT_TYPE(int32_t, Int32, "%d", INT32_MIN, INT32_MAX, CONSTFUNC) -DEFINE_INT_TYPE(int16_t, Int16, "%d", INT16_MIN, INT16_MAX, CONSTFUNC) -DEFINE_INT_TYPE(int8_t, Int8, "%d", INT8_MIN, INT8_MAX, CONSTFUNC) +DEFINE_INT_TYPE(int64_t, Int64, INT64_MIN, INT64_MAX, __attribute__(())) +DEFINE_INT_TYPE(int32_t, Int32, INT32_MIN, INT32_MAX, CONSTFUNC) +DEFINE_INT_TYPE(int16_t, Int16, INT16_MIN, INT16_MAX, CONSTFUNC) +DEFINE_INT_TYPE(int8_t, Int8, INT8_MIN, INT8_MAX, CONSTFUNC) #undef DEFINE_INT_TYPE // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
