]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libbio/brdstr.c
cc: fix wrong "useless or misleading comparison" warning
[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 *oldp, int *np, char *data, int ndata, int delim, int nulldelim)
7 {
8         int n;
9         char *p;
10
11         n = *np;
12         p = realloc(oldp, n+ndata+1);
13         if(p){
14                 memmove(p+n, data, ndata);
15                 n += ndata;
16                 if(n>0 && nulldelim && p[n-1]==delim)
17                         p[--n] = '\0';
18                 else
19                         p[n] = '\0';
20                 *np = n;
21         }else
22                 free(oldp);
23         return p;
24 }
25
26 char*
27 Brdstr(Biobufhdr *bp, int delim, int nulldelim)
28 {
29         char *ip, *ep, *p;
30         int i, j;
31
32         i = -bp->icount;
33         bp->rdline = 0;
34         if(i == 0) {
35                 /*
36                  * eof or other error
37                  */
38                 if(bp->state != Bractive) {
39                         if(bp->state == Bracteof)
40                                 bp->state = Bractive;
41                         bp->gbuf = bp->ebuf;
42                         return nil;
43                 }
44         }
45
46         /*
47          * first try in remainder of buffer (gbuf doesn't change)
48          */
49         ip = (char*)bp->ebuf - i;
50         ep = memchr(ip, delim, i);
51         if(ep) {
52                 j = (ep - ip) + 1;
53                 bp->icount += j;
54                 p = badd(nil, &bp->rdline, ip, j, delim, nulldelim);
55                 goto out;
56         }
57
58         /*
59          * copy data to beginning of buffer
60          */
61         if(i < bp->bsize)
62                 memmove(bp->bbuf, ip, i);
63         bp->gbuf = bp->bbuf;
64
65         /*
66          * append to buffer looking for the delim
67          */
68         p = nil;
69         for(;;){
70                 ip = (char*)bp->bbuf + i;
71                 while(i < bp->bsize) {
72                         j = bp->iof(bp, ip, bp->bsize-i);
73                         if(j < 0)
74                                 Berror(bp, "read error: %r");
75                         if(j <= 0 && i == 0)
76                                 goto out;
77                         if(j <= 0 && i > 0){
78                                 /*
79                                  * end of file but no delim. pretend we got a delim
80                                  * by making the delim \0 and smashing it with nulldelim.
81                                  */
82                                 j = 1;
83                                 ep = ip;
84                                 delim = '\0';
85                                 nulldelim = 1;
86                                 *ep = delim;    /* there will be room for this */
87                         }else{
88                                 bp->offset += j;
89                                 ep = memchr(ip, delim, j);
90                         }
91                         i += j;
92                         if(ep) {
93                                 /*
94                                  * found in new piece
95                                  * copy back up and reset everything
96                                  */
97                                 ip = (char*)bp->ebuf - i;
98                                 if(i < bp->bsize){
99                                         memmove(ip, bp->bbuf, i);
100                                         bp->gbuf = (uchar*)ip;
101                                 }
102                                 j = (ep - (char*)bp->bbuf) + 1;
103                                 bp->icount = j - i;
104                                 p = badd(p, &bp->rdline, ip, j, delim, nulldelim);
105                                 goto out;
106                         }
107                         ip += j;
108                 }
109         
110                 /*
111                  * full buffer without finding; add to user string and continue
112                  */
113                 p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
114                 i = 0;
115                 bp->icount = 0;
116                 bp->gbuf = bp->ebuf;
117         }
118 out:
119         setmalloctag(p, getcallerpc(&bp));
120         return p;
121 }