Skip to content
Newer
Older
100644 1562 lines (1285 sloc) 41.3 KB
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1 /*
2 * Copyright (c) 2005-2010 by KoanLogic s.r.l. - All rights reserved.
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <ctype.h>
8
9 #include <toolbox/json.h>
10 #include <toolbox/carpal.h>
11 #include <toolbox/misc.h>
12 #include <toolbox/memory.h>
13 #include <toolbox/lexer.h>
14
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
15 /* Pointer to the name part of .fqn */
16 #define U_JSON_OBJ_NAME(jo) \
17 ((jo->parent != NULL) ? jo->fqn + strlen(p->fqn) : jo->fqn)
18
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
19 #define U_JSON_OBJ_IS_CONTAINER(jo) \
20 ((jo->type == U_JSON_TYPE_OBJECT) || (jo->type == U_JSON_TYPE_ARRAY))
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
21
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
22 /* Internal representation of any JSON value. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
23 struct u_json_s
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
24 {
25 u_json_type_t type;
26
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
27 char fqn[U_JSON_FQN_SZ]; /* Fully qualified name of this (sub)object. */
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
28 char key[U_TOKEN_SZ]; /* Local name, if applicable (i.e. !anon) */
29 char val[U_TOKEN_SZ]; /* If applicable, i.e. (!OBJECT && !ARRAY) */
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
30
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
31 /* Parent container. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
32 struct u_json_s *parent;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
33
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
34 /* Nodes at the same level as this one (if any). */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
35 TAILQ_ENTRY(u_json_s) siblings;
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
36
37 /* Children nodes' list when i.e. (ARRAY || OBJECT). */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
38 TAILQ_HEAD(u_json_chld_s, u_json_s) children;
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
39
40 /* Cacheing machinery. */
41 unsigned int icur, count; /* Aux stuff used when indexing arrays. */
42 u_hmap_t *map; /* Alias reference to the global cache. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
43 };
44
45 /* Lexer methods */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
46 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
47 static int u_json_match_number_first (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
48 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
49 static int u_json_match_int (u_lexer_t *jl);
50 static int u_json_match_frac_first (char c);
51 static int u_json_match_frac (u_lexer_t *jl);
52 static int u_json_match_exp_first (char c);
53 static int u_json_match_exp (u_lexer_t *jl);
54 static int u_json_match_true_first (u_lexer_t *jl);
55 static int u_json_match_false_first (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
56 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo);
57 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
58 static int u_json_match_null_first (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
59 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo);
60 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
61 static int u_json_match_string_first (u_lexer_t *jl);
62 static int u_json_match_escaped_unicode (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
63 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
64 static int u_json_match_object_first (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
65 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
66 static int u_json_match_array_first (u_lexer_t *jl);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
67 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
68 static int u_json_match_pair_first (u_lexer_t *jl);
69
70 /* Lexer misc stuff. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
71 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type,
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
72 char first, const char *rem, size_t rem_sz);
73 static const char *u_json_type_str (int type);
74
75 /* Objects misc stuff. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
76 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque);
77 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque);
78 static void u_json_do_index (u_json_t *jo, size_t l, void *map);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
79
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
80 /* Encode/Decode/Validate. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
81 static int u_json_do_encode (u_json_t *jo, u_string_t *s);
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
82 static int u_json_do_parse (const char *json, u_json_t **pjo,
83 char status[U_LEXER_ERR_SZ]);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
84
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
85 /* Needed by hmap_easy* because we are storing pointer data not owned by the
86 * hmap. */
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
87 static void nopf (void *dummy) { u_unused_args(dummy); return; }
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
88
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
89 static int u_json_new_container (u_json_type_t type, const char *key,
90 u_json_t **pjo);
91 static int u_json_new_atom (u_json_type_t type, const char *key,
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
92 const char *val, char check, u_json_t **pjo);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
93
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
94 /**
95 \defgroup json JSON
96 \{
2d8e2ce [libu] json += unit test
tho authored May 28, 2010
97 The \ref json module implements encoding and decoding of JSON objects as
98 defined in <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>.
99 TODO
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
100 */
101
102 /**
103 * \brief Create a new and empty JSON object container
104 *
105 * Create a new and empty JSON object container and return its handler as
106 * the result argument \p *pjo
107 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
108 * \param pjo Pointer to the ::u_json_t that will be returned
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
109 *
110 * \retval ~0 on failure
111 * \retval 0 on success
112 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
113 int u_json_new (u_json_t **pjo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
114 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
115 u_json_t *jo = NULL;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
116
117 dbg_return_if (pjo == NULL, ~0);
118
119 warn_err_sif ((jo = u_zalloc(sizeof *jo)) == NULL);
120 TAILQ_INIT(&jo->children);
121 jo->type = U_JSON_TYPE_UNKNOWN;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
122 jo->key[0] = jo->val[0] = jo->fqn[0] = '\0';
123 jo->parent = NULL;
124 jo->map = NULL;
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 27, 2010
125 jo->count = 0;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
126
127 *pjo = jo;
128
129 return 0;
130 err:
131 if (jo)
132 u_free(jo);
133 return ~0;
134 }
135
136 /**
137 * \brief Set the type of a JSON object
138 *
139 * Set the type of the supplied JSON object \p jo to \p type.
140 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
141 * \param jo Pointer to a ::u_json_t object
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
142 * \param type One of the available ::u_json_type_t types
143 *
144 * \retval ~0 on failure
145 * \retval 0 on success
146 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
147 int u_json_set_type (u_json_t *jo, u_json_type_t type)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
148 {
149 dbg_return_if (jo == NULL, ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
150 dbg_return_ifm (jo->map, ~0, "Cannot set type of a cached object");
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
151
152 switch (type)
153 {
154 case U_JSON_TYPE_STRING:
155 case U_JSON_TYPE_NUMBER:
156 case U_JSON_TYPE_ARRAY:
157 case U_JSON_TYPE_OBJECT:
158 case U_JSON_TYPE_TRUE:
159 case U_JSON_TYPE_FALSE:
160 case U_JSON_TYPE_NULL:
161 case U_JSON_TYPE_UNKNOWN:
162 jo->type = type;
163 break;
164 default:
165 u_err("unhandled type %d", type);
166 return ~0;
167 }
168
169 return 0;
170 }
171
172 /**
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
173 * \brief ::u_json_set_val_ex wrapper with no \p val syntax check
174 */
175 int u_json_set_val (u_json_t *jo, const char *val)
176 {
177 return u_json_set_val_ex(jo, val, 0);
178 }
179
180 /*
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
181 * \brief Set the value of a JSON object
182 *
183 * Set the value of the JSON object \p jo to the string value pointed by
184 * \p val. This operation is meaningful only in case the underlying object
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
185 * is a number or a string, in which case the syntax of the supplied value
186 * can be checked by passing non-0 value to the \p check parameter.
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
187 *
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
188 * \param jo Pointer to a ::u_json_t object
189 * \param val Pointer to the (non-NULL) value string
190 * \param check Set to non-0 if you need to syntax check \p val
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
191 *
192 * \retval ~0 on failure
193 * \retval 0 on success
194 */
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
195 int u_json_set_val_ex (u_json_t *jo, const char *val, char check)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
196 {
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
197 u_lexer_t *vl = NULL;
198
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
199 dbg_return_if (jo == NULL, ~0);
200 dbg_return_if (val == NULL, ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
201 /* Note that cached objects allow for value overwrite. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
202
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
203 if (check)
204 {
205 /* if (U_JSON_TYPE_STRING) "-wrap 'val' */
206 dbg_err_if (u_lexer_new(val, &vl));
207 }
208
209 /* If requested, pass 'val' through its validator. */
210 switch (jo->type)
211 {
212 case U_JSON_TYPE_STRING:
213 dbg_err_if (check && u_json_match_string(vl, NULL));
214 break;
215 case U_JSON_TYPE_NUMBER:
216 dbg_err_if (check && u_json_match_number(vl, NULL));
217 break;
218 default:
219 /* Non-critical error, just emit some debug info. */
220 goto end;
221 }
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
222
223 dbg_return_if (u_strlcpy(jo->val, val, sizeof jo->val), ~0);
224
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
225 /* Fall through. */
226 end:
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
227 return 0;
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
228 err:
229 return ~0;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
230 }
231 /**
232 * \brief Set the key of a JSON object
233 *
234 * Set the key of the JSON object \p jo to the string value pointed by
235 * \p key.
236 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
237 * \param jo Pointer to a ::u_json_t object
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
238 * \param key Pointer to the key string. In case \p key \c NULL the value
239 * is reset to the empty string.
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
240 *
241 * \retval ~0 on failure
242 * \retval 0 on success
243 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
244 int u_json_set_key (u_json_t *jo, const char *key)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
245 {
246 dbg_return_if (jo == NULL, ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
247 dbg_return_ifm (jo->map, ~0, "Cannot set key of a cached object");
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
248
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
249 dbg_return_if (u_strlcpy(jo->key, key ? key : "", sizeof jo->key), ~0);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
250
251 return 0;
252 }
253
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
254 /** \brief Wrapper function that creates an array container.
255 * (\p key may be \c NULL). */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
256 int u_json_new_array (const char *key, u_json_t **pjo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
257 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
258 return u_json_new_container(U_JSON_TYPE_ARRAY, key, pjo);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
259 }
260
261 /** \brief Wrapper function that creates an object container
262 * (\p key may be \c NULL). */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
263 int u_json_new_object (const char *key, u_json_t **pjo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
264 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
265 return u_json_new_container(U_JSON_TYPE_OBJECT, key, pjo);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
266 }
267
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
268 /**
269 * \brief Add a child JSON object to its parent container
270 *
271 * Add the child JSON object \p jo to its parent container \p head.
272 *
273 * \param head Pointer to the parent container
274 * \param jo Pointer to the child JSON object that shall be attached
275 *
276 * \retval ~0 on failure
277 * \retval 0 on success
278 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
279 int u_json_add (u_json_t *head, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
280 {
281 dbg_return_if (head == NULL, ~0);
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
282 dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(head), ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
283 dbg_return_ifm (head->map, ~0, "Cannot add new child to a cached object");
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
284 dbg_return_if (jo == NULL, ~0);
285
286 #ifdef U_JSON_OBJ_DEBUG
287 u_con("chld (%p): %s {%s} added", jo, u_json_type_str(jo->type), jo->key);
288 u_con("prnt (%p): %s {%s}\n", head, u_json_type_str(head->type), head->key);
289 #endif /* U_JSON_OBJ_DEBUG */
290
291 TAILQ_INSERT_TAIL(&head->children, jo, siblings);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
292 jo->parent = head;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
293
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
294 /* Adjust children counter for array-type parents. */
295 if (head->type == U_JSON_TYPE_ARRAY)
296 head->count += 1;
297
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
298 return 0;
299 }
300
301 /**
302 * \brief Break down a JSON string into pieces
303 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
304 * Parse and (implicitly) validate the supplied JSON string \p json.
305 * In case of success, its internal representation is returned into the result
306 * argument \p *pjo.
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
307 *
308 * \param json A NUL-terminated string containing some serialized JSON
309 * \param pjo Result argument which will point to the internal
310 * representation of the parsed \p json string
311 *
312 * \retval ~0 on failure
313 * \retval 0 on success
314 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
315 int u_json_decode (const char *json, u_json_t **pjo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
316 {
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
317 return u_json_do_parse(json, pjo, NULL);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
318 }
319
320 /**
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
321 * \brief Validate the supplied JSON string.
322 *
323 * Validate the supplied JSON string \p json. In case \p json contains
324 * invalid syntax, the parser/lexer error message is returned into \p status.
325 *
326 * \param json A NUL-terminated string containing some serialized JSON
327 * \param status In case of error, this result argument will contain an
328 * explanation message from the parser/lexer.
329 *
330 * \retval ~0 on failure
331 * \retval 0 on success
332 */
333 int u_json_validate (const char *json, char status[U_LEXER_ERR_SZ])
334 {
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
335 /* Just try to validate the input string (do not build the tree). */
336 return u_json_do_parse(json, NULL, status);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
337 }
338
339 /**
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
340 * \brief Dispose any resource allocated to a JSON object
341 *
342 * Dispose any resource allocated to the supplied JSON object \p jo
343 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
344 * \param jo Pointer to the ::u_json_t object that must be free'd
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
345 *
346 * \return nothing
347 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
348 void u_json_free (u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
349 {
350 size_t dummy = 0;
351
352 if (jo == NULL)
353 return;
354
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
355 /* If there is an associated hmap free it. */
356 if (jo->map)
357 {
358 u_hmap_easy_free(jo->map);
359 jo->map = NULL;
360 }
361
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
362 /* Walk the tree in post order and free each node while we traverse. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
363 u_json_walk(jo, U_JSON_WALK_POSTORDER, dummy, u_json_do_free, NULL);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
364
365 return;
366 }
367
368 /**
369 * \brief Encode a JSON object
370 *
371 * Encode the supplied JSON object \p jo to the result string pointed by
372 * \p *ps
373 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
374 * \param jo Pointer to the ::u_json_t object that must be encoded
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
375 * \param ps serialized JSON text corresponding to \p jo
376 *
377 * \retval ~0 on failure
378 * \retval 0 on success
379 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
380 int u_json_encode (u_json_t *jo, char **ps)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
381 {
382 u_string_t *s = NULL;
383
384 dbg_return_if (jo == NULL, ~0);
385 dbg_return_if (ps == NULL, ~0);
386
387 dbg_err_if (u_string_create(NULL, 0, &s));
388 dbg_err_if (u_json_do_encode(jo, s));
389 *ps = u_string_c(s);
390
391 return 0;
392 err:
393 if (s)
394 u_string_free(s);
395 return ~0;
396 }
397
398 /**
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
399 * \brief Pre/post-order tree walker
400 *
401 * Traverse the supplied JSON object \p jo in pre/post-order, depending on
402 * \p strategy, invoking the callback function \p cb on each node.
403 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
404 * \param jo Pointer to ::u_json_t object to traverse
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
405 * \param strategy one of ::U_JSON_WALK_PREORDER or ::U_JSON_WALK_POSTORDER
406 * \param l depth level in the JSON tree (the root is at depth 0)
407 * \param cb function to invoke on each traversed node
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
408 * \param cb_args optional opaque data which will be supplied to \p cb
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
409 *
410 * \return nothing
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
411 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
412 void u_json_walk (u_json_t *jo, int strategy, size_t l,
413 void (*cb)(u_json_t *, size_t, void *), void *cb_args)
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
414 {
415 dbg_return_if (strategy != U_JSON_WALK_PREORDER &&
416 strategy != U_JSON_WALK_POSTORDER, );
417
418 if (jo == NULL)
419 return;
420
421 if (strategy == U_JSON_WALK_PREORDER && cb)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
422 cb(jo, l, cb_args);
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
423
424 /* When recurring into the children branch, increment depth by one. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
425 u_json_walk(TAILQ_FIRST(&jo->children), strategy, l + 1, cb, cb_args);
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
426
427 /* Siblings are at the same depth as the current node. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
428 u_json_walk(TAILQ_NEXT(jo, siblings), strategy, l, cb, cb_args);
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
429
430 if (strategy == U_JSON_WALK_POSTORDER && cb)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
431 cb(jo, l, cb_args);
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
432
433 return;
434 }
435
436 /**
437 * \brief Print to stderr the internal representation of a JSON object
438 *
439 * Print to stderr the supplied JSON object \p jo
440 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
441 * \param jo Pointer to the ::u_json_t object that must be printed
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
442 *
443 * \return nothing
444 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
445 void u_json_print (u_json_t *jo)
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
446 {
447 dbg_return_if (jo == NULL, );
448
449 /* Tree root is at '0' depth. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
450 u_json_walk(jo, U_JSON_WALK_PREORDER, 0, u_json_do_print, NULL);
bbf1dce [libu] json += missing doxy
tho authored May 27, 2010
451
452 return;
453 }
454
455 /**
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
456 * \brief Index JSON object contents.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
457 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
458 * Index all contents of the supplied ::u_json_t top-level object \p jo.
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
459 * After data has been indexed, no more key/type modifications are possible
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
460 * on this object; instead, values of leaf nodes can still be changed.
461 * Also, either child node addition nor removal is possible after the object
462 * has been cached. If \p jo needs to be changed in aforementioned ways
463 * (type, key, addition or removal), it must be explicitly ::u_json_unindex'ed.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
464 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
465 * \param jo Pointer to the ::u_json_t object that must be indexed
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
466 *
467 * \return nothing
468 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
469 int u_json_index (u_json_t *jo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
470 {
471 size_t u; /* Unused. */
472 u_hmap_opts_t opts;
473 u_hmap_t *hmap = NULL;
474
475 dbg_return_if (jo == NULL, ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
476 nop_return_if (jo->map, 0); /* If already cached, return ok. */
477 dbg_return_if (jo->parent, ~0); /* Cache can be created on top-objs only. */
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
478
479 /* Create the associative array. */
480 u_hmap_opts_init(&opts);
481 dbg_err_if (u_hmap_opts_set_val_type(&opts, U_HMAP_OPTS_DATATYPE_POINTER));
482 dbg_err_if (u_hmap_opts_set_val_freefunc(&opts, nopf));
483 dbg_err_if (u_hmap_easy_new(&opts, &hmap));
484
485 /* Initialize array elems' indexing. */
486 jo->icur = 0;
487
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
488 /* Walk the tree in pre-order and cache each node while we traverse. */
489 u_json_walk(jo, U_JSON_WALK_PREORDER, u, u_json_do_index, hmap);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
490
491 /* Attach the associative array to the top level object. */
492 jo->map = hmap, hmap = NULL;
493
494 return 0;
495 err:
496 if (hmap)
497 u_hmap_easy_free(hmap);
498 return ~0;
499 }
500
501 /**
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
502 * \brief Remove cache from JSON object.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
503 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
504 * Remove the whole cacheing machinery from the previously ::u_json_index'd
505 * ::u_json_t object \p jo.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
506 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
507 * \param jo Pointer to the ::u_json_t object that must be de-indexed
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
508 *
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
509 * \retval 0 on success
510 * \retval ~0 on failure
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
511 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
512 int u_json_unindex (u_json_t *jo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
513 {
514 dbg_return_if (jo == NULL, ~0);
515 nop_return_if (jo->map == NULL, 0);
516
517 u_hmap_easy_free(jo->map);
518 jo->map = NULL;
519
520 return 0;
521 }
522
523 /**
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
524 * \brief Retrieve JSON node by its cache name.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
525 *
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
526 * Possibly retrieve a JSON node by its (fully qualified, or relative) cache
527 * \p name.
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
528 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
529 * \param jo Pointer to the ::u_json_t object that must be searched
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
530 * \param name name of the element that must be searched
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
531 *
532 * \return the retrieved JSON (sub)object on success; \c NULL in case \p key
533 * was not found
534 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
535 u_json_t *u_json_cache_get (u_json_t *jo, const char *name)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
536 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
537 u_json_t *res, *p;
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
538 char fqn[U_JSON_FQN_SZ];
539
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
540 dbg_return_if (jo == NULL, NULL);
541 dbg_return_if (jo->map == NULL, NULL);
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
542 dbg_return_if (name == NULL, NULL);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
543
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
544 if ((p = jo->parent) == NULL)
545 {
546 /* If 'jo' is top level, 'name' must be fully qualified. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
547 return (u_json_t *) u_hmap_easy_get(jo->map, name);
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
548 }
549
550 /* Else ('jo' != top): first try 'name' as it were fully qualified. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
551 if ((res = (u_json_t *) u_hmap_easy_get(jo->map, name)))
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
552 return res;
553
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
554 /* If 'name' is relative, we need to prefix it with the parent name
555 * space. */
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
556 dbg_if (u_snprintf(fqn, sizeof fqn, "%s%s", jo->fqn, name));
557
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
558 return (u_json_t *) u_hmap_easy_get(jo->map, fqn);
559 }
560
561 /**
562 * \brief Set JSON node's type and value by its cache name.
563 *
564 * Set type and value of the supplied JSON (leaf) node by its (fully qualified
565 * or relative) cache \p name. If \p type is ::U_JSON_TYPE_UNKNOWN the
566 * underlying type will be left untouched.
567 *
568 * \param jo Pointer to an ::u_json_t object
569 * \param name name of the element that must be set
570 * \param type new type (or ::U_JSON_TYPE_UNKNOWN if no type change)
571 * \param val new value. MUST be non-NULL in case we are setting a
572 * string a or number.
573 *
574 * \retval 0 on success
575 * \retval ~0 on failure
576 */
577 int u_json_cache_set_tv (u_json_t *jo, const char *name,
578 u_json_type_t type, const char *val)
579 {
580 u_json_t *res;
581
582 dbg_return_if (U_JSON_OBJ_IS_CONTAINER(jo), ~0);
583 dbg_return_if (type == U_JSON_TYPE_OBJECT || type == U_JSON_TYPE_ARRAY, ~0);
584 /* 'jo' and 'name' will be checked by u_json_cache_get();
585 * 'val' consistency is checked after type has been set. */
586
587 /* Retrieve the node. */
588 dbg_err_if ((res = u_json_cache_get(jo, name)) == NULL);
589
590 /* First set type (in case !unknown) so that we know how to check the
591 * subsequent value setting. */
592 if (type != U_JSON_TYPE_UNKNOWN)
593 res->type = type;
594
595 /* Set value. The caller must have supplied some non-NULL 'val' in case
596 * the final underlying type is a string or a number. */
597 if (res->type == U_JSON_TYPE_STRING || res->type == U_JSON_TYPE_NUMBER)
598 dbg_err_if (val == NULL || u_strlcpy(res->val, val, sizeof res->val));
599
600 return 0;
601 err:
602 return ~0;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
603 }
604
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
605 /** \brief Return the number of elements in array \p jo, or \c 0 on error. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
606 unsigned int u_json_array_count (u_json_t *jo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
607 {
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
608 dbg_return_if (jo == NULL, 0);
609 dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, 0);
610
611 return jo->count;
612 }
613
614 /** \brief Get n-th element from \p jo array. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
615 u_json_t *u_json_array_get_nth (u_json_t *jo, unsigned int n)
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
616 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
617 u_json_t *elem;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
618
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
619 dbg_return_if (jo == NULL, NULL);
620 dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, NULL);
621 dbg_return_if (n >= jo->count, NULL);
622
623 /* Use cache if available. */
624 if (jo->map)
625 {
626 char elem_fqn[U_JSON_FQN_SZ] = { '\0' };
627 dbg_if (u_snprintf(elem_fqn, sizeof elem_fqn, "%s[%u]", jo->fqn, n));
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
628 return u_json_cache_get(jo, elem_fqn);
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
629 }
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
630
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
631 /* Too bad if we don't have cache in place: we have to go through the
632 * list which is quadratic even with the following silly optimisation.
633 * So it's ok for a couple of lookups, but if done systematically it's
634 * an overkill. Freeze instead ! */
635 if (n > (jo->count / 2))
636 {
637 unsigned int r = jo->count - (n + 1);
638
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
639 TAILQ_FOREACH_REVERSE (elem, &jo->children, u_json_chld_s, siblings)
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
640 {
641 if (r == 0)
642 return elem;
643 r -= 1;
644 }
645 }
646 else
647 {
648 TAILQ_FOREACH (elem, &jo->children, siblings)
649 {
650 if (n == 0)
651 return elem;
652 n -= 1;
653 }
654 }
655
656 /* Unreachable. */
657 return NULL;
658 }
659
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
660 /** \brief Get the value associated with the non-container object \p jo. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
661 const char *u_json_get_val (u_json_t *jo)
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
662 {
663 dbg_return_if (jo == NULL, NULL);
664
665 switch (jo->type)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
666 {
667 case U_JSON_TYPE_STRING:
668 case U_JSON_TYPE_NUMBER:
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
669 return jo->val;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
670 case U_JSON_TYPE_TRUE:
671 return "true";
672 case U_JSON_TYPE_FALSE:
673 return "false";
674 case U_JSON_TYPE_NULL:
675 return "null";
676 case U_JSON_TYPE_OBJECT:
677 case U_JSON_TYPE_ARRAY:
678 case U_JSON_TYPE_UNKNOWN:
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
679 default:
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
680 return NULL;
681 }
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
682 }
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
683
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
684 /** \brief Wrapper around ::u_json_cache_get to retrieve string values from
685 * terminal (i.e. non-container) objects. */
686 const char *u_json_cache_get_val (u_json_t *jo, const char *name)
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
687 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
688 u_json_t *res = u_json_cache_get(jo, name);
a709334 @babongo added array iteration primitives to JSON
babongo authored Jun 26, 2010
689
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
690 return u_json_get_val(res);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
691 }
692
693 /**
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
694 * \brief Remove an object from its JSON container.
695 *
696 * Remove an object from its JSON container. This interface falls back to
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
697 * ::u_json_free in case the supplied \p jo is the root node.
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
698 *
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
699 * \param jo Pointer to the ::u_json_t object that must be removed
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
700 *
701 * \retval 0 on success
702 * \retval ~0 on failure
703 */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
704 int u_json_remove (u_json_t *jo)
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
705 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
706 u_json_t *p;
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
707
708 dbg_return_if (jo == NULL, ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
709 dbg_return_ifm (jo->map, ~0, "Cannot remove (from) a cached object");
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
710
711 if ((p = jo->parent))
712 {
713 /* Fix counters when parent is an array. */
714 if (p->type == U_JSON_TYPE_ARRAY)
715 p->count -= 1;
716
717 /* Evict from the parent container. */
718 TAILQ_REMOVE(&p->children, jo, siblings);
719 }
720
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
721 /* Give back the resources allocated to the node (and its children). */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
722 u_json_free(jo);
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
723
724 return 0;
725 }
726
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
727 /** \brief Create new JSON string object. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
728 int u_json_new_string (const char *key, const char *val, u_json_t **pjo)
729 {
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
730 return u_json_new_atom(U_JSON_TYPE_STRING, key, val, 0, pjo);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
731 }
732
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
733 /** \brief Create new JSON number object. */
734 int u_json_new_number (const char *key, const char *val, u_json_t **pjo)
735 {
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
736 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, val, 0, pjo);
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
737 }
738
739 /** \brief Create new JSON number object from double precision FP number. */
740 int u_json_new_real (const char *key, double val, u_json_t **pjo)
741 {
742 char sval[U_TOKEN_SZ];
743
744 /* CHECK FORMAT STRING
745 * especially against json specs about '0' handling after the '.' */
746 dbg_return_if (u_snprintf(sval, sizeof sval, "%f", val), ~0);
747
748 /* Assume 'sval' correctly formatted (no need to validate). */
749 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, 0, pjo);
750 }
751
752 /** \brief Create new JSON number object from long integer. */
753 int u_json_new_int (const char *key, long val, u_json_t **pjo)
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
754 {
755 char sval[U_TOKEN_SZ];
756
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
757 /* CHECK FORMAT STRING */
758 dbg_return_if (u_snprintf(sval, sizeof sval, "%ld", val), ~0);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
759
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
760 /* Assume 'sval' correctly formatted (no need to validate). */
761 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, 0, pjo);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
762 }
763
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
764 /** \brief Create new JSON null object. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
765 int u_json_new_null (const char *key, u_json_t **pjo)
766 {
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
767 /* No need to validate. */
768 return u_json_new_atom(U_JSON_TYPE_NULL, key, NULL, 0, pjo);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
769 }
770
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
771 /** \brief Create new JSON true or false object. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
772 int u_json_new_bool (const char *key, char val, u_json_t **pjo)
773 {
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
774 /* No need to validate. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
775 return u_json_new_atom(val ? U_JSON_TYPE_TRUE : U_JSON_TYPE_FALSE,
bbe6d6a @babongo JSON setters
babongo authored Jun 29, 2010
776 key, NULL, 0, pjo);
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
777 }
778
7d44b4d @babongo * handle conditional dependency of json on hmap;
babongo authored Jun 27, 2010
779 /**
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
780 * \}
781 */
782
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
783 static int u_json_do_encode (u_json_t *jo, u_string_t *s)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
784 {
785 if (jo == NULL)
786 return 0;
787
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
788 /* Optional key. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
789 if (strlen(jo->key))
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
790 dbg_err_if (u_string_aprintf(s, "\"%s\": ", jo->key));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
791
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
792 /* Value. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
793 switch (jo->type)
794 {
795 case U_JSON_TYPE_STRING:
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
796 dbg_err_if (u_string_aprintf(s, "\"%s\"", jo->val));
797 break;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
798 case U_JSON_TYPE_NUMBER:
799 dbg_err_if (u_string_aprintf(s, "%s", jo->val));
800 break;
801 case U_JSON_TYPE_OBJECT:
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
802 dbg_err_if (u_string_aprintf(s, "{ "));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
803 break;
804 case U_JSON_TYPE_ARRAY:
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
805 dbg_err_if (u_string_aprintf(s, "[ "));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
806 break;
807 case U_JSON_TYPE_TRUE:
808 dbg_err_if (u_string_aprintf(s, "true"));
809 break;
810 case U_JSON_TYPE_FALSE:
811 dbg_err_if (u_string_aprintf(s, "false"));
812 break;
813 case U_JSON_TYPE_NULL:
814 dbg_err_if (u_string_aprintf(s, "null"));
815 break;
816 default:
817 dbg_err("!");
818 }
819
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
820 /* Explore depth. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
821 dbg_err_if (u_json_do_encode(TAILQ_FIRST(&jo->children), s));
822
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
823 /* Close matching paren. */
824 switch (jo->type)
825 {
826 case U_JSON_TYPE_ARRAY:
827 dbg_err_if (u_string_aprintf(s, " ]"));
828 break;
829 case U_JSON_TYPE_OBJECT:
830 dbg_err_if (u_string_aprintf(s, " }"));
831 break;
832 default:
833 break;
834 }
835
836 /* When needed, add comma to separate siblings. */
837 if (TAILQ_NEXT(jo, siblings))
838 dbg_err_if (u_string_aprintf(s, ", "));
839
840 /* Explore horizontally. */
841 dbg_err_if (u_json_do_encode(TAILQ_NEXT(jo, siblings), s));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
842
843 return 0;
844 err:
845 return ~0;
846 }
847
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
848 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
849 {
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
850 /* 'jo' can be NULL in case of a validating-only parser. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
851 dbg_return_if (jl == NULL, ~0);
852
853 if (u_json_match_string_first(jl))
854 warn_err_if (u_json_match_string(jl, jo));
855 else if (u_json_match_number_first(jl))
856 warn_err_if (u_json_match_number(jl, jo));
857 else if (u_json_match_object_first(jl))
858 warn_err_if (u_json_match_object(jl, jo));
859 else if (u_json_match_array_first(jl))
860 warn_err_if (u_json_match_array(jl, jo));
861 else if (u_json_match_true_first(jl))
862 warn_err_if (u_json_match_true(jl, jo));
863 else if (u_json_match_false_first(jl))
864 warn_err_if (u_json_match_false(jl, jo));
865 else if (u_json_match_null_first(jl))
866 warn_err_if (u_json_match_null(jl, jo));
867 else
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
868 U_LEXER_ERR(jl, "value not found at \'%s\'", u_lexer_lookahead(jl));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
869
870 return 0;
871 err:
872 return ~0;
873 }
874
875 static int u_json_match_array_first (u_lexer_t *jl)
876 {
877 return (u_lexer_peek(jl) == '[');
878 }
879
880 static int u_json_match_object_first (u_lexer_t *jl)
881 {
882 return (u_lexer_peek(jl) == '{');
883 }
884
885 static int u_json_match_number_first (u_lexer_t *jl)
886 {
887 char r, c = u_lexer_peek(jl);
888
889 if ((r = (c == '-' || isdigit(c))))
890 u_lexer_record_lmatch(jl);
891
892 return r;
893 }
894
895 static int u_json_match_pair_first (u_lexer_t *jl)
896 {
897 return u_json_match_string_first(jl);
898 }
899
900 static int u_json_match_false_first (u_lexer_t *jl)
901 {
902 return (u_lexer_peek(jl) == 'f');
903 }
904
905 static int u_json_match_true_first (u_lexer_t *jl)
906 {
907 return (u_lexer_peek(jl) == 't');
908 }
909
910 static int u_json_match_null_first (u_lexer_t *jl)
911 {
912 return (u_lexer_peek(jl) == 'n');
913 }
914
915 static int u_json_match_string_first (u_lexer_t *jl)
916 {
917 char r, c = u_lexer_peek(jl);
918
919 if ((r = (c == '"')))
920 u_lexer_record_lmatch(jl);
921
922 return r;
923 }
924
925 /* number ::= INT[FRAC][EXP] */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
926 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
927 {
928 char match[U_TOKEN_SZ];
929
930 /* INT is mandatory */
931 warn_err_if (u_json_match_int(jl));
932
933 /* c IN first(FRAC) */
934 if (u_json_match_frac_first(u_lexer_peek(jl)))
935 warn_err_if (u_json_match_frac(jl));
936
937 /* c IN first(EXP) */
938 if (u_json_match_exp_first(u_lexer_peek(jl)))
939 warn_err_if (u_json_match_exp(jl));
940
941 /* Register right side of the matched number. */
942 u_lexer_record_rmatch(jl);
943
944 /* Take care of the fact that the match includes the first non-number char
945 * (see u_json_match_{int,exp,frac} for details). */
946 (void) u_lexer_get_match(jl, match);
947 match[strlen(match) - 1] = '\0';
948
949 /* Push the matched number into the supplied json object. */
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
950 if (jo)
951 {
952 warn_err_if (u_json_set_type(jo, U_JSON_TYPE_NUMBER));
953 warn_err_if (u_json_set_val(jo, match));
954 }
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
955
956 #ifdef U_JSON_LEX_DEBUG
957 u_con("matched number: %s", u_lexer_get_match(jl, match));
958 #endif /* U_JSON_LEX_DEBUG */
959
960 return 0;
961 err:
962 return ~0;
963 }
964
965 static int u_json_match_int (u_lexer_t *jl)
966 {
967 char c = u_lexer_peek(jl);
968
969 /* optional minus sign */
970 if (c == '-')
971 U_LEXER_NEXT(jl, &c);
972
973 /* on '0' as the first char, we're done */
974 if (c == '0')
975 {
976 U_LEXER_NEXT(jl, &c);
977 goto end;
978 }
979
980 /* [1-9][0-9]+ */
981 if (c >= 48 && c <= 57)
982 do { U_LEXER_NEXT(jl, &c); } while (isdigit(c));
983 else
984 U_LEXER_ERR(jl, "bad int syntax at %s", u_lexer_lookahead(jl));
985
986 /* fall through */
987 end:
988 return 0;
989 err:
990 return ~0;
991 }
992
993 static int u_json_match_exp_first (char c)
994 {
995 return (c == 'e' || c == 'E');
996 }
997
998 static int u_json_match_frac_first (char c)
999 {
1000 return (c == '.');
1001 }
1002
1003 static int u_json_match_frac (u_lexer_t *jl)
1004 {
1005 char c = u_lexer_peek(jl);
1006
1007 /* Mandatory dot. */
1008 if (c != '.')
1009 U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
1010
1011 U_LEXER_NEXT(jl, &c);
1012
1013 /* [0-9] */
1014 if (!isdigit(c))
1015 U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
1016
1017 /* [0-9]* */
1018 while (isdigit(c))
1019 U_LEXER_NEXT(jl, &c);
1020
1021 return 0;
1022 err:
1023 return ~0;
1024 }
1025
1026 static int u_json_match_exp (u_lexer_t *jl)
1027 {
1028 char c = u_lexer_peek(jl);
1029
1030 /* [eE] */
1031 if (c != 'e' && c != 'E')
1032 U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
1033
1034 U_LEXER_NEXT(jl, &c);
1035
1036 /* Optional plus/minus sign. */
1037 if (c == '+' || c == '-')
1038 U_LEXER_NEXT(jl, &c);
1039
1040 /* [0-9] */
1041 if (!isdigit(c))
1042 U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
1043
1044 /* [0-9]* */
1045 while (isdigit(c))
1046 U_LEXER_NEXT(jl, &c);
1047
1048 return 0;
1049 err:
1050 return ~0;
1051 }
1052
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1053 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type,
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1054 char first, const char *rem, size_t rem_sz)
1055 {
1056 char c;
1057 size_t i = 0;
1058
1059 if ((c = u_lexer_peek(jl)) != first)
1060 {
1061 U_LEXER_ERR(jl, "expect \'%c\', got %c at %s",
1062 first, c, u_lexer_lookahead(jl));
1063 }
1064
1065 for (i = 0; i < rem_sz; i++)
1066 {
1067 U_LEXER_SKIP(jl, &c);
1068 if (c != *(rem + i))
1069 {
1070 U_LEXER_ERR(jl, "expect \'%c\', got %c at %s",
1071 *(rem + i), c, u_lexer_lookahead(jl));
1072 }
1073 }
1074
1075 /* Consume last checked char. */
1076 U_LEXER_SKIP(jl, NULL);
1077
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1078 if (jo)
1079 warn_err_if (u_json_set_type(jo, type));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1080
1081 #ifdef U_JSON_LEX_DEBUG
1082 u_con("matched \'%s\' sequence", u_json_type_str(type));
1083 #endif /* U_JSON_LEX_DEBUG */
1084 return 0;
1085 err:
1086 return ~0;
1087 }
1088
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1089 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1090 {
1091 return u_json_match_seq(jl, jo, U_JSON_TYPE_NULL,
1092 'n', "ull", strlen("ull"));
1093 }
1094
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1095 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1096 {
1097 return u_json_match_seq(jl, jo, U_JSON_TYPE_TRUE,
1098 't', "rue", strlen("rue"));
1099 }
1100
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1101 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1102 {
1103 return u_json_match_seq(jl, jo, U_JSON_TYPE_FALSE,
1104 'f', "alse", strlen("alse"));
1105 }
1106
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1107 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1108 {
1109 char c;
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1110 u_json_t *elem = NULL;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1111
1112 #ifdef U_JSON_LEX_DEBUG
1113 u_con("ARRAY");
1114 #endif /* U_JSON_LEX_DEBUG */
1115
1116 if ((c = u_lexer_peek(jl)) != '[')
1117 {
1118 U_LEXER_ERR(jl, "expect \'[\', got %c at %s",
1119 c, u_lexer_lookahead(jl));
1120 }
1121
1122 /* Parent object is an array. */
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1123 warn_err_if (u_json_set_type(jo, U_JSON_TYPE_ARRAY));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1124
1125 do {
1126 U_LEXER_SKIP(jl, &c);
1127
1128 if (c == ']') /* break on empty array */
1129 break;
1130
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1131 if (jo)
1132 {
1133 /* Create a new object to store next array element. */
1134 warn_err_if (u_json_new(&elem));
1135 warn_err_if (u_json_set_type(elem, U_JSON_TYPE_UNKNOWN));
1136 }
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1137
1138 /* Fetch new value. */
1139 warn_err_if (u_json_match_value(jl, elem));
1140
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1141 if (jo)
1142 {
1143 /* Push the fetched element to its parent array. */
1144 warn_err_if (u_json_add(jo, elem));
1145 elem = NULL;
1146 }
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1147
1148 /* Consume any trailing white spaces. */
1149 if (isspace(u_lexer_peek(jl)))
1150 U_LEXER_SKIP(jl, NULL);
1151
1152 } while (u_lexer_peek(jl) == ',');
1153
1154 if ((c = u_lexer_peek(jl)) != ']')
1155 {
1156 U_LEXER_ERR(jl, "expect \']\', got %c at %s",
1157 c, u_lexer_lookahead(jl));
1158 }
1159
2d8e2ce [libu] json += unit test
tho authored May 28, 2010
1160 /* Ignore EOT, shall be catched later. */
1161 (void) u_lexer_skip(jl, NULL);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1162
1163 return 0;
1164 err:
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1165 u_json_free(elem);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1166 return ~0;
1167 }
1168
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1169 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1170 {
1171 char c;
1172
1173 #ifdef U_JSON_LEX_DEBUG
1174 u_con("OBJECT");
1175 #endif /* U_JSON_LEX_DEBUG */
1176
1177 if ((c = u_lexer_peek(jl)) != '{')
1178 {
1179 U_LEXER_ERR(jl, "expect \'{\', got %c at %s",
1180 c, u_lexer_lookahead(jl));
1181 }
1182
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1183 if (jo)
1184 warn_err_if (u_json_set_type(jo, U_JSON_TYPE_OBJECT));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1185
1186 do {
1187 U_LEXER_SKIP(jl, &c);
1188
1189 /* Break on empty object. */
1190 if (c == '}')
1191 break;
1192
1193 /* Process assignement. */
1194 warn_err_if (!u_json_match_pair_first(jl) || u_json_match_pair(jl, jo));
1195
1196 /* Consume trailing white spaces, if any. */
1197 if (isspace(u_lexer_peek(jl)))
1198 U_LEXER_SKIP(jl, NULL);
1199
1200 } while (u_lexer_peek(jl) == ',');
1201
1202 if ((c = u_lexer_peek(jl)) != '}')
1203 {
1204 U_LEXER_ERR(jl, "expect \'}\', got %c at %s",
1205 c, u_lexer_lookahead(jl));
1206 }
1207
2d8e2ce [libu] json += unit test
tho authored May 28, 2010
1208 /* Ignore EOT, shall be catched later. */
1209 (void) u_lexer_skip(jl, NULL);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1210
1211 return 0;
1212 err:
1213 return ~0;
1214 }
1215
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1216 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1217 {
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1218 size_t mlen;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1219 char c, match[U_TOKEN_SZ];
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1220 u_json_t *pair = NULL;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1221
1222 dbg_return_if (jl == NULL, ~0);
1223
1224 #ifdef U_JSON_LEX_DEBUG
1225 u_con("PAIR");
1226 #endif /* U_JSON_LEX_DEBUG */
1227
1228 /* Here we use the matched string as the 'key' for the associated value,
1229 * hence there is no associated json object. */
1230 warn_err_if (u_json_match_string(jl, NULL));
1231
1232 /* Initialize new json object to store the key/value pair. */
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1233 if (jo)
1234 warn_err_if (u_json_new(&pair));
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1235
1236 (void) u_lexer_get_match(jl, match);
1237
1238 /* Trim trailing '"'. */
1239 if ((mlen = strlen(match)) >= 1)
1240 match[mlen - 1] = '\0';
1241
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1242 if (jo)
1243 warn_err_if (u_json_set_key(pair, match));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1244
1245 /* Consume ':' */
1246 if ((c = u_lexer_peek(jl)) != ':')
1247 {
1248 U_LEXER_ERR(jl, "expect \':\', got %c at %s",
1249 c, u_lexer_lookahead(jl));
1250 }
1251
1252 U_LEXER_SKIP(jl, &c);
1253
1254 /* Assign value. */
1255 warn_err_if (u_json_match_value(jl, pair));
1256
1257 /* Push the new value to the parent json object. */
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1258 if (jo)
1259 {
1260 warn_err_if (u_json_add(jo, pair));
1261 pair = NULL;
1262 }
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1263
1264 return 0;
1265 err:
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1266 u_json_free(pair);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1267 return ~0;
1268 }
1269
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1270 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1271 {
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1272 size_t mlen;
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1273 char c, match[U_TOKEN_SZ];
1274
1275 /* In case string is matched as an lval (i.e. the key side of a 'pair'),
1276 * there is no json object. */
1277 dbg_return_if (jl == NULL, ~0);
1278
1279 #ifdef U_JSON_LEX_DEBUG
1280 u_con("STRING");
1281 #endif /* U_JSON_LEX_DEBUG */
1282
1283 if ((c = u_lexer_peek(jl)) != '"')
1284 U_LEXER_ERR(jl, "expect \", got %c at %s", c, u_lexer_lookahead(jl));
1285
1286 U_LEXER_NEXT(jl, &c);
1287
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1288 /* Re-record the left side match pointer (trim leading '"'). */
1289 u_lexer_record_lmatch(jl);
1290
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1291 while (c != '"')
1292 {
1293 if (c == '\\')
1294 {
1295 U_LEXER_NEXT(jl, &c);
1296 switch (c)
1297 {
1298 case 'u':
1299 warn_err_if (u_json_match_escaped_unicode(jl));
1300 break;
1301 case '"': case '\\': case '/': case 'b':
1302 case 'f': case 'n': case 'r': case 't':
1303 U_LEXER_NEXT(jl, &c);
1304 break;
1305 default:
1306 U_LEXER_ERR(jl, "invalid char %c in escape", c);
1307 }
1308 }
1309 else if (iscntrl(c))
1310 U_LEXER_ERR(jl, "control character in string", c);
1311 else
1312 U_LEXER_NEXT(jl, &c);
1313 }
1314
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1315 /* Record right match pointer.
1316 * This is a greedy match, which includes the trailing '"', and must
1317 * be taken into account when pulling out the string. */
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1318 u_lexer_record_rmatch(jl);
1319
1320 /* Consume last '"'. */
1321 U_LEXER_NEXT(jl, &c);
1322
1323 #ifdef U_JSON_LEX_DEBUG
1324 u_con("matched string: \'%s\'", u_lexer_get_match(jl, match));
1325 #endif /* U_JSON_LEX_DEBUG */
1326
1327 /* In case the string is matched as an rval, the caller shall
1328 * supply the json object that has to be set. */
1329 if (jo)
1330 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1331 warn_err_if (u_json_set_type(jo, U_JSON_TYPE_STRING));
7ee39db [libu] json += encoder completed ; cleaner string matching
tho authored May 27, 2010
1332
1333 /* Remove trailing '"' from match. */
1334 (void) u_lexer_get_match(jl, match);
1335
1336 /* Trim trailing '"'. */
1337 if ((mlen = strlen(match)) >= 1)
1338 match[mlen - 1] = '\0';
1339
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1340 warn_err_if (u_json_set_val(jo, match));
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1341 }
1342
1343 return 0;
1344 err:
1345 return ~0;
1346 }
1347
1348 static int u_json_match_escaped_unicode (u_lexer_t *jl)
1349 {
1350 char i, c;
1351
1352 for (i = 0; i < 4; i++)
1353 {
1354 U_LEXER_NEXT(jl, &c);
1355
1356 if (!isxdigit(c))
1357 U_LEXER_ERR(jl, "non hex digit %c in escaped unicode", c);
1358 }
1359
1360 return 0;
1361 err:
1362 return ~0;
1363 }
1364
1365 static const char *u_json_type_str (int type)
1366 {
1367 switch (type)
1368 {
1369 case U_JSON_TYPE_STRING: return "string";
1370 case U_JSON_TYPE_NUMBER: return "number";
1371 case U_JSON_TYPE_ARRAY: return "array";
1372 case U_JSON_TYPE_OBJECT: return "object";
1373 case U_JSON_TYPE_TRUE: return "true";
1374 case U_JSON_TYPE_FALSE: return "false";
1375 case U_JSON_TYPE_NULL: return "null";
1376 case U_JSON_TYPE_UNKNOWN: default: break;
1377 }
1378
1379 return "unknown";
1380 }
1381
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1382 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1383 {
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1384 u_unused_args(l, opaque);
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1385
1386 if (jo)
1387 u_free(jo);
1388
1389 return;
1390 }
1391
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1392 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque)
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1393 {
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1394 u_unused_args(opaque);
1395
dac025c [libu] json module integration (wip)
tho authored May 27, 2010
1396 dbg_return_if (jo == NULL, );
1397
1398 switch (jo->type)
1399 {
1400 case U_JSON_TYPE_ARRAY:
1401 case U_JSON_TYPE_OBJECT:
1402 /* No value. */
1403 u_con("%*c %s %s", l, ' ', u_json_type_str(jo->type), jo->key);
1404 break;
1405 default:
1406 u_con("%*c %s %s : \'%s\'", l, ' ',
1407 u_json_type_str(jo->type), jo->key, jo->val);
1408 break;
1409 }
1410
1411 return;
1412 }
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1413
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1414 static void u_json_do_index (u_json_t *jo, size_t l, void *map)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1415 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1416 u_json_t *p;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1417 u_hmap_t *hmap = (u_hmap_t *) map;
1418
1419 u_unused_args(l);
1420
1421 if ((p = jo->parent) == NULL)
1422 {
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
1423 /* Root node is named '.', its name and fully qualified name match. */
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1424 (void) u_strlcpy(jo->fqn, ".", sizeof jo->fqn);
1425 }
1426 else if (p->type == U_JSON_TYPE_OBJECT)
1427 {
1428 /* Nodes in object containers are named after their key. */
1429 dbg_if (u_snprintf(jo->fqn, sizeof jo->fqn, "%s.%s", p->fqn, jo->key));
1430 }
1431 else if (p->type == U_JSON_TYPE_ARRAY)
1432 {
1433 /* Nodes in array containers are named after their ordinal position. */
1434 dbg_if (u_snprintf(jo->fqn, sizeof jo->fqn, "%s[%u]", p->fqn, p->icur));
1435
1436 /* Increment the counting index in the parent array. */
1437 p->icur += 1;
1438
1439 /* In case we have an array inside another array, initialize the
1440 * counter for later recursive invocation. */
1441 if (jo->type == U_JSON_TYPE_ARRAY)
1442 jo->icur = 0;
1443 }
1444 else
1445 warn("Expecting an object, an array, or a top-level node.");
1446
1447 /* Insert node into the hmap. */
1448 dbg_if (u_hmap_easy_put(hmap, jo->fqn, (const void *) jo));
1449
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
1450 /* Stick the map pointer inside each visited node, so that it can
1451 * be readily referenced on retrieval. */
1452 jo->map = map;
1453
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1454 #ifdef U_JSON_IDX_DEBUG
d0490ad @babongo fragmented name match through namespace in JSON
babongo authored Jun 26, 2010
1455 u_con("%p => %s (%s) = %s", jo, jo->fqn, U_JSON_OBJ_NAME(jo), jo->val);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1456 #endif
1457
1458 return;
1459 }
1460
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1461 static int u_json_new_container (u_json_type_t type, const char *key,
1462 u_json_t **pjo)
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1463 {
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1464 u_json_t *jo = NULL;
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1465
1466 dbg_return_if (pjo == NULL, ~0);
1467
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1468 dbg_err_if (u_json_new(&jo));
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1469
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1470 dbg_err_if (u_json_set_type(jo, type));
1471 dbg_err_if (u_json_set_key(jo, key ? key : ""));
1472
1473 *pjo = jo;
1474
1475 return 0;
1476 err:
1477 if (jo)
1478 u_json_free(jo);
1479 return ~0;
1480 }
1481
1482 static int u_json_new_atom (u_json_type_t type, const char *key,
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
1483 const char *val, char check, u_json_t **pjo)
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1484 {
1485 u_json_t *jo = NULL;
1486
1487 dbg_return_if (pjo == NULL, ~0);
1488
1489 dbg_err_if (u_json_new(&jo));
1490
1491 dbg_err_if (u_json_set_type(jo, type));
1492 dbg_err_if (u_json_set_key(jo, key));
1493
1494 /* Values are meaningful only in case of string and number objects,
1495 * "null", "true" and "false" are completely defined by the type. */
1496 switch (type)
1497 {
1498 case U_JSON_TYPE_NUMBER:
1499 case U_JSON_TYPE_STRING:
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
1500 dbg_err_if (u_json_set_val_ex(jo, val, check));
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1501 default: break;
1502 }
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1503
1504 *pjo = jo;
1505
1506 return 0;
1507 err:
1508 if (jo)
0a84aaf @babongo JSON module hi-level logics (wip)
babongo authored Jun 28, 2010
1509 u_json_free(jo);
a63e435 @babongo JSON indexing interface wip (again)
babongo authored Jun 26, 2010
1510 return ~0;
1511 }
1512
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1513 static int u_json_do_parse (const char *json, u_json_t **pjo,
1514 char status[U_LEXER_ERR_SZ])
1515 {
1516 u_json_t *jo = NULL;
1517 u_lexer_t *jl = NULL;
1518
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
1519 /* When 'pjo' is NULL, assume this is a validating-only parser. */
c2f7aea @babongo json validator implemented
babongo authored Jun 29, 2010
1520 dbg_return_if (json == NULL, ~0);
1521
1522 /* Create a disposable lexer context associated to the supplied
1523 * 'json' string. */
1524 warn_err_if (u_lexer_new(json, &jl));
1525
1526 /* Create top level json object. */
1527 warn_err_if (pjo && u_json_new(&jo));
1528
1529 /* Consume any trailing white space before starting actual parsing. */
1530 if (u_lexer_eat_ws(jl) == -1)
1531 U_LEXER_ERR(jl, "Empty JSON text !");
1532
1533 /* Launch the lexer expecting the input JSON text as a serialized object
1534 * or array. */
1535 if (u_json_match_object_first(jl))
1536 warn_err_if (u_json_match_object(jl, jo));
1537 else if (u_json_match_array_first(jl))
1538 warn_err_if (u_json_match_array(jl, jo));
1539 else
1540 U_LEXER_ERR(jl, "Expect \'{\' or \'[\', got \'%c\'.", u_lexer_peek(jl));
1541
1542 /* Dispose the lexer context. */
1543 u_lexer_free(jl);
1544
1545 /* Copy out the broken down tree. */
1546 if (pjo)
1547 *pjo = jo;
1548
1549 return 0;
1550 err:
1551 /* Copy out the lexer error string (if requested). */
1552 if (status)
1553 (void) u_strlcpy(status, u_lexer_geterr(jl), U_LEXER_ERR_SZ);
1554
1555 u_lexer_free(jl);
1556 u_json_free(jo);
1557
1558 return ~0;
1559 }
3eaada8 @babongo u_json_set_val_ex interface added: provides the ability to syntax che…
babongo authored Jun 30, 2010
1560
1561
Something went wrong with that request. Please try again.