1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 static char*
badd(char * p,int * np,char * data,int ndata,int delim,int nulldelim)6 badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
7 {
8 int n;
9
10 n = *np;
11 p = realloc(p, n+ndata+1);
12 if(p){
13 memmove(p+n, data, ndata);
14 n += ndata;
15 if(n>0 && nulldelim && p[n-1]==delim)
16 p[--n] = '\0';
17 else
18 p[n] = '\0';
19 *np = n;
20 }
21 return p;
22 }
23
24 char*
Brdstr(Biobufhdr * bp,int delim,int nulldelim)25 Brdstr(Biobufhdr *bp, int delim, int nulldelim)
26 {
27 char *ip, *ep, *p;
28 int i, j;
29
30 i = -bp->icount;
31 bp->rdline = 0;
32 if(i == 0) {
33 /*
34 * eof or other error
35 */
36 if(bp->state != Bractive) {
37 if(bp->state == Bracteof)
38 bp->state = Bractive;
39 bp->gbuf = bp->ebuf;
40 return nil;
41 }
42 }
43
44 /*
45 * first try in remainder of buffer (gbuf doesn't change)
46 */
47 ip = (char*)bp->ebuf - i;
48 ep = memchr(ip, delim, i);
49 if(ep) {
50 j = (ep - ip) + 1;
51 bp->icount += j;
52 return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
53 }
54
55 /*
56 * copy data to beginning of buffer
57 */
58 if(i < bp->bsize)
59 memmove(bp->bbuf, ip, i);
60 bp->gbuf = bp->bbuf;
61
62 /*
63 * append to buffer looking for the delim
64 */
65 p = nil;
66 for(;;){
67 ip = (char*)bp->bbuf + i;
68 while(i < bp->bsize) {
69 j = read(bp->fid, ip, bp->bsize-i);
70 if(j <= 0 && i == 0)
71 return p;
72 if(j <= 0 && i > 0){
73 /*
74 * end of file but no delim. pretend we got a delim
75 * by making the delim \0 and smashing it with nulldelim.
76 */
77 j = 1;
78 ep = ip;
79 delim = '\0';
80 nulldelim = 1;
81 *ep = delim; /* there will be room for this */
82 }else{
83 bp->offset += j;
84 ep = memchr(ip, delim, j);
85 }
86 i += j;
87 if(ep) {
88 /*
89 * found in new piece
90 * copy back up and reset everything
91 */
92 ip = (char*)bp->ebuf - i;
93 if(i < bp->bsize){
94 memmove(ip, bp->bbuf, i);
95 bp->gbuf = (uchar*)ip;
96 }
97 j = (ep - (char*)bp->bbuf) + 1;
98 bp->icount = j - i;
99 return badd(p, &bp->rdline, ip, j, delim, nulldelim);
100 }
101 ip += j;
102 }
103
104 /*
105 * full buffer without finding; add to user string and continue
106 */
107 p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
108 i = 0;
109 bp->icount = 0;
110 bp->gbuf = bp->ebuf;
111 }
112 }
113