summaryrefslogtreecommitdiff
path: root/src/config/repo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/config/repo.c')
-rw-r--r--src/config/repo.c114
1 files changed, 95 insertions, 19 deletions
diff --git a/src/config/repo.c b/src/config/repo.c
index 8ed8c51..bf847f1 100644
--- a/src/config/repo.c
+++ b/src/config/repo.c
@@ -3,44 +3,120 @@
#include <stdint.h>
#include <string.h>
+#include <skalibs/diuint32.h>
+#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/avltree.h>
+#include <skalibs/cdbmake.h>
#include "shibari-cache-config-internal.h"
-void *node_dtok (uint32_t d, void *data)
+static void *node_dtok (uint32_t d, void *aux)
{
- repo *r = data ;
- return r->storage->s + genalloc_s(node, &r->ga)[d].key ;
+ repo *rp = aux ;
+ return &genalloc_s(node, &rp->list)[d].key ;
}
-int node_cmp (void const *a, void const *b, void *data)
+static int node_cmp (void const *a, void const *b, void *aux)
{
- (void)data ;
- return strcmp((char const *)a, (char const *)b) ;
+ repo *rp = aux ;
+ diuint32 const *ka = a ;
+ diuint32 const *kb = b ;
+ if (ka->right < kb->right) return -1 ;
+ if (ka->right > kb->right) return 1 ;
+ return memcmp(rp->storage.s + ka->left, rp->storage.s + kb->left, ka->right) ;
}
-node const *repo_search (repo const *r, char const *key)
+void repo_init (repo *rp)
{
+ avltree_init(&rp->tree, 32, 3, 8, &node_dtok, &node_cmp, rp) ;
+}
+
+node *repo_search (repo *rp, char const *key, uint32_t keylen)
+{
+ diuint32 ukey = { .left = rp->storage.len, .right = keylen } ;
uint32_t i ;
- return avltree_search(&r->tree, key, &i) ? genalloc_s(node const, &r->ga) + i : 0 ;
+ if (!stralloc_catb(&rp->storage, key, keylen)) dienomem() ;
+ rp->storage.len = ukey.left ;
+ return avltree_search(&rp->tree, &ukey, &i) ? genalloc_s(node, &rp->list) + i : 0 ;
}
-void repo_add (repo *r, node const *nod)
+static int checkunique (memcmp_func_ref f, char const *ar, size_t arlen, char const *ele, size_t elelen)
{
- uint32_t i = genalloc_len(node, &r->ga) ;
- if (!genalloc_append(node, &r->ga, nod)) dienomem() ;
- if (!avltree_insert(&r->tree, i)) dienomem() ;
+ while (arlen >= elelen)
+ {
+ if (!(*f)(ar, ele, elelen)) return 0 ;
+ ar += elelen ;
+ arlen -= elelen ;
+ }
+ return 1 ;
}
-void repo_update (repo *r, node const *nod)
+void repo_add_new (repo *rp, char const *key, uint32_t keylen, char const *data, size_t datalen, uint32_t line, int accu)
{
- uint32_t i ;
- if (avltree_search(&r->tree, r->storage->s + nod->key, &i))
+ node *nod ;
+ uint32_t n = genalloc_len(node, &rp->list) ;
+ if (!genalloc_readyplus(node, &rp->list, 1)) dienomem() ;
+ nod = genalloc_s(node, &rp->list) + n ;
+ nod->key.left = rp->storage.len ;
+ nod->key.right = keylen ;
+ if (!stralloc_catb(&rp->storage, key, keylen)) dienomem() ;
+ nod->line = line ;
+ nod->data = stralloc_zero ;
+ if (accu)
+ {
+ if (!stralloc_catb(&nod->data, data, datalen)) dienomem() ;
+ }
+ else
+ {
+ nod->data.a = rp->storage.len ;
+ nod->data.len = datalen ;
+ if (rp->storage.len + datalen > UINT32_MAX) diestorage() ;
+ if (!stralloc_catb(&rp->storage, data, datalen)) dienomem() ;
+ }
+ genalloc_setlen(node, &rp->list, n + 1) ;
+ if (!avltree_insert(&rp->tree, n)) dienomem() ;
+}
+
+uint32_t repo_add (repo *rp, char const *key, uint32_t keylen, char const *data, size_t datalen, uint32_t line, int accu, memcmp_func_ref f)
+{
+ node *nod ;
+ if (keylen > UINT32_MAX || datalen > UINT32_MAX) diestorage() ;
+ nod = repo_search(rp, key, keylen) ;
+ if (nod)
{
- if (!avltree_delete(&r->tree, r->storage->s + nod->key)) dienomem() ;
- genalloc_s(node, &r->ga)[i] = *nod ;
- if (!avltree_insert(&r->tree, i)) dienomem() ;
+ if (!nod->data.s || !accu) return nod->line ;
+ if (f && !checkunique(f, nod->data.s, nod->data.len, data, datalen)) return nod->line ;
+ if (nod->data.len + datalen > UINT32_MAX) diestorage() ;
+ if (!stralloc_catb(&nod->data, data, datalen)) dienomem() ;
}
- else repo_add(r, nod) ;
+ else repo_add_new(rp, key, keylen, data, datalen, line, accu) ;
+ return 0 ;
+}
+
+static int node_write (cdbmaker *cm, node *nod, char const *s)
+{
+ return cdbmake_add(cm, s + nod->key.left, nod->key.right, nod->data.s ? nod->data.s : s + nod->data.a, nod->data.len) ;
+}
+
+int repo_write (cdbmaker *cm, repo const *rp)
+{
+ for (size_t i = 0 ; i < genalloc_len(node, &rp->list) ; i++)
+ if (!node_write(cm, genalloc_s(node, &rp->list) + i, rp->storage.s))
+ return 0 ;
+ return 1 ;
+}
+
+#if 0
+static void node_free (node *nod)
+{
+ if (nod->data.s) stralloc_free(&nod->data) ;
+}
+
+void repo_free (repo *rp)
+{
+ avltree_free(&rp->tree) ;
+ genalloc_deepfree(node, &rp->list, &node_free) ;
+ stralloc_free(&rp->storage) ;
}
+#endif