shithub: mc

Download patch

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)
+}
+