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