Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b
Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/json/decode_odict.c b/src/json/decode_odict.c
new file mode 100644
index 0000000..cd64aff
--- /dev/null
+++ b/src/json/decode_odict.c
@@ -0,0 +1,125 @@
+/**
+ * @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;
+}