fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

brdstr.c (2190B)


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