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/odict/entry.c b/src/odict/entry.c
new file mode 100644
index 0000000..53daf2b
--- /dev/null
+++ b/src/odict/entry.c
@@ -0,0 +1,152 @@
+/**
+ * @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,
+		    int 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;
+}
+
+
+void odict_entry_del(struct odict *o, const char *key)
+{
+	mem_deref((struct odict_entry *)odict_lookup(o, key));
+}
+
+
+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;
+}