blob: cd64affda0019e309cf6d48067c1d239970ee0be [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file json/decode_odict.c JSON odict decode
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#include <re_json.h>
14
15
16static int container_add(const char *name, unsigned idx,
17 enum odict_type type, struct json_handlers *h)
18{
19 struct odict *o = h->arg, *oc;
20 char index[64];
21 int err;
22
23 if (!name) {
24 if (re_snprintf(index, sizeof(index), "%u", idx) < 0)
25 return ENOMEM;
26
27 name = index;
28 }
29
30 err = odict_alloc(&oc, hash_bsize(o->ht));
31 if (err)
32 return err;
33
34 err = odict_entry_add(o, name, type, oc);
35 mem_deref(oc);
36 h->arg = oc;
37
38 return err;
39}
40
41
42static int object_handler(const char *name, unsigned idx,
43 struct json_handlers *h)
44{
45 return container_add(name, idx, ODICT_OBJECT, h);
46}
47
48
49static int array_handler(const char *name, unsigned idx,
50 struct json_handlers *h)
51{
52 return container_add(name, idx, ODICT_ARRAY, h);
53}
54
55
56static int entry_add(struct odict *o, const char *name,
57 const struct json_value *val)
58{
59 switch (val->type) {
60
61 case JSON_STRING:
62 return odict_entry_add(o, name, ODICT_STRING, val->v.str);
63
64 case JSON_INT:
65 return odict_entry_add(o, name, ODICT_INT, val->v.integer);
66
67 case JSON_DOUBLE:
68 return odict_entry_add(o, name, ODICT_DOUBLE, val->v.dbl);
69
70 case JSON_BOOL:
71 return odict_entry_add(o, name, ODICT_BOOL, val->v.boolean);
72
73 case JSON_NULL:
74 return odict_entry_add(o, name, ODICT_NULL);
75
76 default:
77 return ENOSYS;
78 }
79}
80
81
82static int object_entry_handler(const char *name, const struct json_value *val,
83 void *arg)
84{
85 struct odict *o = arg;
86
87 return entry_add(o, name, val);
88}
89
90
91static int array_entry_handler(unsigned idx, const struct json_value *val,
92 void *arg)
93{
94 struct odict *o = arg;
95 char index[64];
96
97 if (re_snprintf(index, sizeof(index), "%u", idx) < 0)
98 return ENOMEM;
99
100 return entry_add(o, index, val);
101}
102
103
104int json_decode_odict(struct odict **op, uint32_t hash_size, const char *str,
105 size_t len, unsigned maxdepth)
106{
107 struct odict *o;
108 int err;
109
110 if (!op || !str)
111 return EINVAL;
112
113 err = odict_alloc(&o, hash_size);
114 if (err)
115 return err;
116
117 err = json_decode(str, len, maxdepth, object_handler, array_handler,
118 object_entry_handler, array_entry_handler, o);
119 if (err)
120 mem_deref(o);
121 else
122 *op = o;
123
124 return err;
125}