shithub: mc

Download patch

ref: b65a821ba2d8c753e974b02e541229dfd6754a6a
parent: 7596ee5f651a67a62de4b009d8647f5b2cf729fb
author: Ori Bernstein <[email protected]>
date: Mon Apr 20 16:27:37 EDT 2015

Add support for fixed size str buffers.

--- a/libstd/strbuf.myr
+++ b/libstd/strbuf.myr
@@ -14,6 +14,7 @@
 	;;
 
 	const mksb	: (-> strbuf#)
+	const mkbufsb	: (buf : byte[:] -> strbuf#)
 	const sbfin	: (sb : strbuf# -> byte[:])
 	const sbfree	: (sb : strbuf# -> void)
 	const sbpeek	: (sb : strbuf# -> byte[:])
@@ -21,24 +22,40 @@
 	const sbputc	: (sb : strbuf#, v : char -> bool)
 	const sbputs	: (sb : strbuf#, v : byte[:] -> bool)
 	const sbputb	: (sb : strbuf#, v : byte -> bool)
-	const sbtrim	: (sb : strbuf#, len : std.size -> void)
+	const sbtrim	: (sb : strbuf#, len : size -> void)
 ;;
 
-const mksb	= {
+const mksb = {
 	var sb
-	sb = std.zalloc()
-	sb.buf = std.slalloc(1)
+	sb = zalloc()
+	sb.buf = slalloc(1)
 	-> sb
 }
 
-const sbfin = {sb : strbuf#
+const mkbufsb = {buf
+	var sb
+	sb = zalloc()
+	sb.buf = buf
+	sb.fixed = true
+	-> sb
+}
+
+const sbfin = {sb
 	var sl
 
 	sl = sb.buf[:sb.len]
-	std.free(sb)
+	free(sb)
 	-> sl
 }
 
+const sbfree = {sb
+	if !sb.fixed
+		slfree(sb.buf)
+	;;
+	free(sb)
+}
+
+
 const sbpeek = {sb : strbuf#
 	-> sb.buf[:sb.len]
 }
@@ -51,12 +68,15 @@
 	-> true
 }
 const sbputs = {sb, v
-	if !ensure(sb, v.len)
-		-> false
-	;;
-	std.slcp(sb.buf[sb.len:sb.len + v.len], v)
-	sb.len += v.len
-	-> true
+	var ok
+	var len
+
+	ok = ensure(sb, v.len)
+	/* copy what we can */
+	len = min(sb.buf.len - sb.len, v.len)
+	slcp(sb.buf[sb.len:sb.len + len], v[:len])
+	sb.len += len
+	-> ok
 }
 const sbputb = {sb, v
 	if !ensure(sb, 1)
@@ -67,9 +87,9 @@
 }
 
 const sbtrim = {sb, len
-	std.assert(std.abs(len) <= sb.len, "trim out of range\n")
+	assert(abs(len) <= sb.len, "trim out of range\n")
 	if len < 0
-		sb.len -= std.abs(len)
+		sb.len -= abs(len)
 	else
 		sb.len = len
 	;;
@@ -76,7 +96,7 @@
 }
 
 const ensure = {sb, len
-	if sb.fixed && sb.len + len >= sb.buf.len
+	if sb.fixed && sb.len + len > sb.buf.len
 		-> false
 	;;
 	while sb.buf.len < sb.len + len
--- a/libstd/test/strbuf.myr
+++ b/libstd/test/strbuf.myr
@@ -2,6 +2,7 @@
 
 const main = {
 	var sb
+	var buf : byte[16]
 
 	sb = std.mksb()
 	std.assert(std.sleq(std.sbpeek(sb), ""), "mismatched empty str\n")
@@ -20,5 +21,20 @@
 	std.assert(std.sleq(std.sbpeek(sb), "hello, 世界"), "mismatched unicode\n")
 	std.sbputb(sb, 10)
 	std.assert(std.sleq(std.sbpeek(sb), "hello, 世界\n"), "mismatched byte\n")
+
+	sb = std.mkbufsb(buf[:])
+	std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 5 characters */
+	std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 10 characters */
+	std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 15 characters */
+	std.assert(!std.sbputs(sb, "hello"), "erronous success\n") /* 16 characters */
+	std.assert(std.sleq(std.sbpeek(sb), "hellohellohelloh"), "failed to copy as much as possible\n")
+	std.sbtrim(sb, -1)
+	std.assert(std.sleq(std.sbpeek(sb), "hellohellohello"), "failed rtrim\n")
+	std.sbputc(sb, '世')
+	std.assert(std.sleq(std.sbpeek(sb), "hellohellohello"), "modified overflowed putc\n")
+	std.sbtrim(sb, -2)
+	std.assert(std.sleq(std.sbpeek(sb), "hellohellohel"), "failed rtrim\n")
+	std.sbputc(sb, '世')
+	std.assert(std.sleq(std.sbpeek(sb), "hellohellohel世"), "failed to append with putc\n")
 }