tbe.c - libeech - bittorrent library
 (HTM) git clone git://z3bra.org/libeech.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tbe.c (5594B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <ctype.h>
            3 #include <limits.h>
            4 #include <string.h>
            5 
            6 #include "be.h"
            7 
            8 #define MIN(a,b) ((a)<(b)?(a):(b))
            9 #define MAX(a,b) ((a)>(b)?(a):(b))
           10 
           11 int
           12 beinit(struct be *b, char *s, size_t l)
           13 {
           14         if (!b || !s || !l)
           15                 return -1;
           16 
           17         memset(b, 0, sizeof(*b));
           18         b->start = s;
           19         b->end = b->start + l - 1;
           20         b->off = b->start;
           21 
           22         return 0;
           23 }
           24 
           25 int
           26 beatol(char **str, long *l)
           27 {
           28         long s = 1;
           29         long v = 0;
           30         char *sp = *str;
           31 
           32         if (!sp)
           33                 return -1;
           34 
           35         /* define the sign of our number */
           36         if (*sp == '-') {
           37                 s = -1;
           38                 sp++;
           39                 /* -0 is invalid, even for "-03" */
           40                 if (*sp == '0')
           41                         return -1;
           42         }
           43 
           44         /* 0 followed by a number is considered invalid */
           45         if (sp[0] == '0' && isdigit(sp[1]))
           46                 return -1;
           47 
           48         /* read out number until next non-number, or end of string */
           49         while(isdigit(*sp)) {
           50                 v *= 10;
           51                 v += *sp++ - '0';
           52         }
           53 
           54         if (l)
           55                 *l = v * s;
           56 
           57         /* move initial pointer to the actual read data */
           58         *str = sp;
           59 
           60         return 0;
           61 }
           62 
           63 ssize_t
           64 beint(struct be *b, long *n)
           65 {
           66         char *sp;
           67         long num;
           68 
           69         if (!b)
           70                 return -1;
           71 
           72         sp = b->off;
           73 
           74         if (*(sp++) != 'i')
           75                 return -1;
           76 
           77         beatol(&sp, &num);
           78 
           79         if (*sp != 'e')
           80                 return -1;
           81 
           82         if (n)
           83                 *n = num;
           84 
           85         return sp - b->off + 1;
           86 }
           87 
           88 ssize_t
           89 bestr(struct be *b, char **s, size_t *l)
           90 {
           91         char *sp;
           92         ssize_t len;
           93 
           94         if (!b)
           95                 return -1;
           96 
           97         sp = b->off;
           98 
           99         if (beatol(&sp, &len) < 0)
          100                 return -1;
          101 
          102         if (len < 0 || *sp++ != ':')
          103                 return -1;
          104 
          105         if (s)
          106                 *s = sp;
          107 
          108         if (l)
          109                 *l = (size_t)len;
          110 
          111         return sp - b->off + len;
          112 }
          113 
          114 ssize_t
          115 belist(struct be *b, size_t *n)
          116 {
          117         size_t c = 0;
          118         struct be i;
          119 
          120         if (!b)
          121                 return -1;
          122 
          123         beinit(&i, b->off, b->end - b->off + 1);
          124 
          125         while(!belistover(&i)) {
          126                 belistnext(&i);
          127                 c++;
          128         }
          129 
          130         if (*i.off == 'e')
          131                 i.off++;
          132 
          133         if (n)
          134                 *n = c;
          135 
          136         return i.off - b->off;
          137 }
          138 
          139 ssize_t
          140 bedict(struct be *b, size_t *n)
          141 {
          142         size_t c = 0;
          143         struct be i;
          144 
          145         if (!b)
          146                 return -1;
          147 
          148         beinit(&i, b->off, b->end - b->off + 1);
          149 
          150         while(!belistover(&i)) {
          151                 bedictnext(&i, NULL, NULL, NULL);
          152                 c++;
          153         }
          154 
          155         if (*i.off == 'e')
          156                 i.off++;
          157 
          158         if (n)
          159                 *n = c;
          160 
          161         return i.off - b->off;
          162 }
          163 
          164 int
          165 belistover(struct be *b) {
          166         return b->off >= b->end || *b->off == 'e';
          167 }
          168 
          169 int
          170 belistnext(struct be *b)
          171 {
          172         if (!b || *b->off == 'e')
          173                 return -1;
          174 
          175         if (b->off == b->start && *b->off == 'l') {
          176                 b->off++;
          177                 return 0;
          178         }
          179 
          180         return !(benext(b) > 0);
          181 }
          182 
          183 int
          184 bedictnext(struct be *b, char **k, size_t *l, struct be *v)
          185 {
          186         if (!b || *b->off == 'e')
          187                 return -1;
          188 
          189         /* move to first element if we're at the start */
          190         if (b->off == b->start && *b->off == 'd')
          191                 b->off++;
          192 
          193         /* retrieve key name and length */
          194         if (bestr(b, k, l) < 0)
          195                 return -1;
          196 
          197         if (benext(b) > 0 && v)
          198                 beinit(v, b->off, b->end - b->off + 1);
          199 
          200         return !(benext(b) > 0);
          201 }
          202 
          203 ssize_t
          204 benext(struct be *b)
          205 {
          206         int r = 0;
          207 
          208         if (!b)
          209                 return -1;
          210 
          211         /* check for end of buffer */
          212         if (b->off >= b->end)
          213                 return -1;
          214 
          215         /* TODO: implement betype() */
          216         switch(betype(b)) {
          217         case 'i':
          218                 r = beint(b, NULL);
          219                 break;
          220         case 'l':
          221                 r = belist(b, NULL);
          222                 break;
          223         case 'd':
          224                 r = bedict(b, NULL);
          225                 break;
          226         case 's':
          227                 r = bestr(b, NULL, NULL);
          228                 break;
          229         }
          230 
          231         b->off += r;
          232 
          233         return r;
          234 }
          235 
          236 char
          237 betype(struct be *b)
          238 {
          239         switch(*b->off) {
          240         case 'i':
          241         case 'l':
          242         case 'd':
          243                 return *b->off;
          244                 break; /* NOTREACHED */
          245         }
          246         return isdigit(*b->off) ? 's' : 0;
          247 }
          248 
          249 int
          250 bekv(struct be *b, char *k, size_t l, struct be *v)
          251 {
          252         char *key = NULL;
          253         size_t klen = 0;
          254         struct be i;
          255 
          256         if (!b)
          257                 return -1;
          258 
          259         if (*b->off != 'd')
          260                 return -1;
          261 
          262         beinit(&i, b->off, b->end - b->off + 1);
          263 
          264         /* search the data 'till the end */
          265         while (!belistover(&i) && !bedictnext(&i, &key, &klen, v)) {
          266                 /* we found our key! */
          267                 if (!strncmp(k, key, MIN(l, klen)))
          268                         return 0;
          269 
          270                 /* recursive call to search inner dictionaries */
          271                 if (betype(&i) == 'd' && !bekv(&i, k, l, v))
          272                         return 0;
          273         }
          274 
          275         /* couldn't find anything, sorry */
          276         return -1;
          277 }
          278 
          279 int
          280 bepath(struct be *b, char **p, size_t l)
          281 {
          282         char *s;
          283         size_t r;
          284         struct be i;
          285 
          286         if (!b || betype(b) != 'l')
          287                 return -1;
          288 
          289         beinit(&i, b->off, b->end - b->off + 1);
          290 
          291         while(!belistnext(&i) && !belistover(&i)) {
          292                 if (!bestr(&i, &s, &r))
          293                         continue;
          294                 strncat(*p, "/", l);
          295                 strncat(*p, s, r);
          296         }
          297         return 0;
          298 }
          299 
          300 long
          301 bekint(struct be *b, char *k, size_t kl)
          302 {
          303         long n;
          304         struct be v;
          305 
          306         if (bekv(b, k, kl, &v) < 0)
          307                 return -1;
          308         if (beint(&v, &n) < 0)
          309                 return -1;
          310 
          311         return n;
          312 }
          313 
          314 int
          315 bekstr(struct be *b, char *k, size_t kl, struct be *s)
          316 {
          317         char *sp;
          318         size_t vl;
          319         struct be v;
          320 
          321         if (bekv(b, k, kl, &v) < 0)
          322                 return -1;
          323         if (bestr(&v, &sp, &vl) < 0)
          324                 return -1;
          325 
          326         if (s) {
          327                 s->start = v.start;
          328                 s->off = sp;
          329                 s->end = sp + vl;
          330         }
          331 
          332         return 0;
          333 }