ref: f42e53655e9a2a1b516326f6522fba88db59a81c
dir: /sys/src/libbio/brdstr.c/
#include <u.h> #include <libc.h> #include <bio.h> static char* badd(char *oldp, int *np, char *data, int ndata, int delim, int nulldelim) { int n; char *p; n = *np; p = realloc(oldp, n+ndata+1); if(p){ memmove(p+n, data, ndata); n += ndata; if(n>0 && nulldelim && p[n-1]==delim) p[--n] = '\0'; else p[n] = '\0'; *np = n; }else free(oldp); return p; } char* Brdstr(Biobufhdr *bp, int delim, int nulldelim) { char *ip, *ep, *p; int i, j; i = -bp->icount; bp->rdline = 0; if(i == 0) { /* * eof or other error */ if(bp->state != Bractive) { if(bp->state == Bracteof) bp->state = Bractive; bp->gbuf = bp->ebuf; return nil; } } /* * first try in remainder of buffer (gbuf doesn't change) */ ip = (char*)bp->ebuf - i; ep = memchr(ip, delim, i); if(ep) { j = (ep - ip) + 1; bp->icount += j; p = badd(nil, &bp->rdline, ip, j, delim, nulldelim); goto out; } /* * copy data to beginning of buffer */ if(i < bp->bsize) memmove(bp->bbuf, ip, i); bp->gbuf = bp->bbuf; /* * append to buffer looking for the delim */ p = nil; for(;;){ ip = (char*)bp->bbuf + i; while(i < bp->bsize) { j = bp->iof(bp, ip, bp->bsize-i); if(j < 0) Berror(bp, "read error: %r"); if(j <= 0 && i == 0) goto out; if(j <= 0 && i > 0){ /* * end of file but no delim. pretend we got a delim * by making the delim \0 and smashing it with nulldelim. */ j = 1; ep = ip; delim = '\0'; nulldelim = 1; *ep = delim; /* there will be room for this */ }else{ bp->offset += j; ep = memchr(ip, delim, j); } i += j; if(ep) { /* * found in new piece * copy back up and reset everything */ ip = (char*)bp->ebuf - i; if(i < bp->bsize){ memmove(ip, bp->bbuf, i); bp->gbuf = (uchar*)ip; } j = (ep - (char*)bp->bbuf) + 1; bp->icount = j - i; p = badd(p, &bp->rdline, ip, j, delim, nulldelim); goto out; } ip += j; } /* * full buffer without finding; add to user string and continue */ p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0); i = 0; bp->icount = 0; bp->gbuf = bp->ebuf; } out: setmalloctag(p, getcallerpc(&bp)); return p; }