Path: blob/main/external/libucl/src/ucl_emitter_streamline.c
2066 views
/* Copyright (c) 2014, Vsevolod Stakhov1* All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10*11* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY12* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED13* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE14* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY15* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES16* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;17* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND18* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT19* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS20* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.21*/2223#ifdef HAVE_CONFIG_H24#include "config.h"25#endif2627#include "ucl.h"28#include "ucl_internal.h"29#include "ucl_chartable.h"3031struct ucl_emitter_streamline_stack {32bool is_array;33bool empty;34const ucl_object_t *obj;35struct ucl_emitter_streamline_stack *next;36};3738struct ucl_emitter_context_streamline {39/* Inherited from the main context */40/** Name of emitter (e.g. json, compact_json) */41const char *name;42/** Unique id (e.g. UCL_EMIT_JSON for standard emitters */43int id;44/** A set of output functions */45const struct ucl_emitter_functions *func;46/** A set of output operations */47const struct ucl_emitter_operations *ops;48/** Current amount of indent tabs */49unsigned int indent;50/** Top level object */51const ucl_object_t *top;52/** Optional comments */53const ucl_object_t *comments;5455/* Streamline specific fields */56struct ucl_emitter_streamline_stack *containers;57};5859#define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx)6061struct ucl_emitter_context*62ucl_object_emit_streamline_new (const ucl_object_t *obj,63enum ucl_emitter emit_type,64struct ucl_emitter_functions *emitter)65{66const struct ucl_emitter_context *ctx;67struct ucl_emitter_context_streamline *sctx;6869ctx = ucl_emit_get_standard_context (emit_type);70if (ctx == NULL) {71return NULL;72}7374sctx = calloc (1, sizeof (*sctx));75if (sctx == NULL) {76return NULL;77}7879memcpy (sctx, ctx, sizeof (*ctx));80sctx->func = emitter;81sctx->top = obj;8283ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx,84obj);8586return (struct ucl_emitter_context *)sctx;87}8889void90ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,91const ucl_object_t *obj)92{93struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);94struct ucl_emitter_streamline_stack *st, *top;95bool print_key = false;9697/* Check top object presence */98if (sctx->top == NULL) {99sctx->top = obj;100}101102top = sctx->containers;103st = malloc (sizeof (*st));104if (st != NULL) {105st->empty = true;106if (top && !top->is_array) {107print_key = true;108}109110st->obj = obj;111if (obj != NULL && obj->type == UCL_ARRAY) {112st->is_array = true;113sctx->ops->ucl_emitter_start_array (ctx, obj, top == NULL, print_key);114}115else {116st->is_array = false;117sctx->ops->ucl_emitter_start_object (ctx, obj, top == NULL, print_key);118}119LL_PREPEND (sctx->containers, st);120}121}122123void124ucl_object_emit_streamline_add_object (125struct ucl_emitter_context *ctx, const ucl_object_t *obj)126{127struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);128bool is_array = false, is_first = false;129130if (sctx->containers != NULL) {131if (sctx->containers->is_array) {132is_array = true;133}134if (sctx->containers->empty) {135is_first = true;136sctx->containers->empty = false;137}138}139140sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array);141}142143void144ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)145{146struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);147struct ucl_emitter_streamline_stack *st;148149if (sctx->containers != NULL) {150st = sctx->containers;151152if (st->is_array) {153sctx->ops->ucl_emitter_end_array (ctx, st->obj);154}155else {156sctx->ops->ucl_emitter_end_object (ctx, st->obj);157}158sctx->containers = st->next;159free (st);160}161}162163void164ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx)165{166struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);167168while (sctx->containers != NULL) {169ucl_object_emit_streamline_end_container (ctx);170}171172free (sctx);173}174175176