9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

brdstr.c (2086B)


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