Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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