blob: cd64affda0019e309cf6d48067c1d239970ee0be [file] [log] [blame]
/**
* @file json/decode_odict.c JSON odict decode
*
* 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>
#include <re_json.h>
static int container_add(const char *name, unsigned idx,
enum odict_type type, struct json_handlers *h)
{
struct odict *o = h->arg, *oc;
char index[64];
int err;
if (!name) {
if (re_snprintf(index, sizeof(index), "%u", idx) < 0)
return ENOMEM;
name = index;
}
err = odict_alloc(&oc, hash_bsize(o->ht));
if (err)
return err;
err = odict_entry_add(o, name, type, oc);
mem_deref(oc);
h->arg = oc;
return err;
}
static int object_handler(const char *name, unsigned idx,
struct json_handlers *h)
{
return container_add(name, idx, ODICT_OBJECT, h);
}
static int array_handler(const char *name, unsigned idx,
struct json_handlers *h)
{
return container_add(name, idx, ODICT_ARRAY, h);
}
static int entry_add(struct odict *o, const char *name,
const struct json_value *val)
{
switch (val->type) {
case JSON_STRING:
return odict_entry_add(o, name, ODICT_STRING, val->v.str);
case JSON_INT:
return odict_entry_add(o, name, ODICT_INT, val->v.integer);
case JSON_DOUBLE:
return odict_entry_add(o, name, ODICT_DOUBLE, val->v.dbl);
case JSON_BOOL:
return odict_entry_add(o, name, ODICT_BOOL, val->v.boolean);
case JSON_NULL:
return odict_entry_add(o, name, ODICT_NULL);
default:
return ENOSYS;
}
}
static int object_entry_handler(const char *name, const struct json_value *val,
void *arg)
{
struct odict *o = arg;
return entry_add(o, name, val);
}
static int array_entry_handler(unsigned idx, const struct json_value *val,
void *arg)
{
struct odict *o = arg;
char index[64];
if (re_snprintf(index, sizeof(index), "%u", idx) < 0)
return ENOMEM;
return entry_add(o, index, val);
}
int json_decode_odict(struct odict **op, uint32_t hash_size, const char *str,
size_t len, unsigned maxdepth)
{
struct odict *o;
int err;
if (!op || !str)
return EINVAL;
err = odict_alloc(&o, hash_size);
if (err)
return err;
err = json_decode(str, len, maxdepth, object_handler, array_handler,
object_entry_handler, array_entry_handler, o);
if (err)
mem_deref(o);
else
*op = o;
return err;
}