From ce770045072b4173664b44bd486d6ee2dd543d69 Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 11 Dec 2017 18:00:14 +0100 Subject: [PATCH] Update SDB and initial use of MHT for xrefs (disabled by default) --- libr/anal/anal.c | 2 + libr/anal/fcn.c | 4 +- libr/anal/ref.c | 12 +++ libr/anal/xrefs.c | 131 ++++++++++++++++++++++++++- libr/core/disasm.c | 5 +- libr/include/r_anal.h | 6 ++ libr/include/sdb/mht.h | 47 ++++++++++ libr/include/sdb/sdb.h | 15 ++-- libr/util/sdb.mk | 1 + shlr/sdb/src/Makefile | 1 + shlr/sdb/src/mht.c | 197 +++++++++++++++++++++++++++++++++++++++++ shlr/sdb/src/mht.h | 47 ++++++++++ shlr/sdb/src/sdb.h | 15 ++-- shlr/sdb/src/types.h | 3 +- shlr/sdb/src/util.c | 6 ++ 15 files changed, 473 insertions(+), 19 deletions(-) create mode 100644 libr/include/sdb/mht.h create mode 100644 shlr/sdb/src/mht.c create mode 100644 shlr/sdb/src/mht.h diff --git a/libr/anal/anal.c b/libr/anal/anal.c index b33130f4cb..4a7902c431 100644 --- a/libr/anal/anal.c +++ b/libr/anal/anal.c @@ -80,6 +80,8 @@ R_API RAnal *r_anal_new() { anal->sdb_types = sdb_ns (anal->sdb, "types", 1); anal->sdb_cc = sdb_ns (anal->sdb, "cc", 1); anal->sdb_zigns = sdb_ns (anal->sdb, "zigns", 1); + anal->mht_refs = mht_new (32, mht_free); + anal->mht_xrefs = mht_new (32, mht_free); anal->cb_printf = (PrintfCallback) printf; (void)r_anal_pin_init (anal); (void)r_anal_xrefs_init (anal); diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index e96b68e306..51f7e6b770 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -163,7 +163,7 @@ static bool refExists(RList *refs, RAnalRef *ref) { RAnalRef *r; RListIter *iter; r_list_foreach (refs, iter, r) { - if (r->at == ref->at && ref->addr == r->addr) { + if (r && r->at == ref->at && ref->addr == r->addr) { r->type = ref->type; return true; } @@ -184,9 +184,11 @@ R_API int r_anal_fcn_xref_add(RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr, return false; } // set global reference +// r_cons_printf ("C 0x%llx 0x%llx\n", at, addr); r_anal_xrefs_set (a, type, at, addr); // set per-function reference #if FCN_OLD +// TOO OLD we shouldnt be storing this.. or we do? ref->at = at; // from ref->addr = addr; // to ref->type = type; diff --git a/libr/anal/ref.c b/libr/anal/ref.c index 8ef4fb9cf8..05108d2b37 100644 --- a/libr/anal/ref.c +++ b/libr/anal/ref.c @@ -47,11 +47,23 @@ R_API const char *r_anal_ref_to_string(RAnal *anal, int type) { } R_API int r_anal_ref_del(RAnal *anal, ut64 from, ut64 to) { +#if USE_MHT +// TODO Must delete from mht_refs too + mht *m = anal->mht_xrefs; + mhtkv *kv = mht_getr (m, from); + if (kv) { + mht *ht = kv->u; + if (ht) { + mht_del (ht, to); + } + } +#else r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_NULL, from, to); r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CODE, from, to); r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CALL, from, to); r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_DATA, from, to); r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_STRING, from, to); +#endif return true; } diff --git a/libr/anal/xrefs.c b/libr/anal/xrefs.c index b870073ccc..b5cfeac99a 100644 --- a/libr/anal/xrefs.c +++ b/libr/anal/xrefs.c @@ -36,6 +36,84 @@ R_API bool r_anal_xrefs_save(RAnal *anal, const char *prjDir) { return sdb_sync (anal->sdb_xrefs); } +#if USE_MHT + +static void mylistrefs(mht *m, ut64 addr, RList *list) { + int i, j; + for (i = 0; i < m->size; i++) { + mhtkv *kv = m->table[i]; + if (!kv) continue; + while (kv->k != MHTNO) { + if (addr == UT64_MAX || addr == kv->k) { + RAnalRef *ref = r_anal_ref_new (); + if (ref) { +#if 0 + eprintf ("%s 0x%08llx -> 0x%08llx (0x%llx)\n", + kv->u, kv->k, kv->v, addr); +#endif + ref->at = kv->k; + ref->addr = kv->v; + ref->type = kv->u ? *((char *)kv->u): 0; + r_list_append (list, ref); + } + } + kv++; + } + } +} + +static void listrefs(mht *m, ut64 addr, RList *list) { + int i; + if (addr == UT64_MAX) { + for (i = 0; i < m->size; i++) { + mhtkv *kv = m->table[i]; + if (kv) { + mht *ht = kv->u; + while (kv->k != MHTNO) { + mylistrefs (ht, UT64_MAX, list); + kv++; + } + } + } + } else { + mht *ht = mht_getu (m, addr); + if (!ht) { + return; + } + mylistrefs (ht, addr, list); + } +} + +// [from=[from:to,],] +// 10->20 +static void setref(mht *m, ut64 from, ut64 to, int type) { + mhtkv *kv = mht_getr (m, from); + mht *ht = NULL; + if (kv) { + ht = kv->u; + } else { + ht = R_NEW0 (mht); + if (ht) { + mht_init (ht, 9, mht_free); + mht_set (m, from, to, ht); + } + } + if (ht) { + mht_set (ht, from, to, r_anal_xrefs_type_tostring (type)); + } +} + +static void delref(mht *m, ut64 from, ut64 to, int type) { + mhtkv *kv = mht_getr (m, from); + if (kv) { + mht *ht = kv->u; + if (ht) { + mht_del (ht, to); + } + } +} +#endif + R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) { char key[33]; if (!anal || !DB) { @@ -45,13 +123,26 @@ R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut6 return false; } // unknown refs should not be stored. seems wrong +#if 0 if (type == R_ANAL_REF_TYPE_NULL) { return false; } +#endif +#if USE_MHT + // setref (anal->mht_refs, from, to, type); + setref (anal->mht_xrefs, to, from, type); +// setref (anal->mht_xrefs, from, to, type); +// setref (anal->mht_refs, to, from, type); +// eprintf ("set %llx %llx %p\n", from , to, mht_getr(anal->mht_refs, from)); + // mht_getu(m, from, checkType, "ref"); +#else XREFKEY (key, sizeof (key), "ref", type, from); sdb_array_add_num (DB, key, to, 0); + XREFKEY (key, sizeof (key), "xref", type, to); sdb_array_add_num (DB, key, from, 0); +#endif + return true; } @@ -60,10 +151,15 @@ R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut if (!anal || !DB) { return false; } +#if USE_MHT + delref (anal->mht_refs, from, to, type); + delref (anal->mht_xrefs, to, from, type); +#else XREFKEY (key, sizeof (key), "ref", type, from); sdb_array_remove_num (DB, key, to, 0); XREFKEY (key, sizeof (key), "xref", type, to); sdb_array_remove_num (DB, key, from, 0); +#endif return true; } @@ -120,11 +216,18 @@ R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) { if (!list) { return NULL; } +#if USE_MHT + listrefs (anal->mht_refs, to, list); +// XXX, one or the other? + listrefs (anal->mht_xrefs, to, list); + // listrefs (anal->mht_xrefs, to, list); +#else r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_NULL, to); r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CODE, to); r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CALL, to); r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_DATA, to); r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_STRING, to); +#endif if (r_list_empty (list)) { r_list_free (list); list = NULL; @@ -137,11 +240,17 @@ R_API RList *r_anal_refs_get (RAnal *anal, ut64 from) { if (!list) { return NULL; } +#if USE_MHT + listrefs (anal->mht_refs, from, list); + listrefs (anal->mht_xrefs, from, list); +// eprintf ("refs_get from %llx %d\n", from, r_list_length (list)); +#else r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, from); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, from); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, from); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, from); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, from); +#endif if (r_list_empty (list)) { r_list_free (list); list = NULL; @@ -155,15 +264,20 @@ R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) { return NULL; } list->free = NULL; // XXX +#if USE_MHT + listrefs (anal->mht_xrefs, to, list); + listrefs (anal->mht_refs, to, list); +#else r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, to); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, to); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, to); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, to); r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, to); - if (r_list_length (list)<1) { + if (r_list_empty (list)) { r_list_free (list); list = NULL; } +#endif return list; } @@ -289,6 +403,17 @@ static int xrefs_list_cb_plain(RAnal *anal, const char *k, const char *v) { } R_API void r_anal_xrefs_list(RAnal *anal, int rad) { +#if USE_MHT + RListIter *iter; + RAnalRef *ref; + RList *list = r_list_new(); + listrefs (anal->mht_xrefs, UT64_MAX, list); + r_list_foreach (list, iter, ref) { + int type = ref->type? ref->type: ' '; + r_cons_printf ("%c 0x%08llx -> 0x%08llx\n", type, ref->at, ref->addr); + } + r_list_free (list); +#else switch (rad) { case 1: case '*': @@ -318,6 +443,7 @@ R_API void r_anal_xrefs_list(RAnal *anal, int rad) { sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal); break; } +#endif } R_API const char *r_anal_xrefs_type_tostring (char type) { @@ -342,8 +468,9 @@ typedef struct { } CountState; static int countcb(CountState *cs, const char *k, const char *v) { - if (!strncmp (k, "ref.", 4)) + if (!strncmp (k, "ref.", 4)) { cs->count ++; + } return 1; } diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 7ef5669d5a..1eda82beda 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -1077,7 +1077,6 @@ static void ds_show_refs(RDisasmState *ds) { } static void ds_show_xrefs(RDisasmState *ds) { - RList *xrefs; RAnalRef *refi; RListIter *iter; RCore *core = ds->core; @@ -1089,7 +1088,7 @@ static void ds_show_xrefs(RDisasmState *ds) { return; } /* show xrefs */ - xrefs = r_anal_xref_get (core->anal, ds->at); + RList *xrefs = r_anal_xref_get (core->anal, ds->at); if (!xrefs) { return; } @@ -1148,6 +1147,8 @@ static void ds_show_xrefs(RDisasmState *ds) { refi->addr, name, COLOR_RESET (ds)); ds_newline (ds); R_FREE (name); + } else { + eprintf ("Corrupted database?\n"); } } r_list_free (xrefs); diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 88ab67f7d0..cc33443e10 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -3,6 +3,8 @@ #ifndef R2_ANAL_H #define R2_ANAL_H +#define USE_MHT 0 + /* use sdb function storage */ #define FCN_SDB 1 /* use old refs and function storage */ @@ -630,6 +632,10 @@ typedef struct r_anal_t { Sdb *sdb_types; Sdb *sdb_meta; // TODO: Future r_meta api Sdb *sdb_zigns; + + mht *mht_refs; + mht *mht_xrefs; + RSpaces meta_spaces; RSpaces zign_spaces; char *zign_path; diff --git a/libr/include/sdb/mht.h b/libr/include/sdb/mht.h new file mode 100644 index 0000000000..e784a8c038 --- /dev/null +++ b/libr/include/sdb/mht.h @@ -0,0 +1,47 @@ + +#define MHTSZ 32 +#define MHTNO 0 + +typedef ut64 mhti; + +typedef struct { + mhti k; + mhti v; + void *u; +#if 0 + // unaligned + // on 32bits + void *pad; + // on 64bits + void *pad; +#endif +} mhtkv; + +// 4 + 4 + 4 = 12 .. missing 4 more +// 8 + 8 + 4 = 20 .. missing 16, what about 32 ? +// 8 + 8 + 8 = 24 .. still not there, missing 8 +// 4 + 4 + 8 = 16 .. lgtm + +typedef void (*mht_freecb)(void *); + +typedef struct { + void **table; //[MHTSZ]; + mht_freecb f; + ut32 size; +} mht; + +typedef mht SdbMini; + +mht *mht_new(ut32 size, mht_freecb f); +void mht_free(mht*); +void mht_init(mht *m, ut32, mht_freecb f); +void mht_fini(mht *m); +mhti mht_hash(const char *s); +bool mht_set(mht *m, mhti k, mhti v, void *u); +mhtkv *mht_getr(mht *m, mhti k); +mhtkv *mht_getr(mht *m, mhti k); +mhti mht_get(mht *m, mhti k); +mhti mht_get(mht *m, mhti k); +void *mht_getu(mht *m, mhti k); +bool mht_add(mht *m, mhti k, mhti v, void *u); +bool mht_del(mht *m, mhti k); diff --git a/libr/include/sdb/sdb.h b/libr/include/sdb/sdb.h index 42e01bb835..e7254dc698 100644 --- a/libr/include/sdb/sdb.h +++ b/libr/include/sdb/sdb.h @@ -12,6 +12,7 @@ extern "C" { #include "types.h" #include "sdbht.h" #include "ls.h" +#include "mht.h" #include "cdb.h" #include "cdb_make.h" #include "sdb_version.h" @@ -100,6 +101,7 @@ typedef struct sdb_t { SdbKv tmpkv; ut32 depth; bool timestamped; + SdbMini mht; } Sdb; typedef struct sdb_ns_t { @@ -209,12 +211,13 @@ SDB_API int sdb_unlink(Sdb* s); SDB_API int sdb_lock_wait(const char *s UNUSED); /* expiration */ -bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas); -ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas); -ut64 sdb_now(void); -ut64 sdb_unow(void); -ut32 sdb_hash(const char *key); -ut32 sdb_hash_len(const char *key, ut32 *len); +SDB_API bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas); +SDB_API ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas); +SDB_API ut64 sdb_now(void); +SDB_API ut64 sdb_unow(void); +SDB_API ut32 sdb_hash(const char *key); +SDB_API ut32 sdb_hash_len(const char *key, ut32 *len); +SDB_API ut8 sdb_hash_byte(const char *s); /* json api */ SDB_API bool sdb_isjson(const char *k); diff --git a/libr/util/sdb.mk b/libr/util/sdb.mk index d5b2cb37d9..1789fda9ca 100644 --- a/libr/util/sdb.mk +++ b/libr/util/sdb.mk @@ -16,6 +16,7 @@ SDB_OBJS+=query.o SDB_OBJS+=sdb.o SDB_OBJS+=base64.o SDB_OBJS+=disk.o +SDB_OBJS+=mht.o SDB_OBJS+=array.o SDB_OBJS+=fmt.o SDB_OBJS+=match.o diff --git a/shlr/sdb/src/Makefile b/shlr/sdb/src/Makefile index a996afdccc..f66f4ffe78 100644 --- a/shlr/sdb/src/Makefile +++ b/shlr/sdb/src/Makefile @@ -3,6 +3,7 @@ include ../config.mk CFLAGS+=-g OBJ=cdb.o buffer.o cdb_make.o ls.o sdbht.o ht.o sdb.o num.o base64.o match.o OBJ+=json.o ns.o lock.o util.o disk.o query.o array.o fmt.o journal.o +OBJ+=mht.o SOBJ=$(subst .o,.o.o,${OBJ}) diff --git a/shlr/sdb/src/mht.c b/shlr/sdb/src/mht.c new file mode 100644 index 0000000000..805af773f3 --- /dev/null +++ b/shlr/sdb/src/mht.c @@ -0,0 +1,197 @@ +/* sdb - MIT - Copyright 2017 - pancake */ + +#include +#include +#include +#include "sdb.h" + +mht *mht_new(ut32 size, mht_freecb f) { + mht *m = calloc(1, sizeof (mht)); + mht_init (m, size, f); + return m; +} + +void mht_init(mht *m, ut32 size, mht_freecb f) { + if (m) { + memset(m, 0, sizeof (mht)); + if (size > 0) { + m->table = calloc (size, sizeof (mhtkv)); + m->size = size; + } + m->f = f; + } +} + +void mht_fini(mht *m) { + ut32 i; + if (m) { + if (m->f) { + for (i = 0; i < m->size; i++) { + mhtkv *kv = m->table[i]; + if (kv) { + while (kv->k != MHTNO) { + m->f(kv->u); + kv++; + } + } + free (m->table[i]); + } + } else { + for (i = 0; i < m->size; i++) { + free (m->table[i]); + } + } + free (m->table); + mht_init(m, 0, NULL); + } +} + +void mht_free(mht *m) { + mht_fini(m); + free (m); +} + +mhti mht_hash(const char *s) { + return (mhti)sdb_hash(s); +} + +bool mht_set(mht *m, mhti k, mhti v, void *u) { + if (!m || !m->size || k == MHTNO) { + return false; + } + const int bucket = k % m->size; + mhtkv *kv = m->table[bucket]; + if (!kv) { + kv = calloc (sizeof(mhtkv), 2); + if (kv) { + m->table[bucket] = kv; + kv->k = MHTNO; + kv->v = MHTNO; + kv->u = NULL; + return mht_set(m, k, v, u); + } + return false; + } + mhtkv *tmp = kv; + while (kv->k != MHTNO) { + if (kv->k == k) { + kv->v = v; + kv->u = u; + return true; + } + kv++; + } + int cursz = (kv - tmp); + int curln = cursz / sizeof(mhtkv); + mhtkv *newkv = realloc(tmp, (curln + 2) * sizeof(mhtkv)); + if (newkv) { + kv = m->table[bucket] = newkv; + kv += curln; + kv->k = k; + kv->v = v; + kv->u = u; + kv++; + kv->k = MHTNO; + kv->v = MHTNO; + kv->u = NULL; + return false; + } + return true; +} + +mhtkv *mht_getr(mht *m, mhti k) { + int bucket = k % m->size; + mhtkv *kv = m->table[bucket]; + if (kv) { + while (kv->k != MHTNO) { + if (kv->k == k) { + return kv; + } + kv++; + } + } + return NULL; +} + +mhti mht_get(mht *m, mhti k) { + mhtkv *kv = mht_getr(m, k); + return kv? kv->v: MHTNO; +} + +void *mht_getu(mht *m, mhti k) { + mhtkv *kv = mht_getr(m, k); + return kv? kv->u: NULL; +} + +bool mht_add(mht *m, mhti k, mhti v, void *u) { + return mht_getr(m, k) + ? mht_set(m, k, v, u) + : false; +} + +bool mht_del(mht *m, mhti k) { + int bucket = k % m->size; + if (k == MHTNO) { + return false; + } + mhtkv *kv = m->table[bucket]; + if (kv) { + while (kv->k != MHTNO) { + if (kv->k == k) { + if (m->f) { + m->f (kv->u); + } + mhtkv *n = kv + 1; + while (n->k != MHTNO) { + *kv++ = *n++; + } + kv->k = MHTNO; + return true; + } + kv++; + } + } + return false; +} + +#if 0 +static char *mht_str(mht *m, mhti k) { + // walk all buckets and print the data..... we need a printer for kv->u + char *res = malloc (1024); + int bucket = k % m->size; + mhti *kv = m->table[bucket]; + char *p = res; + for (i = 0; i < 1024; i++) { + sprintf (p, "%s%lld", comma, kv->v); + p += strlen (p); + kv++; + } + return res; +} + +static char *mht_str(mht *m) { + char *res = malloc (1024); + int bucket = k % m->size; + mhti *kv = m->table[bucket]; + int i; + char *p = res; + for (i = 0; i < m->size; i++) { + sprintf (p, "%s%lld", comma, kv->v); + p += strlen (p); + kv++; + } + return res; +} + +int main() { + mht m; + mht_init(&m, 32, free); + mht_set(&m, mht_hash("username"), 1024, NULL); + mht_set(&m, 32, 212, strdup("test")); + mht_del(&m, mht_hash("username")); + printf ("%d\n", (int)mht_get(&m, mht_hash("username"))); + printf ("%s\n", mht_getu(&m, 32)); //mht_hash("username"))); + mht_fini(&m); + return 0; +} +#endif diff --git a/shlr/sdb/src/mht.h b/shlr/sdb/src/mht.h new file mode 100644 index 0000000000..e784a8c038 --- /dev/null +++ b/shlr/sdb/src/mht.h @@ -0,0 +1,47 @@ + +#define MHTSZ 32 +#define MHTNO 0 + +typedef ut64 mhti; + +typedef struct { + mhti k; + mhti v; + void *u; +#if 0 + // unaligned + // on 32bits + void *pad; + // on 64bits + void *pad; +#endif +} mhtkv; + +// 4 + 4 + 4 = 12 .. missing 4 more +// 8 + 8 + 4 = 20 .. missing 16, what about 32 ? +// 8 + 8 + 8 = 24 .. still not there, missing 8 +// 4 + 4 + 8 = 16 .. lgtm + +typedef void (*mht_freecb)(void *); + +typedef struct { + void **table; //[MHTSZ]; + mht_freecb f; + ut32 size; +} mht; + +typedef mht SdbMini; + +mht *mht_new(ut32 size, mht_freecb f); +void mht_free(mht*); +void mht_init(mht *m, ut32, mht_freecb f); +void mht_fini(mht *m); +mhti mht_hash(const char *s); +bool mht_set(mht *m, mhti k, mhti v, void *u); +mhtkv *mht_getr(mht *m, mhti k); +mhtkv *mht_getr(mht *m, mhti k); +mhti mht_get(mht *m, mhti k); +mhti mht_get(mht *m, mhti k); +void *mht_getu(mht *m, mhti k); +bool mht_add(mht *m, mhti k, mhti v, void *u); +bool mht_del(mht *m, mhti k); diff --git a/shlr/sdb/src/sdb.h b/shlr/sdb/src/sdb.h index 42e01bb835..e7254dc698 100644 --- a/shlr/sdb/src/sdb.h +++ b/shlr/sdb/src/sdb.h @@ -12,6 +12,7 @@ extern "C" { #include "types.h" #include "sdbht.h" #include "ls.h" +#include "mht.h" #include "cdb.h" #include "cdb_make.h" #include "sdb_version.h" @@ -100,6 +101,7 @@ typedef struct sdb_t { SdbKv tmpkv; ut32 depth; bool timestamped; + SdbMini mht; } Sdb; typedef struct sdb_ns_t { @@ -209,12 +211,13 @@ SDB_API int sdb_unlink(Sdb* s); SDB_API int sdb_lock_wait(const char *s UNUSED); /* expiration */ -bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas); -ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas); -ut64 sdb_now(void); -ut64 sdb_unow(void); -ut32 sdb_hash(const char *key); -ut32 sdb_hash_len(const char *key, ut32 *len); +SDB_API bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas); +SDB_API ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas); +SDB_API ut64 sdb_now(void); +SDB_API ut64 sdb_unow(void); +SDB_API ut32 sdb_hash(const char *key); +SDB_API ut32 sdb_hash_len(const char *key, ut32 *len); +SDB_API ut8 sdb_hash_byte(const char *s); /* json api */ SDB_API bool sdb_isjson(const char *k); diff --git a/shlr/sdb/src/types.h b/shlr/sdb/src/types.h index b8dfa3bc10..3d9cff943e 100644 --- a/shlr/sdb/src/types.h +++ b/shlr/sdb/src/types.h @@ -26,10 +26,9 @@ #define SDB_IPI static #endif + #if MINGW || __MINGW32__ || __MINGW64__ #define __MINGW__ 1 -#else -#define __MINGW__ 0 #endif #if __WIN32__ || __MINGW__ || __WINDOWS__ || _MSC_VER diff --git a/shlr/sdb/src/util.c b/shlr/sdb/src/util.c index 0332599569..7b34f4aa1f 100644 --- a/shlr/sdb/src/util.c +++ b/shlr/sdb/src/util.c @@ -65,6 +65,12 @@ SDB_API ut32 sdb_hash(const char *s) { return sdb_hash_len (s, NULL); } +SDB_API ut8 sdb_hash_byte(const char *s) { + const ut32 hash = sdb_hash_len (s, NULL); + const ut8 *h = (const ut8*)&hash; + return h[0] ^ h[1] ^ h[2] ^ h[3]; +} + // assert (sizeof (s)>64) // if s is null, the returned pointer must be freed!! SDB_API char *sdb_itoa(ut64 n, char *s, int base) {