Skip to content
This repository
Newer
Older
100644 1958 lines (1604 sloc) 54.859 kb
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1 /*
8cc259c6 » stewy
2012-01-13 s/2011/2012
2 * Copyright (c) 2005-2012 by KoanLogic s.r.l. - All rights reserved.
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <ctype.h>
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
8 #include <math.h>
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
9
10 #include <toolbox/json.h>
11 #include <toolbox/carpal.h>
12 #include <toolbox/misc.h>
13 #include <toolbox/memory.h>
14 #include <toolbox/lexer.h>
15
16 /* Internal representation of any JSON value. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
17 struct u_json_s
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
18 {
19 u_json_type_t type;
20
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
21 char fqn[U_JSON_FQN_SZ]; /* Fully qualified name of this (sub)object. */
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
22 char key[U_TOKEN_SZ]; /* Local name, if applicable (i.e. !anon) */
23 char val[U_TOKEN_SZ]; /* If applicable, i.e. (!OBJECT && !ARRAY) */
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
24
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
25 /* Parent container. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
26 struct u_json_s *parent;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
27
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
28 /* Nodes at the same level as this one (if any). */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
29 TAILQ_ENTRY(u_json_s) siblings;
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
30
31 /* Children nodes' list when i.e. (ARRAY || OBJECT). */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
32 TAILQ_HEAD(u_json_chld_s, u_json_s) children;
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
33
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
34 unsigned int depth; /* Depth of this node in the decoded tree. */
35
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
36 /* Cacheing machinery. */
37 unsigned int icur, count; /* Aux stuff used when indexing arrays. */
38 u_hmap_t *map; /* Alias reference to the global cache. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
39 };
40
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
41 /* Pointer to the name part of .fqn */
42 #define U_JSON_OBJ_NAME(jo) \
43 ((jo->parent != NULL) ? jo->fqn + strlen(p->fqn) : jo->fqn)
44
45 #define U_JSON_OBJ_IS_CONTAINER(jo) \
46 ((jo->type == U_JSON_TYPE_OBJECT) || (jo->type == U_JSON_TYPE_ARRAY))
47
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
48 #define U_JSON_OBJ_IS_BOOL(jo) \
49 ((jo->type == U_JSON_TYPE_TRUE) || (jo->type == U_JSON_TYPE_FALSE))
50
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
51 /* Lexer methods */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
52 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
53 static int u_json_match_number_first (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
54 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
55 static int u_json_match_int (u_lexer_t *jl);
56 static int u_json_match_frac_first (char c);
57 static int u_json_match_frac (u_lexer_t *jl);
58 static int u_json_match_exp_first (char c);
59 static int u_json_match_exp (u_lexer_t *jl);
60 static int u_json_match_true_first (u_lexer_t *jl);
61 static int u_json_match_false_first (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
62 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo);
63 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
64 static int u_json_match_null_first (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
65 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo);
66 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
67 static int u_json_match_string_first (u_lexer_t *jl);
68 static int u_json_match_escaped_unicode (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
69 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
70 static int u_json_match_object_first (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
71 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
72 static int u_json_match_array_first (u_lexer_t *jl);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
73 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
74 static int u_json_match_pair_first (u_lexer_t *jl);
75
76 /* Lexer misc stuff. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
77 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type,
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
78 char first, const char *rem, size_t rem_sz);
79 static const char *u_json_type_str (int type);
80
81 /* Objects misc stuff. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
82 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque);
83 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque);
84 static void u_json_do_index (u_json_t *jo, size_t l, void *map);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
85
c2f7aea1 » babongo
2010-06-29 json validator implemented
86 /* Encode/Decode/Validate. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
87 static int u_json_do_encode (u_json_t *jo, u_string_t *s);
c2f7aea1 » babongo
2010-06-29 json validator implemented
88 static int u_json_do_parse (const char *json, u_json_t **pjo,
89 char status[U_LEXER_ERR_SZ]);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
90
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
91 /* Needed by hmap_easy* because we are storing pointer data not owned by the
92 * hmap. */
bbe6d6ac » babongo
2010-06-29 JSON setters
93 static void nopf (void *dummy) { u_unused_args(dummy); return; }
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
94
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
95 static int u_json_new_container (u_json_type_t type, const char *key,
96 u_json_t **pjo);
97 static int u_json_new_atom (u_json_type_t type, const char *key,
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
98 const char *val, char check, u_json_t **pjo);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
99
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
100 static int u_json_set_depth (u_json_t *jo, unsigned int depth);
101
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
102 /**
103 \defgroup json JSON
104 \{
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
105 The \ref json module implements a family of routines that allow
106 encoding, decoding and validation of JSON objects as defined in
107 <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>.
108
042914fa » babongo
2010-07-01 JSON doxy += sections
109
110 \section decode Decoding
111
112 A NUL-terminated string in JSON syntax is decoded into its parse
113 tree by means of the ::u_json_decode function as the showed in the
114 following snippet:
115
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
116 \code
117 u_json_t *jo = NULL;
118 const char *i2 = "[ [ 1, 0 ], [ 0, 1 ] ]";
119
120 dbg_err_if (u_json_decode(i2, &jo));
121 \endcode
042914fa » babongo
2010-07-01 JSON doxy += sections
122
123
124 \section validate Validating
125
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
126 Should you just need to check the supplied string for syntax compliance
127 (i.e. without actually creating the syntax tree), the ::u_json_validate
128 interface can be used:
129 \code
130 char status[U_LEXER_ERR_SZ];
131
132 if (u_json_validate(i2, status))
133 u_con("Syntax error: %s", status);
134 \endcode
042914fa » babongo
2010-07-01 JSON doxy += sections
135
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
136 You should not use the validating interface on untrusted input.
137 In fact no maximum nesting depth is enforced on validation -- on the
138 contrary, the parsing interface has the compile-time define
d9e4a0e0 » babongo
2010-10-27 JSON max depth unit test added
139 ::U_JSON_MAX_DEPTH for such purpose -- so a malicious user could make your
025e39d8 » babongo
2010-10-27 release candidate 14
140 application stack explode by simply supplying a big-enough string made by
141 all \c '[' chars.
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
142 The intended use of the validating interface is for checking your
d9e4a0e0 » babongo
2010-10-27 JSON max depth unit test added
143 hand-crafted JSON strings before pushing them out, i.e. those you've
144 created without going through all the ::u_json_new -> ::u_json_add ->
145 ::u_json_encode chain.
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
146
042914fa » babongo
2010-07-01 JSON doxy += sections
147
148 \section cache Indexing
149
150 Once the string has been parsed and (implicitly or explicitly)
d9e4a0e0 » babongo
2010-10-27 JSON max depth unit test added
151 validated, should your application request frequent and/or massive access
042914fa » babongo
2010-07-01 JSON doxy += sections
152 to its deeply nested attributes, then you may want to create an auxiliary
153 index to the parse tree via ::u_json_index. This way its nodes can be
154 accessed via a unique (and unambiguous -- provided that no anonymous key is
155 embedded into the JSON object) naming scheme, similar to the typical
156 struct/array access in C, i.e.:
157 - "." is the root node;
158 - ".k" is used to access value in the parent object stored under the
159 key "k";
160 - "[i]" is used to access the i-th value in the parent array.
161
162 So, for example, the string ".I2[0][0]" would retrieve the value "1" from
163 "{ "I2": [ [ 1, 0 ], [ 0, 1 ] ] }".
164
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
165 \code
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
166 long l;
167
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
168 dbg_err_if (u_json_index(jo));
169
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
170 u_json_cache_get_int(jo, ".[0][0]", &l); // l = 1
171 u_json_cache_get_int(jo, ".[0][1]", &l); // l = 0
172 u_json_cache_get_int(jo, ".[1][0]", &l); // l = 0
173 u_json_cache_get_int(jo, ".[1][1]", &l); // l = 1
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
174 \endcode
042914fa » babongo
2010-07-01 JSON doxy += sections
175
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
176 Please note that when index'ed, the parse tree enters a "frozen" state
042914fa » babongo
2010-07-01 JSON doxy += sections
177 in which nothing but values and types of non-container objects (i.e.
178 string, number, boolean and null's) can be changed. So, if you want to
179 come back to full tree manipulation, you must remove the indexing structure
180 by means of ::u_json_deindex -- which invalidates any subsequent cached
181 access attempt.
182
183
184 \section build Building and Encoding
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
185
186 JSON objects can be created ex-nihil via the ::u_json_new_* family
187 of functions, and then encoded in their serialized form via the
188 ::u_json_encode interface:
189 \code
190 char *s = NULL;
191 u_json_t *root = NULL, *leaf = NULL;
192
193 dbg_err_if (u_json_new_object(NULL, &root));
194 dbg_err_if (u_json_new_int("integer", 999, &leaf));
195 dbg_err_if (u_json_add(root, leaf));
196 leaf = NULL;
197
198 // encode it, should give: "{ "integer": 999 }"
199 u_json_encode(root, &s);
200 \endcode
201
042914fa » babongo
2010-07-01 JSON doxy += sections
202
203 \section iter Iterators
204
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
205 The last basic concept that the user needs to know to work effectively with
206 the JSON module is iteration. Iterators allow efficient and safe traversal
207 of container types (i.e. arrays and objects), where a naive walk strategy
208 based on ::u_json_array_get_nth would instead lead to performance collapse
209 as access time is quadratic in the number of elements in the container.
042914fa » babongo
2010-07-01 JSON doxy += sections
210
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
211 \code
212 long i, e;
213 u_json_it_t jit;
214 u_json_t *jo = NULL, *cur;
215 const char *s = "[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]";
216
217 dbg_err_if (u_json_decode(s, &jo));
218
219 // init array iterator from first element and go forward.
220 dbg_err_if (u_json_it(u_json_child_first(jo), &jit));
221
222 for (i = 1; (cur = u_json_it_next(&jit)) != NULL; i++)
223 {
224 dbg_err_if (u_json_get_int(cur, &e));
5e6013d8 » babongo
2010-07-01 JSON doxy missing bits
225 dbg_err_if (e != i); // e = 1..10
7fc25fe2 » babongo
2010-07-01 JSON doxy intro
226 }
227 \endcode
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
228
229
230 \section rfcimpl RFC implementation
231
d9e4a0e0 » babongo
2010-10-27 JSON max depth unit test added
232 The following implementation choices have been made (re Section 4. of
233 RFC 4627):
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
234
235 <table>
236 <tr>
237 <th>MAY</th>
238 <th>Answer</th>
239 <th>Notes</th>
240 </tr>
241 <tr>
242 <td>Accept non-JSON forms or extensions ?</td>
243 <td><b>NO</b></td>
244 <td>
245 Trailing non-JSON text is allowed (though warned) at the end of
d9e4a0e0 » babongo
2010-10-27 JSON max depth unit test added
246 string. I.e. the input string in scanned until the outermost
247 container is matched.
9634cd1e » babongo
2010-10-27 JSON doxy bits ++
248 </td>
249 </tr>
250 <tr>
251 <td>Set limits on the size of accepted texts ?</td>
252 <td><b>NO</b></td>
253 <td>
254 Depending only upon the memory available to the parsing process.
255 </td>
256 </tr>
257 <tr>
258 <td>Set limits on the maximum depth of nesting ?</td>
259 <td><b>YES</b></td>
260 <td>
261 Made available to the parsing interface through the compile-time
262 constant ::U_JSON_MAX_DEPTH. The validating interface ignores this
263 limit, and as such should be used with care (i.e. never on untrusted
264 input).
265 </td>
266 </tr>
267 <tr>
268 <td>Set limits on the range of numbers ?</td>
269 <td><b>NO</b></td>
270 <td>
271 All numerical values are stored as strings. Truncation/conversion
272 issues can arise only when trying to extract their \c long or
273 \c double counterparts through the ::u_json_get_int or
274 ::u_json_get_real commodity interfaces. In case they fail you can
275 still access the original (C-string) value through ::u_json_get_val.
276 </td>
277 </tr>
278 <tr>
279 <td>Set limits on the length and character contents of strings ?</td>
280 <td><b>YES</b></td>
281 <td>
282 String length for both keys and values are upper-bounded by
283 the compile-time constant ::U_TOKEN_SZ.
284 </td>
285 </tr>
286 </table>
287
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
288 */
289
290 /**
291 * \brief Create a new and empty JSON object container
292 *
293 * Create a new and empty JSON object container and return its handler as
294 * the result argument \p *pjo
295 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
296 * \param pjo Pointer to the ::u_json_t that will be returned
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
297 *
298 * \retval ~0 on failure
299 * \retval 0 on success
300 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
301 int u_json_new (u_json_t **pjo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
302 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
303 u_json_t *jo = NULL;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
304
305 dbg_return_if (pjo == NULL, ~0);
306
307 warn_err_sif ((jo = u_zalloc(sizeof *jo)) == NULL);
308 TAILQ_INIT(&jo->children);
309 jo->type = U_JSON_TYPE_UNKNOWN;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
310 jo->key[0] = jo->val[0] = jo->fqn[0] = '\0';
311 jo->parent = NULL;
312 jo->map = NULL;
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
313 jo->count = 0;
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
314 jo->depth = 0;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
315
316 *pjo = jo;
317
318 return 0;
319 err:
320 if (jo)
321 u_free(jo);
322 return ~0;
323 }
324
325 /**
326 * \brief Set the type of a JSON object
327 *
328 * Set the type of the supplied JSON object \p jo to \p type.
329 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
330 * \param jo Pointer to a ::u_json_t object
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
331 * \param type One of the available ::u_json_type_t types
332 *
333 * \retval ~0 on failure
334 * \retval 0 on success
335 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
336 int u_json_set_type (u_json_t *jo, u_json_type_t type)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
337 {
338 dbg_return_if (jo == NULL, ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
339 dbg_return_ifm (jo->map, ~0, "Cannot set type of a cached object");
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
340
341 switch (type)
342 {
343 case U_JSON_TYPE_STRING:
344 case U_JSON_TYPE_NUMBER:
345 case U_JSON_TYPE_ARRAY:
346 case U_JSON_TYPE_OBJECT:
347 case U_JSON_TYPE_TRUE:
348 case U_JSON_TYPE_FALSE:
349 case U_JSON_TYPE_NULL:
350 case U_JSON_TYPE_UNKNOWN:
351 jo->type = type;
352 break;
353 default:
354 u_err("unhandled type %d", type);
355 return ~0;
356 }
357
358 return 0;
359 }
360
361 /**
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
362 * \brief ::u_json_set_val_ex wrapper with no \p val syntax check
363 */
364 int u_json_set_val (u_json_t *jo, const char *val)
365 {
366 return u_json_set_val_ex(jo, val, 0);
367 }
368
369 /*
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
370 * \brief Set the value of a JSON object
371 *
372 * Set the value of the JSON object \p jo to the string value pointed by
373 * \p val. This operation is meaningful only in case the underlying object
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
374 * is a number or a string, in which case the syntax of the supplied value
375 * can be checked by passing non-0 value to the \p check parameter.
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
376 *
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
377 * \param jo Pointer to a ::u_json_t object
378 * \param val Pointer to the (non-NULL) value string
379 * \param check Set to non-0 if you need to syntax check \p val
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
380 *
381 * \retval ~0 on failure
382 * \retval 0 on success
383 */
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
384 int u_json_set_val_ex (u_json_t *jo, const char *val, char check)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
385 {
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
386 u_lexer_t *vl = NULL;
387
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
388 dbg_return_if (jo == NULL, ~0);
389 dbg_return_if (val == NULL, ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
390 /* Note that cached objects allow for value overwrite. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
391
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
392 if (check)
393 {
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
394 /* XXX The following declaration assumes C99 or C89+support of variable
395 * length automatic arrays -- as in GCC since at least version
396 * 2.95.3. */
397 char qval[strlen(val) + 3];
398
399 /* If we are supposed to set a string value, we need to quote it. */
201901e0 » babongo
2010-10-16 fix json number validator on setter
400 (void) u_snprintf(qval, sizeof qval,
401 (jo->type == U_JSON_TYPE_STRING) ? "\"%s\"" : "%s", val);
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
402
403 dbg_err_if (u_lexer_new(qval, &vl));
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
404 }
405
406 /* If requested, pass 'val' through its validator. */
407 switch (jo->type)
408 {
409 case U_JSON_TYPE_STRING:
410 dbg_err_if (check && u_json_match_string(vl, NULL));
411 break;
412 case U_JSON_TYPE_NUMBER:
413 dbg_err_if (check && u_json_match_number(vl, NULL));
414 break;
415 default:
416 /* Non-critical error, just emit some debug info. */
417 goto end;
418 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
419
420 dbg_return_if (u_strlcpy(jo->val, val, sizeof jo->val), ~0);
421
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
422 /* Fall through. */
423 end:
5b5f6327 » babongo
2010-10-16 fix memory leak in json encoder
424 u_lexer_free(vl);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
425 return 0;
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
426 err:
5b5f6327 » babongo
2010-10-16 fix memory leak in json encoder
427 u_lexer_free(vl);
3eaada8e » babongo
2010-06-30 u_json_set_val_ex interface added: provides the ability to syntax che…
428 return ~0;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
429 }
430 /**
431 * \brief Set the key of a JSON object
432 *
433 * Set the key of the JSON object \p jo to the string value pointed by
434 * \p key.
435 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
436 * \param jo Pointer to a ::u_json_t object
bbe6d6ac » babongo
2010-06-29 JSON setters
437 * \param key Pointer to the key string. In case \p key \c NULL the value
438 * is reset to the empty string.
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
439 *
440 * \retval ~0 on failure
441 * \retval 0 on success
442 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
443 int u_json_set_key (u_json_t *jo, const char *key)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
444 {
445 dbg_return_if (jo == NULL, ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
446 dbg_return_ifm (jo->map, ~0, "Cannot set key of a cached object");
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
447
bbe6d6ac » babongo
2010-06-29 JSON setters
448 dbg_return_if (u_strlcpy(jo->key, key ? key : "", sizeof jo->key), ~0);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
449
450 return 0;
451 }
452
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
453 /** \brief Wrapper function that creates an array container.
454 * (\p key may be \c NULL). */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
455 int u_json_new_array (const char *key, u_json_t **pjo)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
456 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
457 return u_json_new_container(U_JSON_TYPE_ARRAY, key, pjo);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
458 }
459
460 /** \brief Wrapper function that creates an object container
461 * (\p key may be \c NULL). */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
462 int u_json_new_object (const char *key, u_json_t **pjo)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
463 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
464 return u_json_new_container(U_JSON_TYPE_OBJECT, key, pjo);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
465 }
466
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
467 /**
468 * \brief Add a child JSON object to its parent container
469 *
470 * Add the child JSON object \p jo to its parent container \p head.
471 *
472 * \param head Pointer to the parent container
473 * \param jo Pointer to the child JSON object that shall be attached
474 *
475 * \retval ~0 on failure
476 * \retval 0 on success
477 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
478 int u_json_add (u_json_t *head, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
479 {
480 dbg_return_if (head == NULL, ~0);
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
481 dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(head), ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
482 dbg_return_ifm (head->map, ~0, "Cannot add new child to a cached object");
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
483 dbg_return_if (jo == NULL, ~0);
484
485 #ifdef U_JSON_OBJ_DEBUG
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
486 u_con("chld (%p): %s {%s} added at depth %u",
487 jo, u_json_type_str(jo->type), jo->key, jo->depth);
488 u_con("prnt (%p): %s {%s} at depth %u\n",
489 head, u_json_type_str(head->type), head->key, head->depth);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
490 #endif /* U_JSON_OBJ_DEBUG */
491
492 TAILQ_INSERT_TAIL(&head->children, jo, siblings);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
493 jo->parent = head;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
494
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
495 /* Adjust children counter for array-type parents. */
496 if (head->type == U_JSON_TYPE_ARRAY)
497 head->count += 1;
498
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
499 return 0;
500 }
501
502 /**
503 * \brief Break down a JSON string into pieces
504 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
505 * Parse and (implicitly) validate the supplied JSON string \p json.
506 * In case of success, its internal representation is returned into the result
507 * argument \p *pjo.
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
508 *
509 * \param json A NUL-terminated string containing some serialized JSON
510 * \param pjo Result argument which will point to the internal
511 * representation of the parsed \p json string
512 *
513 * \retval ~0 on failure
514 * \retval 0 on success
515 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
516 int u_json_decode (const char *json, u_json_t **pjo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
517 {
c2f7aea1 » babongo
2010-06-29 json validator implemented
518 return u_json_do_parse(json, pjo, NULL);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
519 }
520
521 /**
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
522 * \brief Validate the supplied JSON string.
523 *
524 * Validate the supplied JSON string \p json. In case \p json contains
525 * invalid syntax, the parser/lexer error message is returned into \p status.
526 *
527 * \param json A NUL-terminated string containing some serialized JSON
528 * \param status In case of error, this result argument will contain an
529 * explanation message from the parser/lexer.
530 *
531 * \retval ~0 on failure
532 * \retval 0 on success
533 */
534 int u_json_validate (const char *json, char status[U_LEXER_ERR_SZ])
535 {
c2f7aea1 » babongo
2010-06-29 json validator implemented
536 /* Just try to validate the input string (do not build the tree). */
537 return u_json_do_parse(json, NULL, status);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
538 }
539
540 /**
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
541 * \brief Dispose any resource allocated to a JSON object
542 *
543 * Dispose any resource allocated to the supplied JSON object \p jo
544 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
545 * \param jo Pointer to the ::u_json_t object that must be free'd
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
546 *
547 * \return nothing
548 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
549 void u_json_free (u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
550 {
551 size_t dummy = 0;
552
553 if (jo == NULL)
554 return;
555
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
556 /* If there is an associated hmap free it. */
557 if (jo->map)
558 {
559 u_hmap_easy_free(jo->map);
560 jo->map = NULL;
561 }
562
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
563 /* Walk the tree in post order and free each node while we traverse. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
564 u_json_walk(jo, U_JSON_WALK_POSTORDER, dummy, u_json_do_free, NULL);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
565
566 return;
567 }
568
569 /**
570 * \brief Encode a JSON object
571 *
572 * Encode the supplied JSON object \p jo to the result string pointed by
573 * \p *ps
574 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
575 * \param jo Pointer to the ::u_json_t object that must be encoded
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
576 * \param ps serialized JSON text corresponding to \p jo
577 *
578 * \retval ~0 on failure
579 * \retval 0 on success
580 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
581 int u_json_encode (u_json_t *jo, char **ps)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
582 {
583 u_string_t *s = NULL;
584
585 dbg_return_if (jo == NULL, ~0);
586 dbg_return_if (ps == NULL, ~0);
587
588 dbg_err_if (u_string_create(NULL, 0, &s));
589 dbg_err_if (u_json_do_encode(jo, s));
ea36157c » babongo
2010-10-16 fix json encoded string copyout logics via new str::u_string_detach_cstr
590 *ps = u_string_detach_cstr(s);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
591
592 return 0;
593 err:
594 if (s)
595 u_string_free(s);
596 return ~0;
597 }
598
599 /**
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
600 * \brief Pre/post-order tree walker
601 *
602 * Traverse the supplied JSON object \p jo in pre/post-order, depending on
603 * \p strategy, invoking the callback function \p cb on each node.
604 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
605 * \param jo Pointer to ::u_json_t object to traverse
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
606 * \param strategy one of ::U_JSON_WALK_PREORDER or ::U_JSON_WALK_POSTORDER
607 * \param l depth level in the JSON tree (the root is at depth 0)
608 * \param cb function to invoke on each traversed node
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
609 * \param cb_args optional opaque data which will be supplied to \p cb
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
610 *
611 * \return nothing
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
612 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
613 void u_json_walk (u_json_t *jo, int strategy, size_t l,
614 void (*cb)(u_json_t *, size_t, void *), void *cb_args)
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
615 {
616 dbg_return_if (strategy != U_JSON_WALK_PREORDER &&
617 strategy != U_JSON_WALK_POSTORDER, );
618
619 if (jo == NULL)
620 return;
621
622 if (strategy == U_JSON_WALK_PREORDER && cb)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
623 cb(jo, l, cb_args);
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
624
625 /* When recurring into the children branch, increment depth by one. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
626 u_json_walk(TAILQ_FIRST(&jo->children), strategy, l + 1, cb, cb_args);
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
627
628 /* Siblings are at the same depth as the current node. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
629 u_json_walk(TAILQ_NEXT(jo, siblings), strategy, l, cb, cb_args);
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
630
631 if (strategy == U_JSON_WALK_POSTORDER && cb)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
632 cb(jo, l, cb_args);
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
633
634 return;
635 }
636
637 /**
638 * \brief Print to stderr the internal representation of a JSON object
639 *
640 * Print to stderr the supplied JSON object \p jo
641 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
642 * \param jo Pointer to the ::u_json_t object that must be printed
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
643 *
644 * \return nothing
645 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
646 void u_json_print (u_json_t *jo)
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
647 {
648 dbg_return_if (jo == NULL, );
649
650 /* Tree root is at '0' depth. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
651 u_json_walk(jo, U_JSON_WALK_PREORDER, 0, u_json_do_print, NULL);
bbf1dce2 » tho
2010-05-27 [libu] json += missing doxy
652
653 return;
654 }
655
656 /**
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
657 * \brief Index JSON object contents.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
658 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
659 * Index all contents of the supplied ::u_json_t top-level object \p jo.
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
660 * After data has been indexed, no more key/type modifications are possible
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
661 * on this object; instead, values of leaf nodes can still be changed.
662 * Also, either child node addition nor removal is possible after the object
663 * has been cached. If \p jo needs to be changed in aforementioned ways
664 * (type, key, addition or removal), it must be explicitly ::u_json_unindex'ed.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
665 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
666 * \param jo Pointer to the ::u_json_t object that must be indexed
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
667 *
668 * \return nothing
669 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
670 int u_json_index (u_json_t *jo)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
671 {
672 size_t u; /* Unused. */
4d62acad » babongo
2010-11-15 update u_connect_ex timeout on EINTR + hmap cleanup
673 u_hmap_opts_t *opts = NULL;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
674 u_hmap_t *hmap = NULL;
675
676 dbg_return_if (jo == NULL, ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
677 nop_return_if (jo->map, 0); /* If already cached, return ok. */
678 dbg_return_if (jo->parent, ~0); /* Cache can be created on top-objs only. */
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
679
680 /* Create the associative array. */
4d62acad » babongo
2010-11-15 update u_connect_ex timeout on EINTR + hmap cleanup
681 dbg_err_if (u_hmap_opts_new(&opts));
682 dbg_err_if (u_hmap_opts_set_val_type(opts, U_HMAP_OPTS_DATATYPE_POINTER));
683 dbg_err_if (u_hmap_opts_set_val_freefunc(opts, nopf));
684 dbg_err_if (u_hmap_easy_new(opts, &hmap));
685 opts = NULL;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
686
687 /* Initialize array elems' indexing. */
688 jo->icur = 0;
689
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
690 /* Walk the tree in pre-order and cache each node while we traverse. */
691 u_json_walk(jo, U_JSON_WALK_PREORDER, u, u_json_do_index, hmap);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
692
693 /* Attach the associative array to the top level object. */
694 jo->map = hmap, hmap = NULL;
695
696 return 0;
697 err:
4d62acad » babongo
2010-11-15 update u_connect_ex timeout on EINTR + hmap cleanup
698 if (opts)
699 u_hmap_opts_free(opts);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
700 if (hmap)
701 u_hmap_easy_free(hmap);
702 return ~0;
703 }
704
705 /**
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
706 * \brief Remove cache from JSON object.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
707 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
708 * Remove the whole cacheing machinery from the previously ::u_json_index'd
709 * ::u_json_t object \p jo.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
710 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
711 * \param jo Pointer to the ::u_json_t object that must be de-indexed
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
712 *
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
713 * \retval 0 on success
714 * \retval ~0 on failure
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
715 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
716 int u_json_unindex (u_json_t *jo)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
717 {
718 dbg_return_if (jo == NULL, ~0);
719 nop_return_if (jo->map == NULL, 0);
720
721 u_hmap_easy_free(jo->map);
722 jo->map = NULL;
723
724 return 0;
725 }
726
727 /**
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
728 * \brief Retrieve JSON node by its cache name.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
729 *
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
730 * Possibly retrieve a JSON node by its (fully qualified, or relative) cache
731 * \p name.
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
732 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
733 * \param jo Pointer to the ::u_json_t object that must be searched
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
734 * \param name name of the element that must be searched
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
735 *
736 * \return the retrieved JSON (sub)object on success; \c NULL in case \p key
737 * was not found
738 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
739 u_json_t *u_json_cache_get (u_json_t *jo, const char *name)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
740 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
741 u_json_t *res, *p;
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
742 char fqn[U_JSON_FQN_SZ];
743
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
744 dbg_return_if (jo == NULL, NULL);
745 dbg_return_if (jo->map == NULL, NULL);
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
746 dbg_return_if (name == NULL, NULL);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
747
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
748 if ((p = jo->parent) == NULL)
749 {
750 /* If 'jo' is top level, 'name' must be fully qualified. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
751 return (u_json_t *) u_hmap_easy_get(jo->map, name);
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
752 }
753
754 /* Else ('jo' != top): first try 'name' as it were fully qualified. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
755 if ((res = (u_json_t *) u_hmap_easy_get(jo->map, name)))
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
756 return res;
757
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
758 /* If 'name' is relative, we need to prefix it with the parent name
759 * space. */
d0490ad6 » babongo
2010-06-26 fragmented name match through namespace in JSON
760 dbg_if (u_snprintf(fqn, sizeof fqn, "%s%s", jo->fqn, name));
761
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
762 return (u_json_t *) u_hmap_easy_get(jo->map, fqn);
763 }
764
765 /**
766 * \brief Set JSON node's type and value by its cache name.
767 *
768 * Set type and value of the supplied JSON (leaf) node by its (fully qualified
769 * or relative) cache \p name. If \p type is ::U_JSON_TYPE_UNKNOWN the
770 * underlying type will be left untouched.
771 *
772 * \param jo Pointer to an ::u_json_t object
773 * \param name name of the element that must be set
774 * \param type new type (or ::U_JSON_TYPE_UNKNOWN if no type change)
775 * \param val new value. MUST be non-NULL in case we are setting a
776 * string a or number.
777 *
778 * \retval 0 on success
779 * \retval ~0 on failure
780 */
781 int u_json_cache_set_tv (u_json_t *jo, const char *name,
782 u_json_type_t type, const char *val)
783 {
784 u_json_t *res;
785
786 dbg_return_if (U_JSON_OBJ_IS_CONTAINER(jo), ~0);
787 dbg_return_if (type == U_JSON_TYPE_OBJECT || type == U_JSON_TYPE_ARRAY, ~0);
788 /* 'jo' and 'name' will be checked by u_json_cache_get();
789 * 'val' consistency is checked after type has been set. */
790
791 /* Retrieve the node. */
792 dbg_err_if ((res = u_json_cache_get(jo, name)) == NULL);
793
794 /* First set type (in case !unknown) so that we know how to check the
795 * subsequent value setting. */
796 if (type != U_JSON_TYPE_UNKNOWN)
797 res->type = type;
798
799 /* Set value. The caller must have supplied some non-NULL 'val' in case
800 * the final underlying type is a string or a number. */
801 if (res->type == U_JSON_TYPE_STRING || res->type == U_JSON_TYPE_NUMBER)
802 dbg_err_if (val == NULL || u_strlcpy(res->val, val, sizeof res->val));
803
804 return 0;
805 err:
806 return ~0;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
807 }
808
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
809 /** \brief Return the number of elements in array \p jo, or \c 0 on error. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
810 unsigned int u_json_array_count (u_json_t *jo)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
811 {
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
812 dbg_return_if (jo == NULL, 0);
813 dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, 0);
814
815 return jo->count;
816 }
817
818 /** \brief Get n-th element from \p jo array. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
819 u_json_t *u_json_array_get_nth (u_json_t *jo, unsigned int n)
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
820 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
821 u_json_t *elem;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
822
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
823 dbg_return_if (jo == NULL, NULL);
824 dbg_return_if (jo->type != U_JSON_TYPE_ARRAY, NULL);
825 dbg_return_if (n >= jo->count, NULL);
826
827 /* Use cache if available. */
828 if (jo->map)
829 {
830 char elem_fqn[U_JSON_FQN_SZ] = { '\0' };
831 dbg_if (u_snprintf(elem_fqn, sizeof elem_fqn, "%s[%u]", jo->fqn, n));
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
832 return u_json_cache_get(jo, elem_fqn);
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
833 }
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
834
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
835 /* Too bad if we don't have cache in place: we have to go through the
836 * list which is quadratic even with the following silly optimisation.
837 * So it's ok for a couple of lookups, but if done systematically it's
838 * an overkill. Freeze instead ! */
839 if (n > (jo->count / 2))
840 {
841 unsigned int r = jo->count - (n + 1);
842
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
843 TAILQ_FOREACH_REVERSE (elem, &jo->children, u_json_chld_s, siblings)
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
844 {
845 if (r == 0)
846 return elem;
847 r -= 1;
848 }
849 }
850 else
851 {
852 TAILQ_FOREACH (elem, &jo->children, siblings)
853 {
854 if (n == 0)
855 return elem;
856 n -= 1;
857 }
858 }
859
860 /* Unreachable. */
861 return NULL;
862 }
863
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
864 /** \brief Get the value associated with the non-container object \p jo. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
865 const char *u_json_get_val (u_json_t *jo)
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
866 {
867 dbg_return_if (jo == NULL, NULL);
868
869 switch (jo->type)
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
870 {
871 case U_JSON_TYPE_STRING:
872 case U_JSON_TYPE_NUMBER:
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
873 return jo->val;
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
874 case U_JSON_TYPE_TRUE:
875 return "true";
876 case U_JSON_TYPE_FALSE:
877 return "false";
878 case U_JSON_TYPE_NULL:
879 return "null";
880 case U_JSON_TYPE_OBJECT:
881 case U_JSON_TYPE_ARRAY:
882 case U_JSON_TYPE_UNKNOWN:
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
883 default:
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
884 return NULL;
885 }
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
886 }
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
887
88ba97e4 » babongo
2010-06-30 JSON += iterators; MISC += u_atol; JSON test += fixes.
888 /** \brief Get the \c long \c int value of the non-container object \p jo. */
889 int u_json_get_int (u_json_t *jo, long *pl)
890 {
891 dbg_return_if (jo == NULL, ~0);
892 dbg_return_if (jo->type != U_JSON_TYPE_NUMBER, ~0);
893 dbg_return_if (pl == NULL, ~0);
894
895 dbg_err_if (u_atol(jo->val, pl));
896
897 return 0;
898 err:
899 return ~0;
900 }
901
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
902 /** \brief Get the \c double precision FP value of the non-container object
903 * \p jo. */
904 int u_json_get_real (u_json_t *jo, double *pd)
905 {
906 dbg_return_if (jo == NULL, ~0);
907 dbg_return_if (jo->type != U_JSON_TYPE_NUMBER, ~0);
908 dbg_return_if (pd == NULL, ~0);
909
aab60aa6 » babongo
2010-07-01 MISC += u_atof interface; JSON += use u_atof interface in real number…
910 dbg_err_if (u_atof(jo->val, pd));
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
911
912 return 0;
aab60aa6 » babongo
2010-07-01 MISC += u_atof interface; JSON += use u_atof interface in real number…
913 err:
914 return ~0;
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
915 }
916
917 /** \brief Get the boolean value of the non-container object \p jo. */
918 int u_json_get_bool (u_json_t *jo, char *pb)
919 {
920 dbg_return_if (jo == NULL, ~0);
921 dbg_return_if (pb == NULL, ~0);
922
923 switch (jo->type)
924 {
925 case U_JSON_TYPE_TRUE:
926 *pb = 1;
927 break;
928 case U_JSON_TYPE_FALSE:
929 *pb = 0;
930 break;
931 default:
932 return ~0;
933 }
934
935 return 0;
936 }
937
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
938 /** \brief Wrapper around ::u_json_cache_get to retrieve string values from
939 * terminal (i.e. non-container) objects. */
940 const char *u_json_cache_get_val (u_json_t *jo, const char *name)
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
941 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
942 u_json_t *res = u_json_cache_get(jo, name);
a7093348 » babongo
2010-06-27 added array iteration primitives to JSON
943
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
944 return u_json_get_val(res);
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
945 }
946
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
947 /** \brief Wrapper around ::u_json_cache_get to retrieve integer values from
948 * terminal (i.e. non-container) objects. */
949 int u_json_cache_get_int (u_json_t *jo, const char *name, long *pval)
950 {
951 u_json_t *res;
952
953 dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
954
955 return u_json_get_int(res, pval);
956 }
957
958 /** \brief Wrapper around ::u_json_cache_get to retrieve double precision FP
959 * values from terminal (i.e. non-container) objects. */
960 int u_json_cache_get_real (u_json_t *jo, const char *name, double *pval)
961 {
962 u_json_t *res;
963
964 dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
965
966 return u_json_get_real(res, pval);
967 }
968
969 /** \brief Wrapper around ::u_json_cache_get to retrieve boolean values from
970 * terminal (i.e. non-container) objects. */
971 int u_json_cache_get_bool (u_json_t *jo, const char *name, char *pval)
972 {
973 u_json_t *res;
974
975 dbg_return_if ((res = u_json_cache_get(jo, name)) == NULL, ~0);
976
977 return u_json_get_bool(res, pval);
978 }
979
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
980 /**
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
981 * \brief Remove an object from its JSON container.
982 *
983 * Remove an object from its JSON container. This interface falls back to
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
984 * ::u_json_free in case the supplied \p jo is the root node.
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
985 *
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
986 * \param jo Pointer to the ::u_json_t object that must be removed
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
987 *
988 * \retval 0 on success
989 * \retval ~0 on failure
990 */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
991 int u_json_remove (u_json_t *jo)
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
992 {
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
993 u_json_t *p;
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
994
995 dbg_return_if (jo == NULL, ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
996 dbg_return_ifm (jo->map, ~0, "Cannot remove (from) a cached object");
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
997
998 if ((p = jo->parent))
999 {
1000 /* Fix counters when parent is an array. */
1001 if (p->type == U_JSON_TYPE_ARRAY)
1002 p->count -= 1;
1003
1004 /* Evict from the parent container. */
1005 TAILQ_REMOVE(&p->children, jo, siblings);
1006 }
1007
bbe6d6ac » babongo
2010-06-29 JSON setters
1008 /* Give back the resources allocated to the node (and its children). */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1009 u_json_free(jo);
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
1010
1011 return 0;
1012 }
1013
bbe6d6ac » babongo
2010-06-29 JSON setters
1014 /** \brief Create new JSON string object. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1015 int u_json_new_string (const char *key, const char *val, u_json_t **pjo)
1016 {
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1017 return u_json_new_atom(U_JSON_TYPE_STRING, key, val, 1, pjo);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1018 }
1019
bbe6d6ac » babongo
2010-06-29 JSON setters
1020 /** \brief Create new JSON number object. */
1021 int u_json_new_number (const char *key, const char *val, u_json_t **pjo)
1022 {
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1023 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, val, 1, pjo);
bbe6d6ac » babongo
2010-06-29 JSON setters
1024 }
1025
1026 /** \brief Create new JSON number object from double precision FP number. */
1027 int u_json_new_real (const char *key, double val, u_json_t **pjo)
1028 {
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1029 char sval[U_TOKEN_SZ], check = 0;
1030
1031 #ifdef HAVE_ISFINITE
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
1032 /* Use isfinite() to avoid infinity's and NaN's which would break the
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1033 * JSON syntax. */
1034 dbg_return_if (!isfinite(val), ~0);
1035 #else
1036 /* If isfinite() is not available (i.e. !C99), force check in
1037 * u_json_new_atom(). */
1038 check = 1;
1039 #endif /* HAVE_ISFINITE */
1040
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
1041 /* "%g" does exponential (i.e. [+-]d.d...dE[+-]dd) or fixed-point (i.e.
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1042 * [+-]d...d.d...d) notation depending on 'val'. Both should be compatible
8ee430d6 » babongo
2010-07-01 JSON += per-type getters (both simple and cached)
1043 * with JSON number spec. */
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1044 dbg_return_if (u_snprintf(sval, sizeof sval, "%g", val), ~0);
bbe6d6ac » babongo
2010-06-29 JSON setters
1045
d7c1a232 » babongo
2010-06-30 check conversion in JSON real numbers setter
1046 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, check, pjo);
bbe6d6ac » babongo
2010-06-29 JSON setters
1047 }
1048
1049 /** \brief Create new JSON number object from long integer. */
1050 int u_json_new_int (const char *key, long val, u_json_t **pjo)
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1051 {
1052 char sval[U_TOKEN_SZ];
1053
bbe6d6ac » babongo
2010-06-29 JSON setters
1054 dbg_return_if (u_snprintf(sval, sizeof sval, "%ld", val), ~0);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1055
bbe6d6ac » babongo
2010-06-29 JSON setters
1056 /* Assume 'sval' correctly formatted (no need to validate). */
1057 return u_json_new_atom(U_JSON_TYPE_NUMBER, key, sval, 0, pjo);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1058 }
1059
bbe6d6ac » babongo
2010-06-29 JSON setters
1060 /** \brief Create new JSON null object. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1061 int u_json_new_null (const char *key, u_json_t **pjo)
1062 {
bbe6d6ac » babongo
2010-06-29 JSON setters
1063 /* No need to validate. */
1064 return u_json_new_atom(U_JSON_TYPE_NULL, key, NULL, 0, pjo);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1065 }
1066
bbe6d6ac » babongo
2010-06-29 JSON setters
1067 /** \brief Create new JSON true or false object. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1068 int u_json_new_bool (const char *key, char val, u_json_t **pjo)
1069 {
bbe6d6ac » babongo
2010-06-29 JSON setters
1070 /* No need to validate. */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1071 return u_json_new_atom(val ? U_JSON_TYPE_TRUE : U_JSON_TYPE_FALSE,
bbe6d6ac » babongo
2010-06-29 JSON setters
1072 key, NULL, 0, pjo);
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1073 }
1074
88ba97e4 » babongo
2010-06-30 JSON += iterators; MISC += u_atol; JSON test += fixes.
1075 /** \brief Return the first child (if any) from the supplied container
1076 * \p jo. */
1077 u_json_t *u_json_child_first (u_json_t *jo)
1078 {
1079 dbg_return_if (jo == NULL, NULL);
1080 dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(jo), NULL);
1081
1082 return TAILQ_FIRST(&jo->children);
1083 }
1084
1085 /** \brief Return the last child (if any) from the supplied container
1086 * \p jo. */
1087 u_json_t *u_json_child_last (u_json_t *jo)
1088 {
1089 dbg_return_if (jo == NULL, NULL);
1090 dbg_return_if (!U_JSON_OBJ_IS_CONTAINER(jo), NULL);
1091
1092 return TAILQ_LAST(&jo->children, u_json_chld_s);
1093 }
1094
1095 /** \brief Initialize the iterator at \p it initially attached to \p jo. */
1096 int u_json_it (u_json_t *jo, u_json_it_t *it)
1097 {
1098 dbg_return_if (it == NULL, ~0);
1099
1100 it->cur = jo;
1101
1102 return 0;
1103 }
1104
1105 /** \brief Get JSON element under cursor and step cursor in the forward
1106 * direction. */
1107 u_json_t *u_json_it_next (u_json_it_t *it)
1108 {
1109 u_json_t *jo;
1110
1111 dbg_return_if (it == NULL, NULL);
1112
1113 if ((jo = it->cur) != NULL)
1114 it->cur = TAILQ_NEXT(jo, siblings);
1115
1116 return jo;
1117 }
1118
1119 /** \brief Get JSON element under cursor and step cursor in the backwards
1120 * direction. */
1121 u_json_t *u_json_it_prev (u_json_it_t *it)
1122 {
1123 u_json_t *jo;
1124
1125 dbg_return_if (it == NULL, NULL);
1126
1127 if ((jo = it->cur) != NULL)
1128 it->cur = TAILQ_PREV(jo, u_json_chld_s, siblings);
1129
1130 return jo;
1131 }
1132
7d44b4d8 » babongo
2010-06-27 * handle conditional dependency of json on hmap;
1133 /**
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1134 * \}
1135 */
1136
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1137 static int u_json_do_encode (u_json_t *jo, u_string_t *s)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1138 {
1139 if (jo == NULL)
1140 return 0;
1141
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1142 /* Optional key. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1143 if (strlen(jo->key))
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1144 dbg_err_if (u_string_aprintf(s, "\"%s\": ", jo->key));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1145
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1146 /* Value. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1147 switch (jo->type)
1148 {
1149 case U_JSON_TYPE_STRING:
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1150 dbg_err_if (u_string_aprintf(s, "\"%s\"", jo->val));
1151 break;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1152 case U_JSON_TYPE_NUMBER:
1153 dbg_err_if (u_string_aprintf(s, "%s", jo->val));
1154 break;
1155 case U_JSON_TYPE_OBJECT:
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1156 dbg_err_if (u_string_aprintf(s, "{ "));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1157 break;
1158 case U_JSON_TYPE_ARRAY:
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1159 dbg_err_if (u_string_aprintf(s, "[ "));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1160 break;
1161 case U_JSON_TYPE_TRUE:
1162 dbg_err_if (u_string_aprintf(s, "true"));
1163 break;
1164 case U_JSON_TYPE_FALSE:
1165 dbg_err_if (u_string_aprintf(s, "false"));
1166 break;
1167 case U_JSON_TYPE_NULL:
1168 dbg_err_if (u_string_aprintf(s, "null"));
1169 break;
1170 default:
1171 dbg_err("!");
1172 }
1173
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1174 /* Explore depth. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1175 dbg_err_if (u_json_do_encode(TAILQ_FIRST(&jo->children), s));
1176
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1177 /* Close matching paren. */
1178 switch (jo->type)
1179 {
1180 case U_JSON_TYPE_ARRAY:
1181 dbg_err_if (u_string_aprintf(s, " ]"));
1182 break;
1183 case U_JSON_TYPE_OBJECT:
1184 dbg_err_if (u_string_aprintf(s, " }"));
1185 break;
1186 default:
1187 break;
1188 }
1189
1190 /* When needed, add comma to separate siblings. */
1191 if (TAILQ_NEXT(jo, siblings))
1192 dbg_err_if (u_string_aprintf(s, ", "));
1193
1194 /* Explore horizontally. */
1195 dbg_err_if (u_json_do_encode(TAILQ_NEXT(jo, siblings), s));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1196
1197 return 0;
1198 err:
1199 return ~0;
1200 }
1201
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1202 static int u_json_match_value (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1203 {
c2f7aea1 » babongo
2010-06-29 json validator implemented
1204 /* 'jo' can be NULL in case of a validating-only parser. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1205 dbg_return_if (jl == NULL, ~0);
1206
1207 if (u_json_match_string_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1208 dbg_err_if (u_json_match_string(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1209 else if (u_json_match_number_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1210 dbg_err_if (u_json_match_number(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1211 else if (u_json_match_object_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1212 dbg_err_if (u_json_match_object(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1213 else if (u_json_match_array_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1214 dbg_err_if (u_json_match_array(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1215 else if (u_json_match_true_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1216 dbg_err_if (u_json_match_true(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1217 else if (u_json_match_false_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1218 dbg_err_if (u_json_match_false(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1219 else if (u_json_match_null_first(jl))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1220 dbg_err_if (u_json_match_null(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1221 else
c2f7aea1 » babongo
2010-06-29 json validator implemented
1222 U_LEXER_ERR(jl, "value not found at \'%s\'", u_lexer_lookahead(jl));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1223
1224 return 0;
1225 err:
1226 return ~0;
1227 }
1228
1229 static int u_json_match_array_first (u_lexer_t *jl)
1230 {
1231 return (u_lexer_peek(jl) == '[');
1232 }
1233
1234 static int u_json_match_object_first (u_lexer_t *jl)
1235 {
1236 return (u_lexer_peek(jl) == '{');
1237 }
1238
1239 static int u_json_match_number_first (u_lexer_t *jl)
1240 {
1241 char r, c = u_lexer_peek(jl);
1242
1243 if ((r = (c == '-' || isdigit(c))))
1244 u_lexer_record_lmatch(jl);
1245
1246 return r;
1247 }
1248
1249 static int u_json_match_pair_first (u_lexer_t *jl)
1250 {
1251 return u_json_match_string_first(jl);
1252 }
1253
1254 static int u_json_match_false_first (u_lexer_t *jl)
1255 {
1256 return (u_lexer_peek(jl) == 'f');
1257 }
1258
1259 static int u_json_match_true_first (u_lexer_t *jl)
1260 {
1261 return (u_lexer_peek(jl) == 't');
1262 }
1263
1264 static int u_json_match_null_first (u_lexer_t *jl)
1265 {
1266 return (u_lexer_peek(jl) == 'n');
1267 }
1268
1269 static int u_json_match_string_first (u_lexer_t *jl)
1270 {
1271 char r, c = u_lexer_peek(jl);
1272
1273 if ((r = (c == '"')))
1274 u_lexer_record_lmatch(jl);
1275
1276 return r;
1277 }
1278
1279 /* number ::= INT[FRAC][EXP] */
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1280 static int u_json_match_number (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1281 {
1282 char match[U_TOKEN_SZ];
1283
1284 /* INT is mandatory */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1285 dbg_err_if (u_json_match_int(jl));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1286
1287 /* c IN first(FRAC) */
1288 if (u_json_match_frac_first(u_lexer_peek(jl)))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1289 dbg_err_if (u_json_match_frac(jl));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1290
1291 /* c IN first(EXP) */
1292 if (u_json_match_exp_first(u_lexer_peek(jl)))
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1293 dbg_err_if (u_json_match_exp(jl));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1294
1295 /* Register right side of the matched number. */
1296 u_lexer_record_rmatch(jl);
1297
1298 /* Take care of the fact that the match includes the first non-number char
1299 * (see u_json_match_{int,exp,frac} for details). */
1300 (void) u_lexer_get_match(jl, match);
1301 match[strlen(match) - 1] = '\0';
1302
1303 /* Push the matched number into the supplied json object. */
c2f7aea1 » babongo
2010-06-29 json validator implemented
1304 if (jo)
1305 {
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1306 dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_NUMBER));
1307 dbg_err_if (u_json_set_val(jo, match));
c2f7aea1 » babongo
2010-06-29 json validator implemented
1308 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1309
1310 #ifdef U_JSON_LEX_DEBUG
1311 u_con("matched number: %s", u_lexer_get_match(jl, match));
1312 #endif /* U_JSON_LEX_DEBUG */
1313
1314 return 0;
1315 err:
1316 return ~0;
1317 }
1318
1319 static int u_json_match_int (u_lexer_t *jl)
1320 {
1321 char c = u_lexer_peek(jl);
1322
1323 /* optional minus sign */
1324 if (c == '-')
1325 U_LEXER_NEXT(jl, &c);
1326
1327 /* on '0' as the first char, we're done */
1328 if (c == '0')
1329 {
1330 U_LEXER_NEXT(jl, &c);
1331 goto end;
1332 }
1333
1334 /* [1-9][0-9]+ */
1335 if (c >= 48 && c <= 57)
1336 do { U_LEXER_NEXT(jl, &c); } while (isdigit(c));
1337 else
1338 U_LEXER_ERR(jl, "bad int syntax at %s", u_lexer_lookahead(jl));
1339
1340 /* fall through */
1341 end:
1342 return 0;
1343 err:
1344 return ~0;
1345 }
1346
1347 static int u_json_match_exp_first (char c)
1348 {
1349 return (c == 'e' || c == 'E');
1350 }
1351
1352 static int u_json_match_frac_first (char c)
1353 {
1354 return (c == '.');
1355 }
1356
1357 static int u_json_match_frac (u_lexer_t *jl)
1358 {
1359 char c = u_lexer_peek(jl);
1360
1361 /* Mandatory dot. */
1362 if (c != '.')
1363 U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
1364
1365 U_LEXER_NEXT(jl, &c);
1366
1367 /* [0-9] */
1368 if (!isdigit(c))
1369 U_LEXER_ERR(jl, "bad frac syntax at %s", u_lexer_lookahead(jl));
1370
1371 /* [0-9]* */
1372 while (isdigit(c))
1373 U_LEXER_NEXT(jl, &c);
1374
1375 return 0;
1376 err:
1377 return ~0;
1378 }
1379
1380 static int u_json_match_exp (u_lexer_t *jl)
1381 {
1382 char c = u_lexer_peek(jl);
1383
1384 /* [eE] */
1385 if (c != 'e' && c != 'E')
1386 U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
1387
1388 U_LEXER_NEXT(jl, &c);
1389
1390 /* Optional plus/minus sign. */
1391 if (c == '+' || c == '-')
1392 U_LEXER_NEXT(jl, &c);
1393
1394 /* [0-9] */
1395 if (!isdigit(c))
1396 U_LEXER_ERR(jl, "bad exp syntax at %s", u_lexer_lookahead(jl));
1397
1398 /* [0-9]* */
1399 while (isdigit(c))
1400 U_LEXER_NEXT(jl, &c);
1401
1402 return 0;
1403 err:
1404 return ~0;
1405 }
1406
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1407 static int u_json_match_seq (u_lexer_t *jl, u_json_t *jo, int type,
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1408 char first, const char *rem, size_t rem_sz)
1409 {
1410 char c;
1411 size_t i = 0;
1412
1413 if ((c = u_lexer_peek(jl)) != first)
1414 {
1415 U_LEXER_ERR(jl, "expect \'%c\', got %c at %s",
1416 first, c, u_lexer_lookahead(jl));
1417 }
1418
1419 for (i = 0; i < rem_sz; i++)
1420 {
1421 U_LEXER_SKIP(jl, &c);
1422 if (c != *(rem + i))
1423 {
1424 U_LEXER_ERR(jl, "expect \'%c\', got %c at %s",
1425 *(rem + i), c, u_lexer_lookahead(jl));
1426 }
1427 }
1428
1429 /* Consume last checked char. */
1430 U_LEXER_SKIP(jl, NULL);
1431
c2f7aea1 » babongo
2010-06-29 json validator implemented
1432 if (jo)
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1433 dbg_err_if (u_json_set_type(jo, type));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1434
1435 #ifdef U_JSON_LEX_DEBUG
1436 u_con("matched \'%s\' sequence", u_json_type_str(type));
1437 #endif /* U_JSON_LEX_DEBUG */
1438 return 0;
1439 err:
1440 return ~0;
1441 }
1442
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1443 static int u_json_match_null (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1444 {
1445 return u_json_match_seq(jl, jo, U_JSON_TYPE_NULL,
1446 'n', "ull", strlen("ull"));
1447 }
1448
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1449 static int u_json_match_true (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1450 {
1451 return u_json_match_seq(jl, jo, U_JSON_TYPE_TRUE,
1452 't', "rue", strlen("rue"));
1453 }
1454
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1455 static int u_json_match_false (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1456 {
1457 return u_json_match_seq(jl, jo, U_JSON_TYPE_FALSE,
1458 'f', "alse", strlen("alse"));
1459 }
1460
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1461 static int u_json_match_array (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1462 {
1463 char c;
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1464 u_json_t *elem = NULL;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1465
1466 #ifdef U_JSON_LEX_DEBUG
1467 u_con("ARRAY");
1468 #endif /* U_JSON_LEX_DEBUG */
1469
1470 if ((c = u_lexer_peek(jl)) != '[')
1471 {
1472 U_LEXER_ERR(jl, "expect \'[\', got %c at %s",
1473 c, u_lexer_lookahead(jl));
1474 }
1475
1476 /* Parent object is an array. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1477 if (jo)
1478 dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_ARRAY));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1479
1480 do {
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1481 /* As long as we want to accept empty arrays in this same scan loop,
1482 * we could let trailing ',' pass unseen when a value has been already
1483 * consumed. So, at each iteration, last non-whitespace char is saved
1484 * to 'd' and checked when testing the empty array condition so that
1485 * we can emit a warn if needed.
1486 * NOTE this is done equivalently in u_json_match_object(). */
1487 char d = u_lexer_peek(jl);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1488
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1489 U_LEXER_SKIP(jl, &c);
1490
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1491 if (c == ']') /* break on empty array */
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1492 {
1493 if (d == ',')
1494 u_warn("Trailing \',\' at the end of array !");
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1495 break;
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1496 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1497
c2f7aea1 » babongo
2010-06-29 json validator implemented
1498 if (jo)
1499 {
1500 /* Create a new object to store next array element. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1501 dbg_err_if (u_json_new(&elem));
1502 dbg_err_if (u_json_set_type(elem, U_JSON_TYPE_UNKNOWN));
1503 dbg_err_if (u_json_set_depth(elem, jo->depth + 1));
c2f7aea1 » babongo
2010-06-29 json validator implemented
1504 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1505
1506 /* Fetch new value. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1507 dbg_err_if (u_json_match_value(jl, elem));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1508
c2f7aea1 » babongo
2010-06-29 json validator implemented
1509 if (jo)
1510 {
1511 /* Push the fetched element to its parent array. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1512 dbg_err_if (u_json_add(jo, elem));
c2f7aea1 » babongo
2010-06-29 json validator implemented
1513 elem = NULL;
1514 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1515
1516 /* Consume any trailing white spaces. */
031755d3 » babongo
2010-10-23 fix warnings coming from minix compilation
1517 if (isspace((int) u_lexer_peek(jl)))
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1518 U_LEXER_SKIP(jl, NULL);
1519
1520 } while (u_lexer_peek(jl) == ',');
1521
1522 if ((c = u_lexer_peek(jl)) != ']')
1523 {
1524 U_LEXER_ERR(jl, "expect \']\', got %c at %s",
1525 c, u_lexer_lookahead(jl));
1526 }
1527
2d8e2ce9 » tho
2010-05-28 [libu] json += unit test
1528 /* Ignore EOT, shall be catched later. */
1529 (void) u_lexer_skip(jl, NULL);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1530
1531 return 0;
1532 err:
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1533 u_json_free(elem);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1534 return ~0;
1535 }
1536
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1537 static int u_json_match_object (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1538 {
1539 char c;
1540
1541 #ifdef U_JSON_LEX_DEBUG
1542 u_con("OBJECT");
1543 #endif /* U_JSON_LEX_DEBUG */
1544
1545 if ((c = u_lexer_peek(jl)) != '{')
1546 {
1547 U_LEXER_ERR(jl, "expect \'{\', got %c at %s",
1548 c, u_lexer_lookahead(jl));
1549 }
1550
c2f7aea1 » babongo
2010-06-29 json validator implemented
1551 if (jo)
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1552 dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_OBJECT));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1553
1554 do {
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1555 char d = u_lexer_peek(jl);
1556
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1557 U_LEXER_SKIP(jl, &c);
1558
1559 /* Break on empty object. */
1560 if (c == '}')
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1561 {
1562 if (d == ',')
1563 u_warn("Trailing \',\' at the end of object !");
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1564 break;
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1565 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1566
1567 /* Process assignement. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1568 dbg_err_if (!u_json_match_pair_first(jl) || u_json_match_pair(jl, jo));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1569
1570 /* Consume trailing white spaces, if any. */
031755d3 » babongo
2010-10-23 fix warnings coming from minix compilation
1571 if (isspace((int) u_lexer_peek(jl)))
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1572 U_LEXER_SKIP(jl, NULL);
1573
1574 } while (u_lexer_peek(jl) == ',');
1575
1576 if ((c = u_lexer_peek(jl)) != '}')
1577 {
1578 U_LEXER_ERR(jl, "expect \'}\', got %c at %s",
1579 c, u_lexer_lookahead(jl));
1580 }
1581
2d8e2ce9 » tho
2010-05-28 [libu] json += unit test
1582 /* Ignore EOT, shall be catched later. */
1583 (void) u_lexer_skip(jl, NULL);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1584
1585 return 0;
1586 err:
1587 return ~0;
1588 }
1589
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1590 static int u_json_match_pair (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1591 {
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1592 size_t mlen;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1593 char c, match[U_TOKEN_SZ];
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1594 u_json_t *pair = NULL;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1595
1596 dbg_return_if (jl == NULL, ~0);
1597
1598 #ifdef U_JSON_LEX_DEBUG
1599 u_con("PAIR");
1600 #endif /* U_JSON_LEX_DEBUG */
1601
1602 /* Here we use the matched string as the 'key' for the associated value,
1603 * hence there is no associated json object. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1604 dbg_err_if (u_json_match_string(jl, NULL));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1605
1606 /* Initialize new json object to store the key/value pair. */
c2f7aea1 » babongo
2010-06-29 json validator implemented
1607 if (jo)
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1608 {
1609 dbg_err_if (u_json_new(&pair));
1610 dbg_err_if (u_json_set_depth(pair, jo->depth + 1));
1611 }
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1612
1613 (void) u_lexer_get_match(jl, match);
1614
1615 /* Trim trailing '"'. */
1616 if ((mlen = strlen(match)) >= 1)
1617 match[mlen - 1] = '\0';
1618
c2f7aea1 » babongo
2010-06-29 json validator implemented
1619 if (jo)
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1620 dbg_err_if (u_json_set_key(pair, match));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1621
4ff8796a » babongo
2010-10-24 fix bug in JSON parser + warn on certain non critical syntactic incon…
1622 /* Consume trailing white spaces, if any. */
1623 if (isspace((int) u_lexer_peek(jl)))
1624 U_LEXER_SKIP(jl, NULL);
1625
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1626 /* Consume ':' */
1627 if ((c = u_lexer_peek(jl)) != ':')
1628 {
1629 U_LEXER_ERR(jl, "expect \':\', got %c at %s",
1630 c, u_lexer_lookahead(jl));
1631 }
1632
1633 U_LEXER_SKIP(jl, &c);
1634
1635 /* Assign value. */
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1636 dbg_err_if (u_json_match_value(jl, pair));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1637
1638 /* Push the new value to the parent json object. */
c2f7aea1 » babongo
2010-06-29 json validator implemented
1639 if (jo)
1640 {
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1641 dbg_err_if (u_json_add(jo, pair));
c2f7aea1 » babongo
2010-06-29 json validator implemented
1642 pair = NULL;
1643 }
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1644
1645 return 0;
1646 err:
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1647 u_json_free(pair);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1648 return ~0;
1649 }
1650
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1651 static int u_json_match_string (u_lexer_t *jl, u_json_t *jo)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1652 {
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1653 size_t mlen;
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1654 char c, match[U_TOKEN_SZ];
1655
1656 /* In case string is matched as an lval (i.e. the key side of a 'pair'),
1657 * there is no json object. */
1658 dbg_return_if (jl == NULL, ~0);
1659
1660 #ifdef U_JSON_LEX_DEBUG
1661 u_con("STRING");
1662 #endif /* U_JSON_LEX_DEBUG */
1663
1664 if ((c = u_lexer_peek(jl)) != '"')
1665 U_LEXER_ERR(jl, "expect \", got %c at %s", c, u_lexer_lookahead(jl));
1666
1667 U_LEXER_NEXT(jl, &c);
1668
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1669 /* Re-record the left side match pointer (trim leading '"'). */
1670 u_lexer_record_lmatch(jl);
1671
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1672 while (c != '"')
1673 {
1674 if (c == '\\')
1675 {
1676 U_LEXER_NEXT(jl, &c);
1677 switch (c)
1678 {
1679 case 'u':
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1680 dbg_err_if (u_json_match_escaped_unicode(jl));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1681 break;
1682 case '"': case '\\': case '/': case 'b':
1683 case 'f': case 'n': case 'r': case 't':
1684 U_LEXER_NEXT(jl, &c);
1685 break;
1686 default:
1687 U_LEXER_ERR(jl, "invalid char %c in escape", c);
1688 }
1689 }
031755d3 » babongo
2010-10-23 fix warnings coming from minix compilation
1690 else if (iscntrl((int) c))
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1691 U_LEXER_ERR(jl, "control character in string", c);
1692 else
1693 U_LEXER_NEXT(jl, &c);
1694 }
1695
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1696 /* Record right match pointer.
1697 * This is a greedy match, which includes the trailing '"', and must
1698 * be taken into account when pulling out the string. */
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1699 u_lexer_record_rmatch(jl);
1700
1701 /* Consume last '"'. */
1702 U_LEXER_NEXT(jl, &c);
1703
1704 #ifdef U_JSON_LEX_DEBUG
1705 u_con("matched string: \'%s\'", u_lexer_get_match(jl, match));
1706 #endif /* U_JSON_LEX_DEBUG */
1707
1708 /* In case the string is matched as an rval, the caller shall
1709 * supply the json object that has to be set. */
1710 if (jo)
1711 {
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1712 dbg_err_if (u_json_set_type(jo, U_JSON_TYPE_STRING));
7ee39dbd » tho
2010-05-27 [libu] json += encoder completed ; cleaner string matching
1713
1714 /* Remove trailing '"' from match. */
1715 (void) u_lexer_get_match(jl, match);
1716
1717 /* Trim trailing '"'. */
1718 if ((mlen = strlen(match)) >= 1)
1719 match[mlen - 1] = '\0';
1720
271476be » babongo
2010-10-26 add U_JSON_MAX_DEPTH machinery (i.e. don't let'em smash our stack)
1721 dbg_err_if (u_json_set_val(jo, match));
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1722 }
1723
1724 return 0;
1725 err:
1726 return ~0;
1727 }
1728
1729 static int u_json_match_escaped_unicode (u_lexer_t *jl)
1730 {
1731 char i, c;
1732
1733 for (i = 0; i < 4; i++)
1734 {
1735 U_LEXER_NEXT(jl, &c);
1736
031755d3 » babongo
2010-10-23 fix warnings coming from minix compilation
1737 if (!isxdigit((int) c))
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1738 U_LEXER_ERR(jl, "non hex digit %c in escaped unicode", c);
1739 }
1740
1741 return 0;
1742 err:
1743 return ~0;
1744 }
1745
1746 static const char *u_json_type_str (int type)
1747 {
1748 switch (type)
1749 {
1750 case U_JSON_TYPE_STRING: return "string";
1751 case U_JSON_TYPE_NUMBER: return "number";
1752 case U_JSON_TYPE_ARRAY: return "array";
1753 case U_JSON_TYPE_OBJECT: return "object";
1754 case U_JSON_TYPE_TRUE: return "true";
1755 case U_JSON_TYPE_FALSE: return "false";
1756 case U_JSON_TYPE_NULL: return "null";
1757 case U_JSON_TYPE_UNKNOWN: default: break;
1758 }
1759
1760 return "unknown";
1761 }
1762
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1763 static void u_json_do_free (u_json_t *jo, size_t l, void *opaque)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1764 {
a63e435a » babongo
2010-06-26 JSON indexing interface wip (again)
1765 u_unused_args(l, opaque);
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)
1766
1767 if (jo)
1768 u_free(jo);
1769
1770 return;
1771 }
1772
0a84aaf0 » babongo
2010-06-28 JSON module hi-level logics (wip)
1773 static void u_json_do_print (u_json_t *jo, size_t l, void *opaque)
dac025c8 » tho
2010-05-27 [libu] json module integration (wip)