brdstr.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }