blob: 53daf2b8ace2a44ef255e71556d208365bec1371 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
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
15static 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
40int 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
109void odict_entry_del(struct odict *o, const char *key)
110{
111 mem_deref((struct odict_entry *)odict_lookup(o, key));
112}
113
114
115int 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}