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;
+}