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.
27 #include "ucl_internal.h"
28 #include "ucl_chartable.h"
32 * Serialise UCL object to various of output formats
36 static void ucl_obj_write_json (ucl_object_t *obj,
37 struct ucl_emitter_functions *func,
41 static void ucl_elt_write_json (ucl_object_t *obj,
42 struct ucl_emitter_functions *func,
46 static void ucl_elt_write_config (ucl_object_t *obj,
47 struct ucl_emitter_functions *func,
52 static void ucl_elt_write_yaml (ucl_object_t *obj,
53 struct ucl_emitter_functions *func,
58 static void ucl_elt_array_write_yaml (ucl_object_t *obj,
59 struct ucl_emitter_functions *func,
65 * Add tabulation to the output buffer
66 * @param buf target buffer
67 * @param tabs number of tabs to add
70 ucl_add_tabs (struct ucl_emitter_functions *func, unsigned int tabs, bool compact)
73 func->ucl_emitter_append_character (' ', tabs * 4, func->ud);
79 * @param str string to emit
80 * @param buf target buffer
83 ucl_elt_string_write_json (const char *str, size_t size,
84 struct ucl_emitter_functions *func)
86 const char *p = str, *c = str;
89 func->ucl_emitter_append_character ('"', 1, func->ud);
91 if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
93 func->ucl_emitter_append_len (c, len, func->ud);
97 func->ucl_emitter_append_len ("\\n", 2, func->ud);
100 func->ucl_emitter_append_len ("\\r", 2, func->ud);
103 func->ucl_emitter_append_len ("\\b", 2, func->ud);
106 func->ucl_emitter_append_len ("\\t", 2, func->ud);
109 func->ucl_emitter_append_len ("\\f", 2, func->ud);
112 func->ucl_emitter_append_len ("\\\\", 2, func->ud);
115 func->ucl_emitter_append_len ("\\\"", 2, func->ud);
128 func->ucl_emitter_append_len (c, len, func->ud);
130 func->ucl_emitter_append_character ('"', 1, func->ud);
134 * Write a single object to the buffer
135 * @param obj object to write
136 * @param buf target buffer
139 ucl_elt_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
140 unsigned int tabs, bool start_tabs, bool compact)
143 ucl_hash_iter_t it = NULL;
146 ucl_add_tabs (func, tabs, compact);
149 func->ucl_emitter_append_character ('{', 1, func->ud);
152 func->ucl_emitter_append_len ("{\n", 2, func->ud);
154 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
155 ucl_add_tabs (func, tabs + 1, compact);
156 if (cur->keylen > 0) {
157 ucl_elt_string_write_json (cur->key, cur->keylen, func);
160 func->ucl_emitter_append_len ("null", 4, func->ud);
163 func->ucl_emitter_append_character (':', 1, func->ud);
166 func->ucl_emitter_append_len (": ", 2, func->ud);
168 ucl_obj_write_json (cur, func, tabs + 1, false, compact);
169 if (ucl_hash_iter_has_next (it)) {
171 func->ucl_emitter_append_character (',', 1, func->ud);
174 func->ucl_emitter_append_len (",\n", 2, func->ud);
178 func->ucl_emitter_append_character ('\n', 1, func->ud);
181 ucl_add_tabs (func, tabs, compact);
182 func->ucl_emitter_append_character ('}', 1, func->ud);
186 * Write a single array to the buffer
187 * @param obj array to write
188 * @param buf target buffer
191 ucl_elt_array_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
192 unsigned int tabs, bool start_tabs, bool compact)
194 ucl_object_t *cur = obj;
197 ucl_add_tabs (func, tabs, compact);
200 func->ucl_emitter_append_character ('[', 1, func->ud);
203 func->ucl_emitter_append_len ("[\n", 2, func->ud);
206 ucl_elt_write_json (cur, func, tabs + 1, true, compact);
207 if (cur->next != NULL) {
209 func->ucl_emitter_append_character (',', 1, func->ud);
212 func->ucl_emitter_append_len (",\n", 2, func->ud);
216 func->ucl_emitter_append_character ('\n', 1, func->ud);
220 ucl_add_tabs (func, tabs, compact);
221 func->ucl_emitter_append_character (']', 1, func->ud);
225 * Emit a single element
230 ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
231 unsigned int tabs, bool start_tabs, bool compact)
238 ucl_add_tabs (func, tabs, compact);
240 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
245 ucl_add_tabs (func, tabs, compact);
247 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
251 ucl_add_tabs (func, tabs, compact);
253 flag = ucl_object_toboolean (obj);
255 func->ucl_emitter_append_len ("true", 4, func->ud);
258 func->ucl_emitter_append_len ("false", 5, func->ud);
263 ucl_add_tabs (func, tabs, compact);
265 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
269 ucl_add_tabs (func, tabs, compact);
271 func->ucl_emitter_append_len ("null", 4, func->ud);
274 ucl_elt_obj_write_json (obj, func, tabs, start_tabs, compact);
277 ucl_elt_array_write_json (obj->value.av, func, tabs, start_tabs, compact);
285 * Write a single object to the buffer
287 * @param buf target buffer
290 ucl_obj_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func,
291 unsigned int tabs, bool start_tabs, bool compact)
294 bool is_array = (obj->next != NULL);
297 /* This is an array actually */
299 ucl_add_tabs (func, tabs, compact);
303 func->ucl_emitter_append_character ('[', 1, func->ud);
306 func->ucl_emitter_append_len ("[\n", 2, func->ud);
309 while (cur != NULL) {
310 ucl_elt_write_json (cur, func, tabs + 1, true, compact);
312 func->ucl_emitter_append_character (',', 1, func->ud);
315 func->ucl_emitter_append_character ('\n', 1, func->ud);
319 ucl_add_tabs (func, tabs, compact);
320 func->ucl_emitter_append_character (']', 1, func->ud);
323 ucl_elt_write_json (obj, func, tabs, start_tabs, compact);
329 * Emit an object to json
331 * @return json output (should be freed after using)
334 ucl_object_emit_json (ucl_object_t *obj, bool compact, struct ucl_emitter_functions *func)
336 ucl_obj_write_json (obj, func, 0, false, compact);
340 * Write a single object to the buffer
341 * @param obj object to write
342 * @param buf target buffer
345 ucl_elt_obj_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func,
346 unsigned int tabs, bool start_tabs, bool is_top)
348 ucl_object_t *cur, *cur_obj;
349 ucl_hash_iter_t it = NULL;
352 ucl_add_tabs (func, tabs, is_top);
355 func->ucl_emitter_append_len ("{\n", 2, func->ud);
358 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
359 LL_FOREACH (cur, cur_obj) {
360 ucl_add_tabs (func, tabs + 1, is_top);
361 if (cur_obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) {
362 ucl_elt_string_write_json (cur_obj->key, cur_obj->keylen, func);
365 func->ucl_emitter_append_len (cur_obj->key, cur_obj->keylen, func->ud);
367 if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) {
368 func->ucl_emitter_append_len (" = ", 3, func->ud);
371 func->ucl_emitter_append_character (' ', 1, func->ud);
373 ucl_elt_write_config (cur_obj, func,
374 is_top ? tabs : tabs + 1,
375 false, false, false);
376 if (cur_obj->type != UCL_OBJECT && cur_obj->type != UCL_ARRAY) {
377 func->ucl_emitter_append_len (";\n", 2, func->ud);
380 func->ucl_emitter_append_character ('\n', 1, func->ud);
385 ucl_add_tabs (func, tabs, is_top);
387 func->ucl_emitter_append_character ('}', 1, func->ud);
392 * Write a single array to the buffer
393 * @param obj array to write
394 * @param buf target buffer
397 ucl_elt_array_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func,
398 unsigned int tabs, bool start_tabs, bool is_top)
400 ucl_object_t *cur = obj;
403 ucl_add_tabs (func, tabs, false);
406 func->ucl_emitter_append_len ("[\n", 2, func->ud);
408 ucl_elt_write_config (cur, func, tabs + 1, true, false, false);
409 func->ucl_emitter_append_len (",\n", 2, func->ud);
412 ucl_add_tabs (func, tabs, false);
413 func->ucl_emitter_append_character (']', 1, func->ud);
417 * Emit a single element
422 ucl_elt_write_config (ucl_object_t *obj, struct ucl_emitter_functions *func,
423 unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
427 if (expand_array && obj->next != NULL) {
428 ucl_elt_array_write_config (obj, func, tabs, start_tabs, is_top);
434 ucl_add_tabs (func, tabs, false);
436 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
441 ucl_add_tabs (func, tabs, false);
443 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
447 ucl_add_tabs (func, tabs, false);
449 flag = ucl_object_toboolean (obj);
451 func->ucl_emitter_append_len ("true", 4, func->ud);
454 func->ucl_emitter_append_len ("false", 5, func->ud);
459 ucl_add_tabs (func, tabs, false);
461 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
465 ucl_add_tabs (func, tabs, false);
467 func->ucl_emitter_append_len ("null", 4, func->ud);
470 ucl_elt_obj_write_config (obj, func, tabs, start_tabs, is_top);
473 ucl_elt_array_write_config (obj->value.av, func, tabs, start_tabs, is_top);
482 * Emit an object to rcl
484 * @return rcl output (should be freed after using)
487 ucl_object_emit_config (ucl_object_t *obj, struct ucl_emitter_functions *func)
489 ucl_elt_write_config (obj, func, 0, false, true, true);
494 ucl_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
495 unsigned int tabs, bool start_tabs)
497 bool is_array = (obj->next != NULL);
500 ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, false);
503 ucl_elt_write_yaml (obj, func, tabs, start_tabs, false, true);
508 * Write a single object to the buffer
509 * @param obj object to write
510 * @param buf target buffer
513 ucl_elt_obj_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
514 unsigned int tabs, bool start_tabs, bool is_top)
517 ucl_hash_iter_t it = NULL;
520 ucl_add_tabs (func, tabs, is_top);
523 func->ucl_emitter_append_len ("{\n", 2, func->ud);
526 while ((cur = ucl_hash_iterate (obj->value.ov, &it))) {
527 ucl_add_tabs (func, tabs + 1, is_top);
528 if (cur->keylen > 0) {
529 ucl_elt_string_write_json (cur->key, cur->keylen, func);
532 func->ucl_emitter_append_len ("null", 4, func->ud);
534 func->ucl_emitter_append_len (": ", 2, func->ud);
535 ucl_obj_write_yaml (cur, func, is_top ? tabs : tabs + 1, false);
536 if (ucl_hash_iter_has_next(it)) {
538 func->ucl_emitter_append_len (",\n", 2, func->ud);
541 func->ucl_emitter_append_character ('\n', 1, func->ud);
545 func->ucl_emitter_append_character ('\n', 1, func->ud);
549 ucl_add_tabs (func, tabs, is_top);
551 func->ucl_emitter_append_character ('}', 1, func->ud);
556 * Write a single array to the buffer
557 * @param obj array to write
558 * @param buf target buffer
561 ucl_elt_array_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
562 unsigned int tabs, bool start_tabs, bool is_top)
564 ucl_object_t *cur = obj;
567 ucl_add_tabs (func, tabs, false);
570 func->ucl_emitter_append_len ("[\n", 2, func->ud);
572 ucl_elt_write_yaml (cur, func, tabs + 1, true, false, false);
573 func->ucl_emitter_append_len (",\n", 2, func->ud);
576 ucl_add_tabs (func, tabs, false);
577 func->ucl_emitter_append_character (']', 1, func->ud);
581 * Emit a single element
586 ucl_elt_write_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func,
587 unsigned int tabs, bool start_tabs, bool is_top, bool expand_array)
591 if (expand_array && obj->next != NULL ) {
592 ucl_elt_array_write_yaml (obj, func, tabs, start_tabs, is_top);
598 ucl_add_tabs (func, tabs, false);
600 func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud);
605 ucl_add_tabs (func, tabs, false);
607 func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud);
611 ucl_add_tabs (func, tabs, false);
613 flag = ucl_object_toboolean (obj);
615 func->ucl_emitter_append_len ("true", 4, func->ud);
618 func->ucl_emitter_append_len ("false", 5, func->ud);
623 ucl_add_tabs (func, tabs, false);
625 ucl_elt_string_write_json (obj->value.sv, obj->len, func);
629 ucl_add_tabs (func, tabs, false);
631 func->ucl_emitter_append_len ("null", 4, func->ud);
634 ucl_elt_obj_write_yaml (obj, func, tabs, start_tabs, is_top);
637 ucl_elt_array_write_yaml (obj->value.av, func, tabs, start_tabs, is_top);
646 * Emit an object to rcl
648 * @return rcl output (should be freed after using)
651 ucl_object_emit_yaml (ucl_object_t *obj, struct ucl_emitter_functions *func)
653 ucl_elt_write_yaml (obj, func, 0, false, true, true);
657 * Generic utstring output
660 ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
665 utstring_append_c (buf, c);
668 utstring_reserve (buf, len);
669 memset (&buf->d[buf->i], c, len);
671 buf->d[buf->i] = '\0';
678 ucl_utstring_append_len (const unsigned char *str, size_t len, void *ud)
682 utstring_append_len (buf, str, len);
688 ucl_utstring_append_int (int64_t val, void *ud)
692 utstring_printf (buf, "%jd", (intmax_t)val);
697 ucl_utstring_append_double (double val, void *ud)
700 const double delta = 0.0000001;
702 if (val == (double)(int)val) {
703 utstring_printf (buf, "%.1lf", val);
705 else if (fabs (val - (double)(int)val) < delta) {
706 /* Write at maximum precision */
707 utstring_printf (buf, "%.*lg", DBL_DIG, val);
710 utstring_printf (buf, "%lf", val);
718 ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type)
720 UT_string *buf = NULL;
721 unsigned char *res = NULL;
722 struct ucl_emitter_functions func = {
723 .ucl_emitter_append_character = ucl_utstring_append_character,
724 .ucl_emitter_append_len = ucl_utstring_append_len,
725 .ucl_emitter_append_int = ucl_utstring_append_int,
726 .ucl_emitter_append_double = ucl_utstring_append_double
737 if (emit_type == UCL_EMIT_JSON) {
738 ucl_object_emit_json (obj, false, &func);
740 else if (emit_type == UCL_EMIT_JSON_COMPACT) {
741 ucl_object_emit_json (obj, true, &func);
743 else if (emit_type == UCL_EMIT_YAML) {
744 ucl_object_emit_yaml (obj, &func);
747 ucl_object_emit_config (obj, &func);
750 res = utstring_body (buf);
758 ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type,
759 struct ucl_emitter_functions *emitter)
761 if (emit_type == UCL_EMIT_JSON) {
762 ucl_object_emit_json (obj, false, emitter);
764 else if (emit_type == UCL_EMIT_JSON_COMPACT) {
765 ucl_object_emit_json (obj, true, emitter);
767 else if (emit_type == UCL_EMIT_YAML) {
768 ucl_object_emit_yaml (obj, emitter);
771 ucl_object_emit_config (obj, emitter);
774 /* XXX: need some error checks here */
780 ucl_object_emit_single_json (ucl_object_t *obj)
782 UT_string *buf = NULL;
783 unsigned char *res = NULL;
794 ucl_utstring_append_len ("object", 6, buf);
797 ucl_utstring_append_len ("array", 5, buf);
800 ucl_utstring_append_int (obj->value.iv, buf);
804 ucl_utstring_append_double (obj->value.dv, buf);
807 ucl_utstring_append_len ("null", 4, buf);
811 ucl_utstring_append_len ("true", 4, buf);
814 ucl_utstring_append_len ("false", 5, buf);
818 ucl_utstring_append_len (obj->value.sv, obj->len, buf);
821 ucl_utstring_append_len ("userdata", 8, buf);
824 res = utstring_body (buf);