shithub: mc

Download patch

ref: 34ce6323c60f83f3eba916f1198b86d36c395f52
parent: 3668e19263f2c0a17055eb6fc31c97b16617f32d
author: Ori Bernstein <[email protected]>
date: Wed Dec 25 16:16:02 EST 2013

Handle EOF correctly for get[bl]e()

--- a/bio.myr
+++ b/bio.myr
@@ -41,8 +41,8 @@
 	/* typed binary reads */
 	generic putbe	: (f : file#, v : @a::(tctest,tcnum,tcint) -> std.size)
 	generic putle	: (f : file#, v : @a::(tctest,tcnum,tcint) -> std.size)
-	generic getbe	: (f : file# -> @a::(tctest,tcnum,tcint))
-	generic getle	: (f : file# -> @a::(tctest,tcnum,tcint))
+	generic getbe	: (f : file# -> std.option(@a::(tctest,tcnum,tcint)))
+	generic getle	: (f : file# -> std.option(@a::(tctest,tcnum,tcint)))
 
 	/* peeking */
 	const peekb	: (f : file# -> byte)
@@ -292,17 +292,19 @@
   reads a single integer-like value to the output stream, in
   big endian format
 */
-generic getbe = {f -> @a::(tcnum,tcint,tctest)
+generic getbe = {f
 	var ret
 	var i
 
 	ret = 0
-	ensureread(f, sizeof(@a))
+	if !ensureread(f, sizeof(@a))
+		-> `std.None
+	;;
 	for i = 0; i < sizeof(@a); i++
 		ret <<= 8
 		ret |= (getb(f) castto(@a::(tcnum,tcint,tctest)))
 	;;
-	-> ret
+	-> `std.Some ret
 }
 
 /*
@@ -309,18 +311,20 @@
   reads a single integer-like value to the output stream, in
   little endian format
 */
-generic getle = {f -> @a::(tcnum,tcint,tctest)
+generic getle = {f
 	var ret
 	var b
 	var i
 
 	ret = 0
-	ensureread(f, sizeof(@a))
+	if !ensureread(f, sizeof(@a))
+		-> `std.None
+	;;
 	for i = 0; i < sizeof(@a); i++
 		b = getb(f) castto(@a::(tcnum,tcint,tctest))
 		ret = ret | (b << (8*i))
 	;;
-	-> ret
+	-> `std.Some ret
 }
 
 /* peeks a single byte from an input stream */
--- a/test/bio-endianrd.myr
+++ b/test/bio-endianrd.myr
@@ -1,6 +1,20 @@
 use std
 use bio
 
+generic getle = {fd -> @a::(tcint,tcnum,tctest)
+	match bio.getle(fd)
+	| `std.Some val:	-> val
+	| `std.None:	std.fatal(1, "read failed")
+	;;
+}
+
+generic getbe = {fd -> @a::(tcint,tcnum,tctest)
+	match bio.getbe(fd)
+	| `std.Some val:	-> val
+	| `std.None:	std.fatal(1, "read faibed")
+	;;
+}
+
 const main = {
 	var b : byte
 	var w : uint16
@@ -19,27 +33,33 @@
 	/* FIXME: compiler bug. multiplication on byte
 	   values is currently broken. */
 	b = 0xaa
-	std.assert(bio.getle(f) == b, "le byte broken\n")
-	std.assert(bio.getbe(f) == b, "be byte broken\n")
+	std.assert(getle(f) == b, "le byte broken\n")
+	std.assert(getbe(f) == b, "be byte broken\n")
 	*/
 
 	/* word */
 	w = 0xaabb
-	std.assert(bio.getle(f) == w, "le word broken\n")
-	std.assert(bio.getbe(f) == w, "be word broken\n")
+	std.assert(getle(f) == w, "le word broken\n")
+	std.assert(getbe(f) == w, "be word broken\n")
 
 	/* long */
 	l = 0xaabbccdd
-	std.assert(bio.getle(f) == l, "le long broken\n")
-	std.assert(bio.getbe(f) == l, "be long broken\n")
+	std.assert(getle(f) == l, "le long broken\n")
+	std.assert(getbe(f) == l, "be long broken\n")
 
 	/* quad */
 	q = 0x11223344aabbccdd castto(uint64)
-	std.assert(bio.getle(f) == q, "le quad broken\n")
-	std.assert(bio.getbe(f) == q, "be quad broken\n")
+	std.assert(getle(f) == q, "le quad broken\n")
+	std.assert(getbe(f) == q, "be quad broken\n")
 
-	/* and test for flush on close */
+	/* end of file */
+	match bio.getle(f)
+	| `std.None:
+	| `std.Some v:	std.die("read past end of file\n")
+	;;
+
 	bio.close(f);
 
 	std.put("success: all reads matched\n")
 }
+