skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

netstring_get.c (1385B)


      1 /* ISC license. */
      2 
      3 #include <errno.h>
      4 
      5 #include <skalibs/types.h>
      6 #include <skalibs/allreadwrite.h>
      7 #include <skalibs/bytestr.h>
      8 #include <skalibs/buffer.h>
      9 #include <skalibs/stralloc.h>
     10 #include <skalibs/netstring.h>
     11 #include <skalibs/posixishard.h>
     12 
     13 int netstring_okeof (buffer *b, size_t w)
     14 {
     15   return (errno == EPIPE) && !w && buffer_isempty(b) ? (errno = 0, 1) : 0 ;
     16 }
     17 
     18 int netstring_get (buffer *b, stralloc *sa, size_t *state)
     19 {
     20   if (!*state)
     21   {
     22     size_t n ;
     23     size_t len ;
     24     char buf[SIZE_FMT] ;
     25     if (b->c.a < SIZE_FMT+1) return (errno = EINVAL, -1) ;
     26     for (;;)
     27     {
     28       ssize_t r ;
     29       len = buffer_getnofill(b, buf, SIZE_FMT) ;
     30       n = byte_chr(buf, len, ':') ;  /* XXX: accepts :, as a valid netstring */
     31       if (n >= SIZE_FMT)
     32       {
     33         buffer_unget(b, len) ;
     34         return (errno = EPROTO, -1) ;
     35       }
     36       if (n < len) break ;
     37       buffer_unget(b, len) ;
     38       r = sanitize_read(buffer_fill(b)) ;
     39       if (r <= 0) return r ;
     40     }
     41     buffer_unget(b, len - n - 1) ;
     42     if (!n || n != size_scan(buf, &len)) return (errno = EPROTO, -1) ;
     43     if (!stralloc_readyplus(sa, len + 1)) return -1 ;
     44     *state = len + 1 ;
     45   }
     46   {
     47     size_t w = 0 ;
     48     int r = buffer_getall(b, sa->s + sa->len, *state, &w) ;
     49     sa->len += w ;
     50     *state -= w ;
     51     if (r <= 0) return r ;
     52   }
     53   return (sa->s[--sa->len] == ',') ? 1 : (errno = EPROTO, -1) ;
     54 }