shithub: mc

Download patch

ref: 35bde60621ecf5cbcf07b743cafd9724f87faccb
parent: 7264545dc13abc231f1f5b386619990caec195b4
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Oct 3 22:51:57 EDT 2015

Fix handling '\r\n' with libbio.

--- /dev/null
+++ b/.gitattributes
@@ -1,0 +1,1 @@
+lib/bio/test/data/bio-delim-expected binary
--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -370,9 +370,39 @@
 	;;
 }
 
-/* Same as readto, but the delimiter is always a '\n' */
+/* Same as delim, but with special handling for '\n', '\r', and '\r\n' */
 const readln = {f
-	-> readto(f, "\n")
+	var ret, c, n
+
+	ret = [][:]
+	while true
+		/* get at least delimiter count of characters */
+		if !ensureread(f, 1)
+			ret = readinto(f, ret, f.rend - f.rstart)
+			if ret.len > 0
+				-> `std.Some ret
+			else
+				-> `std.None
+			;;
+		;;
+		/* scan for delimiter */
+		for var i = f.rstart; i < f.rend; i++
+			c = f.rbuf[i] castto(char)
+			if c == '\r' || c == '\n'
+				n = 1
+				/* if we have '\r', we can get '\r\n'. */
+				if c == '\r' && std.getv(peekc(f), -1) == '\n'
+					n = 2
+				;;
+				ret = readinto(f, ret, i - f.rstart)
+				f.rstart += n
+				-> `std.Some ret
+			;;
+:nextitergetln
+		;;
+		ret = readinto(f, ret, f.rend - f.rstart)
+	;;
+	std.die("unreachable")
 }
 
 const readdelim = {f, delim, drop
@@ -380,6 +410,7 @@
 
 	ret = [][:]
 	while true
+		/* get at least delimiter count of characters */
 		if !ensureread(f, delim.len)
 			if !drop
 				ret = readinto(f, ret, f.rend - f.rstart)
--- a/lib/bio/test/bio-delim.myr
+++ b/lib/bio/test/bio-delim.myr
@@ -22,6 +22,18 @@
 	std.write(1, "\n")
 	std.slfree(d)
 
+	/* read second line, should not include \r\n */
+	d = readln(f)
+	std.write(1, d)
+	std.write(1, "\n")
+	std.slfree(d)
+
+	/* read second line, should not include \r */
+	d = readln(f)
+	std.write(1, d)
+	std.write(1, "\n")
+	std.slfree(d)
+
 	/* read to ';' */
 	d = readto(f, ";")
 	std.write(1, d)
--- a/lib/bio/test/data/bio-delim-expected
+++ b/lib/bio/test/data/bio-delim-expected
@@ -1,5 +1,7 @@
 first line
 second line
+with-\r\n
+with-\r
 data with
 semicolons
 
--- a/lib/bio/test/data/lines
+++ b/lib/bio/test/data/lines
@@ -1,4 +1,5 @@
 first line
 second line
-data with;semicolons;
+with-\r\n
+with-\r
data with;semicolons;
 and--no-terminator