1 /* Copyright (c) 2013, Vsevolod Stakhov
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.
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.
29 #include "ucl_internal.h"
30 #include "ucl_chartable.h"
40 * Serialise UCL object to various of output formats
44 static void ucl_obj_write_json (const ucl_object_t *obj,
45 struct ucl_emitter_functions *func,
49 static void ucl_elt_write_json (const ucl_object_t *obj,
50 struct ucl_emitter_functions *func,
54 static void ucl_elt_write_config (const ucl_object_t *obj,
55 struct ucl_emitter_functions *func,
60 static void ucl_elt_write_yaml (const ucl_object_t *obj,
61 struct ucl_emitter_functions *func,
66 static void ucl_elt_array_write_yaml (const ucl_object_t *obj,
67 struct ucl_emitter_functions *func,
73 * Add tabulation to the output buffer
74 * @param buf target buffer
75 * @param tabs number of tabs to add
78 ucl_add_tabs (struct ucl_emitter_functions *func, unsigned int tabs, bool compact)
81 func->ucl_emitter_append_character (' ', tabs * 4, func->ud);
87 * @param str string to emit
88 * @param buf target buffer
91 ucl_elt_string_write_json (const char *str, size_t size,
92 struct ucl_emitter_functions *func)
94 const char *p = str, *c = str;
97 func->ucl_emitter_append_character ('"', 1, func->ud);
99 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
101 func->ucl_emitter_append_len (c, len, func->ud);
105 func->ucl_emitter_append_len ("\\n", 2, func->ud);
108 func->ucl_emitter_append_len ("\\r", 2, func->ud);
111 func->ucl_emitter_append_len ("\\b", 2, func->ud);
114 func->ucl_emitter_append_len ("\\t", 2, func->ud);
117 func->ucl_emitter_append_len ("\\f", 2, func->ud);
120 func->ucl_emitter_append_len ("\\\\", 2, func->ud);
123 func->ucl_emitter_append_len ("\\\"", 2, func->ud);
136 func->ucl_emitter_append_len (c, len, func->ud);
138 func->ucl_emitter_append_character ('"', 1, func->ud);
142 * Write a single object to the buffer
143 * @param obj object to write
144 * @param buf target buffer
147 ucl_elt_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
148 unsigned int tabs, bool start_tabs, bool compact)
150 const ucl_object_t *cur;
151 ucl_hash_iter_t it = NULL;
154 ucl_add_tabs (func, tabs, compact);
157 func->ucl_emitter_append_character ('{', 1, func->ud);
160 func->ucl_emitter_append_len ("{\n", 2, func->ud);
162 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
163 ucl_add_tabs (func, tabs + 1, compact);
164 if (cur->keylen > 0) {
165 ucl_elt_string_write_json (cur->key, cur->keylen, func);
168 func->ucl_emitter_append_len ("null", 4, func->ud);
171 func->ucl_emitter_append_character (':', 1, func->ud);
174 func->ucl_emitter_append_len (": ", 2, func->ud);
176 ucl_obj_write_json (cur, func, tabs + 1, false, compact);
177 if (ucl_hash_iter_has_next (it)) {
179 func->ucl_emitter_append_character (',', 1, func->ud);
182 func->ucl_emitter_append_len (",\n", 2, func->ud);
186 func->ucl_emitter_append_character ('\n', 1, func->ud);
189 ucl_add_tabs (func, tabs, compact);
190 func->ucl_emitter_append_character ('}', 1, func->ud);
194 * Write a single array to the buffer
195 * @param obj array to write
196 * @param buf target buffer
199 ucl_elt_array_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
200 unsigned int tabs, bool start_tabs, bool compact)
202 const ucl_object_t *cur = obj;
205 ucl_add_tabs (func, tabs, compact);
208 func->ucl_emitter_append_character ('[', 1, func->ud);
211 func->ucl_emitter_append_len ("[\n", 2, func->ud);
214 ucl_elt_write_json (cur, func, tabs + 1, true, compact);
215 if (cur->next != NULL) {
217 func->ucl_emitter_append_character (',', 1, func->ud);
220 func->ucl_emitter_append_len (",\n", 2, func->ud);
224 func->ucl_emitter_append_character ('\n', 1, func->ud);
228 ucl_add_tabs (func, tabs, compact);
229 func->ucl_emitter_append_character (']', 1, func->ud);
233 * Emit a single element
238 ucl_elt_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
239 unsigned int tabs, bool start_tabs, bool compact)
246 ucl_add_tabs (func, tabs, compact);
248 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
253 ucl_add_tabs (func, tabs, compact);
255 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
259 ucl_add_tabs (func, tabs, compact);
261 flag = ucl_object_toboolean (obj);
263 func->ucl_emitter_append_len ("true", 4, func->ud);
266 func->ucl_emitter_append_len ("false", 5, func->ud);
271 ucl_add_tabs (func, tabs, compact);
273 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
277 ucl_add_tabs (func, tabs, compact);
279 func->ucl_emitter_append_len ("null", 4, func->ud);
282 ucl_elt_obj_write_json (obj, func, tabs, start_tabs, compact);
285 ucl_elt_array_write_json (obj->value.av, func, tabs, start_tabs, compact);
293 * Write a single object to the buffer
295 * @param buf target buffer
298 ucl_obj_write_json (const ucl_object_t *obj, struct ucl_emitter_functions *func,
299 unsigned int tabs, bool start_tabs, bool compact)
301 const ucl_object_t *cur;
302 bool is_array = (obj->next != NULL);
305 /* This is an array actually */
307 ucl_add_tabs (func, tabs, compact);
311 func->ucl_emitter_append_character ('[', 1, func->ud);
314 func->ucl_emitter_append_len ("[\n", 2, func->ud);
317 while (cur != NULL) {
318 ucl_elt_write_json (cur, func, tabs + 1, true, compact);
320 func->ucl_emitter_append_character (',', 1, func->ud);
323 func->ucl_emitter_append_character ('\n', 1, func->ud);
327 ucl_add_tabs (func, tabs, compact);
328 func->ucl_emitter_append_character (']', 1, func->ud);
331 ucl_elt_write_json (obj, func, tabs, start_tabs, compact);
337 * Emit an object to json
339 * @return json output (should be freed after using)
342 ucl_object_emit_json (const ucl_object_t *obj, bool compact,
343 struct ucl_emitter_functions *func)
345 ucl_obj_write_json (obj, func, 0, false, compact);
349 * Write a single object to the buffer
350 * @param obj object to write
351 * @param buf target buffer
354 ucl_elt_obj_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
355 unsigned int tabs, bool start_tabs, bool is_top)
357 const ucl_object_t *cur, *cur_obj;
358 ucl_hash_iter_t it = NULL;
361 ucl_add_tabs (func, tabs, is_top);
364 func->ucl_emitter_append_len ("{\n", 2, func->ud);
367 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
368 LL_FOREACH (cur, cur_obj) {
369 ucl_add_tabs (func, tabs + 1, is_top);
370 if (cur_obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
371 ucl_elt_string_write_json (cur_obj->key, cur_obj->keylen, func);
374 func->ucl_emitter_append_len (cur_obj->key, cur_obj->keylen, func->ud);
376 if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) {
377 func->ucl_emitter_append_len (" = ", 3, func->ud);
380 func->ucl_emitter_append_character (' ', 1, func->ud);
382 ucl_elt_write_config (cur_obj, func,
383 is_top ? tabs : tabs + 1,
384 false, false, false);
385 if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) {
386 func->ucl_emitter_append_len (";\n", 2, func->ud);
389 func->ucl_emitter_append_character ('\n', 1, func->ud);
394 ucl_add_tabs (func, tabs, is_top);
396 func->ucl_emitter_append_character ('}', 1, func->ud);
401 * Write a single array to the buffer
402 * @param obj array to write
403 * @param buf target buffer
406 ucl_elt_array_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
407 unsigned int tabs, bool start_tabs, bool is_top)
409 const ucl_object_t *cur = obj;
412 ucl_add_tabs (func, tabs, false);
415 func->ucl_emitter_append_len ("[\n", 2, func->ud);
417 ucl_elt_write_config (cur, func, tabs + 1, true, false, false);
418 func->ucl_emitter_append_len (",\n", 2, func->ud);
421 ucl_add_tabs (func, tabs, false);
422 func->ucl_emitter_append_character (']', 1, func->ud);
426 * Emit a single element
431 ucl_elt_write_config (const ucl_object_t *obj, struct ucl_emitter_functions *func,
432 unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
436 if (expand_array && obj->next != NULL) {
437 ucl_elt_array_write_config (obj, func, tabs, start_tabs, is_top);
443 ucl_add_tabs (func, tabs, false);
445 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
450 ucl_add_tabs (func, tabs, false);
452 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
456 ucl_add_tabs (func, tabs, false);
458 flag = ucl_object_toboolean (obj);
460 func->ucl_emitter_append_len ("true", 4, func->ud);
463 func->ucl_emitter_append_len ("false", 5, func->ud);
468 ucl_add_tabs (func, tabs, false);
470 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
474 ucl_add_tabs (func, tabs, false);
476 func->ucl_emitter_append_len ("null", 4, func->ud);
479 ucl_elt_obj_write_config (obj, func, tabs, start_tabs, is_top);
482 ucl_elt_array_write_config (obj->value.av, func, tabs, start_tabs, is_top);
491 * Emit an object to rcl
493 * @return rcl output (should be freed after using)
496 ucl_object_emit_config (const ucl_object_t *obj, struct ucl_emitter_functions *func)
498 ucl_elt_write_config (obj, func, 0, false, true, true);
503 ucl_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
504 unsigned int tabs, bool start_tabs)
506 bool is_array = (obj->next != NULL);
509 ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, false);
512 ucl_elt_write_yaml (obj, func, tabs, start_tabs, false, true);
517 * Write a single object to the buffer
518 * @param obj object to write
519 * @param buf target buffer
522 ucl_elt_obj_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
523 unsigned int tabs, bool start_tabs, bool is_top)
525 const ucl_object_t *cur;
526 ucl_hash_iter_t it = NULL;
529 ucl_add_tabs (func, tabs, is_top);
532 func->ucl_emitter_append_len ("{\n", 2, func->ud);
535 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
536 ucl_add_tabs (func, tabs + 1, is_top);
537 if (cur->keylen > 0) {
538 ucl_elt_string_write_json (cur->key, cur->keylen, func);
541 func->ucl_emitter_append_len ("null", 4, func->ud);
543 func->ucl_emitter_append_len (": ", 2, func->ud);
544 ucl_obj_write_yaml (cur, func, is_top ? tabs : tabs + 1, false);
545 if (ucl_hash_iter_has_next(it)) {
547 func->ucl_emitter_append_len (",\n", 2, func->ud);
550 func->ucl_emitter_append_character ('\n', 1, func->ud);
554 func->ucl_emitter_append_character ('\n', 1, func->ud);
558 ucl_add_tabs (func, tabs, is_top);
560 func->ucl_emitter_append_character ('}', 1, func->ud);
565 * Write a single array to the buffer
566 * @param obj array to write
567 * @param buf target buffer
570 ucl_elt_array_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
571 unsigned int tabs, bool start_tabs, bool is_top)
573 const ucl_object_t *cur = obj;
576 ucl_add_tabs (func, tabs, false);
579 func->ucl_emitter_append_len ("[\n", 2, func->ud);
581 ucl_elt_write_yaml (cur, func, tabs + 1, true, false, false);
582 func->ucl_emitter_append_len (",\n", 2, func->ud);
585 ucl_add_tabs (func, tabs, false);
586 func->ucl_emitter_append_character (']', 1, func->ud);
590 * Emit a single element
595 ucl_elt_write_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func,
596 unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
600 if (expand_array && obj->next != NULL ) {
601 ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, is_top);
607 ucl_add_tabs (func, tabs, false);
609 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
614 ucl_add_tabs (func, tabs, false);
616 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
620 ucl_add_tabs (func, tabs, false);
622 flag = ucl_object_toboolean (obj);
624 func->ucl_emitter_append_len ("true", 4, func->ud);
627 func->ucl_emitter_append_len ("false", 5, func->ud);
632 ucl_add_tabs (func, tabs, false);
634 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
638 ucl_add_tabs (func, tabs, false);
640 func->ucl_emitter_append_len ("null", 4, func->ud);
643 ucl_elt_obj_write_yaml (obj, func, tabs, start_tabs, is_top);
646 ucl_elt_array_write_yaml (obj->value.av, func, tabs, start_tabs, is_top);
655 * Emit an object to rcl
657 * @return rcl output (should be freed after using)
660 ucl_object_emit_yaml (const ucl_object_t *obj, struct ucl_emitter_functions *func)
662 ucl_elt_write_yaml (obj, func, 0, false, true, true);
666 * Generic utstring output
669 ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
674 utstring_append_c (buf, c);
677 utstring_reserve (buf, len);
678 memset (&buf->d[buf->i], c, len);
680 buf->d[buf->i] = '\0';
687 ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud)
691 utstring_append_len (buf, str, len);
697 ucl_utstring_append_int (int64_t val, void *ud)
701 utstring_printf (buf, "%jd", (intmax_t)val);
706 ucl_utstring_append_double (double val, void *ud)
709 const double delta = 0.0000001;
711 if (val == (double)(int)val) {
712 utstring_printf (buf, "%.1lf", val);
714 else if (fabs (val - (double)(int)val) < delta) {
715 /* Write at maximum precision */
716 utstring_printf (buf, "%.*lg", DBL_DIG, val);
719 utstring_printf (buf, "%lf", val);
727 ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
729 UT_string *buf = NULL;
730 unsigned char *res = NULL;
731 struct ucl_emitter_functions func = {
732 .ucl_emitter_append_character = ucl_utstring_append_character,
733 .ucl_emitter_append_len = ucl_utstring_append_len,
734 .ucl_emitter_append_int = ucl_utstring_append_int,
735 .ucl_emitter_append_double = ucl_utstring_append_double
746 if (emit_type == UCL_EMIT_JSON) {
747 ucl_object_emit_json (obj, false, &func);
749 else if (emit_type == UCL_EMIT_JSON_COMPACT) {
750 ucl_object_emit_json (obj, true, &func);
752 else if (emit_type == UCL_EMIT_YAML) {
753 ucl_object_emit_yaml (obj, &func);
756 ucl_object_emit_config (obj, &func);
759 res = utstring_body (buf);
767 ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
768 struct ucl_emitter_functions *emitter)
770 if (emit_type == UCL_EMIT_JSON) {
771 ucl_object_emit_json (obj, false, emitter);
773 else if (emit_type == UCL_EMIT_JSON_COMPACT) {
774 ucl_object_emit_json (obj, true, emitter);
776 else if (emit_type == UCL_EMIT_YAML) {
777 ucl_object_emit_yaml (obj, emitter);
780 ucl_object_emit_config (obj, emitter);
783 /* XXX: need some error checks here */
789 ucl_object_emit_single_json (const ucl_object_t *obj)
791 UT_string *buf = NULL;
792 unsigned char *res = NULL;
803 ucl_utstring_append_len ("object", 6, buf);
806 ucl_utstring_append_len ("array", 5, buf);
809 ucl_utstring_append_int (obj->value.iv, buf);
813 ucl_utstring_append_double (obj->value.dv, buf);
816 ucl_utstring_append_len ("null", 4, buf);
820 ucl_utstring_append_len ("true", 4, buf);
823 ucl_utstring_append_len ("false", 5, buf);
827 ucl_utstring_append_len (obj->value.sv, obj->len, buf);
830 ucl_utstring_append_len ("userdata", 8, buf);
833 res = utstring_body (buf);