xref: /freebsd/contrib/libucl/src/ucl_emitter.c (revision a0409676120c1e558d0ade943019934e0f15118d)
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
ucl_add_tabs(const struct ucl_emitter_functions * func,unsigned int tabs,bool compact)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
ucl_emitter_print_key(bool print_key,struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool compact)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
ucl_emitter_finish_object(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool compact,bool is_array)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
ucl_emitter_common_end_object(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool compact)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
ucl_emitter_common_end_array(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool compact)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
ucl_emitter_common_start_array(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool print_key,bool compact)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 */
271d9f0ce31SBaptiste 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
ucl_emitter_common_start_object(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool print_key,bool compact)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
ucl_emitter_common_elt(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool first,bool print_key,bool compact)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;
365d9f0ce31SBaptiste 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 
383d9f0ce31SBaptiste Daroussin 	if (ctx->comments && ctx->id == UCL_EMIT_CONFIG) {
384d9f0ce31SBaptiste Daroussin 		comment = ucl_object_lookup_len (ctx->comments, (const char *)&obj,
385d9f0ce31SBaptiste Daroussin 				sizeof (void *));
386d9f0ce31SBaptiste Daroussin 
387d9f0ce31SBaptiste Daroussin 		if (comment) {
388d9f0ce31SBaptiste Daroussin 			if (!(comment->flags & UCL_OBJECT_INHERITED)) {
389d9f0ce31SBaptiste Daroussin 				DL_FOREACH (comment, cur_comment) {
390d9f0ce31SBaptiste Daroussin 					func->ucl_emitter_append_len (cur_comment->value.sv,
391d9f0ce31SBaptiste Daroussin 							cur_comment->len,
392d9f0ce31SBaptiste Daroussin 							func->ud);
393d9f0ce31SBaptiste Daroussin 					func->ucl_emitter_append_character ('\n', 1, func->ud);
394d9f0ce31SBaptiste Daroussin 					ucl_add_tabs (func, ctx->indent, compact);
395d9f0ce31SBaptiste Daroussin 				}
396d9f0ce31SBaptiste Daroussin 
397d9f0ce31SBaptiste Daroussin 				comment = NULL;
398d9f0ce31SBaptiste Daroussin 			}
399d9f0ce31SBaptiste Daroussin 		}
400d9f0ce31SBaptiste Daroussin 	}
401d9f0ce31SBaptiste 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);
427*a0409676SBaptiste Daroussin 		if (ctx->id == UCL_EMIT_CONFIG) {
428*a0409676SBaptiste Daroussin 			if (ucl_maybe_long_string (obj)) {
4294bf54857SBaptiste Daroussin 				ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx);
430*a0409676SBaptiste Daroussin 			} else {
431*a0409676SBaptiste Daroussin 				if (obj->flags & UCL_OBJECT_SQUOTED) {
432*a0409676SBaptiste Daroussin 					ucl_elt_string_write_squoted (obj->value.sv, obj->len, ctx);
433*a0409676SBaptiste Daroussin 				} else {
434*a0409676SBaptiste Daroussin 					ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
435*a0409676SBaptiste Daroussin 				}
436*a0409676SBaptiste Daroussin 			}
4374bf54857SBaptiste Daroussin 		}
4384bf54857SBaptiste Daroussin 		else {
4393dcf5eb7SBaptiste Daroussin 			ucl_elt_string_write_json (obj->value.sv, obj->len, ctx);
4404bf54857SBaptiste Daroussin 		}
4413dcf5eb7SBaptiste Daroussin 		ucl_emitter_finish_object (ctx, obj, compact, !print_key);
442c99fb5f9SBaptiste Daroussin 		break;
443c99fb5f9SBaptiste Daroussin 	case UCL_NULL:
4443dcf5eb7SBaptiste Daroussin 		ucl_emitter_print_key (print_key, ctx, obj, compact);
445c99fb5f9SBaptiste Daroussin 		func->ucl_emitter_append_len ("null", 4, func->ud);
4463dcf5eb7SBaptiste Daroussin 		ucl_emitter_finish_object (ctx, obj, compact, !print_key);
447c99fb5f9SBaptiste Daroussin 		break;
448c99fb5f9SBaptiste Daroussin 	case UCL_OBJECT:
4493dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_start_object (ctx, obj, print_key, compact);
4503dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_end_object (ctx, obj, compact);
451c99fb5f9SBaptiste Daroussin 		break;
452c99fb5f9SBaptiste Daroussin 	case UCL_ARRAY:
4533dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_start_array (ctx, obj, print_key, compact);
4543dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_end_array (ctx, obj, compact);
455c99fb5f9SBaptiste Daroussin 		break;
456c99fb5f9SBaptiste Daroussin 	case UCL_USERDATA:
4574bf54857SBaptiste Daroussin 		ud = (struct ucl_object_userdata *)obj;
4584bf54857SBaptiste Daroussin 		ucl_emitter_print_key (print_key, ctx, obj, compact);
4594bf54857SBaptiste Daroussin 		if (ud->emitter) {
4604bf54857SBaptiste Daroussin 			ud_out = ud->emitter (obj->value.ud);
4614bf54857SBaptiste Daroussin 			if (ud_out == NULL) {
4624bf54857SBaptiste Daroussin 				ud_out = "null";
4634bf54857SBaptiste Daroussin 			}
4644bf54857SBaptiste Daroussin 		}
4654bf54857SBaptiste Daroussin 		ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx);
4664bf54857SBaptiste Daroussin 		ucl_emitter_finish_object (ctx, obj, compact, !print_key);
467c99fb5f9SBaptiste Daroussin 		break;
468c99fb5f9SBaptiste Daroussin 	}
469d9f0ce31SBaptiste Daroussin 
470d9f0ce31SBaptiste Daroussin 	if (comment) {
471d9f0ce31SBaptiste Daroussin 		DL_FOREACH (comment, cur_comment) {
472d9f0ce31SBaptiste Daroussin 			func->ucl_emitter_append_len (cur_comment->value.sv,
473d9f0ce31SBaptiste Daroussin 					cur_comment->len,
474d9f0ce31SBaptiste Daroussin 					func->ud);
475d9f0ce31SBaptiste Daroussin 			func->ucl_emitter_append_character ('\n', 1, func->ud);
476d9f0ce31SBaptiste Daroussin 
477d9f0ce31SBaptiste Daroussin 			if (cur_comment->next) {
478d9f0ce31SBaptiste Daroussin 				ucl_add_tabs (func, ctx->indent, compact);
479d9f0ce31SBaptiste Daroussin 			}
480d9f0ce31SBaptiste Daroussin 		}
481d9f0ce31SBaptiste Daroussin 	}
482c99fb5f9SBaptiste Daroussin }
483c99fb5f9SBaptiste Daroussin 
484c99fb5f9SBaptiste Daroussin /*
4853dcf5eb7SBaptiste Daroussin  * Specific standard implementations of the emitter functions
486c99fb5f9SBaptiste Daroussin  */
4873dcf5eb7SBaptiste Daroussin #define UCL_EMIT_TYPE_IMPL(type, compact)		\
4883dcf5eb7SBaptiste Daroussin 	static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx,	\
4893dcf5eb7SBaptiste Daroussin 		const ucl_object_t *obj, bool first, bool print_key) {	\
4903dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_elt (ctx, obj, first, print_key, (compact));	\
4913dcf5eb7SBaptiste Daroussin 	}	\
4923dcf5eb7SBaptiste Daroussin 	static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx,	\
4933dcf5eb7SBaptiste Daroussin 		const ucl_object_t *obj, bool print_key) {	\
4943dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_start_object (ctx, obj, print_key, (compact));	\
4953dcf5eb7SBaptiste Daroussin 	}	\
4963dcf5eb7SBaptiste Daroussin 	static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx,	\
4973dcf5eb7SBaptiste Daroussin 		const ucl_object_t *obj, bool print_key) {	\
4983dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_start_array (ctx, obj, print_key, (compact));	\
4993dcf5eb7SBaptiste Daroussin 	}	\
5003dcf5eb7SBaptiste Daroussin 	static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx,	\
5013dcf5eb7SBaptiste Daroussin 		const ucl_object_t *obj) {	\
5023dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_end_object (ctx, obj, (compact));	\
5033dcf5eb7SBaptiste Daroussin 	}	\
5043dcf5eb7SBaptiste Daroussin 	static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx,	\
5053dcf5eb7SBaptiste Daroussin 		const ucl_object_t *obj) {	\
5063dcf5eb7SBaptiste Daroussin 		ucl_emitter_common_end_array (ctx, obj, (compact));	\
507c99fb5f9SBaptiste Daroussin 	}
508c99fb5f9SBaptiste Daroussin 
UCL_EMIT_TYPE_IMPL(json,false)5094bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(json, false)
5104bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(json_compact, true)
5114bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(config, false)
5124bf54857SBaptiste Daroussin UCL_EMIT_TYPE_IMPL(yaml, false)
513c99fb5f9SBaptiste Daroussin 
51439ee7a7aSBaptiste Daroussin static void
51539ee7a7aSBaptiste Daroussin ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
51639ee7a7aSBaptiste Daroussin 		const ucl_object_t *obj, bool first, bool print_key)
51739ee7a7aSBaptiste Daroussin {
51839ee7a7aSBaptiste Daroussin 	ucl_object_iter_t it;
51939ee7a7aSBaptiste Daroussin 	struct ucl_object_userdata *ud;
52039ee7a7aSBaptiste Daroussin 	const char *ud_out;
52139ee7a7aSBaptiste Daroussin 	const ucl_object_t *cur, *celt;
52239ee7a7aSBaptiste Daroussin 
52339ee7a7aSBaptiste Daroussin 	switch (obj->type) {
52439ee7a7aSBaptiste Daroussin 	case UCL_INT:
52539ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
52639ee7a7aSBaptiste Daroussin 		ucl_emitter_print_int_msgpack (ctx, ucl_object_toint (obj));
52739ee7a7aSBaptiste Daroussin 		break;
52839ee7a7aSBaptiste Daroussin 
52939ee7a7aSBaptiste Daroussin 	case UCL_FLOAT:
53039ee7a7aSBaptiste Daroussin 	case UCL_TIME:
53139ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
53239ee7a7aSBaptiste Daroussin 		ucl_emitter_print_double_msgpack (ctx, ucl_object_todouble (obj));
53339ee7a7aSBaptiste Daroussin 		break;
53439ee7a7aSBaptiste Daroussin 
53539ee7a7aSBaptiste Daroussin 	case UCL_BOOLEAN:
53639ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
53739ee7a7aSBaptiste Daroussin 		ucl_emitter_print_bool_msgpack (ctx, ucl_object_toboolean (obj));
53839ee7a7aSBaptiste Daroussin 		break;
53939ee7a7aSBaptiste Daroussin 
54039ee7a7aSBaptiste Daroussin 	case UCL_STRING:
54139ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
54239ee7a7aSBaptiste Daroussin 
54339ee7a7aSBaptiste Daroussin 		if (obj->flags & UCL_OBJECT_BINARY) {
54439ee7a7aSBaptiste Daroussin 			ucl_emitter_print_binary_string_msgpack (ctx, obj->value.sv,
54539ee7a7aSBaptiste Daroussin 					obj->len);
54639ee7a7aSBaptiste Daroussin 		}
54739ee7a7aSBaptiste Daroussin 		else {
54839ee7a7aSBaptiste Daroussin 			ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
54939ee7a7aSBaptiste Daroussin 		}
55039ee7a7aSBaptiste Daroussin 		break;
55139ee7a7aSBaptiste Daroussin 
55239ee7a7aSBaptiste Daroussin 	case UCL_NULL:
55339ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
55439ee7a7aSBaptiste Daroussin 		ucl_emitter_print_null_msgpack (ctx);
55539ee7a7aSBaptiste Daroussin 		break;
55639ee7a7aSBaptiste Daroussin 
55739ee7a7aSBaptiste Daroussin 	case UCL_OBJECT:
55839ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
55939ee7a7aSBaptiste Daroussin 		ucl_emit_msgpack_start_obj (ctx, obj, print_key);
56039ee7a7aSBaptiste Daroussin 		it = NULL;
56139ee7a7aSBaptiste Daroussin 
562d9f0ce31SBaptiste Daroussin 		while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
56339ee7a7aSBaptiste Daroussin 			LL_FOREACH (cur, celt) {
56439ee7a7aSBaptiste Daroussin 				ucl_emit_msgpack_elt (ctx, celt, false, true);
56539ee7a7aSBaptiste Daroussin 				/* XXX:
56639ee7a7aSBaptiste Daroussin 				 * in msgpack the length of objects is encoded within a single elt
56739ee7a7aSBaptiste Daroussin 				 * so in case of multi-value keys we are using merely the first
56839ee7a7aSBaptiste Daroussin 				 * element ignoring others
56939ee7a7aSBaptiste Daroussin 				 */
57039ee7a7aSBaptiste Daroussin 				break;
57139ee7a7aSBaptiste Daroussin 			}
57239ee7a7aSBaptiste Daroussin 		}
57339ee7a7aSBaptiste Daroussin 
57439ee7a7aSBaptiste Daroussin 		break;
57539ee7a7aSBaptiste Daroussin 
57639ee7a7aSBaptiste Daroussin 	case UCL_ARRAY:
57739ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
57839ee7a7aSBaptiste Daroussin 		ucl_emit_msgpack_start_array (ctx, obj, print_key);
57939ee7a7aSBaptiste Daroussin 		it = NULL;
58039ee7a7aSBaptiste Daroussin 
581d9f0ce31SBaptiste Daroussin 		while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
58239ee7a7aSBaptiste Daroussin 			ucl_emit_msgpack_elt (ctx, cur, false, false);
58339ee7a7aSBaptiste Daroussin 		}
58439ee7a7aSBaptiste Daroussin 
58539ee7a7aSBaptiste Daroussin 		break;
58639ee7a7aSBaptiste Daroussin 
58739ee7a7aSBaptiste Daroussin 	case UCL_USERDATA:
58839ee7a7aSBaptiste Daroussin 		ud = (struct ucl_object_userdata *)obj;
58939ee7a7aSBaptiste Daroussin 		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
59039ee7a7aSBaptiste Daroussin 
59139ee7a7aSBaptiste Daroussin 		if (ud->emitter) {
59239ee7a7aSBaptiste Daroussin 			ud_out = ud->emitter (obj->value.ud);
59339ee7a7aSBaptiste Daroussin 			if (ud_out == NULL) {
59439ee7a7aSBaptiste Daroussin 				ud_out = "null";
59539ee7a7aSBaptiste Daroussin 			}
59639ee7a7aSBaptiste Daroussin 		}
59739ee7a7aSBaptiste Daroussin 		ucl_emitter_print_string_msgpack (ctx, obj->value.sv, obj->len);
59839ee7a7aSBaptiste Daroussin 		break;
59939ee7a7aSBaptiste Daroussin 	}
60039ee7a7aSBaptiste Daroussin }
60139ee7a7aSBaptiste Daroussin 
60239ee7a7aSBaptiste Daroussin static void
ucl_emit_msgpack_start_obj(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool print_key)60339ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
60439ee7a7aSBaptiste Daroussin 		const ucl_object_t *obj, bool print_key)
60539ee7a7aSBaptiste Daroussin {
60639ee7a7aSBaptiste Daroussin 	ucl_emitter_print_object_msgpack (ctx, obj->len);
60739ee7a7aSBaptiste Daroussin }
60839ee7a7aSBaptiste Daroussin 
60939ee7a7aSBaptiste Daroussin static void
ucl_emit_msgpack_start_array(struct ucl_emitter_context * ctx,const ucl_object_t * obj,bool print_key)61039ee7a7aSBaptiste Daroussin ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
61139ee7a7aSBaptiste Daroussin 		const ucl_object_t *obj, bool print_key)
61239ee7a7aSBaptiste Daroussin {
61339ee7a7aSBaptiste Daroussin 	ucl_emitter_print_array_msgpack (ctx, obj->len);
61439ee7a7aSBaptiste Daroussin }
61539ee7a7aSBaptiste Daroussin 
61639ee7a7aSBaptiste Daroussin static void
ucl_emit_msgpack_end_object(struct ucl_emitter_context * ctx,const ucl_object_t * obj)61739ee7a7aSBaptiste Daroussin ucl_emit_msgpack_end_object (struct ucl_emitter_context *ctx,
61839ee7a7aSBaptiste Daroussin 		const ucl_object_t *obj)
61939ee7a7aSBaptiste Daroussin {
62039ee7a7aSBaptiste Daroussin 
62139ee7a7aSBaptiste Daroussin }
62239ee7a7aSBaptiste Daroussin 
62339ee7a7aSBaptiste Daroussin static void
ucl_emit_msgpack_end_array(struct ucl_emitter_context * ctx,const ucl_object_t * obj)62439ee7a7aSBaptiste Daroussin ucl_emit_msgpack_end_array (struct ucl_emitter_context *ctx,
62539ee7a7aSBaptiste Daroussin 		const ucl_object_t *obj)
62639ee7a7aSBaptiste Daroussin {
62739ee7a7aSBaptiste Daroussin 
62839ee7a7aSBaptiste Daroussin }
62939ee7a7aSBaptiste Daroussin 
630c99fb5f9SBaptiste Daroussin unsigned char *
ucl_object_emit(const ucl_object_t * obj,enum ucl_emitter emit_type)631b04a7a0bSBaptiste Daroussin ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type)
632c99fb5f9SBaptiste Daroussin {
63339ee7a7aSBaptiste Daroussin 	return ucl_object_emit_len (obj, emit_type, NULL);
63439ee7a7aSBaptiste Daroussin }
63539ee7a7aSBaptiste Daroussin 
63639ee7a7aSBaptiste Daroussin unsigned char *
ucl_object_emit_len(const ucl_object_t * obj,enum ucl_emitter emit_type,size_t * outlen)63739ee7a7aSBaptiste Daroussin ucl_object_emit_len (const ucl_object_t *obj, enum ucl_emitter emit_type,
63839ee7a7aSBaptiste Daroussin 		size_t *outlen)
63939ee7a7aSBaptiste Daroussin {
640c99fb5f9SBaptiste Daroussin 	unsigned char *res = NULL;
6413dcf5eb7SBaptiste Daroussin 	struct ucl_emitter_functions *func;
64239ee7a7aSBaptiste Daroussin 	UT_string *s;
64339ee7a7aSBaptiste Daroussin 
644c99fb5f9SBaptiste Daroussin 	if (obj == NULL) {
645c99fb5f9SBaptiste Daroussin 		return NULL;
646c99fb5f9SBaptiste Daroussin 	}
647c99fb5f9SBaptiste Daroussin 
6483dcf5eb7SBaptiste Daroussin 	func = ucl_object_emit_memory_funcs ((void **)&res);
649c99fb5f9SBaptiste Daroussin 
6503dcf5eb7SBaptiste Daroussin 	if (func != NULL) {
651d9f0ce31SBaptiste Daroussin 		s = func->ud;
652d9f0ce31SBaptiste Daroussin 		ucl_object_emit_full (obj, emit_type, func, NULL);
65339ee7a7aSBaptiste Daroussin 
65439ee7a7aSBaptiste Daroussin 		if (outlen != NULL) {
65539ee7a7aSBaptiste Daroussin 			*outlen = s->i;
65639ee7a7aSBaptiste Daroussin 		}
65739ee7a7aSBaptiste Daroussin 
6583dcf5eb7SBaptiste Daroussin 		ucl_object_emit_funcs_free (func);
659c99fb5f9SBaptiste Daroussin 	}
660c99fb5f9SBaptiste Daroussin 
661c99fb5f9SBaptiste Daroussin 	return res;
662c99fb5f9SBaptiste Daroussin }
663c99fb5f9SBaptiste Daroussin 
664c99fb5f9SBaptiste Daroussin bool
ucl_object_emit_full(const ucl_object_t * obj,enum ucl_emitter emit_type,struct ucl_emitter_functions * emitter,const ucl_object_t * comments)665b04a7a0bSBaptiste Daroussin ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type,
666d9f0ce31SBaptiste Daroussin 		struct ucl_emitter_functions *emitter,
667d9f0ce31SBaptiste Daroussin 		const ucl_object_t *comments)
668c99fb5f9SBaptiste Daroussin {
6693dcf5eb7SBaptiste Daroussin 	const struct ucl_emitter_context *ctx;
6703dcf5eb7SBaptiste Daroussin 	struct ucl_emitter_context my_ctx;
6713dcf5eb7SBaptiste Daroussin 	bool res = false;
672c99fb5f9SBaptiste Daroussin 
6733dcf5eb7SBaptiste Daroussin 	ctx = ucl_emit_get_standard_context (emit_type);
6743dcf5eb7SBaptiste Daroussin 	if (ctx != NULL) {
6753dcf5eb7SBaptiste Daroussin 		memcpy (&my_ctx, ctx, sizeof (my_ctx));
6763dcf5eb7SBaptiste Daroussin 		my_ctx.func = emitter;
6774bf54857SBaptiste Daroussin 		my_ctx.indent = 0;
6783dcf5eb7SBaptiste Daroussin 		my_ctx.top = obj;
679d9f0ce31SBaptiste Daroussin 		my_ctx.comments = comments;
680c99fb5f9SBaptiste Daroussin 
6813dcf5eb7SBaptiste Daroussin 		my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false);
6823dcf5eb7SBaptiste Daroussin 		res = true;
683c99fb5f9SBaptiste Daroussin 	}
684c99fb5f9SBaptiste Daroussin 
685c99fb5f9SBaptiste Daroussin 	return res;
686c99fb5f9SBaptiste Daroussin }
687