Skip to content

Commit

Permalink
add odict
Browse files Browse the repository at this point in the history
  • Loading branch information
alfredh committed Aug 31, 2015
1 parent e16054b commit 9ff3373
Show file tree
Hide file tree
Showing 9 changed files with 619 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ MODULES += fmt tmr main mem dbg sys lock mqueue
MODULES += mod conf
MODULES += bfcp
MODULES += aes srtp
MODULES += odict

INSTALL := install
ifeq ($(DESTDIR),)
Expand Down
1 change: 1 addition & 0 deletions include/re.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C" {
#include "re_mod.h"
#include "re_mqueue.h"
#include "re_net.h"
#include "re_odict.h"
#include "re_rtp.h"
#include "re_sdp.h"
#include "re_uri.h"
Expand Down
2 changes: 2 additions & 0 deletions include/re_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ uint32_t hash_joaat_str(const char *str);
uint32_t hash_joaat_str_ci(const char *str);
uint32_t hash_joaat_pl(const struct pl *pl);
uint32_t hash_joaat_pl_ci(const struct pl *pl);
uint32_t hash_fast(const char *k, size_t len);
uint32_t hash_fast_str(const char *str);
44 changes: 44 additions & 0 deletions include/re_odict.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @file re_odict.h Interface to Ordered Dictionary
*
* Copyright (C) 2010 - 2015 Creytiv.com
*/

struct odict {
struct list lst;
struct hash *ht;
};

struct odict_entry {
struct le le, he;
char *key;
union {
struct odict *odict; /* ODICT_OBJECT / OJECT_ARRAY */
char *str; /* ODICT_STRING */
int64_t integer; /* ODICT_INT */
double dbl; /* ODICT_DOUBLE */
bool boolean; /* ODICT_BOOL */
} u;
enum odict_type {
ODICT_OBJECT,
ODICT_ARRAY,
ODICT_STRING,
ODICT_INT,
ODICT_DOUBLE,
ODICT_BOOL,
ODICT_NULL,
} type;
};

int odict_alloc(struct odict **op, uint32_t hash_size);
const struct odict_entry *odict_lookup(const struct odict *o, const char *key);
size_t odict_count(const struct odict *o, bool nested);
int odict_debug(struct re_printf *pf, const struct odict *o);

int odict_entry_add(struct odict *o, const char *key,
enum odict_type type, ...);
int odict_entry_debug(struct re_printf *pf, const struct odict_entry *e);

bool odict_type_iscontainer(enum odict_type type);
bool odict_type_isreal(enum odict_type type);
const char *odict_type_name(enum odict_type type);
233 changes: 233 additions & 0 deletions src/hash/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,236 @@ uint32_t hash_joaat_pl_ci(const struct pl *pl)
{
return pl ? hash_joaat_ci(pl->p, pl->l) : 0;
}


/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
*/
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || \
defined(vax) || defined(MIPSEL))
# define HASH_LITTLE_ENDIAN 1
# define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || \
defined(mc68000) || defined(sel))
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#else
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 0
#endif

#define hashsize(n) ((uint32_t)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))

#define mix(a,b,c) { \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}


#define final(a,b,c) \
{ \
c ^= b; c -= rot(b,14); \
a ^= c; a -= rot(c,11); \
b ^= a; b -= rot(a,25); \
c ^= b; c -= rot(b,16); \
a ^= c; a -= rot(c,4); \
b ^= a; b -= rot(a,14); \
c ^= b; c -= rot(b,24); \
}


static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
{
uint32_t a,b,c;
union { const void *ptr; size_t i; } u;

/* Set up the internal state */
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;

u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key;

while (length > 12) {
a += k[0];
b += k[1];
c += k[2];
mix(a,b,c);
length -= 12;
k += 3;
}

#ifndef VALGRIND
switch (length) {

case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
case 5 : b+=k[1]&0xff; a+=k[0]; break;
case 4 : a+=k[0]; break;
case 3 : a+=k[0]&0xffffff; break;
case 2 : a+=k[0]&0xffff; break;
case 1 : a+=k[0]&0xff; break;
case 0 : return c;
}

#else /* make valgrind happy */

const uint8_t *k8 = (const uint8_t *)k;
switch (length) {

case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 1 : a+=k8[0]; break;
case 0 : return c;
}

#endif /* !valgrind */

}
else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key;
const uint8_t *k8;

while (length > 12) {
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
mix(a,b,c);
length -= 12;
k += 6;
}

k8 = (const uint8_t *)k;

switch (length) {

case 12: c+=k[4]+(((uint32_t)k[5])<<16);
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
break;
case 0 : return c;
}
}
else {
const uint8_t *k = (const uint8_t *)key;

while (length > 12) {
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
mix(a,b,c);
length -= 12;
k += 12;
}

/* all the case statements fall through */
switch (length) {

case 12: c+=((uint32_t)k[11])<<24;
case 11: c+=((uint32_t)k[10])<<16;
case 10: c+=((uint32_t)k[9])<<8;
case 9 : c+=k[8];
case 8 : b+=((uint32_t)k[7])<<24;
case 7 : b+=((uint32_t)k[6])<<16;
case 6 : b+=((uint32_t)k[5])<<8;
case 5 : b+=k[4];
case 4 : a+=((uint32_t)k[3])<<24;
case 3 : a+=((uint32_t)k[2])<<16;
case 2 : a+=((uint32_t)k[1])<<8;
case 1 : a+=k[0];
break;
case 0 : return c;
}
}

final(a,b,c);
return c;
}


/**
* Calculate hash-value using fast hash algorithm.
*
* @param k Pointer to key
* @param len Key length
*
* @return Calculated hash-value
*/
uint32_t hash_fast(const char *k, size_t len)
{
static volatile int random_seed = 0x304a0012;

if (!k)
return 0;

return hashlittle(k, len, random_seed);
}


/**
* Calculate hash-value for a NULL-terminated string
*
* @param str String
*
* @return Calculated hash-value
*/
uint32_t hash_fast_str(const char *str)
{
return hash_fast(str, str_len(str));
}
Loading

0 comments on commit 9ff3373

Please sign in to comment.