1 /**
2  * @file odict/entry.c  Ordered Dictionary -- entry
3  *
4  * Copyright (C) 2010 - 2015 Creytiv.com
5  */
6 
7 #include "re_types.h"
8 #include "re_fmt.h"
9 #include "re_mem.h"
10 #include "re_list.h"
11 #include "re_hash.h"
12 #include "re_odict.h"
13 
14 
destructor(void * arg)15 static void destructor(void *arg)
16 {
17 	struct odict_entry *e = arg;
18 
19 	switch (e->type) {
20 
21 	case ODICT_OBJECT:
22 	case ODICT_ARRAY:
23 		mem_deref(e->u.odict);
24 		break;
25 
26 	case ODICT_STRING:
27 		mem_deref(e->u.str);
28 		break;
29 
30 	default:
31 		break;
32 	}
33 
34 	hash_unlink(&e->he);
35 	list_unlink(&e->le);
36 	mem_deref(e->key);
37 }
38 
39 
odict_entry_add(struct odict * o,const char * key,int type,...)40 int odict_entry_add(struct odict *o, const char *key,
41 		    int type, ...)
42 {
43 	struct odict_entry *e;
44 	va_list ap;
45 	int err;
46 
47 	if (!o || !key)
48 		return EINVAL;
49 
50 	e = mem_zalloc(sizeof(*e), destructor);
51 	if (!e)
52 		return ENOMEM;
53 
54 	e->type = type;
55 
56 	err = str_dup(&e->key, key);
57 	if (err)
58 		goto out;
59 
60 	va_start(ap, type);
61 
62 	switch (e->type) {
63 
64 	case ODICT_OBJECT:
65 	case ODICT_ARRAY:
66 		e->u.odict = mem_ref(va_arg(ap, struct odict *));
67 		break;
68 
69 	case ODICT_STRING:
70 		err = str_dup(&e->u.str, va_arg(ap, const char *));
71 		break;
72 
73 	case ODICT_INT:
74 		e->u.integer = va_arg(ap, int64_t);
75 		break;
76 
77 	case ODICT_DOUBLE:
78 		e->u.dbl = va_arg(ap, double);
79 		break;
80 
81 	case ODICT_BOOL:
82 		e->u.boolean = va_arg(ap, int);
83 		break;
84 
85 	case ODICT_NULL:
86 		break;
87 
88 	default:
89 		err = EINVAL;
90 		break;
91 	}
92 
93 	va_end(ap);
94 
95 	if (err)
96 		goto out;
97 
98 	list_append(&o->lst, &e->le, e);
99 	hash_append(o->ht, hash_fast_str(e->key), &e->he, e);
100 
101  out:
102 	if (err)
103 		mem_deref(e);
104 
105 	return err;
106 }
107 
108 
odict_entry_del(struct odict * o,const char * key)109 void odict_entry_del(struct odict *o, const char *key)
110 {
111 	mem_deref((struct odict_entry *)odict_lookup(o, key));
112 }
113 
114 
odict_entry_debug(struct re_printf * pf,const struct odict_entry * e)115 int odict_entry_debug(struct re_printf *pf, const struct odict_entry *e)
116 {
117 	int err;
118 
119 	if (!e)
120 		return 0;
121 
122 	err = re_hprintf(pf, "%s", e->key);
123 
124 	switch (e->type) {
125 
126 	case ODICT_OBJECT:
127 	case ODICT_ARRAY:
128 		err |= re_hprintf(pf, ":%H", odict_debug, e->u.odict);
129 		break;
130 
131 	case ODICT_STRING:
132 		err |= re_hprintf(pf, ":%s", e->u.str);
133 		break;
134 
135 	case ODICT_INT:
136 		err |= re_hprintf(pf, ":%lli", e->u.integer);
137 		break;
138 
139 	case ODICT_DOUBLE:
140 		err |= re_hprintf(pf, ":%f", e->u.dbl);
141 		break;
142 
143 	case ODICT_BOOL:
144 		err |= re_hprintf(pf, ":%s", e->u.boolean ? "true" : "false");
145 		break;
146 
147 	case ODICT_NULL:
148 		break;
149 	}
150 
151 	return err;
152 }
153