aboutsummaryrefslogtreecommitdiff
path: root/src/base/bufio/readuntil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/bufio/readuntil.c')
-rw-r--r--src/base/bufio/readuntil.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/base/bufio/readuntil.c b/src/base/bufio/readuntil.c
new file mode 100644
index 0000000..8084cca
--- /dev/null
+++ b/src/base/bufio/readuntil.c
@@ -0,0 +1,64 @@
+#include "internal.h"
+
+void *
+bio·readuntil(io·Header *io, int delim)
+{
+ char *b, *e;
+ intptr i, j;
+
+ i = -io->ilen;
+ if(i==0){
+ if(io->state != io·BufRdr){
+ if(io->state == io·BufEnd)
+ io->state = io·BufRdr;
+ io->line = 0;
+ io->g = io->e;
+ return nil;
+ }
+ }
+
+ /* best case, we find it in the remaining bytes */
+ b = (char*)io->e - i;
+ if((e = mem·findc(b, i, delim)) != nil){
+ j = (e - b)+1;
+ io->line = j;
+ io->ilen += j;
+ return b;
+ }
+ /* ok no luck, shift over the data and get more */
+ if(i < io->cap)
+ mem·move(io->b, b, i);
+ io->g = io->b;
+ /* write to the buffer while we search for delim */
+ b = (char *)io->b + i;
+ while(i < io->cap){
+ if(sys·read(io->fd, io->cap-i, b, &j)){
+ mem·move(io->e-i, io->b, i);
+ io->line = +i;
+ io->ilen = -i;
+ io->g = io->e - i;
+ return 0;
+ }
+ io->pos += j;
+ i += j;
+ e = mem·findc(b, j, delim);
+ if(e!=nil){
+ /* finally have a hit. reset the world */
+ b = (char*)io->e - i;
+ if(i < io->cap){
+ mem·move(b, io->b, i);
+ io->g = (uchar *)b;
+ }
+ j = (e - (char*)io->b) + 1;
+ io->line = j;
+ io->ilen = j - i;
+ return b;
+ }
+ b += j;
+ }
+
+ io->line = +io->cap;
+ io->ilen = -io->cap;
+ io->g = io->b;
+ return 0;
+}