1*2bc180efSBaptiste Daroussin /*
2*2bc180efSBaptiste Daroussin * emitter.c, LibYAML emitter binding for Lua
3*2bc180efSBaptiste Daroussin * Written by Gary V. Vaughan, 2013
4*2bc180efSBaptiste Daroussin *
5*2bc180efSBaptiste Daroussin * Copyright (C) 2013-2022 Gary V. Vaughan
6*2bc180efSBaptiste Daroussin *
7*2bc180efSBaptiste Daroussin * Permission is hereby granted, free of charge, to any person obtaining a copy
8*2bc180efSBaptiste Daroussin * of this software and associated documentation files (the "Software"), to deal
9*2bc180efSBaptiste Daroussin * in the Software without restriction, including without limitation the rights
10*2bc180efSBaptiste Daroussin * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*2bc180efSBaptiste Daroussin * copies of the Software, and to permit persons to whom the Software is
12*2bc180efSBaptiste Daroussin * furnished to do so, subject to the following conditions:
13*2bc180efSBaptiste Daroussin *
14*2bc180efSBaptiste Daroussin * The above copyright notice and this permission notice shall be included in
15*2bc180efSBaptiste Daroussin * all copies or substantial portions of the Software.
16*2bc180efSBaptiste Daroussin *
17*2bc180efSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*2bc180efSBaptiste Daroussin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*2bc180efSBaptiste Daroussin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*2bc180efSBaptiste Daroussin * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*2bc180efSBaptiste Daroussin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*2bc180efSBaptiste Daroussin * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23*2bc180efSBaptiste Daroussin * THE SOFTWARE.
24*2bc180efSBaptiste Daroussin */
25*2bc180efSBaptiste Daroussin
26*2bc180efSBaptiste Daroussin #include <assert.h>
27*2bc180efSBaptiste Daroussin
28*2bc180efSBaptiste Daroussin #include "lyaml.h"
29*2bc180efSBaptiste Daroussin
30*2bc180efSBaptiste Daroussin
31*2bc180efSBaptiste Daroussin typedef struct {
32*2bc180efSBaptiste Daroussin yaml_emitter_t emitter;
33*2bc180efSBaptiste Daroussin
34*2bc180efSBaptiste Daroussin /* output accumulator */
35*2bc180efSBaptiste Daroussin lua_State *outputL;
36*2bc180efSBaptiste Daroussin luaL_Buffer yamlbuff;
37*2bc180efSBaptiste Daroussin
38*2bc180efSBaptiste Daroussin /* error handling */
39*2bc180efSBaptiste Daroussin lua_State *errL;
40*2bc180efSBaptiste Daroussin luaL_Buffer errbuff;
41*2bc180efSBaptiste Daroussin int error;
42*2bc180efSBaptiste Daroussin } lyaml_emitter;
43*2bc180efSBaptiste Daroussin
44*2bc180efSBaptiste Daroussin
45*2bc180efSBaptiste Daroussin /* Emit a STREAM_START event. */
46*2bc180efSBaptiste Daroussin static int
emit_STREAM_START(lua_State * L,lyaml_emitter * emitter)47*2bc180efSBaptiste Daroussin emit_STREAM_START (lua_State *L, lyaml_emitter *emitter)
48*2bc180efSBaptiste Daroussin {
49*2bc180efSBaptiste Daroussin yaml_event_t event;
50*2bc180efSBaptiste Daroussin yaml_encoding_t yaml_encoding;
51*2bc180efSBaptiste Daroussin const char *encoding = NULL;
52*2bc180efSBaptiste Daroussin
53*2bc180efSBaptiste Daroussin RAWGET_STRDUP (encoding); lua_pop (L, 1);
54*2bc180efSBaptiste Daroussin
55*2bc180efSBaptiste Daroussin #define MENTRY(_s) (STREQ (encoding, #_s)) { yaml_encoding = YAML_##_s##_ENCODING; }
56*2bc180efSBaptiste Daroussin if (encoding == NULL) { yaml_encoding = YAML_ANY_ENCODING; } else
57*2bc180efSBaptiste Daroussin if MENTRY( UTF8 ) else
58*2bc180efSBaptiste Daroussin if MENTRY( UTF16LE ) else
59*2bc180efSBaptiste Daroussin if MENTRY( UTF16BE ) else
60*2bc180efSBaptiste Daroussin {
61*2bc180efSBaptiste Daroussin emitter->error++;
62*2bc180efSBaptiste Daroussin luaL_addsize (&emitter->errbuff,
63*2bc180efSBaptiste Daroussin sprintf (luaL_prepbuffer (&emitter->errbuff),
64*2bc180efSBaptiste Daroussin "invalid stream encoding '%s'", encoding));
65*2bc180efSBaptiste Daroussin }
66*2bc180efSBaptiste Daroussin #undef MENTRY
67*2bc180efSBaptiste Daroussin
68*2bc180efSBaptiste Daroussin if (encoding) free ((void *) encoding);
69*2bc180efSBaptiste Daroussin
70*2bc180efSBaptiste Daroussin if (emitter->error != 0)
71*2bc180efSBaptiste Daroussin return 0;
72*2bc180efSBaptiste Daroussin
73*2bc180efSBaptiste Daroussin yaml_stream_start_event_initialize (&event, yaml_encoding);
74*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
75*2bc180efSBaptiste Daroussin }
76*2bc180efSBaptiste Daroussin
77*2bc180efSBaptiste Daroussin
78*2bc180efSBaptiste Daroussin /* Emit a STREAM_END event. */
79*2bc180efSBaptiste Daroussin static int
emit_STREAM_END(lua_State * L,lyaml_emitter * emitter)80*2bc180efSBaptiste Daroussin emit_STREAM_END (lua_State *L, lyaml_emitter *emitter)
81*2bc180efSBaptiste Daroussin {
82*2bc180efSBaptiste Daroussin yaml_event_t event;
83*2bc180efSBaptiste Daroussin yaml_stream_end_event_initialize (&event);
84*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
85*2bc180efSBaptiste Daroussin }
86*2bc180efSBaptiste Daroussin
87*2bc180efSBaptiste Daroussin
88*2bc180efSBaptiste Daroussin /* Emit a DOCUMENT_START event. */
89*2bc180efSBaptiste Daroussin static int
emit_DOCUMENT_START(lua_State * L,lyaml_emitter * emitter)90*2bc180efSBaptiste Daroussin emit_DOCUMENT_START (lua_State *L, lyaml_emitter *emitter)
91*2bc180efSBaptiste Daroussin {
92*2bc180efSBaptiste Daroussin yaml_event_t event;
93*2bc180efSBaptiste Daroussin yaml_version_directive_t version_directive, *Pversion_directive = NULL;
94*2bc180efSBaptiste Daroussin yaml_tag_directive_t *tag_directives_start = NULL, *tag_directives_end = NULL;
95*2bc180efSBaptiste Daroussin int implicit = 0;
96*2bc180efSBaptiste Daroussin
97*2bc180efSBaptiste Daroussin RAWGET_PUSHTABLE ("version_directive");
98*2bc180efSBaptiste Daroussin if (lua_type (L, -1) == LUA_TTABLE)
99*2bc180efSBaptiste Daroussin {
100*2bc180efSBaptiste Daroussin RAWGETS_INTEGER (version_directive.major, "major");
101*2bc180efSBaptiste Daroussin ERROR_IFNIL ("version_directive missing key 'major'");
102*2bc180efSBaptiste Daroussin if (emitter->error == 0)
103*2bc180efSBaptiste Daroussin {
104*2bc180efSBaptiste Daroussin RAWGETS_INTEGER (version_directive.minor, "minor");
105*2bc180efSBaptiste Daroussin ERROR_IFNIL ("version_directive missing key 'minor'");
106*2bc180efSBaptiste Daroussin }
107*2bc180efSBaptiste Daroussin Pversion_directive = &version_directive;
108*2bc180efSBaptiste Daroussin }
109*2bc180efSBaptiste Daroussin lua_pop (L, 1); /* pop version_directive rawget */
110*2bc180efSBaptiste Daroussin
111*2bc180efSBaptiste Daroussin RAWGET_PUSHTABLE ("tag_directives");
112*2bc180efSBaptiste Daroussin if (lua_type (L, -1) == LUA_TTABLE)
113*2bc180efSBaptiste Daroussin {
114*2bc180efSBaptiste Daroussin size_t bytes = lua_objlen (L, -1) * sizeof (yaml_tag_directive_t);
115*2bc180efSBaptiste Daroussin
116*2bc180efSBaptiste Daroussin tag_directives_start = (yaml_tag_directive_t *) malloc (bytes);
117*2bc180efSBaptiste Daroussin tag_directives_end = tag_directives_start;
118*2bc180efSBaptiste Daroussin
119*2bc180efSBaptiste Daroussin lua_pushnil (L); /* first key */
120*2bc180efSBaptiste Daroussin while (lua_next (L, -2) != 0)
121*2bc180efSBaptiste Daroussin {
122*2bc180efSBaptiste Daroussin RAWGETS_STRDUP (tag_directives_end->handle, "handle");
123*2bc180efSBaptiste Daroussin ERROR_IFNIL ("tag_directives item missing key 'handle'");
124*2bc180efSBaptiste Daroussin lua_pop (L, 1); /* pop handle */
125*2bc180efSBaptiste Daroussin
126*2bc180efSBaptiste Daroussin RAWGETS_STRDUP (tag_directives_end->prefix, "prefix");
127*2bc180efSBaptiste Daroussin ERROR_IFNIL ("tag_directives item missing key 'prefix'");
128*2bc180efSBaptiste Daroussin lua_pop (L, 1); /* pop prefix */
129*2bc180efSBaptiste Daroussin
130*2bc180efSBaptiste Daroussin tag_directives_end += 1;
131*2bc180efSBaptiste Daroussin
132*2bc180efSBaptiste Daroussin /* pop tag_directives list elewent, leave key for next iteration */
133*2bc180efSBaptiste Daroussin lua_pop (L, 1);
134*2bc180efSBaptiste Daroussin }
135*2bc180efSBaptiste Daroussin }
136*2bc180efSBaptiste Daroussin lua_pop (L, 1); /* pop lua_rawget "tag_directives" result */
137*2bc180efSBaptiste Daroussin
138*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (implicit); lua_pop (L, 1);
139*2bc180efSBaptiste Daroussin
140*2bc180efSBaptiste Daroussin if (emitter->error != 0)
141*2bc180efSBaptiste Daroussin return 0;
142*2bc180efSBaptiste Daroussin
143*2bc180efSBaptiste Daroussin yaml_document_start_event_initialize (&event, Pversion_directive,
144*2bc180efSBaptiste Daroussin tag_directives_start, tag_directives_end, implicit);
145*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
146*2bc180efSBaptiste Daroussin }
147*2bc180efSBaptiste Daroussin
148*2bc180efSBaptiste Daroussin
149*2bc180efSBaptiste Daroussin /* Emit a DOCUMENT_END event. */
150*2bc180efSBaptiste Daroussin static int
emit_DOCUMENT_END(lua_State * L,lyaml_emitter * emitter)151*2bc180efSBaptiste Daroussin emit_DOCUMENT_END (lua_State *L, lyaml_emitter *emitter)
152*2bc180efSBaptiste Daroussin {
153*2bc180efSBaptiste Daroussin yaml_event_t event;
154*2bc180efSBaptiste Daroussin int implicit = 0;
155*2bc180efSBaptiste Daroussin
156*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (implicit);
157*2bc180efSBaptiste Daroussin
158*2bc180efSBaptiste Daroussin yaml_document_end_event_initialize (&event, implicit);
159*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
160*2bc180efSBaptiste Daroussin }
161*2bc180efSBaptiste Daroussin
162*2bc180efSBaptiste Daroussin
163*2bc180efSBaptiste Daroussin /* Emit a MAPPING_START event. */
164*2bc180efSBaptiste Daroussin static int
emit_MAPPING_START(lua_State * L,lyaml_emitter * emitter)165*2bc180efSBaptiste Daroussin emit_MAPPING_START (lua_State *L, lyaml_emitter *emitter)
166*2bc180efSBaptiste Daroussin {
167*2bc180efSBaptiste Daroussin yaml_event_t event;
168*2bc180efSBaptiste Daroussin yaml_mapping_style_t yaml_style;
169*2bc180efSBaptiste Daroussin yaml_char_t *anchor = NULL, *tag = NULL;
170*2bc180efSBaptiste Daroussin int implicit = 1;
171*2bc180efSBaptiste Daroussin const char *style = NULL;
172*2bc180efSBaptiste Daroussin
173*2bc180efSBaptiste Daroussin RAWGET_STRDUP (style); lua_pop (L, 1);
174*2bc180efSBaptiste Daroussin
175*2bc180efSBaptiste Daroussin #define MENTRY(_s) (STREQ (style, #_s)) { yaml_style = YAML_##_s##_MAPPING_STYLE; }
176*2bc180efSBaptiste Daroussin if (style == NULL) { yaml_style = YAML_ANY_MAPPING_STYLE; } else
177*2bc180efSBaptiste Daroussin if MENTRY( BLOCK ) else
178*2bc180efSBaptiste Daroussin if MENTRY( FLOW ) else
179*2bc180efSBaptiste Daroussin {
180*2bc180efSBaptiste Daroussin emitter->error++;
181*2bc180efSBaptiste Daroussin luaL_addsize (&emitter->errbuff,
182*2bc180efSBaptiste Daroussin sprintf (luaL_prepbuffer (&emitter->errbuff),
183*2bc180efSBaptiste Daroussin "invalid mapping style '%s'", style));
184*2bc180efSBaptiste Daroussin }
185*2bc180efSBaptiste Daroussin #undef MENTRY
186*2bc180efSBaptiste Daroussin
187*2bc180efSBaptiste Daroussin if (style) free ((void *) style);
188*2bc180efSBaptiste Daroussin
189*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (anchor); lua_pop (L, 1);
190*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (tag); lua_pop (L, 1);
191*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (implicit); lua_pop (L, 1);
192*2bc180efSBaptiste Daroussin
193*2bc180efSBaptiste Daroussin yaml_mapping_start_event_initialize (&event, anchor, tag, implicit, yaml_style);
194*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
195*2bc180efSBaptiste Daroussin }
196*2bc180efSBaptiste Daroussin
197*2bc180efSBaptiste Daroussin
198*2bc180efSBaptiste Daroussin /* Emit a MAPPING_END event. */
199*2bc180efSBaptiste Daroussin static int
emit_MAPPING_END(lua_State * L,lyaml_emitter * emitter)200*2bc180efSBaptiste Daroussin emit_MAPPING_END (lua_State *L, lyaml_emitter *emitter)
201*2bc180efSBaptiste Daroussin {
202*2bc180efSBaptiste Daroussin yaml_event_t event;
203*2bc180efSBaptiste Daroussin yaml_mapping_end_event_initialize (&event);
204*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
205*2bc180efSBaptiste Daroussin }
206*2bc180efSBaptiste Daroussin
207*2bc180efSBaptiste Daroussin
208*2bc180efSBaptiste Daroussin /* Emit a SEQUENCE_START event. */
209*2bc180efSBaptiste Daroussin static int
emit_SEQUENCE_START(lua_State * L,lyaml_emitter * emitter)210*2bc180efSBaptiste Daroussin emit_SEQUENCE_START (lua_State *L, lyaml_emitter *emitter)
211*2bc180efSBaptiste Daroussin {
212*2bc180efSBaptiste Daroussin yaml_event_t event;
213*2bc180efSBaptiste Daroussin yaml_sequence_style_t yaml_style;
214*2bc180efSBaptiste Daroussin yaml_char_t *anchor = NULL, *tag = NULL;
215*2bc180efSBaptiste Daroussin int implicit = 1;
216*2bc180efSBaptiste Daroussin const char *style = NULL;
217*2bc180efSBaptiste Daroussin
218*2bc180efSBaptiste Daroussin RAWGET_STRDUP (style); lua_pop (L, 1);
219*2bc180efSBaptiste Daroussin
220*2bc180efSBaptiste Daroussin #define MENTRY(_s) (STREQ (style, #_s)) { yaml_style = YAML_##_s##_SEQUENCE_STYLE; }
221*2bc180efSBaptiste Daroussin if (style == NULL) { yaml_style = YAML_ANY_SEQUENCE_STYLE; } else
222*2bc180efSBaptiste Daroussin if MENTRY( BLOCK ) else
223*2bc180efSBaptiste Daroussin if MENTRY( FLOW ) else
224*2bc180efSBaptiste Daroussin {
225*2bc180efSBaptiste Daroussin emitter->error++;
226*2bc180efSBaptiste Daroussin luaL_addsize (&emitter->errbuff,
227*2bc180efSBaptiste Daroussin sprintf (luaL_prepbuffer (&emitter->errbuff),
228*2bc180efSBaptiste Daroussin "invalid sequence style '%s'", style));
229*2bc180efSBaptiste Daroussin }
230*2bc180efSBaptiste Daroussin #undef MENTRY
231*2bc180efSBaptiste Daroussin
232*2bc180efSBaptiste Daroussin if (style) free ((void *) style);
233*2bc180efSBaptiste Daroussin
234*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (anchor); lua_pop (L, 1);
235*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (tag); lua_pop (L, 1);
236*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (implicit); lua_pop (L, 1);
237*2bc180efSBaptiste Daroussin
238*2bc180efSBaptiste Daroussin yaml_sequence_start_event_initialize (&event, anchor, tag, implicit, yaml_style);
239*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
240*2bc180efSBaptiste Daroussin }
241*2bc180efSBaptiste Daroussin
242*2bc180efSBaptiste Daroussin
243*2bc180efSBaptiste Daroussin /* Emit a SEQUENCE_END event. */
244*2bc180efSBaptiste Daroussin static int
emit_SEQUENCE_END(lua_State * L,lyaml_emitter * emitter)245*2bc180efSBaptiste Daroussin emit_SEQUENCE_END (lua_State *L, lyaml_emitter *emitter)
246*2bc180efSBaptiste Daroussin {
247*2bc180efSBaptiste Daroussin yaml_event_t event;
248*2bc180efSBaptiste Daroussin yaml_sequence_end_event_initialize (&event);
249*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
250*2bc180efSBaptiste Daroussin }
251*2bc180efSBaptiste Daroussin
252*2bc180efSBaptiste Daroussin
253*2bc180efSBaptiste Daroussin /* Emit a SCALAR event. */
254*2bc180efSBaptiste Daroussin static int
emit_SCALAR(lua_State * L,lyaml_emitter * emitter)255*2bc180efSBaptiste Daroussin emit_SCALAR (lua_State *L, lyaml_emitter *emitter)
256*2bc180efSBaptiste Daroussin {
257*2bc180efSBaptiste Daroussin yaml_event_t event;
258*2bc180efSBaptiste Daroussin yaml_scalar_style_t yaml_style;
259*2bc180efSBaptiste Daroussin yaml_char_t *anchor = NULL, *tag = NULL, *value;
260*2bc180efSBaptiste Daroussin int length = 0, plain_implicit = 1, quoted_implicit = 1;
261*2bc180efSBaptiste Daroussin const char *style = NULL;
262*2bc180efSBaptiste Daroussin
263*2bc180efSBaptiste Daroussin RAWGET_STRDUP (style); lua_pop (L, 1);
264*2bc180efSBaptiste Daroussin
265*2bc180efSBaptiste Daroussin #define MENTRY(_s) (STREQ (style, #_s)) { yaml_style = YAML_##_s##_SCALAR_STYLE; }
266*2bc180efSBaptiste Daroussin if (style == NULL) { yaml_style = YAML_ANY_SCALAR_STYLE; } else
267*2bc180efSBaptiste Daroussin if MENTRY( PLAIN ) else
268*2bc180efSBaptiste Daroussin if MENTRY( SINGLE_QUOTED ) else
269*2bc180efSBaptiste Daroussin if MENTRY( DOUBLE_QUOTED ) else
270*2bc180efSBaptiste Daroussin if MENTRY( LITERAL ) else
271*2bc180efSBaptiste Daroussin if MENTRY( FOLDED ) else
272*2bc180efSBaptiste Daroussin {
273*2bc180efSBaptiste Daroussin emitter->error++;
274*2bc180efSBaptiste Daroussin luaL_addsize (&emitter->errbuff,
275*2bc180efSBaptiste Daroussin sprintf (luaL_prepbuffer (&emitter->errbuff),
276*2bc180efSBaptiste Daroussin "invalid scalar style '%s'", style));
277*2bc180efSBaptiste Daroussin }
278*2bc180efSBaptiste Daroussin #undef MENTRY
279*2bc180efSBaptiste Daroussin
280*2bc180efSBaptiste Daroussin if (style) free ((void *) style);
281*2bc180efSBaptiste Daroussin
282*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (anchor); lua_pop (L, 1);
283*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (tag); lua_pop (L, 1);
284*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (value); length = lua_objlen (L, -1); lua_pop (L, 1);
285*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (plain_implicit);
286*2bc180efSBaptiste Daroussin RAWGET_BOOLEAN (quoted_implicit);
287*2bc180efSBaptiste Daroussin
288*2bc180efSBaptiste Daroussin yaml_scalar_event_initialize (&event, anchor, tag, value, length,
289*2bc180efSBaptiste Daroussin plain_implicit, quoted_implicit, yaml_style);
290*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
291*2bc180efSBaptiste Daroussin }
292*2bc180efSBaptiste Daroussin
293*2bc180efSBaptiste Daroussin
294*2bc180efSBaptiste Daroussin /* Emit an ALIAS event. */
295*2bc180efSBaptiste Daroussin static int
emit_ALIAS(lua_State * L,lyaml_emitter * emitter)296*2bc180efSBaptiste Daroussin emit_ALIAS (lua_State *L, lyaml_emitter *emitter)
297*2bc180efSBaptiste Daroussin {
298*2bc180efSBaptiste Daroussin yaml_event_t event;
299*2bc180efSBaptiste Daroussin yaml_char_t *anchor;
300*2bc180efSBaptiste Daroussin
301*2bc180efSBaptiste Daroussin RAWGET_YAML_CHARP (anchor);
302*2bc180efSBaptiste Daroussin
303*2bc180efSBaptiste Daroussin yaml_alias_event_initialize (&event, anchor);
304*2bc180efSBaptiste Daroussin return yaml_emitter_emit (&emitter->emitter, &event);
305*2bc180efSBaptiste Daroussin }
306*2bc180efSBaptiste Daroussin
307*2bc180efSBaptiste Daroussin
308*2bc180efSBaptiste Daroussin static int
emit(lua_State * L)309*2bc180efSBaptiste Daroussin emit (lua_State *L)
310*2bc180efSBaptiste Daroussin {
311*2bc180efSBaptiste Daroussin lyaml_emitter *emitter;
312*2bc180efSBaptiste Daroussin int yaml_ok = 0;
313*2bc180efSBaptiste Daroussin int finalize = 0;
314*2bc180efSBaptiste Daroussin
315*2bc180efSBaptiste Daroussin luaL_argcheck (L, lua_istable (L, 1), 1, "expected table");
316*2bc180efSBaptiste Daroussin
317*2bc180efSBaptiste Daroussin emitter = (lyaml_emitter *) lua_touserdata (L, lua_upvalueindex (1));
318*2bc180efSBaptiste Daroussin
319*2bc180efSBaptiste Daroussin {
320*2bc180efSBaptiste Daroussin const char *type;
321*2bc180efSBaptiste Daroussin
322*2bc180efSBaptiste Daroussin RAWGET_STRDUP (type); lua_pop (L, 1);
323*2bc180efSBaptiste Daroussin
324*2bc180efSBaptiste Daroussin if (type == NULL)
325*2bc180efSBaptiste Daroussin {
326*2bc180efSBaptiste Daroussin emitter->error++;
327*2bc180efSBaptiste Daroussin luaL_addstring (&emitter->errbuff, "no type field in event table");
328*2bc180efSBaptiste Daroussin }
329*2bc180efSBaptiste Daroussin #define MENTRY(_s) (STREQ (type, #_s)) { yaml_ok = emit_##_s (L, emitter); }
330*2bc180efSBaptiste Daroussin /* Minimize comparisons by putting more common types earlier. */
331*2bc180efSBaptiste Daroussin else if MENTRY( SCALAR )
332*2bc180efSBaptiste Daroussin else if MENTRY( MAPPING_START )
333*2bc180efSBaptiste Daroussin else if MENTRY( MAPPING_END )
334*2bc180efSBaptiste Daroussin else if MENTRY( SEQUENCE_START )
335*2bc180efSBaptiste Daroussin else if MENTRY( SEQUENCE_END )
336*2bc180efSBaptiste Daroussin else if MENTRY( DOCUMENT_START )
337*2bc180efSBaptiste Daroussin else if MENTRY( DOCUMENT_END )
338*2bc180efSBaptiste Daroussin else if MENTRY( STREAM_START )
339*2bc180efSBaptiste Daroussin else if MENTRY( STREAM_END )
340*2bc180efSBaptiste Daroussin else if MENTRY( ALIAS )
341*2bc180efSBaptiste Daroussin #undef MENTRY
342*2bc180efSBaptiste Daroussin else
343*2bc180efSBaptiste Daroussin {
344*2bc180efSBaptiste Daroussin emitter->error++;
345*2bc180efSBaptiste Daroussin luaL_addsize (&emitter->errbuff,
346*2bc180efSBaptiste Daroussin sprintf (luaL_prepbuffer (&emitter->errbuff),
347*2bc180efSBaptiste Daroussin "invalid event type '%s'", type));
348*2bc180efSBaptiste Daroussin }
349*2bc180efSBaptiste Daroussin
350*2bc180efSBaptiste Daroussin /* If the stream has finished, finalize the YAML output. */
351*2bc180efSBaptiste Daroussin if (type && STREQ (type, "STREAM_END"))
352*2bc180efSBaptiste Daroussin finalize = 1;
353*2bc180efSBaptiste Daroussin
354*2bc180efSBaptiste Daroussin if (type) free ((void *) type);
355*2bc180efSBaptiste Daroussin }
356*2bc180efSBaptiste Daroussin
357*2bc180efSBaptiste Daroussin /* Copy any yaml_emitter_t errors into the error buffer. */
358*2bc180efSBaptiste Daroussin if (!emitter->error && !yaml_ok)
359*2bc180efSBaptiste Daroussin {
360*2bc180efSBaptiste Daroussin if (emitter->emitter.problem)
361*2bc180efSBaptiste Daroussin luaL_addstring (&emitter->errbuff, emitter->emitter.problem);
362*2bc180efSBaptiste Daroussin else
363*2bc180efSBaptiste Daroussin luaL_addstring (&emitter->errbuff, "LibYAML call failed");
364*2bc180efSBaptiste Daroussin emitter->error++;
365*2bc180efSBaptiste Daroussin }
366*2bc180efSBaptiste Daroussin
367*2bc180efSBaptiste Daroussin /* Report errors back to the caller as `false, "error message"`. */
368*2bc180efSBaptiste Daroussin if (emitter->error != 0)
369*2bc180efSBaptiste Daroussin {
370*2bc180efSBaptiste Daroussin assert (emitter->error == 1); /* bail on uncaught additional errors */
371*2bc180efSBaptiste Daroussin lua_pushboolean (L, 0);
372*2bc180efSBaptiste Daroussin luaL_pushresult (&emitter->errbuff);
373*2bc180efSBaptiste Daroussin lua_xmove (emitter->errL, L, 1);
374*2bc180efSBaptiste Daroussin return 2;
375*2bc180efSBaptiste Daroussin }
376*2bc180efSBaptiste Daroussin
377*2bc180efSBaptiste Daroussin /* Return `true, "YAML string"` after accepting a STREAM_END event. */
378*2bc180efSBaptiste Daroussin if (finalize)
379*2bc180efSBaptiste Daroussin {
380*2bc180efSBaptiste Daroussin lua_pushboolean (L, 1);
381*2bc180efSBaptiste Daroussin luaL_pushresult (&emitter->yamlbuff);
382*2bc180efSBaptiste Daroussin lua_xmove (emitter->outputL, L, 1);
383*2bc180efSBaptiste Daroussin return 2;
384*2bc180efSBaptiste Daroussin }
385*2bc180efSBaptiste Daroussin
386*2bc180efSBaptiste Daroussin /* Otherwise, just report success to the caller as `true`. */
387*2bc180efSBaptiste Daroussin lua_pushboolean (L, 1);
388*2bc180efSBaptiste Daroussin return 1;
389*2bc180efSBaptiste Daroussin }
390*2bc180efSBaptiste Daroussin
391*2bc180efSBaptiste Daroussin
392*2bc180efSBaptiste Daroussin static int
append_output(void * arg,unsigned char * buff,size_t len)393*2bc180efSBaptiste Daroussin append_output (void *arg, unsigned char *buff, size_t len)
394*2bc180efSBaptiste Daroussin {
395*2bc180efSBaptiste Daroussin lyaml_emitter *emitter = (lyaml_emitter *) arg;
396*2bc180efSBaptiste Daroussin luaL_addlstring (&emitter->yamlbuff, (char *) buff, len);
397*2bc180efSBaptiste Daroussin return 1;
398*2bc180efSBaptiste Daroussin }
399*2bc180efSBaptiste Daroussin
400*2bc180efSBaptiste Daroussin
401*2bc180efSBaptiste Daroussin static int
emitter_gc(lua_State * L)402*2bc180efSBaptiste Daroussin emitter_gc (lua_State *L)
403*2bc180efSBaptiste Daroussin {
404*2bc180efSBaptiste Daroussin lyaml_emitter *emitter = (lyaml_emitter *) lua_touserdata (L, 1);
405*2bc180efSBaptiste Daroussin
406*2bc180efSBaptiste Daroussin if (emitter)
407*2bc180efSBaptiste Daroussin yaml_emitter_delete (&emitter->emitter);
408*2bc180efSBaptiste Daroussin
409*2bc180efSBaptiste Daroussin return 0;
410*2bc180efSBaptiste Daroussin }
411*2bc180efSBaptiste Daroussin
412*2bc180efSBaptiste Daroussin
413*2bc180efSBaptiste Daroussin int
Pemitter(lua_State * L)414*2bc180efSBaptiste Daroussin Pemitter (lua_State *L)
415*2bc180efSBaptiste Daroussin {
416*2bc180efSBaptiste Daroussin lyaml_emitter *emitter;
417*2bc180efSBaptiste Daroussin
418*2bc180efSBaptiste Daroussin lua_newtable (L); /* object table */
419*2bc180efSBaptiste Daroussin
420*2bc180efSBaptiste Daroussin /* Create a user datum to store the emitter. */
421*2bc180efSBaptiste Daroussin emitter = (lyaml_emitter *) lua_newuserdata (L, sizeof (*emitter));
422*2bc180efSBaptiste Daroussin emitter->error = 0;
423*2bc180efSBaptiste Daroussin
424*2bc180efSBaptiste Daroussin /* Initialize the emitter. */
425*2bc180efSBaptiste Daroussin if (!yaml_emitter_initialize (&emitter->emitter))
426*2bc180efSBaptiste Daroussin {
427*2bc180efSBaptiste Daroussin if (!emitter->emitter.problem)
428*2bc180efSBaptiste Daroussin emitter->emitter.problem = "cannot initialize emitter";
429*2bc180efSBaptiste Daroussin return luaL_error (L, "%s", emitter->emitter.problem);
430*2bc180efSBaptiste Daroussin }
431*2bc180efSBaptiste Daroussin yaml_emitter_set_unicode (&emitter->emitter, 1);
432*2bc180efSBaptiste Daroussin yaml_emitter_set_width (&emitter->emitter, 2);
433*2bc180efSBaptiste Daroussin yaml_emitter_set_output (&emitter->emitter, &append_output, emitter);
434*2bc180efSBaptiste Daroussin
435*2bc180efSBaptiste Daroussin /* Set it's metatable, and ensure it is garbage collected properly. */
436*2bc180efSBaptiste Daroussin luaL_newmetatable (L, "lyaml.emitter");
437*2bc180efSBaptiste Daroussin lua_pushcfunction (L, emitter_gc);
438*2bc180efSBaptiste Daroussin lua_setfield (L, -2, "__gc");
439*2bc180efSBaptiste Daroussin lua_setmetatable (L, -2);
440*2bc180efSBaptiste Daroussin
441*2bc180efSBaptiste Daroussin /* Set the emit method of object as a closure over the user datum, and
442*2bc180efSBaptiste Daroussin return the whole object. */
443*2bc180efSBaptiste Daroussin lua_pushcclosure (L, emit, 1);
444*2bc180efSBaptiste Daroussin lua_setfield (L, -2, "emit");
445*2bc180efSBaptiste Daroussin
446*2bc180efSBaptiste Daroussin /* Set up a separate thread to collect error messages; save the thread
447*2bc180efSBaptiste Daroussin in the returned table so that it's not garbage collected when the
448*2bc180efSBaptiste Daroussin function call stack for Pemitter is cleaned up. */
449*2bc180efSBaptiste Daroussin emitter->errL = lua_newthread (L);
450*2bc180efSBaptiste Daroussin luaL_buffinit (emitter->errL, &emitter->errbuff);
451*2bc180efSBaptiste Daroussin lua_setfield (L, -2, "errthread");
452*2bc180efSBaptiste Daroussin
453*2bc180efSBaptiste Daroussin /* Create a thread for the YAML buffer. */
454*2bc180efSBaptiste Daroussin emitter->outputL = lua_newthread (L);
455*2bc180efSBaptiste Daroussin luaL_buffinit (emitter->outputL, &emitter->yamlbuff);
456*2bc180efSBaptiste Daroussin lua_setfield (L, -2, "outputthread");
457*2bc180efSBaptiste Daroussin
458*2bc180efSBaptiste Daroussin return 1;
459*2bc180efSBaptiste Daroussin }
460