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 }