ref: e3ee0361d0918fbf3d92ef7c4123cf6b0d9265a7
parent: 11be53a01c3112de8fd6bcf81b306ee7c39a37ec
author: Ori Bernstein <[email protected]>
date: Wed Aug 7 12:21:17 EDT 2013
Add integer parsing, string comparisons, and zeroed allocations.
--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -6,6 +6,7 @@
die.myr \
extremum.myr \
fmt.myr \
+ intparse.myr \
optparse.myr \
rand.myr \
slappend.myr \
@@ -12,6 +13,7 @@
slcp.myr \
sleq.myr \
slurp.myr \
+ strcmp.myr \
sys.myr \
types.myr \
utf.myr \
--- a/libstd/alloc.myr
+++ b/libstd/alloc.myr
@@ -26,9 +26,11 @@
pkg std =
generic alloc : ( -> @a#)
+ generic zalloc : ( -> @a#)
generic free : (v:@a# -> void)
generic slalloc : (len : size -> @a[:])
+ generic slzalloc : (len : size -> @a[:])
generic slgrow : (sl : @a[:], len : size -> @a[:])
generic slfree : (sl : @a[:] -> void)
@@ -40,7 +42,7 @@
;;
/* null pointers. only used internally. */
-const Zbyte = 0 castto(byte#)
+const Zbyteptr = 0 castto(byte#)
const Zslab = 0 castto(slab#)
const Zchunk = 0 castto(chunk#)
@@ -76,6 +78,10 @@
-> bytealloc(sizeof(@a)) castto(@a#)
}
+generic zalloc = {-> @a#
+ -> zbytealloc(sizeof(@a)) castto(@a#)
+}
+
/* Frees a value of type @a */
generic free = {v:@a# -> void
bytefree(v castto(byte#), sizeof(@a))
@@ -83,12 +89,14 @@
/* allocates a slice of 'len' elements. */
generic slalloc = {len
- var p
+ -> (bytealloc(len*sizeof(@a)) castto(@a#))[0:len]
+}
- p = bytealloc(len*sizeof(@a)) castto(@a#)
- -> p[0:len]
+generic slzalloc = {len
+ -> (zbytealloc(len*sizeof(@a)) castto(@a#))[0:len]
}
+
/* Frees a slice */
generic slfree = {sl
bytefree(sl castto(byte#), sl.len * sizeof(@a))
@@ -124,6 +132,19 @@
;;
}
+const zbytealloc = {sz
+ var p
+ var sl
+ var i
+
+ p = bytealloc(sz)
+ sl = p[0:sz]
+ for i = 0; i < sl.len; i++
+ sl[i] = 0
+ ;;
+ -> p
+}
+
/* Allocates a blob that is 'sz' bytes long. Dies if the allocation fails */
const bytealloc = {sz
var i
@@ -140,7 +161,7 @@
bkt = &buckets[bktnum(sz)]
-> bktalloc(bkt)
else
- -> mmap(Zbyte, sz, Mprotrw, Mpriv | Manon, -1, 0)
+ -> mmap(Zbyteptr, sz, Mprotrw, Mpriv | Manon, -1, 0)
;;
}
@@ -185,7 +206,7 @@
cost us memory, and 64 bits of address space means that we're not
going to have issues with running out of address space for a
while. On a 32 bit system this would be a bad idea. */
- p = mmap(Zbyte, Slabsz*2, Mprotrw, Mpriv | Manon, -1, 0)
+ p = mmap(Zbyteptr, Slabsz*2, Mprotrw, Mpriv | Manon, -1, 0)
if p == Mapbad
die("Unable to mmap")
;;
--- /dev/null
+++ b/libstd/intparse.myr
@@ -1,0 +1,60 @@
+use "die.use"
+use "strcmp.use"
+use "types.use"
+use "utf.use"
+
+pkg std =
+ generic intparsebase : (s : byte[:], base : int -> @a::(tcint,tcnum,tctest))
+ generic intparse : (s : byte[:] -> @a::(tcint,tcnum,tctest))
+;;
+
+generic parseint = {s
+ if hasprefix(s, "0x")
+ -> parsebase(s[2:], 16)
+ elif hasprefix(s, "0o")
+ -> parsebase(s[2:], 8)
+ elif hasprefix(s, "0b")
+ -> parsebase(s[2:], 2)
+ else
+ -> parsebase(s[2:], 10)
+ ;;
+}
+
+
+generic charval = {c, base -> @a :: (tcint,tcnum,tctest)
+ var v = -1
+
+ if c >= '0' && c <= '9'
+ v = (c - '0') castto(@a::(tcint,tcnum,tctest))
+ elif c >= 'a' && c <= 'z'
+ v = (c - 'a') castto(@a::(tcint,tcnum,tctest))
+ elif c >= 'A' && c <= 'Z'
+ v = (c - 'A') castto(@a::(tcint,tcnum,tctest))
+ ;;
+
+ if v < 0 || v > (base castto(@a::(tcint,tcnum,tctest)))
+ die("Character out of range for base when parsing integer")
+ ;;
+ -> v
+}
+
+generic parsebase = {s, base -> @a::(tcint,tcnum,tctest)
+ var v : @a::(tcint,tcnum,tctest)
+ var c
+
+ assert(base <= 36, "Base for parsing values is too big")
+ v = 0
+ while s.len != 0
+ (c, s) = striter(s)
+ v *= base castto(@a::(tcint,tcnum,tctest))
+ v += charval(c, base)
+ ;;
+ -> v
+}
+
+const hasprefix = {s, pre
+ if strncmp(s, pre, pre.len) == `Equal
+ -> true
+ ;;
+}
+
--- /dev/null
+++ b/libstd/strcmp.myr
@@ -1,0 +1,48 @@
+use "extremum.use"
+use "types.use"
+
+pkg std =
+ type comparison
+
+ const strcmp : (a : byte[:], b : byte[:] -> comparison)
+ const strncmp : (a : byte[:], b : byte[:], n : size -> comparison)
+;;
+
+type comparison = union
+ `Equal
+ `Before
+ `After
+;;
+
+
+const strcmp = {a, b
+ var l
+ var i
+ var v
+
+ l = min(a.len, b.len)
+ for i = 0; i < l; i++
+ v = b[i] - a[i]
+ if v < 0
+ -> `Before
+ elif v < 0
+ -> `After
+ ;;
+ ;;
+
+ if a.len < b.len
+ -> `Before
+ elif a.len > b.len
+ -> `After
+ else
+ -> `Equal
+ ;;
+
+}
+
+const strncmp = {a, b, n
+ a = a[:min(a.len, n)]
+ b = b[:min(b.len, n)]
+ -> strcmp(a, b)
+}
+