shithub: mc

Download patch

ref: 469769a5581ce0909cc3bec7fc59d8e71b9fe58b
parent: 0aa91dfcd722ba65c021038a54c38397d90106fd
author: Ori Bernstein <[email protected]>
date: Wed Dec 25 17:39:10 EST 2013

Handle EOF correctly for readln()

--- a/bio.myr
+++ b/bio.myr
@@ -49,8 +49,8 @@
 	const peekc	: (f : file# -> char)
 
 	/* delimited read; returns freshly allocated buffer. */
-	const readln	: (f : file#	-> byte[:])
-	const readto	: (f : file#, delim : byte[:]	-> byte[:])
+	const readln	: (f : file#	-> std.option(byte[:]))
+	const readto	: (f : file#, delim : byte[:]	-> std.option(byte[:]))
 
 	/* formatted i/o */
 	const put	: (f : file#, fmt : byte[:], args : ... -> std.size)
@@ -260,7 +260,7 @@
 	elif b & 0xf8 == 0xf0 	/* 0b1111_0xxx */
 		len = 4
 	else
-		-> false
+		len = 1		/* invalid unicode char */
 	;;
 	-> ensureread(f, len)
 }
@@ -361,7 +361,12 @@
 	ret = [][:]
 	while true
 		if !ensureread(f, delim.len)
-			-> readinto(f, ret, f.rend - f.rstart)
+			ret = readinto(f, ret, f.rend - f.rstart)
+			if ret.len > 0
+				-> `std.Some ret
+			else
+				-> `std.None
+			;;
 		;;
 		for i = f.rstart; i < f.rend; i++
 			if f.rbuf[i] == delim[0]
@@ -372,13 +377,13 @@
 				;;
 				ret = readinto(f, ret, i - f.rstart)
 				f.rstart += delim.len
-				-> ret
+				-> `std.Some ret
 			;;
 :nextiter
 		;;
 		ret = readinto(f, ret, i - f.rstart)
 	;;
-	-> ret
+	std.die("unreachable")
 }
 
 /* Same as readto, but the delimiter is always a '\n' */
--- a/test/bio-delim.myr
+++ b/test/bio-delim.myr
@@ -11,40 +11,60 @@
 	;;
 
 	/* read first line */
-	d = bio.readln(f)
+	d = readln(f)
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
 
 	/* read second line, should not include \n */
-	d = bio.readln(f)
+	d = readln(f)
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
 
 	/* read to ';' */
-	d = bio.readto(f, ";")
+	d = readto(f, ";")
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
 
 	/* read to ';'  again */
-	d = bio.readto(f, ";")
+	d = readto(f, ";")
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
 
 	/* '--'  this time */
-	d = bio.readto(f, "--")
+	d = readto(f, "--")
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
 
 	/* and without the terminator, we should get the remaining text */
-	d = bio.readto(f, "not-there")
+	d = readto(f, "not-there")
 	std.write(1, d)
 	std.write(1, "\n")
 	std.slfree(d)
+
+	/* and now, eof */
+	d = readln(f)
+	d = readto(f, "actually, eof")
 	
 	bio.close(f)
+}
+
+const readln = {f
+	match bio.readln(f)
+	| `std.Some d:	-> d
+	| `std.None:	std.put("eof\n")
+			-> [][:]
+	;;
+}
+
+const readto = {f, delim
+	match bio.readto(f, delim)
+	| `std.Some d:	-> d
+	| `std.None:	std.put("eof\n")
+			-> [][:]
+	;;
 }
--- a/test/data/bio-delim-expected
+++ b/test/data/bio-delim-expected
@@ -6,3 +6,5 @@
 and
 no-terminator
 
+eof
+eof