mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-22 15:21:18 +00:00
Update SDB and initial use of MHT for xrefs (disabled by default)
This commit is contained in:
parent
3570f6c669
commit
ce77004507
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
47
libr/include/sdb/mht.h
Normal file
47
libr/include/sdb/mht.h
Normal file
@ -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);
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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})
|
||||
|
||||
|
197
shlr/sdb/src/mht.c
Normal file
197
shlr/sdb/src/mht.c
Normal file
@ -0,0 +1,197 @@
|
||||
/* sdb - MIT - Copyright 2017 - pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#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
|
47
shlr/sdb/src/mht.h
Normal file
47
shlr/sdb/src/mht.h
Normal file
@ -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);
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user