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