/src/rtpproxy/external/libucl/src/ucl_emitter.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2013, Vsevolod Stakhov |
2 | | * All rights reserved. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or without |
5 | | * modification, are permitted provided that the following conditions are met: |
6 | | * * Redistributions of source code must retain the above copyright |
7 | | * notice, this list of conditions and the following disclaimer. |
8 | | * * Redistributions in binary form must reproduce the above copyright |
9 | | * notice, this list of conditions and the following disclaimer in the |
10 | | * documentation and/or other materials provided with the distribution. |
11 | | * |
12 | | * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY |
13 | | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
14 | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
15 | | * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY |
16 | | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
17 | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
18 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
19 | | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
20 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
21 | | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
22 | | */ |
23 | | |
24 | | #ifdef HAVE_CONFIG_H |
25 | | #include "config.h" |
26 | | #endif |
27 | | |
28 | | #include "ucl.h" |
29 | | #include "ucl_internal.h" |
30 | | #include "ucl_chartable.h" |
31 | | #ifdef HAVE_FLOAT_H |
32 | | #include <float.h> |
33 | | #endif |
34 | | #ifdef HAVE_MATH_H |
35 | | #include <math.h> |
36 | | #endif |
37 | | |
38 | | /** |
39 | | * @file ucl_emitter.c |
40 | | * Serialise UCL object to various of output formats |
41 | | */ |
42 | | |
43 | | static void ucl_emitter_common_elt (struct ucl_emitter_context *ctx, |
44 | | const ucl_object_t *obj, bool first, bool print_key, bool compact); |
45 | | |
46 | | #define UCL_EMIT_TYPE_OPS(type) \ |
47 | | static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \ |
48 | | const ucl_object_t *obj, bool first, bool print_key); \ |
49 | | static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \ |
50 | | const ucl_object_t *obj, bool print_key); \ |
51 | | static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \ |
52 | | const ucl_object_t *obj, bool print_key); \ |
53 | | static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \ |
54 | | const ucl_object_t *obj); \ |
55 | | static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \ |
56 | | const ucl_object_t *obj) |
57 | | |
58 | | /* |
59 | | * JSON format operations |
60 | | */ |
61 | | UCL_EMIT_TYPE_OPS(json); |
62 | | UCL_EMIT_TYPE_OPS(json_compact); |
63 | | UCL_EMIT_TYPE_OPS(config); |
64 | | UCL_EMIT_TYPE_OPS(yaml); |
65 | | UCL_EMIT_TYPE_OPS(msgpack); |
66 | | |
67 | | #define UCL_EMIT_TYPE_CONTENT(type) { \ |
68 | | .ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \ |
69 | | .ucl_emitter_start_object = ucl_emit_ ## type ##_start_obj, \ |
70 | | .ucl_emitter_start_array = ucl_emit_ ## type ##_start_array, \ |
71 | | .ucl_emitter_end_object = ucl_emit_ ## type ##_end_object, \ |
72 | | .ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \ |
73 | | } |
74 | | |
75 | | const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = { |
76 | | [UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json), |
77 | | [UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact), |
78 | | [UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config), |
79 | | [UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml), |
80 | | [UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack) |
81 | | }; |
82 | | |
83 | | /* |
84 | | * Utility to check whether we need a top object |
85 | | */ |
86 | 0 | #define UCL_EMIT_IDENT_TOP_OBJ(ctx, obj) ((ctx)->top != (obj) || \ |
87 | 0 | ((ctx)->id == UCL_EMIT_JSON_COMPACT || (ctx)->id == UCL_EMIT_JSON)) |
88 | | |
89 | | |
90 | | /** |
91 | | * Add tabulation to the output buffer |
92 | | * @param buf target buffer |
93 | | * @param tabs number of tabs to add |
94 | | */ |
95 | | static inline void |
96 | | ucl_add_tabs (const struct ucl_emitter_functions *func, unsigned int tabs, |
97 | | bool compact) |
98 | 0 | { |
99 | 0 | if (!compact && tabs > 0) { |
100 | 0 | func->ucl_emitter_append_character (' ', tabs * 4, func->ud); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | /** |
105 | | * Print key for the element |
106 | | * @param ctx |
107 | | * @param obj |
108 | | */ |
109 | | static void |
110 | | ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx, |
111 | | const ucl_object_t *obj, bool compact) |
112 | 0 | { |
113 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
114 | |
|
115 | 0 | if (!print_key) { |
116 | 0 | return; |
117 | 0 | } |
118 | | |
119 | 0 | if (ctx->id == UCL_EMIT_CONFIG) { |
120 | 0 | if (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { |
121 | 0 | ucl_elt_string_write_json (obj->key, obj->keylen, ctx); |
122 | 0 | } |
123 | 0 | else { |
124 | 0 | func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud); |
125 | 0 | } |
126 | |
|
127 | 0 | if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) { |
128 | 0 | func->ucl_emitter_append_len (" = ", 3, func->ud); |
129 | 0 | } |
130 | 0 | else { |
131 | 0 | func->ucl_emitter_append_character (' ', 1, func->ud); |
132 | 0 | } |
133 | 0 | } |
134 | 0 | else if (ctx->id == UCL_EMIT_YAML) { |
135 | 0 | if (obj->keylen > 0 && (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE)) { |
136 | 0 | ucl_elt_string_write_json (obj->key, obj->keylen, ctx); |
137 | 0 | } |
138 | 0 | else if (obj->keylen > 0) { |
139 | 0 | func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud); |
140 | 0 | } |
141 | 0 | else { |
142 | 0 | func->ucl_emitter_append_len ("null", 4, func->ud); |
143 | 0 | } |
144 | |
|
145 | 0 | func->ucl_emitter_append_len (": ", 2, func->ud); |
146 | 0 | } |
147 | 0 | else { |
148 | 0 | if (obj->keylen > 0) { |
149 | 0 | ucl_elt_string_write_json (obj->key, obj->keylen, ctx); |
150 | 0 | } |
151 | 0 | else { |
152 | 0 | func->ucl_emitter_append_len ("null", 4, func->ud); |
153 | 0 | } |
154 | |
|
155 | 0 | if (compact) { |
156 | 0 | func->ucl_emitter_append_character (':', 1, func->ud); |
157 | 0 | } |
158 | 0 | else { |
159 | 0 | func->ucl_emitter_append_len (": ", 2, func->ud); |
160 | 0 | } |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | static void |
165 | | ucl_emitter_finish_object (struct ucl_emitter_context *ctx, |
166 | | const ucl_object_t *obj, bool compact, bool is_array) |
167 | 0 | { |
168 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
169 | |
|
170 | 0 | if (ctx->id == UCL_EMIT_CONFIG && obj != ctx->top) { |
171 | 0 | if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) { |
172 | 0 | if (!is_array) { |
173 | | /* Objects are split by ';' */ |
174 | 0 | func->ucl_emitter_append_len (";\n", 2, func->ud); |
175 | 0 | } |
176 | 0 | else { |
177 | | /* Use commas for arrays */ |
178 | 0 | func->ucl_emitter_append_len (",\n", 2, func->ud); |
179 | 0 | } |
180 | 0 | } |
181 | 0 | else { |
182 | 0 | func->ucl_emitter_append_character ('\n', 1, func->ud); |
183 | 0 | } |
184 | 0 | } |
185 | 0 | } |
186 | | |
187 | | /** |
188 | | * End standard ucl object |
189 | | * @param ctx emitter context |
190 | | * @param compact compact flag |
191 | | */ |
192 | | static void |
193 | | ucl_emitter_common_end_object (struct ucl_emitter_context *ctx, |
194 | | const ucl_object_t *obj, bool compact) |
195 | 0 | { |
196 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
197 | |
|
198 | 0 | if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) { |
199 | 0 | ctx->indent --; |
200 | 0 | if (compact) { |
201 | 0 | func->ucl_emitter_append_character ('}', 1, func->ud); |
202 | 0 | } |
203 | 0 | else { |
204 | 0 | if (ctx->id != UCL_EMIT_CONFIG) { |
205 | | /* newline is already added for this format */ |
206 | 0 | func->ucl_emitter_append_character ('\n', 1, func->ud); |
207 | 0 | } |
208 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
209 | 0 | func->ucl_emitter_append_character ('}', 1, func->ud); |
210 | 0 | } |
211 | 0 | } |
212 | |
|
213 | 0 | ucl_emitter_finish_object (ctx, obj, compact, false); |
214 | 0 | } |
215 | | |
216 | | /** |
217 | | * End standard ucl array |
218 | | * @param ctx emitter context |
219 | | * @param compact compact flag |
220 | | */ |
221 | | static void |
222 | | ucl_emitter_common_end_array (struct ucl_emitter_context *ctx, |
223 | | const ucl_object_t *obj, bool compact) |
224 | 0 | { |
225 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
226 | |
|
227 | 0 | ctx->indent --; |
228 | 0 | if (compact) { |
229 | 0 | func->ucl_emitter_append_character (']', 1, func->ud); |
230 | 0 | } |
231 | 0 | else { |
232 | 0 | if (ctx->id != UCL_EMIT_CONFIG) { |
233 | | /* newline is already added for this format */ |
234 | 0 | func->ucl_emitter_append_character ('\n', 1, func->ud); |
235 | 0 | } |
236 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
237 | 0 | func->ucl_emitter_append_character (']', 1, func->ud); |
238 | 0 | } |
239 | |
|
240 | 0 | ucl_emitter_finish_object (ctx, obj, compact, true); |
241 | 0 | } |
242 | | |
243 | | /** |
244 | | * Start emit standard UCL array |
245 | | * @param ctx emitter context |
246 | | * @param obj object to write |
247 | | * @param compact compact flag |
248 | | */ |
249 | | static void |
250 | | ucl_emitter_common_start_array (struct ucl_emitter_context *ctx, |
251 | | const ucl_object_t *obj, bool print_key, bool compact) |
252 | 0 | { |
253 | 0 | const ucl_object_t *cur; |
254 | 0 | ucl_object_iter_t iter = NULL; |
255 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
256 | 0 | bool first = true; |
257 | |
|
258 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
259 | |
|
260 | 0 | if (compact) { |
261 | 0 | func->ucl_emitter_append_character ('[', 1, func->ud); |
262 | 0 | } |
263 | 0 | else { |
264 | 0 | func->ucl_emitter_append_len ("[\n", 2, func->ud); |
265 | 0 | } |
266 | |
|
267 | 0 | ctx->indent ++; |
268 | |
|
269 | 0 | if (obj->type == UCL_ARRAY) { |
270 | | /* explicit array */ |
271 | 0 | while ((cur = ucl_object_iterate (obj, &iter, true)) != NULL) { |
272 | 0 | ucl_emitter_common_elt (ctx, cur, first, false, compact); |
273 | 0 | first = false; |
274 | 0 | } |
275 | 0 | } |
276 | 0 | else { |
277 | | /* implicit array */ |
278 | 0 | cur = obj; |
279 | 0 | while (cur) { |
280 | 0 | ucl_emitter_common_elt (ctx, cur, first, false, compact); |
281 | 0 | first = false; |
282 | 0 | cur = cur->next; |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | |
|
287 | 0 | } |
288 | | |
289 | | /** |
290 | | * Start emit standard UCL object |
291 | | * @param ctx emitter context |
292 | | * @param obj object to write |
293 | | * @param compact compact flag |
294 | | */ |
295 | | static void |
296 | | ucl_emitter_common_start_object (struct ucl_emitter_context *ctx, |
297 | | const ucl_object_t *obj, bool print_key, bool compact) |
298 | 0 | { |
299 | 0 | ucl_hash_iter_t it = NULL; |
300 | 0 | const ucl_object_t *cur, *elt; |
301 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
302 | 0 | bool first = true; |
303 | |
|
304 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
305 | | /* |
306 | | * Print <ident_level>{ |
307 | | * <ident_level + 1><object content> |
308 | | */ |
309 | 0 | if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) { |
310 | 0 | if (compact) { |
311 | 0 | func->ucl_emitter_append_character ('{', 1, func->ud); |
312 | 0 | } |
313 | 0 | else { |
314 | 0 | func->ucl_emitter_append_len ("{\n", 2, func->ud); |
315 | 0 | } |
316 | 0 | ctx->indent ++; |
317 | 0 | } |
318 | |
|
319 | 0 | while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { |
320 | |
|
321 | 0 | if (ctx->id == UCL_EMIT_CONFIG) { |
322 | 0 | LL_FOREACH (cur, elt) { |
323 | 0 | ucl_emitter_common_elt (ctx, elt, first, true, compact); |
324 | 0 | } |
325 | 0 | } |
326 | 0 | else { |
327 | | /* Expand implicit arrays */ |
328 | 0 | if (cur->next != NULL) { |
329 | 0 | if (!first) { |
330 | 0 | if (compact) { |
331 | 0 | func->ucl_emitter_append_character (',', 1, func->ud); |
332 | 0 | } |
333 | 0 | else { |
334 | 0 | func->ucl_emitter_append_len (",\n", 2, func->ud); |
335 | 0 | } |
336 | 0 | } |
337 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
338 | 0 | ucl_emitter_common_start_array (ctx, cur, true, compact); |
339 | 0 | ucl_emitter_common_end_array (ctx, cur, compact); |
340 | 0 | } |
341 | 0 | else { |
342 | 0 | ucl_emitter_common_elt (ctx, cur, first, true, compact); |
343 | 0 | } |
344 | 0 | } |
345 | |
|
346 | 0 | first = false; |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | /** |
351 | | * Common choice of object emitting |
352 | | * @param ctx emitter context |
353 | | * @param obj object to print |
354 | | * @param first flag to mark the first element |
355 | | * @param print_key print key of an object |
356 | | * @param compact compact output |
357 | | */ |
358 | | static void |
359 | | ucl_emitter_common_elt (struct ucl_emitter_context *ctx, |
360 | | const ucl_object_t *obj, bool first, bool print_key, bool compact) |
361 | 0 | { |
362 | 0 | const struct ucl_emitter_functions *func = ctx->func; |
363 | 0 | bool flag; |
364 | 0 | struct ucl_object_userdata *ud; |
365 | 0 | const ucl_object_t *comment = NULL, *cur_comment; |
366 | 0 | const char *ud_out = ""; |
367 | |
|
368 | 0 | if (ctx->id != UCL_EMIT_CONFIG && !first) { |
369 | 0 | if (compact) { |
370 | 0 | func->ucl_emitter_append_character (',', 1, func->ud); |
371 | 0 | } |
372 | 0 | else { |
373 | 0 | if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) { |
374 | 0 | func->ucl_emitter_append_len ("\n", 1, func->ud); |
375 | 0 | } else { |
376 | 0 | func->ucl_emitter_append_len (",\n", 2, func->ud); |
377 | 0 | } |
378 | 0 | } |
379 | 0 | } |
380 | |
|
381 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
382 | |
|
383 | 0 | if (ctx->comments && ctx->id == UCL_EMIT_CONFIG) { |
384 | 0 | comment = ucl_object_lookup_len (ctx->comments, (const char *)&obj, |
385 | 0 | sizeof (void *)); |
386 | |
|
387 | 0 | if (comment) { |
388 | 0 | if (!(comment->flags & UCL_OBJECT_INHERITED)) { |
389 | 0 | DL_FOREACH (comment, cur_comment) { |
390 | 0 | func->ucl_emitter_append_len (cur_comment->value.sv, |
391 | 0 | cur_comment->len, |
392 | 0 | func->ud); |
393 | 0 | func->ucl_emitter_append_character ('\n', 1, func->ud); |
394 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
395 | 0 | } |
396 | |
|
397 | 0 | comment = NULL; |
398 | 0 | } |
399 | 0 | } |
400 | 0 | } |
401 | |
|
402 | 0 | switch (obj->type) { |
403 | 0 | case UCL_INT: |
404 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
405 | 0 | func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); |
406 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
407 | 0 | break; |
408 | 0 | case UCL_FLOAT: |
409 | 0 | case UCL_TIME: |
410 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
411 | 0 | func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); |
412 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
413 | 0 | break; |
414 | 0 | case UCL_BOOLEAN: |
415 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
416 | 0 | flag = ucl_object_toboolean (obj); |
417 | 0 | if (flag) { |
418 | 0 | func->ucl_emitter_append_len ("true", 4, func->ud); |
419 | 0 | } |
420 | 0 | else { |
421 | 0 | func->ucl_emitter_append_len ("false", 5, func->ud); |
422 | 0 | } |
423 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
424 | 0 | break; |
425 | 0 | case UCL_STRING: |
426 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
427 | 0 | if (ctx->id == UCL_EMIT_CONFIG && ucl_maybe_long_string (obj)) { |
428 | 0 | ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx); |
429 | 0 | } |
430 | 0 | else { |
431 | 0 | ucl_elt_string_write_json (obj->value.sv, obj->len, ctx); |
432 | 0 | } |
433 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
434 | 0 | break; |
435 | 0 | case UCL_NULL: |
436 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
437 | 0 | func->ucl_emitter_append_len ("null", 4, func->ud); |
438 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
439 | 0 | break; |
440 | 0 | case UCL_OBJECT: |
441 | 0 | ucl_emitter_common_start_object (ctx, obj, print_key, compact); |
442 | 0 | ucl_emitter_common_end_object (ctx, obj, compact); |
443 | 0 | break; |
444 | 0 | case UCL_ARRAY: |
445 | 0 | ucl_emitter_common_start_array (ctx, obj, print_key, compact); |
446 | 0 | ucl_emitter_common_end_array (ctx, obj, compact); |
447 | 0 | break; |
448 | 0 | case UCL_USERDATA: |
449 | 0 | ud = (struct ucl_object_userdata *)obj; |
450 | 0 | ucl_emitter_print_key (print_key, ctx, obj, compact); |
451 | 0 | if (ud->emitter) { |
452 | 0 | ud_out = ud->emitter (obj->value.ud); |
453 | 0 | if (ud_out == NULL) { |
454 | 0 | ud_out = "null"; |
455 | 0 | } |
456 | 0 | } |
457 | 0 | ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx); |
458 | 0 | ucl_emitter_finish_object (ctx, obj, compact, !print_key); |
459 | 0 | break; |
460 | 0 | } |
461 | | |
462 | 0 | if (comment) { |
463 | 0 | DL_FOREACH (comment, cur_comment) { |
464 | 0 | func->ucl_emitter_append_len (cur_comment->value.sv, |
465 | 0 | cur_comment->len, |
466 | 0 | func->ud); |
467 | 0 | func->ucl_emitter_append_character ('\n', 1, func->ud); |
468 | |
|
469 | 0 | if (cur_comment->next) { |
470 | 0 | ucl_add_tabs (func, ctx->indent, compact); |
471 | 0 | } |
472 | 0 | } |
473 | 0 | } |
474 | 0 | } |
475 | | |
476 | | /* |
477 | | * Specific standard implementations of the emitter functions |
478 | | */ |
479 | | #define UCL_EMIT_TYPE_IMPL(type, compact) \ |
480 | | static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \ |
481 | 0 | const ucl_object_t *obj, bool first, bool print_key) { \ |
482 | 0 | ucl_emitter_common_elt (ctx, obj, first, print_key, (compact)); \ |
483 | 0 | } \ Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_elt Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_compact_elt Unexecuted instantiation: ucl_emitter.c:ucl_emit_config_elt Unexecuted instantiation: ucl_emitter.c:ucl_emit_yaml_elt |
484 | | static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \ |
485 | 0 | const ucl_object_t *obj, bool print_key) { \ |
486 | 0 | ucl_emitter_common_start_object (ctx, obj, print_key, (compact)); \ |
487 | 0 | } \ Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_start_obj Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_compact_start_obj Unexecuted instantiation: ucl_emitter.c:ucl_emit_config_start_obj Unexecuted instantiation: ucl_emitter.c:ucl_emit_yaml_start_obj |
488 | | static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \ |
489 | 0 | const ucl_object_t *obj, bool print_key) { \ |
490 | 0 | ucl_emitter_common_start_array (ctx, obj, print_key, (compact)); \ |
491 | 0 | } \ Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_start_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_compact_start_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_config_start_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_yaml_start_array |
492 | | static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \ |
493 | 0 | const ucl_object_t *obj) { \ |
494 | 0 | ucl_emitter_common_end_object (ctx, obj, (compact)); \ |
495 | 0 | } \ Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_end_object Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_compact_end_object Unexecuted instantiation: ucl_emitter.c:ucl_emit_config_end_object Unexecuted instantiation: ucl_emitter.c:ucl_emit_yaml_end_object |
496 | | static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \ |
497 | 0 | const ucl_object_t *obj) { \ |
498 | 0 | ucl_emitter_common_end_array (ctx, obj, (compact)); \ |
499 | 0 | } Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_end_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_json_compact_end_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_config_end_array Unexecuted instantiation: ucl_emitter.c:ucl_emit_yaml_end_array |
500 | | |
501 | | UCL_EMIT_TYPE_IMPL(json, false) |
502 | | UCL_EMIT_TYPE_IMPL(json_compact, true) |
503 | | UCL_EMIT_TYPE_IMPL(config, false) |
504 | | UCL_EMIT_TYPE_IMPL(yaml, false) |
505 | | |
506 | | static void |
507 | | ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx, |
508 | | const ucl_object_t *obj, bool first, bool print_key) |
509 | 0 | { |
510 | 0 | ucl_object_iter_t it; |
511 | 0 | struct ucl_object_userdata *ud; |
512 | 0 | const char *ud_out; |
513 | 0 | const ucl_object_t *cur, *celt; |
514 | |
|
515 | 0 | switch (obj->type) { |
516 | 0 | case UCL_INT: |
517 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
518 | 0 | ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj)); |
519 | 0 | break; |
520 | | |
521 | 0 | case UCL_FLOAT: |
522 | 0 | case UCL_TIME: |
523 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
524 | 0 | ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj)); |
525 | 0 | break; |
526 | | |
527 | 0 | case UCL_BOOLEAN: |
528 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
529 | 0 | ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj)); |
530 | 0 | break; |
531 | | |
532 | 0 | case UCL_STRING: |
533 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
534 | |
|
535 | 0 | if (obj->flags & UCL_OBJECT_BINARY) { |
536 | 0 | ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv, |
537 | 0 | obj->len); |
538 | 0 | } |
539 | 0 | else { |
540 | 0 | ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len); |
541 | 0 | } |
542 | 0 | break; |
543 | | |
544 | 0 | case UCL_NULL: |
545 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
546 | 0 | ucl_emitter_print_null_msgpack (ctx); |
547 | 0 | break; |
548 | | |
549 | 0 | case UCL_OBJECT: |
550 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
551 | 0 | ucl_emit_msgpack_start_obj (ctx, obj, print_key); |
552 | 0 | it = NULL; |
553 | |
|
554 | 0 | while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) { |
555 | 0 | LL_FOREACH (cur, celt) { |
556 | 0 | ucl_emit_msgpack_elt (ctx, celt, false, true); |
557 | | /* XXX: |
558 | | * in msgpack the length of objects is encoded within a single elt |
559 | | * so in case of multi-value keys we are using merely the first |
560 | | * element ignoring others |
561 | | */ |
562 | 0 | break; |
563 | 0 | } |
564 | 0 | } |
565 | |
|
566 | 0 | break; |
567 | | |
568 | 0 | case UCL_ARRAY: |
569 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
570 | 0 | ucl_emit_msgpack_start_array (ctx, obj, print_key); |
571 | 0 | it = NULL; |
572 | |
|
573 | 0 | while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) { |
574 | 0 | ucl_emit_msgpack_elt (ctx, cur, false, false); |
575 | 0 | } |
576 | |
|
577 | 0 | break; |
578 | | |
579 | 0 | case UCL_USERDATA: |
580 | 0 | ud = (struct ucl_object_userdata *)obj; |
581 | 0 | ucl_emitter_print_key_msgpack (print_key, ctx, obj); |
582 | |
|
583 | 0 | if (ud->emitter) { |
584 | 0 | ud_out = ud->emitter (obj->value.ud); |
585 | 0 | if (ud_out == NULL) { |
586 | 0 | ud_out = "null"; |
587 | 0 | } |
588 | 0 | } |
589 | 0 | ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len); |
590 | 0 | break; |
591 | 0 | } |
592 | 0 | } |
593 | | |
594 | | static void |
595 | | ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx, |
596 | | const ucl_object_t *obj, bool print_key) |
597 | 0 | { |
598 | 0 | ucl_emitter_print_object_msgpack (ctx, obj->len); |
599 | 0 | } |
600 | | |
601 | | static void |
602 | | ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx, |
603 | | const ucl_object_t *obj, bool print_key) |
604 | 0 | { |
605 | 0 | ucl_emitter_print_array_msgpack (ctx, obj->len); |
606 | 0 | } |
607 | | |
608 | | static void |
609 | | ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx, |
610 | | const ucl_object_t *obj) |
611 | 0 | { |
612 | |
|
613 | 0 | } |
614 | | |
615 | | static void |
616 | | ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx, |
617 | | const ucl_object_t *obj) |
618 | 0 | { |
619 | |
|
620 | 0 | } |
621 | | |
622 | | unsigned char * |
623 | | ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type) |
624 | 0 | { |
625 | 0 | return ucl_object_emit_len (obj, emit_type, NULL); |
626 | 0 | } |
627 | | |
628 | | unsigned char * |
629 | | ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type, |
630 | | size_t *outlen) |
631 | 0 | { |
632 | 0 | unsigned char *res = NULL; |
633 | 0 | struct ucl_emitter_functions *func; |
634 | 0 | UT_string *s; |
635 | |
|
636 | 0 | if (obj == NULL) { |
637 | 0 | return NULL; |
638 | 0 | } |
639 | | |
640 | 0 | func = ucl_object_emit_memory_funcs ((void **)&res); |
641 | |
|
642 | 0 | if (func != NULL) { |
643 | 0 | s = func->ud; |
644 | 0 | ucl_object_emit_full (obj, emit_type, func, NULL); |
645 | |
|
646 | 0 | if (outlen != NULL) { |
647 | 0 | *outlen = s->i; |
648 | 0 | } |
649 | |
|
650 | 0 | ucl_object_emit_funcs_free (func); |
651 | 0 | } |
652 | |
|
653 | 0 | return res; |
654 | 0 | } |
655 | | |
656 | | bool |
657 | | ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, |
658 | | struct ucl_emitter_functions *emitter, |
659 | | const ucl_object_t *comments) |
660 | 0 | { |
661 | 0 | const struct ucl_emitter_context *ctx; |
662 | 0 | struct ucl_emitter_context my_ctx; |
663 | 0 | bool res = false; |
664 | |
|
665 | 0 | ctx = ucl_emit_get_standard_context (emit_type); |
666 | 0 | if (ctx != NULL) { |
667 | 0 | memcpy (&my_ctx, ctx, sizeof (my_ctx)); |
668 | 0 | my_ctx.func = emitter; |
669 | 0 | my_ctx.indent = 0; |
670 | 0 | my_ctx.top = obj; |
671 | 0 | my_ctx.comments = comments; |
672 | |
|
673 | 0 | my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false); |
674 | 0 | res = true; |
675 | 0 | } |
676 | |
|
677 | 0 | return res; |
678 | 0 | } |