1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include "lib9.h"
#include <bio.h>
static char*
badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
{
int n;
n = *np;
p = realloc(p, 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;
}
return p;
}
char*
Brdstr(Biobuf *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;
return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
}
/*
* 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 = read(bp->fid, ip, bp->bsize-i);
if(j <= 0 && i == 0)
return p;
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 = (unsigned char*)ip;
}
j = (ep - (char*)bp->bbuf) + 1;
bp->icount = j - i;
return badd(p, &bp->rdline, ip, j, delim, nulldelim);
}
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;
}
return 0; /* never happens */
}
|