1c99fb5f9SBaptiste Daroussin /* Copyright (c) 2013, Vsevolod Stakhov 2c99fb5f9SBaptiste Daroussin * All rights reserved. 3c99fb5f9SBaptiste Daroussin * 4c99fb5f9SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 5c99fb5f9SBaptiste Daroussin * modification, are permitted provided that the following conditions are met: 6c99fb5f9SBaptiste Daroussin * * Redistributions of source code must retain the above copyright 7c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 8c99fb5f9SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright 9c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 10c99fb5f9SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 11c99fb5f9SBaptiste Daroussin * 12c99fb5f9SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13c99fb5f9SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14c99fb5f9SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15c99fb5f9SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16c99fb5f9SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17c99fb5f9SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18c99fb5f9SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19c99fb5f9SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20c99fb5f9SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21c99fb5f9SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22c99fb5f9SBaptiste Daroussin */ 23c99fb5f9SBaptiste Daroussin 2497bd480fSBaptiste Daroussin #ifdef HAVE_CONFIG_H 2597bd480fSBaptiste Daroussin #include "config.h" 2697bd480fSBaptiste Daroussin #endif 2797bd480fSBaptiste Daroussin 28c99fb5f9SBaptiste Daroussin #include "ucl.h" 29c99fb5f9SBaptiste Daroussin #include "ucl_internal.h" 30c99fb5f9SBaptiste Daroussin #include "ucl_chartable.h" 3197bd480fSBaptiste Daroussin #ifdef HAVE_FLOAT_H 3297bd480fSBaptiste Daroussin #include <float.h> 3397bd480fSBaptiste Daroussin #endif 3497bd480fSBaptiste Daroussin #ifdef HAVE_MATH_H 3597bd480fSBaptiste Daroussin #include <math.h> 3697bd480fSBaptiste Daroussin #endif 37c99fb5f9SBaptiste Daroussin 38c99fb5f9SBaptiste Daroussin /** 393dcf5eb7SBaptiste Daroussin * @file ucl_emitter.c 40c99fb5f9SBaptiste Daroussin * Serialise UCL object to various of output formats 41c99fb5f9SBaptiste Daroussin */ 42c99fb5f9SBaptiste Daroussin 433dcf5eb7SBaptiste Daroussin static void ucl_emitter_common_elt (struct ucl_emitter_context *ctx, 443dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool first, bool print_key, bool compact); 45c99fb5f9SBaptiste Daroussin 463dcf5eb7SBaptiste Daroussin #define UCL_EMIT_TYPE_OPS(type) \ 473dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \ 483dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool first, bool print_key); \ 493dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \ 503dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key); \ 513dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \ 523dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key); \ 533dcf5eb7SBaptiste Daroussin static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \ 543dcf5eb7SBaptiste Daroussin const ucl_object_t *obj); \ 553dcf5eb7SBaptiste Daroussin static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \ 563dcf5eb7SBaptiste Daroussin const ucl_object_t *obj) 573dcf5eb7SBaptiste Daroussin 583dcf5eb7SBaptiste Daroussin /* 593dcf5eb7SBaptiste Daroussin * JSON format operations 603dcf5eb7SBaptiste Daroussin */ 613dcf5eb7SBaptiste Daroussin UCL_EMIT_TYPE_OPS(json); 623dcf5eb7SBaptiste Daroussin UCL_EMIT_TYPE_OPS(json_compact); 633dcf5eb7SBaptiste Daroussin UCL_EMIT_TYPE_OPS(config); 643dcf5eb7SBaptiste Daroussin UCL_EMIT_TYPE_OPS(yaml); 6539ee7a7aSBaptiste Daroussin UCL_EMIT_TYPE_OPS(msgpack); 663dcf5eb7SBaptiste Daroussin 673dcf5eb7SBaptiste Daroussin #define UCL_EMIT_TYPE_CONTENT(type) { \ 683dcf5eb7SBaptiste Daroussin .ucl_emitter_write_elt = ucl_emit_ ## type ## _elt, \ 693dcf5eb7SBaptiste Daroussin .ucl_emitter_start_object = ucl_emit_ ## type ##_start_obj, \ 703dcf5eb7SBaptiste Daroussin .ucl_emitter_start_array = ucl_emit_ ## type ##_start_array, \ 713dcf5eb7SBaptiste Daroussin .ucl_emitter_end_object = ucl_emit_ ## type ##_end_object, \ 723dcf5eb7SBaptiste Daroussin .ucl_emitter_end_array = ucl_emit_ ## type ##_end_array \ 733dcf5eb7SBaptiste Daroussin } 743dcf5eb7SBaptiste Daroussin 753dcf5eb7SBaptiste Daroussin const struct ucl_emitter_operations ucl_standartd_emitter_ops[] = { 763dcf5eb7SBaptiste Daroussin [UCL_EMIT_JSON] = UCL_EMIT_TYPE_CONTENT(json), 773dcf5eb7SBaptiste Daroussin [UCL_EMIT_JSON_COMPACT] = UCL_EMIT_TYPE_CONTENT(json_compact), 783dcf5eb7SBaptiste Daroussin [UCL_EMIT_CONFIG] = UCL_EMIT_TYPE_CONTENT(config), 7939ee7a7aSBaptiste Daroussin [UCL_EMIT_YAML] = UCL_EMIT_TYPE_CONTENT(yaml), 8039ee7a7aSBaptiste Daroussin [UCL_EMIT_MSGPACK] = UCL_EMIT_TYPE_CONTENT(msgpack) 813dcf5eb7SBaptiste Daroussin }; 823dcf5eb7SBaptiste Daroussin 833dcf5eb7SBaptiste Daroussin /* 843dcf5eb7SBaptiste Daroussin * Utility to check whether we need a top object 853dcf5eb7SBaptiste Daroussin */ 863dcf5eb7SBaptiste Daroussin #define UCL_EMIT_IDENT_TOP_OBJ(ctx, obj) ((ctx)->top != (obj) || \ 873dcf5eb7SBaptiste Daroussin ((ctx)->id == UCL_EMIT_JSON_COMPACT || (ctx)->id == UCL_EMIT_JSON)) 883dcf5eb7SBaptiste Daroussin 89c99fb5f9SBaptiste Daroussin 90c99fb5f9SBaptiste Daroussin /** 91c99fb5f9SBaptiste Daroussin * Add tabulation to the output buffer 92c99fb5f9SBaptiste Daroussin * @param buf target buffer 93c99fb5f9SBaptiste Daroussin * @param tabs number of tabs to add 94c99fb5f9SBaptiste Daroussin */ 95c99fb5f9SBaptiste Daroussin static inline void 963dcf5eb7SBaptiste Daroussin ucl_add_tabs (const struct ucl_emitter_functions *func, unsigned int tabs, 973dcf5eb7SBaptiste Daroussin bool compact) 98c99fb5f9SBaptiste Daroussin { 993dcf5eb7SBaptiste Daroussin if (!compact && tabs > 0) { 100c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_character (' ', tabs * 4, func->ud); 101c99fb5f9SBaptiste Daroussin } 102c99fb5f9SBaptiste Daroussin } 103c99fb5f9SBaptiste Daroussin 104c99fb5f9SBaptiste Daroussin /** 1053dcf5eb7SBaptiste Daroussin * Print key for the element 1063dcf5eb7SBaptiste Daroussin * @param ctx 1073dcf5eb7SBaptiste Daroussin * @param obj 108c99fb5f9SBaptiste Daroussin */ 109c99fb5f9SBaptiste Daroussin static void 1103dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx, 1113dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool compact) 112c99fb5f9SBaptiste Daroussin { 1133dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 114c99fb5f9SBaptiste Daroussin 1153dcf5eb7SBaptiste Daroussin if (!print_key) { 1163dcf5eb7SBaptiste Daroussin return; 117c99fb5f9SBaptiste Daroussin } 1183dcf5eb7SBaptiste Daroussin 1193dcf5eb7SBaptiste Daroussin if (ctx->id == UCL_EMIT_CONFIG) { 1203dcf5eb7SBaptiste Daroussin if (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE) { 1213dcf5eb7SBaptiste Daroussin ucl_elt_string_write_json (obj->key, obj->keylen, ctx); 122c99fb5f9SBaptiste Daroussin } 123c99fb5f9SBaptiste Daroussin else { 1243dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud); 125c99fb5f9SBaptiste Daroussin } 126c99fb5f9SBaptiste Daroussin 1273dcf5eb7SBaptiste Daroussin if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) { 1283dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (" = ", 3, func->ud); 129c99fb5f9SBaptiste Daroussin } 130c99fb5f9SBaptiste Daroussin else { 1313dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character (' ', 1, func->ud); 132c99fb5f9SBaptiste Daroussin } 1333dcf5eb7SBaptiste Daroussin } 1344bf54857SBaptiste Daroussin else if (ctx->id == UCL_EMIT_YAML) { 1354bf54857SBaptiste Daroussin if (obj->keylen > 0 && (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE)) { 1364bf54857SBaptiste Daroussin ucl_elt_string_write_json (obj->key, obj->keylen, ctx); 1374bf54857SBaptiste Daroussin } 1384bf54857SBaptiste Daroussin else if (obj->keylen > 0) { 1394bf54857SBaptiste Daroussin func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud); 1404bf54857SBaptiste Daroussin } 1414bf54857SBaptiste Daroussin else { 1424bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("null", 4, func->ud); 1434bf54857SBaptiste Daroussin } 1444bf54857SBaptiste Daroussin 1454bf54857SBaptiste Daroussin func->ucl_emitter_append_len (": ", 2, func->ud); 1464bf54857SBaptiste Daroussin } 1473dcf5eb7SBaptiste Daroussin else { 1483dcf5eb7SBaptiste Daroussin if (obj->keylen > 0) { 1493dcf5eb7SBaptiste Daroussin ucl_elt_string_write_json (obj->key, obj->keylen, ctx); 150c99fb5f9SBaptiste Daroussin } 151c99fb5f9SBaptiste Daroussin else { 152c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len ("null", 4, func->ud); 153c99fb5f9SBaptiste Daroussin } 1543dcf5eb7SBaptiste Daroussin 155c99fb5f9SBaptiste Daroussin if (compact) { 156c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_character (':', 1, func->ud); 157c99fb5f9SBaptiste Daroussin } 158c99fb5f9SBaptiste Daroussin else { 159c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len (": ", 2, func->ud); 160c99fb5f9SBaptiste Daroussin } 161c99fb5f9SBaptiste Daroussin } 162c99fb5f9SBaptiste Daroussin } 163c99fb5f9SBaptiste Daroussin 164c99fb5f9SBaptiste Daroussin static void 1653dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (struct ucl_emitter_context *ctx, 1663dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool compact, bool is_array) 167c99fb5f9SBaptiste Daroussin { 1683dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 169c99fb5f9SBaptiste Daroussin 1703dcf5eb7SBaptiste Daroussin if (ctx->id == UCL_EMIT_CONFIG && obj != ctx->top) { 1713dcf5eb7SBaptiste Daroussin if (obj->type != UCL_OBJECT && obj->type != UCL_ARRAY) { 1723dcf5eb7SBaptiste Daroussin if (!is_array) { 1733dcf5eb7SBaptiste Daroussin /* Objects are split by ';' */ 174c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len (";\n", 2, func->ud); 175c99fb5f9SBaptiste Daroussin } 176c99fb5f9SBaptiste Daroussin else { 1773dcf5eb7SBaptiste Daroussin /* Use commas for arrays */ 1783dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (",\n", 2, func->ud); 1793dcf5eb7SBaptiste Daroussin } 1803dcf5eb7SBaptiste Daroussin } 1813dcf5eb7SBaptiste Daroussin else { 182c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_character ('\n', 1, func->ud); 183c99fb5f9SBaptiste Daroussin } 184c99fb5f9SBaptiste Daroussin } 185c99fb5f9SBaptiste Daroussin } 186c99fb5f9SBaptiste Daroussin 1873dcf5eb7SBaptiste Daroussin /** 1883dcf5eb7SBaptiste Daroussin * End standard ucl object 1893dcf5eb7SBaptiste Daroussin * @param ctx emitter context 1903dcf5eb7SBaptiste Daroussin * @param compact compact flag 1913dcf5eb7SBaptiste Daroussin */ 1923dcf5eb7SBaptiste Daroussin static void 1933dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_object (struct ucl_emitter_context *ctx, 1943dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool compact) 1953dcf5eb7SBaptiste Daroussin { 1963dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 1973dcf5eb7SBaptiste Daroussin 1983dcf5eb7SBaptiste Daroussin if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) { 1994bf54857SBaptiste Daroussin ctx->indent --; 2003dcf5eb7SBaptiste Daroussin if (compact) { 2013dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('}', 1, func->ud); 2023dcf5eb7SBaptiste Daroussin } 2033dcf5eb7SBaptiste Daroussin else { 2043dcf5eb7SBaptiste Daroussin if (ctx->id != UCL_EMIT_CONFIG) { 2053dcf5eb7SBaptiste Daroussin /* newline is already added for this format */ 2063dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('\n', 1, func->ud); 2073dcf5eb7SBaptiste Daroussin } 2084bf54857SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 209c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_character ('}', 1, func->ud); 210c99fb5f9SBaptiste Daroussin } 211c99fb5f9SBaptiste Daroussin } 212c99fb5f9SBaptiste Daroussin 2133dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, false); 2143dcf5eb7SBaptiste Daroussin } 2153dcf5eb7SBaptiste Daroussin 216c99fb5f9SBaptiste Daroussin /** 2173dcf5eb7SBaptiste Daroussin * End standard ucl array 2183dcf5eb7SBaptiste Daroussin * @param ctx emitter context 2193dcf5eb7SBaptiste Daroussin * @param compact compact flag 220c99fb5f9SBaptiste Daroussin */ 221c99fb5f9SBaptiste Daroussin static void 2223dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_array (struct ucl_emitter_context *ctx, 2233dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool compact) 224c99fb5f9SBaptiste Daroussin { 2253dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 226c99fb5f9SBaptiste Daroussin 2274bf54857SBaptiste Daroussin ctx->indent --; 2283dcf5eb7SBaptiste Daroussin if (compact) { 2293dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character (']', 1, func->ud); 230c99fb5f9SBaptiste Daroussin } 2313dcf5eb7SBaptiste Daroussin else { 2323dcf5eb7SBaptiste Daroussin if (ctx->id != UCL_EMIT_CONFIG) { 2333dcf5eb7SBaptiste Daroussin /* newline is already added for this format */ 2343dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('\n', 1, func->ud); 235c99fb5f9SBaptiste Daroussin } 2364bf54857SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 237c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_character (']', 1, func->ud); 238c99fb5f9SBaptiste Daroussin } 239c99fb5f9SBaptiste Daroussin 2403dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, true); 241c99fb5f9SBaptiste Daroussin } 242c99fb5f9SBaptiste Daroussin 243c99fb5f9SBaptiste Daroussin /** 2443dcf5eb7SBaptiste Daroussin * Start emit standard UCL array 2453dcf5eb7SBaptiste Daroussin * @param ctx emitter context 246c99fb5f9SBaptiste Daroussin * @param obj object to write 2473dcf5eb7SBaptiste Daroussin * @param compact compact flag 248c99fb5f9SBaptiste Daroussin */ 249c99fb5f9SBaptiste Daroussin static void 2503dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_array (struct ucl_emitter_context *ctx, 2513dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key, bool compact) 252c99fb5f9SBaptiste Daroussin { 253b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 2548e3b1ab2SBaptiste Daroussin ucl_object_iter_t iter = NULL; 2553dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 2563dcf5eb7SBaptiste Daroussin bool first = true; 257c99fb5f9SBaptiste Daroussin 2583dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 2593dcf5eb7SBaptiste Daroussin 2603dcf5eb7SBaptiste Daroussin if (compact) { 2613dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('[', 1, func->ud); 262c99fb5f9SBaptiste Daroussin } 2633dcf5eb7SBaptiste Daroussin else { 2643dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len ("[\n", 2, func->ud); 2653dcf5eb7SBaptiste Daroussin } 2663dcf5eb7SBaptiste Daroussin 2674bf54857SBaptiste Daroussin ctx->indent ++; 2683dcf5eb7SBaptiste Daroussin 2693dcf5eb7SBaptiste Daroussin if (obj->type == UCL_ARRAY) { 2703dcf5eb7SBaptiste Daroussin /* explicit array */ 271*d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (obj, &iter, true)) != NULL) { 2728e3b1ab2SBaptiste Daroussin ucl_emitter_common_elt (ctx, cur, first, false, compact); 2738e3b1ab2SBaptiste Daroussin first = false; 2748e3b1ab2SBaptiste Daroussin } 2753dcf5eb7SBaptiste Daroussin } 2763dcf5eb7SBaptiste Daroussin else { 2773dcf5eb7SBaptiste Daroussin /* implicit array */ 2783dcf5eb7SBaptiste Daroussin cur = obj; 2793dcf5eb7SBaptiste Daroussin while (cur) { 2803dcf5eb7SBaptiste Daroussin ucl_emitter_common_elt (ctx, cur, first, false, compact); 2813dcf5eb7SBaptiste Daroussin first = false; 2823dcf5eb7SBaptiste Daroussin cur = cur->next; 2833dcf5eb7SBaptiste Daroussin } 2843dcf5eb7SBaptiste Daroussin } 2853dcf5eb7SBaptiste Daroussin 2868e3b1ab2SBaptiste Daroussin 2878e3b1ab2SBaptiste Daroussin } 2888e3b1ab2SBaptiste Daroussin 2893dcf5eb7SBaptiste Daroussin /** 2903dcf5eb7SBaptiste Daroussin * Start emit standard UCL object 2913dcf5eb7SBaptiste Daroussin * @param ctx emitter context 2923dcf5eb7SBaptiste Daroussin * @param obj object to write 2933dcf5eb7SBaptiste Daroussin * @param compact compact flag 2943dcf5eb7SBaptiste Daroussin */ 2953dcf5eb7SBaptiste Daroussin static void 2963dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_object (struct ucl_emitter_context *ctx, 2973dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key, bool compact) 2983dcf5eb7SBaptiste Daroussin { 2993dcf5eb7SBaptiste Daroussin ucl_hash_iter_t it = NULL; 3003dcf5eb7SBaptiste Daroussin const ucl_object_t *cur, *elt; 3013dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 3023dcf5eb7SBaptiste Daroussin bool first = true; 3033dcf5eb7SBaptiste Daroussin 3043dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 3053dcf5eb7SBaptiste Daroussin /* 3063dcf5eb7SBaptiste Daroussin * Print <ident_level>{ 3073dcf5eb7SBaptiste Daroussin * <ident_level + 1><object content> 3083dcf5eb7SBaptiste Daroussin */ 3093dcf5eb7SBaptiste Daroussin if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) { 3103dcf5eb7SBaptiste Daroussin if (compact) { 3113dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character ('{', 1, func->ud); 3123dcf5eb7SBaptiste Daroussin } 3133dcf5eb7SBaptiste Daroussin else { 314c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len ("{\n", 2, func->ud); 315c99fb5f9SBaptiste Daroussin } 3164bf54857SBaptiste Daroussin ctx->indent ++; 3173dcf5eb7SBaptiste Daroussin } 318c99fb5f9SBaptiste Daroussin 319c99fb5f9SBaptiste Daroussin while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { 3203dcf5eb7SBaptiste Daroussin 3213dcf5eb7SBaptiste Daroussin if (ctx->id == UCL_EMIT_CONFIG) { 3223dcf5eb7SBaptiste Daroussin LL_FOREACH (cur, elt) { 3233dcf5eb7SBaptiste Daroussin ucl_emitter_common_elt (ctx, elt, first, true, compact); 3243dcf5eb7SBaptiste Daroussin } 325c99fb5f9SBaptiste Daroussin } 326c99fb5f9SBaptiste Daroussin else { 3273dcf5eb7SBaptiste Daroussin /* Expand implicit arrays */ 3283dcf5eb7SBaptiste Daroussin if (cur->next != NULL) { 3293dcf5eb7SBaptiste Daroussin if (!first) { 3303dcf5eb7SBaptiste Daroussin if (compact) { 3313dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character (',', 1, func->ud); 332c99fb5f9SBaptiste Daroussin } 3333dcf5eb7SBaptiste Daroussin else { 334c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len (",\n", 2, func->ud); 335c99fb5f9SBaptiste Daroussin } 336c99fb5f9SBaptiste Daroussin } 3374bf54857SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 3383dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_array (ctx, cur, true, compact); 3393dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_array (ctx, cur, compact); 340c99fb5f9SBaptiste Daroussin } 341c99fb5f9SBaptiste Daroussin else { 3423dcf5eb7SBaptiste Daroussin ucl_emitter_common_elt (ctx, cur, first, true, compact); 343c99fb5f9SBaptiste Daroussin } 344c99fb5f9SBaptiste Daroussin } 345c99fb5f9SBaptiste Daroussin 3463dcf5eb7SBaptiste Daroussin first = false; 347c99fb5f9SBaptiste Daroussin } 348c99fb5f9SBaptiste Daroussin } 349c99fb5f9SBaptiste Daroussin 350c99fb5f9SBaptiste Daroussin /** 3513dcf5eb7SBaptiste Daroussin * Common choice of object emitting 3523dcf5eb7SBaptiste Daroussin * @param ctx emitter context 3533dcf5eb7SBaptiste Daroussin * @param obj object to print 3543dcf5eb7SBaptiste Daroussin * @param first flag to mark the first element 3553dcf5eb7SBaptiste Daroussin * @param print_key print key of an object 3563dcf5eb7SBaptiste Daroussin * @param compact compact output 357c99fb5f9SBaptiste Daroussin */ 358c99fb5f9SBaptiste Daroussin static void 3593dcf5eb7SBaptiste Daroussin ucl_emitter_common_elt (struct ucl_emitter_context *ctx, 3603dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool first, bool print_key, bool compact) 361c99fb5f9SBaptiste Daroussin { 3623dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func = ctx->func; 363c99fb5f9SBaptiste Daroussin bool flag; 3644bf54857SBaptiste Daroussin struct ucl_object_userdata *ud; 365*d9f0ce31SBaptiste Daroussin const ucl_object_t *comment = NULL, *cur_comment; 3664bf54857SBaptiste Daroussin const char *ud_out = ""; 367c99fb5f9SBaptiste Daroussin 3683dcf5eb7SBaptiste Daroussin if (ctx->id != UCL_EMIT_CONFIG && !first) { 3693dcf5eb7SBaptiste Daroussin if (compact) { 3703dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_character (',', 1, func->ud); 371c99fb5f9SBaptiste Daroussin } 372c99fb5f9SBaptiste Daroussin else { 3734bf54857SBaptiste Daroussin if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) { 3744bf54857SBaptiste Daroussin func->ucl_emitter_append_len ("\n", 1, func->ud); 3754bf54857SBaptiste Daroussin } else { 3763dcf5eb7SBaptiste Daroussin func->ucl_emitter_append_len (",\n", 2, func->ud); 3773dcf5eb7SBaptiste Daroussin } 3783dcf5eb7SBaptiste Daroussin } 3794bf54857SBaptiste Daroussin } 3803dcf5eb7SBaptiste Daroussin 3814bf54857SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 3823dcf5eb7SBaptiste Daroussin 383*d9f0ce31SBaptiste Daroussin if (ctx->comments && ctx->id == UCL_EMIT_CONFIG) { 384*d9f0ce31SBaptiste Daroussin comment = ucl_object_lookup_len (ctx->comments, (const char *)&obj, 385*d9f0ce31SBaptiste Daroussin sizeof (void *)); 386*d9f0ce31SBaptiste Daroussin 387*d9f0ce31SBaptiste Daroussin if (comment) { 388*d9f0ce31SBaptiste Daroussin if (!(comment->flags & UCL_OBJECT_INHERITED)) { 389*d9f0ce31SBaptiste Daroussin DL_FOREACH (comment, cur_comment) { 390*d9f0ce31SBaptiste Daroussin func->ucl_emitter_append_len (cur_comment->value.sv, 391*d9f0ce31SBaptiste Daroussin cur_comment->len, 392*d9f0ce31SBaptiste Daroussin func->ud); 393*d9f0ce31SBaptiste Daroussin func->ucl_emitter_append_character ('\n', 1, func->ud); 394*d9f0ce31SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 395*d9f0ce31SBaptiste Daroussin } 396*d9f0ce31SBaptiste Daroussin 397*d9f0ce31SBaptiste Daroussin comment = NULL; 398*d9f0ce31SBaptiste Daroussin } 399*d9f0ce31SBaptiste Daroussin } 400*d9f0ce31SBaptiste Daroussin } 401*d9f0ce31SBaptiste Daroussin 402c99fb5f9SBaptiste Daroussin switch (obj->type) { 403c99fb5f9SBaptiste Daroussin case UCL_INT: 4043dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 405c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); 4063dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 407c99fb5f9SBaptiste Daroussin break; 408c99fb5f9SBaptiste Daroussin case UCL_FLOAT: 409c99fb5f9SBaptiste Daroussin case UCL_TIME: 4103dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 411c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); 4123dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 413c99fb5f9SBaptiste Daroussin break; 414c99fb5f9SBaptiste Daroussin case UCL_BOOLEAN: 4153dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 416c99fb5f9SBaptiste Daroussin flag = ucl_object_toboolean (obj); 417c99fb5f9SBaptiste Daroussin if (flag) { 418c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len ("true", 4, func->ud); 419c99fb5f9SBaptiste Daroussin } 420c99fb5f9SBaptiste Daroussin else { 421c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len ("false", 5, func->ud); 422c99fb5f9SBaptiste Daroussin } 4233dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 424c99fb5f9SBaptiste Daroussin break; 425c99fb5f9SBaptiste Daroussin case UCL_STRING: 4263dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 4274bf54857SBaptiste Daroussin if (ctx->id == UCL_EMIT_CONFIG && ucl_maybe_long_string (obj)) { 4284bf54857SBaptiste Daroussin ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx); 4294bf54857SBaptiste Daroussin } 4304bf54857SBaptiste Daroussin else { 4313dcf5eb7SBaptiste Daroussin ucl_elt_string_write_json (obj->value.sv, obj->len, ctx); 4324bf54857SBaptiste Daroussin } 4333dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 434c99fb5f9SBaptiste Daroussin break; 435c99fb5f9SBaptiste Daroussin case UCL_NULL: 4363dcf5eb7SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 437c99fb5f9SBaptiste Daroussin func->ucl_emitter_append_len ("null", 4, func->ud); 4383dcf5eb7SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 439c99fb5f9SBaptiste Daroussin break; 440c99fb5f9SBaptiste Daroussin case UCL_OBJECT: 4413dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_object (ctx, obj, print_key, compact); 4423dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_object (ctx, obj, compact); 443c99fb5f9SBaptiste Daroussin break; 444c99fb5f9SBaptiste Daroussin case UCL_ARRAY: 4453dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_array (ctx, obj, print_key, compact); 4463dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_array (ctx, obj, compact); 447c99fb5f9SBaptiste Daroussin break; 448c99fb5f9SBaptiste Daroussin case UCL_USERDATA: 4494bf54857SBaptiste Daroussin ud = (struct ucl_object_userdata *)obj; 4504bf54857SBaptiste Daroussin ucl_emitter_print_key (print_key, ctx, obj, compact); 4514bf54857SBaptiste Daroussin if (ud->emitter) { 4524bf54857SBaptiste Daroussin ud_out = ud->emitter (obj->value.ud); 4534bf54857SBaptiste Daroussin if (ud_out == NULL) { 4544bf54857SBaptiste Daroussin ud_out = "null"; 4554bf54857SBaptiste Daroussin } 4564bf54857SBaptiste Daroussin } 4574bf54857SBaptiste Daroussin ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx); 4584bf54857SBaptiste Daroussin ucl_emitter_finish_object (ctx, obj, compact, !print_key); 459c99fb5f9SBaptiste Daroussin break; 460c99fb5f9SBaptiste Daroussin } 461*d9f0ce31SBaptiste Daroussin 462*d9f0ce31SBaptiste Daroussin if (comment) { 463*d9f0ce31SBaptiste Daroussin DL_FOREACH (comment, cur_comment) { 464*d9f0ce31SBaptiste Daroussin func->ucl_emitter_append_len (cur_comment->value.sv, 465*d9f0ce31SBaptiste Daroussin cur_comment->len, 466*d9f0ce31SBaptiste Daroussin func->ud); 467*d9f0ce31SBaptiste Daroussin func->ucl_emitter_append_character ('\n', 1, func->ud); 468*d9f0ce31SBaptiste Daroussin 469*d9f0ce31SBaptiste Daroussin if (cur_comment->next) { 470*d9f0ce31SBaptiste Daroussin ucl_add_tabs (func, ctx->indent, compact); 471*d9f0ce31SBaptiste Daroussin } 472*d9f0ce31SBaptiste Daroussin } 473*d9f0ce31SBaptiste Daroussin } 474c99fb5f9SBaptiste Daroussin } 475c99fb5f9SBaptiste Daroussin 476c99fb5f9SBaptiste Daroussin /* 4773dcf5eb7SBaptiste Daroussin * Specific standard implementations of the emitter functions 478c99fb5f9SBaptiste Daroussin */ 4793dcf5eb7SBaptiste Daroussin #define UCL_EMIT_TYPE_IMPL(type, compact) \ 4803dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx, \ 4813dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool first, bool print_key) { \ 4823dcf5eb7SBaptiste Daroussin ucl_emitter_common_elt (ctx, obj, first, print_key, (compact)); \ 4833dcf5eb7SBaptiste Daroussin } \ 4843dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx, \ 4853dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key) { \ 4863dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_object (ctx, obj, print_key, (compact)); \ 4873dcf5eb7SBaptiste Daroussin } \ 4883dcf5eb7SBaptiste Daroussin static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx, \ 4893dcf5eb7SBaptiste Daroussin const ucl_object_t *obj, bool print_key) { \ 4903dcf5eb7SBaptiste Daroussin ucl_emitter_common_start_array (ctx, obj, print_key, (compact)); \ 4913dcf5eb7SBaptiste Daroussin } \ 4923dcf5eb7SBaptiste Daroussin static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx, \ 4933dcf5eb7SBaptiste Daroussin const ucl_object_t *obj) { \ 4943dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_object (ctx, obj, (compact)); \ 4953dcf5eb7SBaptiste Daroussin } \ 4963dcf5eb7SBaptiste Daroussin static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx, \ 4973dcf5eb7SBaptiste Daroussin const ucl_object_t *obj) { \ 4983dcf5eb7SBaptiste Daroussin ucl_emitter_common_end_array (ctx, obj, (compact)); \ 499c99fb5f9SBaptiste Daroussin } 500c99fb5f9SBaptiste Daroussin 5014bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(json, false) 5024bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(json_compact, true) 5034bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(config, false) 5044bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(yaml, false) 505c99fb5f9SBaptiste Daroussin 50639ee7a7aSBaptiste Daroussin static void 50739ee7a7aSBaptiste Daroussin ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx, 50839ee7a7aSBaptiste Daroussin const ucl_object_t *obj, bool first, bool print_key) 50939ee7a7aSBaptiste Daroussin { 51039ee7a7aSBaptiste Daroussin ucl_object_iter_t it; 51139ee7a7aSBaptiste Daroussin struct ucl_object_userdata *ud; 51239ee7a7aSBaptiste Daroussin const char *ud_out; 51339ee7a7aSBaptiste Daroussin const ucl_object_t *cur, *celt; 51439ee7a7aSBaptiste Daroussin 51539ee7a7aSBaptiste Daroussin switch (obj->type) { 51639ee7a7aSBaptiste Daroussin case UCL_INT: 51739ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 51839ee7a7aSBaptiste Daroussin ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj)); 51939ee7a7aSBaptiste Daroussin break; 52039ee7a7aSBaptiste Daroussin 52139ee7a7aSBaptiste Daroussin case UCL_FLOAT: 52239ee7a7aSBaptiste Daroussin case UCL_TIME: 52339ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 52439ee7a7aSBaptiste Daroussin ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj)); 52539ee7a7aSBaptiste Daroussin break; 52639ee7a7aSBaptiste Daroussin 52739ee7a7aSBaptiste Daroussin case UCL_BOOLEAN: 52839ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 52939ee7a7aSBaptiste Daroussin ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj)); 53039ee7a7aSBaptiste Daroussin break; 53139ee7a7aSBaptiste Daroussin 53239ee7a7aSBaptiste Daroussin case UCL_STRING: 53339ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 53439ee7a7aSBaptiste Daroussin 53539ee7a7aSBaptiste Daroussin if (obj->flags & UCL_OBJECT_BINARY) { 53639ee7a7aSBaptiste Daroussin ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv, 53739ee7a7aSBaptiste Daroussin obj->len); 53839ee7a7aSBaptiste Daroussin } 53939ee7a7aSBaptiste Daroussin else { 54039ee7a7aSBaptiste Daroussin ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len); 54139ee7a7aSBaptiste Daroussin } 54239ee7a7aSBaptiste Daroussin break; 54339ee7a7aSBaptiste Daroussin 54439ee7a7aSBaptiste Daroussin case UCL_NULL: 54539ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 54639ee7a7aSBaptiste Daroussin ucl_emitter_print_null_msgpack (ctx); 54739ee7a7aSBaptiste Daroussin break; 54839ee7a7aSBaptiste Daroussin 54939ee7a7aSBaptiste Daroussin case UCL_OBJECT: 55039ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 55139ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_obj (ctx, obj, print_key); 55239ee7a7aSBaptiste Daroussin it = NULL; 55339ee7a7aSBaptiste Daroussin 554*d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) { 55539ee7a7aSBaptiste Daroussin LL_FOREACH (cur, celt) { 55639ee7a7aSBaptiste Daroussin ucl_emit_msgpack_elt (ctx, celt, false, true); 55739ee7a7aSBaptiste Daroussin /* XXX: 55839ee7a7aSBaptiste Daroussin * in msgpack the length of objects is encoded within a single elt 55939ee7a7aSBaptiste Daroussin * so in case of multi-value keys we are using merely the first 56039ee7a7aSBaptiste Daroussin * element ignoring others 56139ee7a7aSBaptiste Daroussin */ 56239ee7a7aSBaptiste Daroussin break; 56339ee7a7aSBaptiste Daroussin } 56439ee7a7aSBaptiste Daroussin } 56539ee7a7aSBaptiste Daroussin 56639ee7a7aSBaptiste Daroussin break; 56739ee7a7aSBaptiste Daroussin 56839ee7a7aSBaptiste Daroussin case UCL_ARRAY: 56939ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 57039ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_array (ctx, obj, print_key); 57139ee7a7aSBaptiste Daroussin it = NULL; 57239ee7a7aSBaptiste Daroussin 573*d9f0ce31SBaptiste Daroussin while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) { 57439ee7a7aSBaptiste Daroussin ucl_emit_msgpack_elt (ctx, cur, false, false); 57539ee7a7aSBaptiste Daroussin } 57639ee7a7aSBaptiste Daroussin 57739ee7a7aSBaptiste Daroussin break; 57839ee7a7aSBaptiste Daroussin 57939ee7a7aSBaptiste Daroussin case UCL_USERDATA: 58039ee7a7aSBaptiste Daroussin ud = (struct ucl_object_userdata *)obj; 58139ee7a7aSBaptiste Daroussin ucl_emitter_print_key_msgpack (print_key, ctx, obj); 58239ee7a7aSBaptiste Daroussin 58339ee7a7aSBaptiste Daroussin if (ud->emitter) { 58439ee7a7aSBaptiste Daroussin ud_out = ud->emitter (obj->value.ud); 58539ee7a7aSBaptiste Daroussin if (ud_out == NULL) { 58639ee7a7aSBaptiste Daroussin ud_out = "null"; 58739ee7a7aSBaptiste Daroussin } 58839ee7a7aSBaptiste Daroussin } 58939ee7a7aSBaptiste Daroussin ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len); 59039ee7a7aSBaptiste Daroussin break; 59139ee7a7aSBaptiste Daroussin } 59239ee7a7aSBaptiste Daroussin } 59339ee7a7aSBaptiste Daroussin 59439ee7a7aSBaptiste Daroussin static void 59539ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx, 59639ee7a7aSBaptiste Daroussin const ucl_object_t *obj, bool print_key) 59739ee7a7aSBaptiste Daroussin { 59839ee7a7aSBaptiste Daroussin ucl_emitter_print_object_msgpack (ctx, obj->len); 59939ee7a7aSBaptiste Daroussin } 60039ee7a7aSBaptiste Daroussin 60139ee7a7aSBaptiste Daroussin static void 60239ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx, 60339ee7a7aSBaptiste Daroussin const ucl_object_t *obj, bool print_key) 60439ee7a7aSBaptiste Daroussin { 60539ee7a7aSBaptiste Daroussin ucl_emitter_print_array_msgpack (ctx, obj->len); 60639ee7a7aSBaptiste Daroussin } 60739ee7a7aSBaptiste Daroussin 60839ee7a7aSBaptiste Daroussin static void 60939ee7a7aSBaptiste Daroussin ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx, 61039ee7a7aSBaptiste Daroussin const ucl_object_t *obj) 61139ee7a7aSBaptiste Daroussin { 61239ee7a7aSBaptiste Daroussin 61339ee7a7aSBaptiste Daroussin } 61439ee7a7aSBaptiste Daroussin 61539ee7a7aSBaptiste Daroussin static void 61639ee7a7aSBaptiste Daroussin ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx, 61739ee7a7aSBaptiste Daroussin const ucl_object_t *obj) 61839ee7a7aSBaptiste Daroussin { 61939ee7a7aSBaptiste Daroussin 62039ee7a7aSBaptiste Daroussin } 62139ee7a7aSBaptiste Daroussin 622c99fb5f9SBaptiste Daroussin unsigned char * 623b04a7a0bSBaptiste Daroussin ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type) 624c99fb5f9SBaptiste Daroussin { 62539ee7a7aSBaptiste Daroussin return ucl_object_emit_len (obj, emit_type, NULL); 62639ee7a7aSBaptiste Daroussin } 62739ee7a7aSBaptiste Daroussin 62839ee7a7aSBaptiste Daroussin unsigned char * 62939ee7a7aSBaptiste Daroussin ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type, 63039ee7a7aSBaptiste Daroussin size_t *outlen) 63139ee7a7aSBaptiste Daroussin { 632c99fb5f9SBaptiste Daroussin unsigned char *res = NULL; 6333dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *func; 63439ee7a7aSBaptiste Daroussin UT_string *s; 63539ee7a7aSBaptiste Daroussin 636c99fb5f9SBaptiste Daroussin if (obj == NULL) { 637c99fb5f9SBaptiste Daroussin return NULL; 638c99fb5f9SBaptiste Daroussin } 639c99fb5f9SBaptiste Daroussin 6403dcf5eb7SBaptiste Daroussin func = ucl_object_emit_memory_funcs ((void **)&res); 641c99fb5f9SBaptiste Daroussin 6423dcf5eb7SBaptiste Daroussin if (func != NULL) { 643*d9f0ce31SBaptiste Daroussin s = func->ud; 644*d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, emit_type, func, NULL); 64539ee7a7aSBaptiste Daroussin 64639ee7a7aSBaptiste Daroussin if (outlen != NULL) { 64739ee7a7aSBaptiste Daroussin *outlen = s->i; 64839ee7a7aSBaptiste Daroussin } 64939ee7a7aSBaptiste Daroussin 6503dcf5eb7SBaptiste Daroussin ucl_object_emit_funcs_free (func); 651c99fb5f9SBaptiste Daroussin } 652c99fb5f9SBaptiste Daroussin 653c99fb5f9SBaptiste Daroussin return res; 654c99fb5f9SBaptiste Daroussin } 655c99fb5f9SBaptiste Daroussin 656c99fb5f9SBaptiste Daroussin bool 657b04a7a0bSBaptiste Daroussin ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, 658*d9f0ce31SBaptiste Daroussin struct ucl_emitter_functions *emitter, 659*d9f0ce31SBaptiste Daroussin const ucl_object_t *comments) 660c99fb5f9SBaptiste Daroussin { 6613dcf5eb7SBaptiste Daroussin const struct ucl_emitter_context *ctx; 6623dcf5eb7SBaptiste Daroussin struct ucl_emitter_context my_ctx; 6633dcf5eb7SBaptiste Daroussin bool res = false; 664c99fb5f9SBaptiste Daroussin 6653dcf5eb7SBaptiste Daroussin ctx = ucl_emit_get_standard_context (emit_type); 6663dcf5eb7SBaptiste Daroussin if (ctx != NULL) { 6673dcf5eb7SBaptiste Daroussin memcpy (&my_ctx, ctx, sizeof (my_ctx)); 6683dcf5eb7SBaptiste Daroussin my_ctx.func = emitter; 6694bf54857SBaptiste Daroussin my_ctx.indent = 0; 6703dcf5eb7SBaptiste Daroussin my_ctx.top = obj; 671*d9f0ce31SBaptiste Daroussin my_ctx.comments = comments; 672c99fb5f9SBaptiste Daroussin 6733dcf5eb7SBaptiste Daroussin my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false); 6743dcf5eb7SBaptiste Daroussin res = true; 675c99fb5f9SBaptiste Daroussin } 676c99fb5f9SBaptiste Daroussin 677c99fb5f9SBaptiste Daroussin return res; 678c99fb5f9SBaptiste Daroussin } 679