add odict
This commit is contained in:
parent
e16054be2c
commit
9ff337301d
9 changed files with 619 additions and 0 deletions
1
Makefile
1
Makefile
|
@ -30,6 +30,7 @@ MODULES += fmt tmr main mem dbg sys lock mqueue
|
||||||
MODULES += mod conf
|
MODULES += mod conf
|
||||||
MODULES += bfcp
|
MODULES += bfcp
|
||||||
MODULES += aes srtp
|
MODULES += aes srtp
|
||||||
|
MODULES += odict
|
||||||
|
|
||||||
INSTALL := install
|
INSTALL := install
|
||||||
ifeq ($(DESTDIR),)
|
ifeq ($(DESTDIR),)
|
||||||
|
|
|
@ -39,6 +39,7 @@ extern "C" {
|
||||||
#include "re_mod.h"
|
#include "re_mod.h"
|
||||||
#include "re_mqueue.h"
|
#include "re_mqueue.h"
|
||||||
#include "re_net.h"
|
#include "re_net.h"
|
||||||
|
#include "re_odict.h"
|
||||||
#include "re_rtp.h"
|
#include "re_rtp.h"
|
||||||
#include "re_sdp.h"
|
#include "re_sdp.h"
|
||||||
#include "re_uri.h"
|
#include "re_uri.h"
|
||||||
|
|
|
@ -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_str_ci(const char *str);
|
||||||
uint32_t hash_joaat_pl(const struct pl *pl);
|
uint32_t hash_joaat_pl(const struct pl *pl);
|
||||||
uint32_t hash_joaat_pl_ci(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
include/re_odict.h
Normal file
44
include/re_odict.h
Normal file
|
@ -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
src/hash/func.c
233
src/hash/func.c
|
@ -134,3 +134,236 @@ uint32_t hash_joaat_pl_ci(const struct pl *pl)
|
||||||
{
|
{
|
||||||
return pl ? hash_joaat_ci(pl->p, pl->l) : 0;
|
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));
|
||||||
|
}
|
||||||
|
|
146
src/odict/entry.c
Normal file
146
src/odict/entry.c
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/**
|
||||||
|
* @file odict/entry.c Ordered Dictionary -- entry
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 - 2015 Creytiv.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "re_types.h"
|
||||||
|
#include "re_fmt.h"
|
||||||
|
#include "re_mem.h"
|
||||||
|
#include "re_list.h"
|
||||||
|
#include "re_hash.h"
|
||||||
|
#include "re_odict.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void destructor(void *arg)
|
||||||
|
{
|
||||||
|
struct odict_entry *e = arg;
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT:
|
||||||
|
case ODICT_ARRAY:
|
||||||
|
mem_deref(e->u.odict);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_STRING:
|
||||||
|
mem_deref(e->u.str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_unlink(&e->he);
|
||||||
|
list_unlink(&e->le);
|
||||||
|
mem_deref(e->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int odict_entry_add(struct odict *o, const char *key,
|
||||||
|
enum odict_type type, ...)
|
||||||
|
{
|
||||||
|
struct odict_entry *e;
|
||||||
|
va_list ap;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!o || !key)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
e = mem_zalloc(sizeof(*e), destructor);
|
||||||
|
if (!e)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
e->type = type;
|
||||||
|
|
||||||
|
err = str_dup(&e->key, key);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
va_start(ap, type);
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT:
|
||||||
|
case ODICT_ARRAY:
|
||||||
|
e->u.odict = mem_ref(va_arg(ap, struct odict *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_STRING:
|
||||||
|
err = str_dup(&e->u.str, va_arg(ap, const char *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_INT:
|
||||||
|
e->u.integer = va_arg(ap, int64_t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_DOUBLE:
|
||||||
|
e->u.dbl = va_arg(ap, double);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_BOOL:
|
||||||
|
e->u.boolean = va_arg(ap, int);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_NULL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
list_append(&o->lst, &e->le, e);
|
||||||
|
hash_append(o->ht, hash_fast_str(e->key), &e->he, e);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (err)
|
||||||
|
mem_deref(e);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int odict_entry_debug(struct re_printf *pf, const struct odict_entry *e)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = re_hprintf(pf, "%s", e->key);
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT:
|
||||||
|
case ODICT_ARRAY:
|
||||||
|
err |= re_hprintf(pf, ":%H", odict_debug, e->u.odict);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_STRING:
|
||||||
|
err |= re_hprintf(pf, ":%s", e->u.str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_INT:
|
||||||
|
err |= re_hprintf(pf, ":%lli", e->u.integer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_DOUBLE:
|
||||||
|
err |= re_hprintf(pf, ":%f", e->u.dbl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_BOOL:
|
||||||
|
err |= re_hprintf(pf, ":%s", e->u.boolean ? "true" : "false");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ODICT_NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
9
src/odict/mod.mk
Normal file
9
src/odict/mod.mk
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# mod.mk
|
||||||
|
#
|
||||||
|
# Copyright (C) 2010 - 2015 Creytiv.com
|
||||||
|
#
|
||||||
|
|
||||||
|
SRCS += odict/entry.c
|
||||||
|
SRCS += odict/odict.c
|
||||||
|
SRCS += odict/type.c
|
124
src/odict/odict.c
Normal file
124
src/odict/odict.c
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* @file odict.c Ordered Dictionary
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Creytiv.com
|
||||||
|
*/
|
||||||
|
#include "re_types.h"
|
||||||
|
#include "re_fmt.h"
|
||||||
|
#include "re_mem.h"
|
||||||
|
#include "re_list.h"
|
||||||
|
#include "re_hash.h"
|
||||||
|
#include "re_odict.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void destructor(void *arg)
|
||||||
|
{
|
||||||
|
struct odict *o = arg;
|
||||||
|
|
||||||
|
hash_clear(o->ht);
|
||||||
|
list_flush(&o->lst);
|
||||||
|
mem_deref(o->ht);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int odict_alloc(struct odict **op, uint32_t hash_size)
|
||||||
|
{
|
||||||
|
struct odict *o;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!op || !hash_size)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
o = mem_zalloc(sizeof(*o), destructor);
|
||||||
|
if (!o)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
err = hash_alloc(&o->ht, hash_valid_size(hash_size));
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (err)
|
||||||
|
mem_deref(o);
|
||||||
|
else
|
||||||
|
*op = o;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct odict_entry *odict_lookup(const struct odict *o, const char *key)
|
||||||
|
{
|
||||||
|
struct le *le;
|
||||||
|
|
||||||
|
if (!o || !key)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
le = list_head(hash_list(o->ht, hash_fast_str(key)));
|
||||||
|
|
||||||
|
while (le) {
|
||||||
|
const struct odict_entry *e = le->data;
|
||||||
|
|
||||||
|
if (!str_cmp(e->key, key))
|
||||||
|
return e;
|
||||||
|
|
||||||
|
le = le->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t odict_count(const struct odict *o, bool nested)
|
||||||
|
{
|
||||||
|
struct le *le;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if (!o)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!nested)
|
||||||
|
return list_count(&o->lst);
|
||||||
|
|
||||||
|
for (le=o->lst.head; le; le=le->next) {
|
||||||
|
|
||||||
|
const struct odict_entry *e = le->data;
|
||||||
|
|
||||||
|
switch (e->type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT:
|
||||||
|
case ODICT_ARRAY:
|
||||||
|
n += odict_count(e->u.odict, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
n += 1; /* count all entries */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int odict_debug(struct re_printf *pf, const struct odict *o)
|
||||||
|
{
|
||||||
|
struct le *le;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!o)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = re_hprintf(pf, "{");
|
||||||
|
|
||||||
|
for (le=o->lst.head; le; le=le->next) {
|
||||||
|
|
||||||
|
const struct odict_entry *e = le->data;
|
||||||
|
|
||||||
|
err |= re_hprintf(pf, " %H", odict_entry_debug, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
err |= re_hprintf(pf, " }");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
59
src/odict/type.c
Normal file
59
src/odict/type.c
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* @file type.c Ordered Dictionary -- value types
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 - 2015 Creytiv.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "re_types.h"
|
||||||
|
#include "re_fmt.h"
|
||||||
|
#include "re_mem.h"
|
||||||
|
#include "re_list.h"
|
||||||
|
#include "re_hash.h"
|
||||||
|
#include "re_odict.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool odict_type_iscontainer(enum odict_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT:
|
||||||
|
case ODICT_ARRAY:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool odict_type_isreal(enum odict_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case ODICT_STRING:
|
||||||
|
case ODICT_INT:
|
||||||
|
case ODICT_DOUBLE:
|
||||||
|
case ODICT_BOOL:
|
||||||
|
case ODICT_NULL:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *odict_type_name(enum odict_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case ODICT_OBJECT: return "Object";
|
||||||
|
case ODICT_ARRAY: return "Array";
|
||||||
|
case ODICT_STRING: return "String";
|
||||||
|
case ODICT_INT: return "Integer";
|
||||||
|
case ODICT_DOUBLE: return "Double";
|
||||||
|
case ODICT_BOOL: return "Boolean";
|
||||||
|
case ODICT_NULL: return "Null";
|
||||||
|
default: return "???";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue