Simple hash storage (~memcpy)
#ifndef __STASH_H_
#define __STASH_H_
#define MAX_HASH_SPAN 96
#define MIN_HASH_SPAN 32
#ifndef byte
typedef unsigned char byte;
#endif
typedef struct stash_t stash_t;
struct stash_t {
stash_t *next[MAX_HASH_SPAN];
byte *data;
int size;
};
extern stash_t* new_stash();
extern void destroy_stash(stash_t* node);
extern byte* stash_prep(stash_t* node, const char *path, int size);
extern byte* stash_peek(stash_t* node, const char *path);
extern stash_t* stash_put(stash_t* node, const char *path, byte* var, int size);
extern stash_t* stash_get(stash_t* node, const char *path, byte* var);
extern stash_t* stash_unset(stash_t* node, const char *path);
/* Helpers */
extern int* stash_int(int Num);
#define H_INT(A) ((byte*)stash_int((A)))
#define H_INV(A) ((byte*)& (A))
#define H_PTR(A) ((byte*) (A))
#define H_REV(A, T) *((T*)A)
/* Wrappers */
#define H_PUT(NODE, PATH, NAME) stash_put(NODE, PATH, H_INV(NAME), sizeof(NAME))
#define H_PUTI(NODE, PATH, NAME) stash_put(NODE, PATH, H_INT(NAME), sizeof(int))
#define H_PEEK(NODE, PATH, TYPE) H_REV(stash_peek(NODE, PATH), TYPE)
#define H_GET(NODE, PATH, NAME) stash_get(NODE, PATH, H_INV(NAME))
#endif#include "stash.h"
#include "malloc.h"
stash_t* new_stash() {
int i;
stash_t* node = NULL;
if ((node = malloc(sizeof(stash_t))))
{
node->data = NULL;
node->size = 0;
for (i = 0; i < MAX_HASH_SPAN; i++) node->next[i] = NULL;
}
return node;
}
void destroy_stash(stash_t* node) {
int i;
for (i = 0; i < MAX_HASH_SPAN; i++)
if (node->next[i])
destroy_stash(node->next[i]);
if (node->size) free(node->data);
free(node);
}
byte* stash_ralloc(stash_t* node, int size) {
if (node->size != size) {
if (node->size) free(node->data);
if (size && !(node->data = malloc(size))) size = 0;
node->size = size;
}
return node->data;
}
stash_t* stash_path(stash_t *node, const char* path, int pave) {
if (path[0] && node) {
byte id = path[0] - MIN_HASH_SPAN;
if (id > MAX_HASH_SPAN - 1) id = MAX_HASH_SPAN - 1;
if (!node->next[id] && pave) node->next[id] = new_stash();
return stash_path(node->next[id], &path[1], pave);
}
return node;
}
void stash_ncpy(byte *dst, byte *src, int size) {
if (dst) while(size--) dst[size] = src[size]; }
byte* stash_prep(stash_t* node, const char *path, int size) {
return ((node = stash_path(node, path, 1)) ?
stash_ralloc(node, size) : NULL);
}
byte* stash_peek(stash_t* node, const char *path) {
return ((!(node = stash_path(node, path, 0)) || !node->size) ?
NULL : (byte*)node->data);
}
stash_t* stash_put(stash_t* node, const char *path, byte *var, int size) {
if ((node = stash_path(node, path, 1)))
stash_ncpy(stash_ralloc(node, size), var, size);
return node;
}
stash_t* stash_get(stash_t* node, const char *path, byte *var) {
if ((node = stash_path(node, path, 0))) {
if (node->size) stash_ncpy(var, node->data, node->size);
else node = NULL;
}
return node;
}
stash_t* stash_unset(stash_t* node, const char *path) {
if ((node = stash_path(node, path, 0)) && node->size) stash_ralloc(node, 0);
return node;
}
void stash_merge(stash_t *target, stash_t *node) {
int i;
for (i = 0; i < MAX_HASH_SPAN; i++) {
if (node->next[i]) {
char path[2] = { i + MIN_HASH_SPAN, 0 };
stash_merge(stash_path(target, path, 1), node->next[i]);
}
}
if (node->size)
stash_ncpy(stash_ralloc(target, node->size), node->data, node->size);
}
int* stash_int(int Num) { static int XNum; XNum = Num; return &XNum; }
#include "stash.h"
#include "stdio.h"
typedef struct demo_struct
{
char name[80];
int color;
} demo_type;
int main( int argc, char* args[])
{
int a;
demo_type s1 = { "apple", 5 };
demo_type s2 = { "orange", 9 };
demo_type *p1 = &s1;
demo_type *p2 = 0;
/* Init */
stash_t* tbl = new_stash();
/* Store */
H_PUTI(tbl, "integer", 0x01010101);
H_PUT(tbl, "struct", s1);
H_PUT(tbl, "pointer", p1);
/* Retreive */
H_GET(tbl, "struct", s2);
a = H_PEEK(tbl, "integer", int);
p2 = H_PEEK(tbl, "pointer", demo_type*);
/* Kill */
destroy_stash(tbl);
printf("%08x, %s, %d\n", a, s2.name, p2->color);
// Outputs: 01010101, apple, 5
return 0;
}