summaryrefslogtreecommitdiff
path: root/src/libstddjb/cdb_findnext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstddjb/cdb_findnext.c')
-rw-r--r--src/libstddjb/cdb_findnext.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/libstddjb/cdb_findnext.c b/src/libstddjb/cdb_findnext.c
new file mode 100644
index 0000000..6cd376c
--- /dev/null
+++ b/src/libstddjb/cdb_findnext.c
@@ -0,0 +1,57 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/cdb.h>
+#include "cdb-internal.h"
+
+int cdb_findnext (cdb const *c, cdb_data *out, char const *key, uint32_t len, cdb_find_state *d)
+{
+ if (!d->loop)
+ {
+ uint32_t u = cdb_hash(key, len) ;
+ char const *p = cdb_p(c, 8, (u << 3) & 2047) ;
+ if (!p) return -1 ;
+ uint32_unpack(p + 4, &d->hslots) ;
+ if (!d->hslots) return 0 ;
+ uint32_unpack(p, &d->hpos) ;
+ d->khash = u ;
+ u >>= 8 ;
+ u %= d->hslots ;
+ u <<= 3 ;
+ d->kpos = d->hpos + u ;
+ }
+
+ while (d->loop < d->hslots)
+ {
+ uint32_t pos, u ;
+ char const *p = cdb_p(c, 8, d->kpos) ;
+ if (!p) return -1 ;
+ uint32_unpack(p + 4, &pos) ;
+ if (!pos) return 0 ;
+ d->loop++ ;
+ d->kpos += 8 ;
+ if (d->kpos == d->hpos + (d->hslots << 3)) d->kpos = d->hpos ;
+ uint32_unpack(p, &u) ;
+ if (u == d->khash)
+ {
+ p = cdb_p(c, 8, pos) ;
+ if (!p) return -1 ;
+ uint32_unpack(p, &u) ;
+ if (u == len)
+ {
+ char const *k = cdb_p(c, len, pos + 8) ;
+ if (!k) return -1 ;
+ if (!memcmp(key, k, len))
+ {
+ uint32_unpack(p + 4, &out->len) ;
+ out->s = c->map + pos + 8 + len ;
+ return 1 ;
+ }
+ }
+ }
+ }
+ return 0 ;
+}