Branch data Line data Source code
1 : : /* Copyright (c) 2014, Vsevolod Stakhov
2 : : * All rights reserved.
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions are met:
6 : : * * Redistributions of source code must retain the above copyright
7 : : * notice, this list of conditions and the following disclaimer.
8 : : * * Redistributions in binary form must reproduce the above copyright
9 : : * notice, this list of conditions and the following disclaimer in the
10 : : * documentation and/or other materials provided with the distribution.
11 : : *
12 : : * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13 : : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 : : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 : : * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16 : : * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 : : * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 : : */
23 : :
24 : : #ifdef HAVE_CONFIG_H
25 : : #include "config.h"
26 : : #endif
27 : :
28 : : #include "ucl.h"
29 : : #include "ucl_internal.h"
30 : : #include "ucl_chartable.h"
31 : :
32 : : struct ucl_emitter_streamline_stack {
33 : : bool is_array;
34 : : bool empty;
35 : : const ucl_object_t *obj;
36 : : struct ucl_emitter_streamline_stack *next;
37 : : };
38 : :
39 : : struct ucl_emitter_context_streamline {
40 : : /* Inherited from the main context */
41 : : /** Name of emitter (e.g. json, compact_json) */
42 : : const char *name;
43 : : /** Unique id (e.g. UCL_EMIT_JSON for standard emitters */
44 : : int id;
45 : : /** A set of output functions */
46 : : const struct ucl_emitter_functions *func;
47 : : /** A set of output operations */
48 : : const struct ucl_emitter_operations *ops;
49 : : /** Current amount of indent tabs */
50 : : unsigned int indent;
51 : : /** Top level object */
52 : : const ucl_object_t *top;
53 : : /** Optional comments */
54 : : const ucl_object_t *comments;
55 : :
56 : : /* Streamline specific fields */
57 : : struct ucl_emitter_streamline_stack *containers;
58 : : };
59 : :
60 : : #define TO_STREAMLINE(ctx) (struct ucl_emitter_context_streamline *)(ctx)
61 : :
62 : : struct ucl_emitter_context*
63 : 0 : ucl_object_emit_streamline_new (const ucl_object_t *obj,
64 : : enum ucl_emitter emit_type,
65 : : struct ucl_emitter_functions *emitter)
66 : : {
67 : : const struct ucl_emitter_context *ctx;
68 : : struct ucl_emitter_context_streamline *sctx;
69 : :
70 : 0 : ctx = ucl_emit_get_standard_context (emit_type);
71 [ # # ]: 0 : if (ctx == NULL) {
72 : 0 : return NULL;
73 : : }
74 : :
75 : 0 : sctx = calloc (1, sizeof (*sctx));
76 [ # # ]: 0 : if (sctx == NULL) {
77 : 0 : return NULL;
78 : : }
79 : :
80 : 0 : memcpy (sctx, ctx, sizeof (*ctx));
81 : 0 : sctx->func = emitter;
82 : 0 : sctx->top = obj;
83 : :
84 : 0 : ucl_object_emit_streamline_start_container ((struct ucl_emitter_context *)sctx,
85 : 0 : obj);
86 : :
87 : 0 : return (struct ucl_emitter_context *)sctx;
88 : 0 : }
89 : :
90 : : void
91 : 0 : ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
92 : : const ucl_object_t *obj)
93 : : {
94 : 0 : struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
95 : : struct ucl_emitter_streamline_stack *st, *top;
96 : 0 : bool print_key = false;
97 : :
98 : : /* Check top object presence */
99 [ # # ]: 0 : if (sctx->top == NULL) {
100 : 0 : sctx->top = obj;
101 : 0 : }
102 : :
103 : 0 : top = sctx->containers;
104 : 0 : st = malloc (sizeof (*st));
105 [ # # ]: 0 : if (st != NULL) {
106 [ # # # # ]: 0 : if (top != NULL && !top->is_array) {
107 : 0 : print_key = true;
108 : 0 : }
109 : 0 : st->empty = true;
110 : 0 : st->obj = obj;
111 [ # # # # ]: 0 : if (obj != NULL && obj->type == UCL_ARRAY) {
112 : 0 : st->is_array = true;
113 : 0 : sctx->ops->ucl_emitter_start_array (ctx, obj, print_key);
114 : 0 : }
115 : : else {
116 : 0 : st->is_array = false;
117 : 0 : sctx->ops->ucl_emitter_start_object (ctx, obj, print_key);
118 : : }
119 : 0 : LL_PREPEND (sctx->containers, st);
120 : 0 : }
121 : 0 : }
122 : :
123 : : void
124 : 0 : ucl_object_emit_streamline_add_object (
125 : : struct ucl_emitter_context *ctx, const ucl_object_t *obj)
126 : : {
127 : 0 : struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
128 : 0 : bool is_array = false, is_first = false;
129 : :
130 [ # # ]: 0 : if (sctx->containers != NULL) {
131 [ # # ]: 0 : if (sctx->containers->is_array) {
132 : 0 : is_array = true;
133 : 0 : }
134 [ # # ]: 0 : if (sctx->containers->empty) {
135 : 0 : is_first = true;
136 : 0 : sctx->containers->empty = false;
137 : 0 : }
138 : 0 : }
139 : :
140 : 0 : sctx->ops->ucl_emitter_write_elt (ctx, obj, is_first, !is_array);
141 : 0 : }
142 : :
143 : : void
144 : 0 : ucl_object_emit_streamline_end_container (struct ucl_emitter_context *ctx)
145 : : {
146 : 0 : struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
147 : : struct ucl_emitter_streamline_stack *st;
148 : :
149 [ # # ]: 0 : if (sctx->containers != NULL) {
150 : 0 : st = sctx->containers;
151 : :
152 [ # # ]: 0 : if (st->is_array) {
153 : 0 : sctx->ops->ucl_emitter_end_array (ctx, st->obj);
154 : 0 : }
155 : : else {
156 : 0 : sctx->ops->ucl_emitter_end_object (ctx, st->obj);
157 : : }
158 : 0 : sctx->containers = st->next;
159 : 0 : free (st);
160 : 0 : }
161 : 0 : }
162 : :
163 : : void
164 : 0 : ucl_object_emit_streamline_finish (struct ucl_emitter_context *ctx)
165 : : {
166 : 0 : struct ucl_emitter_context_streamline *sctx = TO_STREAMLINE(ctx);
167 : :
168 [ # # ]: 0 : while (sctx->containers != NULL) {
169 : 0 : ucl_object_emit_streamline_end_container (ctx);
170 : : }
171 : :
172 : 0 : free (sctx);
173 : 0 : }
|