]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libbio/brdstr.c
merge
[plan9front.git] / sys / src / libbio / brdstr.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        <bio.h>
4
5 static char*
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*
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)
71                                 Berror(bp, "read error: %r");
72                         if(j <= 0 && i == 0)
73                                 return p;
74                         if(j <= 0 && i > 0){
75                                 /*
76                                  * end of file but no delim. pretend we got a delim
77                                  * by making the delim \0 and smashing it with nulldelim.
78                                  */
79                                 j = 1;
80                                 ep = ip;
81                                 delim = '\0';
82                                 nulldelim = 1;
83                                 *ep = delim;    /* there will be room for this */
84                         }else{
85                                 bp->offset += j;
86                                 ep = memchr(ip, delim, j);
87                         }
88                         i += j;
89                         if(ep) {
90                                 /*
91                                  * found in new piece
92                                  * copy back up and reset everything
93                                  */
94                                 ip = (char*)bp->ebuf - i;
95                                 if(i < bp->bsize){
96                                         memmove(ip, bp->bbuf, i);
97                                         bp->gbuf = (uchar*)ip;
98                                 }
99                                 j = (ep - (char*)bp->bbuf) + 1;
100                                 bp->icount = j - i;
101                                 return badd(p, &bp->rdline, ip, j, delim, nulldelim);
102                         }
103                         ip += j;
104                 }
105         
106                 /*
107                  * full buffer without finding; add to user string and continue
108                  */
109                 p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
110                 i = 0;
111                 bp->icount = 0;
112                 bp->gbuf = bp->ebuf;
113         }
114 }