13dcf5eb7SBaptiste Daroussin /* Copyright (c) 2014, Vsevolod Stakhov
23dcf5eb7SBaptiste Daroussin * All rights reserved.
33dcf5eb7SBaptiste Daroussin *
43dcf5eb7SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
53dcf5eb7SBaptiste Daroussin * modification, are permitted provided that the following conditions are met:
63dcf5eb7SBaptiste Daroussin * * Redistributions of source code must retain the above copyright
73dcf5eb7SBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
83dcf5eb7SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright
93dcf5eb7SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
103dcf5eb7SBaptiste Daroussin * documentation and/or other materials provided with the distribution.
113dcf5eb7SBaptiste Daroussin *
123dcf5eb7SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
133dcf5eb7SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
143dcf5eb7SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
153dcf5eb7SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
163dcf5eb7SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
173dcf5eb7SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
183dcf5eb7SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
193dcf5eb7SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
203dcf5eb7SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
213dcf5eb7SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
223dcf5eb7SBaptiste Daroussin */
233dcf5eb7SBaptiste Daroussin
243dcf5eb7SBaptiste Daroussin #ifdef HAVE_CONFIG_H
253dcf5eb7SBaptiste Daroussin #include "config.h"
263dcf5eb7SBaptiste Daroussin #endif
273dcf5eb7SBaptiste Daroussin
283dcf5eb7SBaptiste Daroussin #include "ucl.h"
293dcf5eb7SBaptiste Daroussin #include "ucl_internal.h"
303dcf5eb7SBaptiste Daroussin #include "ucl_chartable.h"
313dcf5eb7SBaptiste Daroussin
323dcf5eb7SBaptiste Daroussin struct ucl_emitter_streamline_stack {
333dcf5eb7SBaptiste Daroussin bool is_array;
343dcf5eb7SBaptiste Daroussin bool empty;
353dcf5eb7SBaptiste Daroussin const ucl_object_t *obj;
363dcf5eb7SBaptiste Daroussin struct ucl_emitter_streamline_stack *next;
373dcf5eb7SBaptiste Daroussin };
383dcf5eb7SBaptiste Daroussin
393dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline {
403dcf5eb7SBaptiste Daroussin /* Inherited from the main context */
41*d9f0ce31SBaptiste Daroussin /** Name of emitter (e.g. json, compact_json) */
423dcf5eb7SBaptiste Daroussin const char *name;
43*d9f0ce31SBaptiste Daroussin /** Unique id (e.g. UCL_EMIT_JSON for standard emitters */
443dcf5eb7SBaptiste Daroussin int id;
45*d9f0ce31SBaptiste Daroussin /** A set of output functions */
463dcf5eb7SBaptiste Daroussin const struct ucl_emitter_functions *func;
47*d9f0ce31SBaptiste Daroussin /** A set of output operations */
483dcf5eb7SBaptiste Daroussin const struct ucl_emitter_operations *ops;
49*d9f0ce31SBaptiste Daroussin /** Current amount of indent tabs */
50*d9f0ce31SBaptiste Daroussin unsigned int indent;
51*d9f0ce31SBaptiste Daroussin /** Top level object */
523dcf5eb7SBaptiste Daroussin const ucl_object_t *top;
53*d9f0ce31SBaptiste Daroussin /** Optional comments */
54*d9f0ce31SBaptiste Daroussin const ucl_object_t *comments;
553dcf5eb7SBaptiste Daroussin
563dcf5eb7SBaptiste Daroussin /* Streamline specific fields */
573dcf5eb7SBaptiste Daroussin struct ucl_emitter_streamline_stack *containers;
583dcf5eb7SBaptiste Daroussin };
593dcf5eb7SBaptiste Daroussin
603dcf5eb7SBaptiste Daroussin #define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx)
613dcf5eb7SBaptiste Daroussin
623dcf5eb7SBaptiste Daroussin struct ucl_emitter_context*
ucl_object_emit_streamline_new(const ucl_object_t * obj,enum ucl_emitter emit_type,struct ucl_emitter_functions * emitter)633dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_new (const ucl_object_t *obj,
643dcf5eb7SBaptiste Daroussin enum ucl_emitter emit_type,
653dcf5eb7SBaptiste Daroussin struct ucl_emitter_functions *emitter)
663dcf5eb7SBaptiste Daroussin {
673dcf5eb7SBaptiste Daroussin const struct ucl_emitter_context *ctx;
683dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline *sctx;
693dcf5eb7SBaptiste Daroussin
703dcf5eb7SBaptiste Daroussin ctx = ucl_emit_get_standard_context (emit_type);
713dcf5eb7SBaptiste Daroussin if (ctx == NULL) {
723dcf5eb7SBaptiste Daroussin return NULL;
733dcf5eb7SBaptiste Daroussin }
743dcf5eb7SBaptiste Daroussin
753dcf5eb7SBaptiste Daroussin sctx = calloc (1, sizeof (*sctx));
763dcf5eb7SBaptiste Daroussin if (sctx == NULL) {
773dcf5eb7SBaptiste Daroussin return NULL;
783dcf5eb7SBaptiste Daroussin }
793dcf5eb7SBaptiste Daroussin
803dcf5eb7SBaptiste Daroussin memcpy (sctx, ctx, sizeof (*ctx));
813dcf5eb7SBaptiste Daroussin sctx->func = emitter;
823dcf5eb7SBaptiste Daroussin sctx->top = obj;
833dcf5eb7SBaptiste Daroussin
843dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx,
853dcf5eb7SBaptiste Daroussin obj);
863dcf5eb7SBaptiste Daroussin
873dcf5eb7SBaptiste Daroussin return (struct ucl_emitter_context *)sctx;
883dcf5eb7SBaptiste Daroussin }
893dcf5eb7SBaptiste Daroussin
903dcf5eb7SBaptiste Daroussin void
ucl_object_emit_streamline_start_container(struct ucl_emitter_context * ctx,const ucl_object_t * obj)913dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
923dcf5eb7SBaptiste Daroussin const ucl_object_t *obj)
933dcf5eb7SBaptiste Daroussin {
943dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
953dcf5eb7SBaptiste Daroussin struct ucl_emitter_streamline_stack *st, *top;
963dcf5eb7SBaptiste Daroussin bool print_key = false;
973dcf5eb7SBaptiste Daroussin
983dcf5eb7SBaptiste Daroussin /* Check top object presence */
993dcf5eb7SBaptiste Daroussin if (sctx->top == NULL) {
1003dcf5eb7SBaptiste Daroussin sctx->top = obj;
1013dcf5eb7SBaptiste Daroussin }
1023dcf5eb7SBaptiste Daroussin
1033dcf5eb7SBaptiste Daroussin top = sctx->containers;
1043dcf5eb7SBaptiste Daroussin st = malloc (sizeof (*st));
1053dcf5eb7SBaptiste Daroussin if (st != NULL) {
1063dcf5eb7SBaptiste Daroussin if (top != NULL && !top->is_array) {
1073dcf5eb7SBaptiste Daroussin print_key = true;
1083dcf5eb7SBaptiste Daroussin }
1093dcf5eb7SBaptiste Daroussin st->empty = true;
1103dcf5eb7SBaptiste Daroussin st->obj = obj;
1113dcf5eb7SBaptiste Daroussin if (obj != NULL && obj->type == UCL_ARRAY) {
1123dcf5eb7SBaptiste Daroussin st->is_array = true;
1133dcf5eb7SBaptiste Daroussin sctx->ops->ucl_emitter_start_array (ctx, obj, print_key);
1143dcf5eb7SBaptiste Daroussin }
1153dcf5eb7SBaptiste Daroussin else {
1163dcf5eb7SBaptiste Daroussin st->is_array = false;
1173dcf5eb7SBaptiste Daroussin sctx->ops->ucl_emitter_start_object (ctx, obj, print_key);
1183dcf5eb7SBaptiste Daroussin }
1193dcf5eb7SBaptiste Daroussin LL_PREPEND (sctx->containers, st);
1203dcf5eb7SBaptiste Daroussin }
1214bf54857SBaptiste Daroussin }
1223dcf5eb7SBaptiste Daroussin
1233dcf5eb7SBaptiste Daroussin void
ucl_object_emit_streamline_add_object(struct ucl_emitter_context * ctx,const ucl_object_t * obj)1243dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_add_object (
1253dcf5eb7SBaptiste Daroussin struct ucl_emitter_context *ctx, const ucl_object_t *obj)
1263dcf5eb7SBaptiste Daroussin {
1273dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
1283dcf5eb7SBaptiste Daroussin bool is_array = false, is_first = false;
1293dcf5eb7SBaptiste Daroussin
1303dcf5eb7SBaptiste Daroussin if (sctx->containers != NULL) {
1313dcf5eb7SBaptiste Daroussin if (sctx->containers->is_array) {
1323dcf5eb7SBaptiste Daroussin is_array = true;
1333dcf5eb7SBaptiste Daroussin }
1343dcf5eb7SBaptiste Daroussin if (sctx->containers->empty) {
1353dcf5eb7SBaptiste Daroussin is_first = true;
1363dcf5eb7SBaptiste Daroussin sctx->containers->empty = false;
1373dcf5eb7SBaptiste Daroussin }
1383dcf5eb7SBaptiste Daroussin }
1393dcf5eb7SBaptiste Daroussin
1403dcf5eb7SBaptiste Daroussin sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array);
1413dcf5eb7SBaptiste Daroussin }
1423dcf5eb7SBaptiste Daroussin
1433dcf5eb7SBaptiste Daroussin void
ucl_object_emit_streamline_end_container(struct ucl_emitter_context * ctx)1443dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)
1453dcf5eb7SBaptiste Daroussin {
1463dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
1473dcf5eb7SBaptiste Daroussin struct ucl_emitter_streamline_stack *st;
1483dcf5eb7SBaptiste Daroussin
1493dcf5eb7SBaptiste Daroussin if (sctx->containers != NULL) {
1503dcf5eb7SBaptiste Daroussin st = sctx->containers;
1513dcf5eb7SBaptiste Daroussin
1523dcf5eb7SBaptiste Daroussin if (st->is_array) {
1533dcf5eb7SBaptiste Daroussin sctx->ops->ucl_emitter_end_array (ctx, st->obj);
1543dcf5eb7SBaptiste Daroussin }
1553dcf5eb7SBaptiste Daroussin else {
1563dcf5eb7SBaptiste Daroussin sctx->ops->ucl_emitter_end_object (ctx, st->obj);
1573dcf5eb7SBaptiste Daroussin }
1583dcf5eb7SBaptiste Daroussin sctx->containers = st->next;
1593dcf5eb7SBaptiste Daroussin free (st);
1603dcf5eb7SBaptiste Daroussin }
1613dcf5eb7SBaptiste Daroussin }
1623dcf5eb7SBaptiste Daroussin
1633dcf5eb7SBaptiste Daroussin void
ucl_object_emit_streamline_finish(struct ucl_emitter_context * ctx)1643dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx)
1653dcf5eb7SBaptiste Daroussin {
1663dcf5eb7SBaptiste Daroussin struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
1673dcf5eb7SBaptiste Daroussin
1683dcf5eb7SBaptiste Daroussin while (sctx->containers != NULL) {
1693dcf5eb7SBaptiste Daroussin ucl_object_emit_streamline_end_container (ctx);
1703dcf5eb7SBaptiste Daroussin }
1713dcf5eb7SBaptiste Daroussin
1723dcf5eb7SBaptiste Daroussin free (sctx);
1733dcf5eb7SBaptiste Daroussin }
174