diff options
Diffstat (limited to 'src/base/io/readuntil.c')
-rw-r--r-- | src/base/io/readuntil.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/base/io/readuntil.c b/src/base/io/readuntil.c new file mode 100644 index 0000000..d5c2ed6 --- /dev/null +++ b/src/base/io/readuntil.c @@ -0,0 +1,65 @@ +#include "internal.h" + +void * +io·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->nread = 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->nread = 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) || j == 0){ + mem·move(io->e-i, io->b, i); + io->nread = +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->nread = j; + io->ilen = j - i; + return b; + } + b += j; + } + + io->nread = +io->cap; + io->ilen = -io->cap; + io->g = io->b; + return nil; +} |