bigkv_fill.c (1893B)
1 /* ISC license. */ 2 3 #include <stdint.h> 4 #include <string.h> 5 #include <errno.h> 6 7 #include <skalibs/bytestr.h> 8 #include <skalibs/stralloc.h> 9 #include <skalibs/genalloc.h> 10 #include <skalibs/avltree.h> 11 #include <skalibs/bigkv.h> 12 13 static void *bigkv_dtok (uint32_t d, void *p) 14 { 15 bigkv *b = p ; 16 return b->storage.s + genalloc_s(bigkv_node, &b->nodes)[d].k ; 17 } 18 19 static int bigkv_cmp (void const *a, void const *b, void *p) 20 { 21 (void)p ; 22 return strcmp((char const *)a, (char const *)b) ; 23 } 24 25 int bigkv_fill (bigkv *b, char const *const *argv, char delim, char const *prefix, char const *stop, uint32_t options) 26 { 27 int i = 0 ; 28 size_t prefixlen = prefix ? strlen(prefix) : 0 ; 29 avltree_init(&b->map, 3, 3, 8, &bigkv_dtok, &bigkv_cmp, b) ; 30 for (; argv[i] && !(stop && !strcmp(argv[i], stop)) ; i++) 31 { 32 bigkv_node node = { .k = b->storage.len } ; 33 char const *s = argv[i] ; 34 size_t len = strlen(s) ; 35 size_t pos ; 36 int isdup ; 37 uint32_t d ; 38 if (prefixlen) 39 { 40 if (!strncmp(s, prefix, prefixlen)) return i+1 ; 41 s += prefixlen ; 42 len -= prefixlen ; 43 } 44 pos = byte_chr(s, len, delim) ; 45 if (!stralloc_catb(&b->storage, s, pos+1)) goto err ; 46 b->storage.s[pos] = 0 ; 47 isdup = avltree_search(&b->map, s, &d) ; 48 if (isdup) 49 { 50 if (options & BIGKV_OPTIONS_NODUP) goto invalid ; 51 b->storage.len = node.k ; 52 } 53 if (pos < len) 54 { 55 node.v = b->storage.len ; 56 if (!stralloc_catb(&b->storage, s + pos + 1, len - pos)) goto err ; 57 } 58 else node.v = b->storage.len - 1 ; 59 if (isdup) genalloc_s(bigkv_node, &b->nodes)[d].v = node.v ; 60 else 61 { 62 d = genalloc_len(bigkv_node, &b->nodes) ; 63 if (!genalloc_append(bigkv_node, &b->nodes, &node)) goto err ; 64 if (!avltree_insert(&b->map, d)) goto err ; 65 } 66 } 67 return i ; 68 69 invalid: 70 errno = EINVAL ; 71 err: 72 bigkv_free(b) ; 73 return -1 ; 74 }