Simple hash trie 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;
}