summaryrefslogtreecommitdiff
path: root/lib/std/intparse.myr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/intparse.myr')
-rw-r--r--lib/std/intparse.myr70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/std/intparse.myr b/lib/std/intparse.myr
new file mode 100644
index 0000000..4180f8c
--- /dev/null
+++ b/lib/std/intparse.myr
@@ -0,0 +1,70 @@
+use "chartype.use"
+use "die.use"
+use "hasprefix.use"
+use "option.use"
+use "types.use"
+use "utf.use"
+
+pkg std =
+ generic intparsebase : (s : byte[:], base : int -> option(@a::(integral,numeric)))
+ generic intparse : (s : byte[:] -> option(@a::(integral,numeric)))
+;;
+
+generic intparse = {s
+ var isneg
+
+ isneg = false
+ if hasprefix(s, "-")
+ s = s[1:]
+ isneg = true
+ ;;
+
+ if hasprefix(s, "0x")
+ -> doparse(s[2:], isneg, 16)
+ elif hasprefix(s, "0o")
+ -> doparse(s[2:], isneg, 8)
+ elif hasprefix(s, "0b")
+ -> doparse(s[2:], isneg, 2)
+ else
+ -> doparse(s, isneg, 10)
+ ;;
+}
+
+generic intparsebase = {s, base
+ var isneg
+
+ isneg = false
+ if hasprefix(s, "-")
+ s = s[1:]
+ isneg = true
+ ;;
+
+ -> doparse(s, isneg, base)
+}
+
+generic doparse = {s, isneg, base
+ var c
+ var v
+ var cv : int32
+
+ v = 0
+ while s.len != 0
+ (c, s) = striter(s)
+ if c == '_'
+ continue
+ ;;
+ cv = charval(c, base)
+ if cv >= 0
+ v *= (base castto(@a::(integral,numeric)))
+ v += cv castto(@a::(integral,numeric))
+ else
+ -> `None
+ ;;
+ ;;
+
+ if isneg
+ -> `Some -v
+ else
+ -> `Some v
+ ;;
+}