shithub: mc

Download patch

ref: 770c90d4a5b16a5d598072b6983e50969151b166
parent: 5197866beb5ead9160183b6ada7a76244686f9f8
author: Carlin Bingham <cb@walcyrge.org>
date: Sat Mar 16 06:58:26 EDT 2019

bio.readto and EOF

Hi,

When using bio.readto I often want to be able to tell if the delimeter
was found, or if the file was truncated, but there doesn't appear to
be a way to tell if readto stopped searching because it found what it
was looking for or if it reached EOF, other than to do another read.

A simple solution to this would be a new function that reads to and
includes the delimeter in the returned slice if it was found, which can
be used intead when you care. I've tentatively included a patch for this.

Is this something that would be wanted? Is there a better solution? Or a
better name?

--
Carlin

NB. I've stolen the `Keep tag that was already there but apparently
never used. Not sure if it was intended for a higher purpose.

>From c230b380fbf0e7ba2c24aae332e4ce8016843d66 Mon Sep 17 00:00:00 2001
From: Carlin Bingham <cb@viennan.net>
Date: Sat, 16 Mar 2019 10:20:23 +1300
Subject: [PATCH] Add bio.readtoinc - read to including delimiter
X-Spam-Status: No, hits=0.000000 required=0.900000

Similar to bio.readto except it includes the delimeter in the returned
slice if it was found, making the absence of the delimiter indicate EOF

--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -28,6 +28,7 @@
 	/* delimited read; returns freshly allocated buffer. */
 	const readln	: (f : file#	-> std.result(byte[:], err))
 	const readto	: (f : file#, delim : byte[:]	-> std.result(byte[:], err))
+	const readtoinc	: (f: file#, delim : byte[:]	-> std.result(byte[:], err))
 	const skipto	: (f : file#, delim : byte[:]	-> bool)
 	const skipspace	: (f : file# -> bool)
 
@@ -327,6 +328,11 @@
 	-> readdelim(f, delim, `Read)
 }
 
+/* same as readto, but includes the delimiter if it was found */
+const readtoinc = {f, delim
+	-> readdelim(f, delim, `Keep)
+}
+
 /* same as readto, but drops the read data. */
 const skipto = {f, delim
 	match readdelim(f, delim, `Drop)
@@ -413,7 +419,7 @@
 			match mode
 			| `Drop:	f.rstart += f.rend - f.rstart
 			| `Read:	readinto(f, &ret, f.rend - f.rstart)
-			| `Keep:
+			| `Keep:	readinto(f, &ret, f.rend - f.rstart)
 			;;
 			match ret.len
 			| 0:	-> `std.Err `Eof
@@ -432,11 +438,14 @@
 			;;
 			/* If we found it, return that information */
 			match mode
-			| `Drop:	f.rstart = i
-			| `Read:	readinto(f, &ret, i - f.rstart)
-			| `Keep:	
+			| `Drop:
+				f.rstart = i + delim.len
+			| `Read:
+				readinto(f, &ret, i - f.rstart)
+				f.rstart += delim.len
+			| `Keep:
+				readinto(f, &ret, i + delim.len - f.rstart)
 			;;
-			f.rstart += delim.len
 			-> `std.Ok ret
 :nextiter
 		;;
@@ -443,7 +452,7 @@
 		match mode
 		| `Drop:	f.rstart = i
 		| `Read:	readinto(f, &ret, i - f.rstart)
-		| `Keep:
+		| `Keep:	readinto(f, &ret, i - f.rstart)
 		;;
 	;;
 	std.die("unreachable")
--- /dev/null
+++ b/lib/bio/test/bio-readtoinc.myr
@@ -1,0 +1,30 @@
+use std
+use bio
+
+const main = {
+	var f
+
+	f = std.try(bio.open("data/bio-readtoinc", bio.Rd))
+
+	readtoinc(f, ";")
+	readtoinc(f, "]]]")
+	readtoinc(f, "\n")
+	readtoinc(f, ",")
+	readtoinc(f, ",")
+	readtoinc(f, ",")
+	readtoinc(f, "the end")
+
+	bio.close(f)
+}
+
+const readtoinc = {f, d
+	match bio.readtoinc(f, d)
+	| `std.Ok s:
+		std.put("{}\n", s)
+		std.slfree(s)
+	| `std.Err `bio.Eof:
+		std.put("eof\n")
+	| `std.Err _:
+		std.put("err\n")
+	;;
+}
--- /dev/null
+++ b/lib/bio/test/data/bio-readtoinc
@@ -1,0 +1,2 @@
+data with semicolon;multiple delims]]]a new line
+data separated,with commas until,no more
--- /dev/null
+++ b/lib/bio/test/data/bio-readtoinc-expected
@@ -1,0 +1,9 @@
+data with semicolon;
+multiple delims]]]
+a new line
+
+data separated,
+with commas until,
+no more
+
+eof
--- a/lib/bio/test/tests
+++ b/lib/bio/test/tests
@@ -24,6 +24,7 @@
 B bio-read	C
 B bio-write	F	tmpout/test-write
 B bio-delim	C
+B bio-readtoinc	C
 B bio-endianwr	F	tmpout/test-endianwr
 B bio-endianrd	C
 B bio-unitwr	F	tmpout/test-unitwr