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