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