commit 95feeffe79767bb2b7a59948d8acffdfc18d9eb5
parent bdec75d3f4712d6db9ce28ecbd35e483d8b9f3e1
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 24 Jan 2021 13:16:56 -0500
strconv: new module
Diffstat:
4 files changed, 260 insertions(+), 0 deletions(-)
diff --git a/bytes/reverse.ha b/bytes/reverse.ha
@@ -0,0 +1,10 @@
+// Reverses a slice of bytes.
+export fn reverse(b: []u8) void = {
+ for (let s = 0z, e = len(b) - 1z; s < e) {
+ let x = b[s];
+ b[s] = b[e];
+ b[e] = x;
+ s += 1z;
+ e -= 1z;
+ };
+};
diff --git a/strconv/itos.ha b/strconv/itos.ha
@@ -0,0 +1,94 @@
+use bytes;
+use types;
+
+// Converts an i64 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::i64tos(1234);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::i64tos(1234);
+// let b = strconv::i64tos(4321);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn i64tos(i: i64) const str = {
+ static assert(types::I64_MAX == 9223372036854775807i64);
+ static let buf: [22]u8 = [0u8...]; // 20 chars plus NUL and -
+ buf = [0u8...];
+
+ let s = struct {
+ b: *[*]u8 = &buf,
+ l: size = 0z,
+ c: size = 0z,
+ };
+
+ const isneg = i < 0i64;
+ if (isneg) {
+ s.b[s.l] = '-': u32: u8;
+ s.l += 1z;
+ i = -i;
+ } else if (i == 0i64) {
+ s.b[s.l] = '0': u32: u8;
+ s.l += 1z;
+ };
+
+ for (i > 0i64) {
+ s.b[s.l] = '0': u32: u8 + (i % 10i64): u8;
+ s.l += 1z;
+ i /= 10i64;
+ };
+
+ const x: size = if (isneg) 1z else 0z;
+ bytes::reverse(s.b[x..s.l]);
+
+ s.b[s.l] = 0u8;
+ return *(&s: *str);
+};
+
+// Converts an i8 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::i8tos(123);
+// io::printf("%s", a); // 123
+//
+// let a = strconv::i8tos(123);
+// let b = strconv::i8tos(321);
+// io::printf("%s %s", a, b); // 321 321
+export fn i8tos(i: i8) const str = i64tos(i: i64);
+
+// Converts an i16 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::i16tos(1234);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::i16tos(1234);
+// let b = strconv::i16tos(4321);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn i16tos(i: i16) const str = i64tos(i: i64);
+
+// Converts an i32 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::i32tos(1234);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::i32tos(1234);
+// let b = strconv::i32tos(4321);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn i32tos(i: i32) const str = i64tos(i: i64);
+
+// Converts an int to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::itos(1234);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::itos(1234);
+// let b = strconv::itos(4321);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn itos(i: int) const str = i64tos(i: i64);
diff --git a/strconv/numeric.ha b/strconv/numeric.ha
@@ -0,0 +1,45 @@
+use types;
+
+// Converts any types::signed to a string in base 10. The return value is
+// statically allocated and will be overwritten on subsequent calls; see
+// [strings::dup] to duplicate the result, or [strconv::itosb] to pass your own
+// string buffer.
+//
+// let a = strconv::signedtos(123);
+// io::printf("%s", a); // 123
+//
+// let a = strconv::signedtos(123);
+// let b = strconv::signedtos(321);
+// io::printf("%s %s", a, b); // 321 321
+export fn signedtos(n: types::signed) const str = {
+ return match (n) {
+ i: int => itos(i),
+ i: i8 => i8tos(i),
+ i: i16 => i16tos(i),
+ i: i32 => i32tos(i),
+ i: i64 => i64tos(i),
+ };
+};
+
+// Converts any types::unsigned to a string in base 10. The return value is
+// statically allocated and will be overwritten on subsequent calls; see
+// [strings::dup] to duplicate the result, or [strconv::itosb] to pass your own
+// string buffer.
+//
+// let a = strconv::unsignedtos(123);
+// io::printf("%s", a); // 123
+//
+// let a = strconv::unsignedtos(123);
+// let b = strconv::unsignedtos(321);
+// io::printf("%s %s", a, b); // 321 321
+export fn unsignedtos(n: (...types::unsigned | uintptr)) const str = {
+ return match (n) {
+ u: size => ztos(u),
+ u: uint => utos(u),
+ u: uintptr => uptrtos(u),
+ u: u8 => u8tos(u),
+ u: u16 => u16tos(u),
+ u: u32 => u32tos(u),
+ u: u64 => u64tos(u),
+ };
+};
diff --git a/strconv/utos.ha b/strconv/utos.ha
@@ -0,0 +1,111 @@
+use bytes;
+use types;
+
+// Converts a u64 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::u64tos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::u64tos(1234u);
+// let b = strconv::u64tos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn u64tos(u: u64) const str = {
+ static assert(types::U64_MAX == 18446744073709551615u64);
+ static let buf: [21]u8 = [0u8...]; // 20 digits plus NUL
+ buf = [0u8...];
+
+ let s = struct {
+ b: *[*]u8 = &buf,
+ l: size = 0z,
+ c: size = 0z,
+ };
+
+ if (u == 0u64) {
+ s.b[s.l] = '0': u32: u8;
+ s.l += 1z;
+ };
+
+ for (u > 0u64) {
+ s.b[s.l] = '0': u32: u8 + (u % 10u64): u8;
+ s.l += 1z;
+ u /= 10u64;
+ };
+
+ bytes::reverse(s.b[..s.l]);
+ s.b[s.l] = 0u8;
+ return *(&s: *str);
+};
+
+// Converts a u8 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::u64tos(123u);
+// io::printf("%s", a); // 123
+//
+// let a = strconv::u64tos(123u);
+// let b = strconv::u64tos(321u);
+// io::printf("%s %s", a, b); // 321 321
+export fn u8tos(u: u8) const str = u64tos(u: u64);
+
+// Converts a u16 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::u16tos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::u16tos(1234u);
+// let b = strconv::u16tos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn u16tos(u: u16) const str = u64tos(u: u64);
+
+// Converts a u32 to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::u32tos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::u32tos(1234u);
+// let b = strconv::u32tos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn u32tos(u: u32) const str = u64tos(u: u64);
+
+// Converts a uint to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::utos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::utos(1234u);
+// let b = strconv::utos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn utos(u: uint) const str = u64tos(u: u64);
+
+// Converts a size to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::ztos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::ztos(1234u);
+// let b = strconv::ztos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn ztos(z: size) const str = u64tos(z: u64);
+
+// Converts a uintptr to a string, in base 10. The return value is statically
+// allocated and will be overwritten on subsequent calls; see [strings::dup] to
+// duplicate the result, or [strconv::itosb] to pass your own string buffer.
+//
+// let a = strconv::uptrtos(1234u);
+// io::printf("%s", a); // 1234
+//
+// let a = strconv::uptrtos(1234u);
+// let b = strconv::uptrtos(4321u);
+// io::printf("%s %s", a, b); // 4321 4321
+export fn uptrtos(uptr: uintptr) const str = u64tos(uptr: u64);