rubysl-syck 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/ext/rubysl/syck/bytecode.c +1166 -0
- data/ext/rubysl/syck/emitter.c +1242 -0
- data/ext/rubysl/syck/extconf.rb +5 -0
- data/ext/rubysl/syck/gram.c +1894 -0
- data/ext/rubysl/syck/gram.h +79 -0
- data/ext/rubysl/syck/handler.c +174 -0
- data/ext/rubysl/syck/implicit.c +2990 -0
- data/ext/rubysl/syck/node.c +408 -0
- data/ext/rubysl/syck/rubyext.c +2366 -0
- data/ext/rubysl/syck/st.c +576 -0
- data/ext/rubysl/syck/st.h +72 -0
- data/ext/rubysl/syck/syck.c +504 -0
- data/ext/rubysl/syck/syck.h +458 -0
- data/ext/rubysl/syck/token.c +2725 -0
- data/ext/rubysl/syck/yaml2byte.c +257 -0
- data/ext/rubysl/syck/yamlbyte.h +170 -0
- data/lib/rubysl/syck/version.rb +5 -0
- data/lib/rubysl/syck.rb +7 -0
- data/rubysl-syck.gemspec +22 -0
- metadata +97 -0
@@ -0,0 +1,1242 @@
|
|
1
|
+
/*
|
2
|
+
* emitter.c
|
3
|
+
*
|
4
|
+
* $Author: shyouhei $
|
5
|
+
* $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
|
6
|
+
*
|
7
|
+
* Copyright (C) 2003 why the lucky stiff
|
8
|
+
*
|
9
|
+
* All Base64 code from Ruby's pack.c.
|
10
|
+
* Ruby is Copyright (C) 1993-2003 Yukihiro Matsumoto
|
11
|
+
*/
|
12
|
+
#include "ruby.h"
|
13
|
+
|
14
|
+
#include <stdio.h>
|
15
|
+
#include <string.h>
|
16
|
+
|
17
|
+
#include "syck.h"
|
18
|
+
|
19
|
+
#define DEFAULT_ANCHOR_FORMAT "id%03d"
|
20
|
+
|
21
|
+
const char hex_table[] =
|
22
|
+
"0123456789ABCDEF";
|
23
|
+
static char b64_table[] =
|
24
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
25
|
+
|
26
|
+
/*
|
27
|
+
* Built-in base64 (from Ruby's pack.c)
|
28
|
+
*/
|
29
|
+
char *
|
30
|
+
syck_base64enc( char *s, long len )
|
31
|
+
{
|
32
|
+
long i = 0;
|
33
|
+
int padding = '=';
|
34
|
+
char *buff = S_ALLOC_N(char, len * 4 / 3 + 6);
|
35
|
+
|
36
|
+
while (len >= 3) {
|
37
|
+
buff[i++] = b64_table[077 & (*s >> 2)];
|
38
|
+
buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
|
39
|
+
buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
|
40
|
+
buff[i++] = b64_table[077 & s[2]];
|
41
|
+
s += 3;
|
42
|
+
len -= 3;
|
43
|
+
}
|
44
|
+
if (len == 2) {
|
45
|
+
buff[i++] = b64_table[077 & (*s >> 2)];
|
46
|
+
buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
|
47
|
+
buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
|
48
|
+
buff[i++] = padding;
|
49
|
+
}
|
50
|
+
else if (len == 1) {
|
51
|
+
buff[i++] = b64_table[077 & (*s >> 2)];
|
52
|
+
buff[i++] = b64_table[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
|
53
|
+
buff[i++] = padding;
|
54
|
+
buff[i++] = padding;
|
55
|
+
}
|
56
|
+
buff[i++] = '\n';
|
57
|
+
return buff;
|
58
|
+
}
|
59
|
+
|
60
|
+
char *
|
61
|
+
syck_base64dec( char *s, long len )
|
62
|
+
{
|
63
|
+
int a = -1,b = -1,c = 0,d;
|
64
|
+
static int first = 1;
|
65
|
+
static int b64_xtable[256];
|
66
|
+
char *ptr = syck_strndup( s, len );
|
67
|
+
char *end = ptr;
|
68
|
+
char *send = s + len;
|
69
|
+
|
70
|
+
if (first) {
|
71
|
+
int i;
|
72
|
+
first = 0;
|
73
|
+
|
74
|
+
for (i = 0; i < 256; i++) {
|
75
|
+
b64_xtable[i] = -1;
|
76
|
+
}
|
77
|
+
for (i = 0; i < 64; i++) {
|
78
|
+
b64_xtable[(int)b64_table[i]] = i;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
while (s < send) {
|
82
|
+
while (s[0] == '\r' || s[0] == '\n') { s++; }
|
83
|
+
if ((a = b64_xtable[(int)s[0]]) == -1) break;
|
84
|
+
if ((b = b64_xtable[(int)s[1]]) == -1) break;
|
85
|
+
if ((c = b64_xtable[(int)s[2]]) == -1) break;
|
86
|
+
if ((d = b64_xtable[(int)s[3]]) == -1) break;
|
87
|
+
*end++ = a << 2 | b >> 4;
|
88
|
+
*end++ = b << 4 | c >> 2;
|
89
|
+
*end++ = c << 6 | d;
|
90
|
+
s += 4;
|
91
|
+
}
|
92
|
+
if (a != -1 && b != -1) {
|
93
|
+
if (s + 2 < send && s[2] == '=')
|
94
|
+
*end++ = a << 2 | b >> 4;
|
95
|
+
if (c != -1 && s + 3 < send && s[3] == '=') {
|
96
|
+
*end++ = a << 2 | b >> 4;
|
97
|
+
*end++ = b << 4 | c >> 2;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
*end = '\0';
|
101
|
+
/*RSTRING(buf)->len = ptr - RSTRING(buf)->ptr;*/
|
102
|
+
return ptr;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* Allocate an emitter
|
107
|
+
*/
|
108
|
+
SyckEmitter *
|
109
|
+
syck_new_emitter()
|
110
|
+
{
|
111
|
+
SyckEmitter *e;
|
112
|
+
e = S_ALLOC( SyckEmitter );
|
113
|
+
e->headless = 0;
|
114
|
+
e->use_header = 0;
|
115
|
+
e->use_version = 0;
|
116
|
+
e->sort_keys = 0;
|
117
|
+
e->anchor_format = NULL;
|
118
|
+
e->explicit_typing = 0;
|
119
|
+
e->best_width = 80;
|
120
|
+
e->style = scalar_none;
|
121
|
+
e->stage = doc_open;
|
122
|
+
e->indent = 2;
|
123
|
+
e->level = -1;
|
124
|
+
e->anchors = NULL;
|
125
|
+
e->markers = NULL;
|
126
|
+
e->anchored = NULL;
|
127
|
+
e->bufsize = SYCK_BUFFERSIZE;
|
128
|
+
e->buffer = NULL;
|
129
|
+
e->marker = NULL;
|
130
|
+
e->bufpos = 0;
|
131
|
+
e->emitter_handler = NULL;
|
132
|
+
e->output_handler = NULL;
|
133
|
+
e->lvl_idx = 0;
|
134
|
+
e->lvl_capa = ALLOC_CT;
|
135
|
+
e->levels = S_ALLOC_N( SyckLevel, e->lvl_capa );
|
136
|
+
syck_emitter_reset_levels( e );
|
137
|
+
e->bonus = NULL;
|
138
|
+
return e;
|
139
|
+
}
|
140
|
+
|
141
|
+
int
|
142
|
+
syck_st_free_anchors( char *key, char *name, char *arg )
|
143
|
+
{
|
144
|
+
S_FREE( name );
|
145
|
+
return ST_CONTINUE;
|
146
|
+
}
|
147
|
+
|
148
|
+
void
|
149
|
+
syck_emitter_st_free( SyckEmitter *e )
|
150
|
+
{
|
151
|
+
/*
|
152
|
+
* Free the anchor tables
|
153
|
+
*/
|
154
|
+
if ( e->anchors != NULL )
|
155
|
+
{
|
156
|
+
st_foreach( e->anchors, syck_st_free_anchors, 0 );
|
157
|
+
st_free_table( e->anchors );
|
158
|
+
e->anchors = NULL;
|
159
|
+
}
|
160
|
+
|
161
|
+
if ( e->anchored != NULL )
|
162
|
+
{
|
163
|
+
st_free_table( e->anchored );
|
164
|
+
e->anchored = NULL;
|
165
|
+
}
|
166
|
+
|
167
|
+
/*
|
168
|
+
* Free the markers tables
|
169
|
+
*/
|
170
|
+
if ( e->markers != NULL )
|
171
|
+
{
|
172
|
+
st_free_table( e->markers );
|
173
|
+
e->markers = NULL;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
SyckLevel *
|
178
|
+
syck_emitter_current_level( SyckEmitter *e )
|
179
|
+
{
|
180
|
+
return &e->levels[e->lvl_idx-1];
|
181
|
+
}
|
182
|
+
|
183
|
+
SyckLevel *
|
184
|
+
syck_emitter_parent_level( SyckEmitter *e )
|
185
|
+
{
|
186
|
+
return &e->levels[e->lvl_idx-2];
|
187
|
+
}
|
188
|
+
|
189
|
+
void
|
190
|
+
syck_emitter_pop_level( SyckEmitter *e )
|
191
|
+
{
|
192
|
+
ASSERT( e != NULL );
|
193
|
+
|
194
|
+
/* The root level should never be popped */
|
195
|
+
if ( e->lvl_idx <= 1 ) return;
|
196
|
+
|
197
|
+
e->lvl_idx -= 1;
|
198
|
+
free( e->levels[e->lvl_idx].domain );
|
199
|
+
}
|
200
|
+
|
201
|
+
void
|
202
|
+
syck_emitter_add_level( SyckEmitter *e, int len, enum syck_level_status status )
|
203
|
+
{
|
204
|
+
ASSERT( e != NULL );
|
205
|
+
if ( e->lvl_idx + 1 > e->lvl_capa )
|
206
|
+
{
|
207
|
+
e->lvl_capa += ALLOC_CT;
|
208
|
+
S_REALLOC_N( e->levels, SyckLevel, e->lvl_capa );
|
209
|
+
}
|
210
|
+
|
211
|
+
ASSERT( len > e->levels[e->lvl_idx-1].spaces );
|
212
|
+
e->levels[e->lvl_idx].spaces = len;
|
213
|
+
e->levels[e->lvl_idx].ncount = 0;
|
214
|
+
e->levels[e->lvl_idx].domain = syck_strndup( e->levels[e->lvl_idx-1].domain, strlen( e->levels[e->lvl_idx-1].domain ) );
|
215
|
+
e->levels[e->lvl_idx].status = status;
|
216
|
+
e->levels[e->lvl_idx].anctag = 0;
|
217
|
+
e->lvl_idx += 1;
|
218
|
+
}
|
219
|
+
|
220
|
+
void
|
221
|
+
syck_emitter_reset_levels( SyckEmitter *e )
|
222
|
+
{
|
223
|
+
while ( e->lvl_idx > 1 )
|
224
|
+
{
|
225
|
+
syck_emitter_pop_level( e );
|
226
|
+
}
|
227
|
+
|
228
|
+
if ( e->lvl_idx < 1 )
|
229
|
+
{
|
230
|
+
e->lvl_idx = 1;
|
231
|
+
e->levels[0].spaces = -1;
|
232
|
+
e->levels[0].ncount = 0;
|
233
|
+
e->levels[0].domain = syck_strndup( "", 0 );
|
234
|
+
e->levels[0].anctag = 0;
|
235
|
+
}
|
236
|
+
e->levels[0].status = syck_lvl_header;
|
237
|
+
}
|
238
|
+
|
239
|
+
void
|
240
|
+
syck_emitter_handler( SyckEmitter *e, SyckEmitterHandler hdlr )
|
241
|
+
{
|
242
|
+
e->emitter_handler = hdlr;
|
243
|
+
}
|
244
|
+
|
245
|
+
void
|
246
|
+
syck_output_handler( SyckEmitter *e, SyckOutputHandler hdlr )
|
247
|
+
{
|
248
|
+
e->output_handler = hdlr;
|
249
|
+
}
|
250
|
+
|
251
|
+
void
|
252
|
+
syck_free_emitter( SyckEmitter *e )
|
253
|
+
{
|
254
|
+
/*
|
255
|
+
* Free tables
|
256
|
+
*/
|
257
|
+
syck_emitter_st_free( e );
|
258
|
+
syck_emitter_reset_levels( e );
|
259
|
+
S_FREE( e->levels[0].domain );
|
260
|
+
S_FREE( e->levels );
|
261
|
+
if ( e->buffer != NULL )
|
262
|
+
{
|
263
|
+
S_FREE( e->buffer );
|
264
|
+
}
|
265
|
+
S_FREE( e );
|
266
|
+
}
|
267
|
+
|
268
|
+
void
|
269
|
+
syck_emitter_clear( SyckEmitter *e )
|
270
|
+
{
|
271
|
+
if ( e->buffer == NULL )
|
272
|
+
{
|
273
|
+
e->buffer = S_ALLOC_N( char, e->bufsize );
|
274
|
+
S_MEMZERO( e->buffer, char, e->bufsize );
|
275
|
+
}
|
276
|
+
e->buffer[0] = '\0';
|
277
|
+
e->marker = e->buffer;
|
278
|
+
e->bufpos = 0;
|
279
|
+
}
|
280
|
+
|
281
|
+
/*
|
282
|
+
* Raw write to the emitter buffer.
|
283
|
+
*/
|
284
|
+
void
|
285
|
+
syck_emitter_write( SyckEmitter *e, char *str, long len )
|
286
|
+
{
|
287
|
+
long at;
|
288
|
+
ASSERT( str != NULL )
|
289
|
+
if ( e->buffer == NULL )
|
290
|
+
{
|
291
|
+
syck_emitter_clear( e );
|
292
|
+
}
|
293
|
+
|
294
|
+
/*
|
295
|
+
* Flush if at end of buffer
|
296
|
+
*/
|
297
|
+
at = e->marker - e->buffer;
|
298
|
+
if ( len + at >= e->bufsize )
|
299
|
+
{
|
300
|
+
syck_emitter_flush( e, 0 );
|
301
|
+
for (;;) {
|
302
|
+
long rest = e->bufsize - (e->marker - e->buffer);
|
303
|
+
if (len <= rest) break;
|
304
|
+
S_MEMCPY( e->marker, str, char, rest );
|
305
|
+
e->marker += rest;
|
306
|
+
str += rest;
|
307
|
+
len -= rest;
|
308
|
+
syck_emitter_flush( e, 0 );
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
/*
|
313
|
+
* Write to buffer
|
314
|
+
*/
|
315
|
+
S_MEMCPY( e->marker, str, char, len );
|
316
|
+
e->marker += len;
|
317
|
+
}
|
318
|
+
|
319
|
+
/*
|
320
|
+
* Write a chunk of data out.
|
321
|
+
*/
|
322
|
+
void
|
323
|
+
syck_emitter_flush( SyckEmitter *e, long check_room )
|
324
|
+
{
|
325
|
+
/*
|
326
|
+
* Check for enough space in the buffer for check_room length.
|
327
|
+
*/
|
328
|
+
if ( check_room > 0 )
|
329
|
+
{
|
330
|
+
if ( e->bufsize > ( e->marker - e->buffer ) + check_room )
|
331
|
+
{
|
332
|
+
return;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
else
|
336
|
+
{
|
337
|
+
check_room = e->bufsize;
|
338
|
+
}
|
339
|
+
|
340
|
+
/*
|
341
|
+
* Commit buffer.
|
342
|
+
*/
|
343
|
+
if ( check_room > e->marker - e->buffer )
|
344
|
+
{
|
345
|
+
check_room = e->marker - e->buffer;
|
346
|
+
}
|
347
|
+
(e->output_handler)( e, e->buffer, check_room );
|
348
|
+
e->bufpos += check_room;
|
349
|
+
e->marker -= check_room;
|
350
|
+
}
|
351
|
+
|
352
|
+
/*
|
353
|
+
* Start emitting from the given node, check for anchoring and then
|
354
|
+
* issue the callback to the emitter handler.
|
355
|
+
*/
|
356
|
+
void
|
357
|
+
syck_emit( SyckEmitter *e, st_data_t n )
|
358
|
+
{
|
359
|
+
SYMID oid;
|
360
|
+
char *anchor_name = NULL;
|
361
|
+
int indent = 0;
|
362
|
+
long x = 0;
|
363
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
364
|
+
|
365
|
+
/*
|
366
|
+
* Determine headers.
|
367
|
+
*/
|
368
|
+
if ( e->stage == doc_open && ( e->headless == 0 || e->use_header == 1 ) )
|
369
|
+
{
|
370
|
+
if ( e->use_version == 1 )
|
371
|
+
{
|
372
|
+
char *header = S_ALLOC_N( char, 64 );
|
373
|
+
S_MEMZERO( header, char, 64 );
|
374
|
+
sprintf( header, "--- %%YAML:%d.%d ", SYCK_YAML_MAJOR, SYCK_YAML_MINOR );
|
375
|
+
syck_emitter_write( e, header, strlen( header ) );
|
376
|
+
S_FREE( header );
|
377
|
+
}
|
378
|
+
else
|
379
|
+
{
|
380
|
+
syck_emitter_write( e, "--- ", 4 );
|
381
|
+
}
|
382
|
+
e->stage = doc_processing;
|
383
|
+
}
|
384
|
+
|
385
|
+
/* Add new level */
|
386
|
+
if ( lvl->spaces >= 0 ) {
|
387
|
+
indent = lvl->spaces + e->indent;
|
388
|
+
}
|
389
|
+
syck_emitter_add_level( e, indent, syck_lvl_open );
|
390
|
+
lvl = syck_emitter_current_level( e );
|
391
|
+
|
392
|
+
/* Look for anchor */
|
393
|
+
if ( e->anchors != NULL &&
|
394
|
+
st_lookup( e->markers, n, (st_data_t *)&oid ) &&
|
395
|
+
st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
|
396
|
+
{
|
397
|
+
if ( e->anchored == NULL )
|
398
|
+
{
|
399
|
+
e->anchored = st_init_numtable();
|
400
|
+
}
|
401
|
+
|
402
|
+
if ( ! st_lookup( e->anchored, (st_data_t)anchor_name, (st_data_t *)&x ) )
|
403
|
+
{
|
404
|
+
char *an = S_ALLOC_N( char, strlen( anchor_name ) + 3 );
|
405
|
+
sprintf( an, "&%s ", anchor_name );
|
406
|
+
syck_emitter_write( e, an, strlen( anchor_name ) + 2 );
|
407
|
+
free( an );
|
408
|
+
|
409
|
+
x = 1;
|
410
|
+
st_insert( e->anchored, (st_data_t)anchor_name, (st_data_t)x );
|
411
|
+
lvl->anctag = 1;
|
412
|
+
}
|
413
|
+
else
|
414
|
+
{
|
415
|
+
char *an = S_ALLOC_N( char, strlen( anchor_name ) + 2 );
|
416
|
+
sprintf( an, "*%s", anchor_name );
|
417
|
+
syck_emitter_write( e, an, strlen( anchor_name ) + 1 );
|
418
|
+
free( an );
|
419
|
+
|
420
|
+
goto end_emit;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
(e->emitter_handler)( e, n );
|
425
|
+
|
426
|
+
/* Pop the level */
|
427
|
+
end_emit:
|
428
|
+
syck_emitter_pop_level( e );
|
429
|
+
if ( e->lvl_idx == 1 ) {
|
430
|
+
syck_emitter_write( e, "\n", 1 );
|
431
|
+
e->headless = 0;
|
432
|
+
e->stage = doc_open;
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
/*
|
437
|
+
* Determine what tag needs to be written, based on the taguri of the node
|
438
|
+
* and the implicit tag which would be assigned to this node. If a tag is
|
439
|
+
* required, write the tag.
|
440
|
+
*/
|
441
|
+
void syck_emit_tag( SyckEmitter *e, char *tag, char *ignore )
|
442
|
+
{
|
443
|
+
SyckLevel *lvl;
|
444
|
+
if ( tag == NULL ) return;
|
445
|
+
if ( ignore != NULL && syck_tagcmp( tag, ignore ) == 0 && e->explicit_typing == 0 ) return;
|
446
|
+
lvl = syck_emitter_current_level( e );
|
447
|
+
|
448
|
+
/* implicit */
|
449
|
+
if ( strlen( tag ) == 0 ) {
|
450
|
+
syck_emitter_write( e, "! ", 2 );
|
451
|
+
|
452
|
+
/* global types */
|
453
|
+
} else if ( strncmp( tag, "tag:", 4 ) == 0 ) {
|
454
|
+
int taglen = strlen( tag );
|
455
|
+
syck_emitter_write( e, "!", 1 );
|
456
|
+
if ( strncmp( tag + 4, YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
|
457
|
+
int skip = 4 + strlen( YAML_DOMAIN ) + 1;
|
458
|
+
syck_emitter_write( e, tag + skip, taglen - skip );
|
459
|
+
} else {
|
460
|
+
char *subd = tag + 4;
|
461
|
+
while ( *subd != ':' && *subd != '\0' ) subd++;
|
462
|
+
if ( *subd == ':' ) {
|
463
|
+
if ( subd - tag > ( strlen( YAML_DOMAIN ) + 5 ) &&
|
464
|
+
strncmp( subd - strlen( YAML_DOMAIN ), YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
|
465
|
+
syck_emitter_write( e, tag + 4, subd - strlen( YAML_DOMAIN ) - ( tag + 4 ) - 1 );
|
466
|
+
syck_emitter_write( e, "/", 1 );
|
467
|
+
syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
|
468
|
+
} else {
|
469
|
+
syck_emitter_write( e, tag + 4, subd - ( tag + 4 ) );
|
470
|
+
syck_emitter_write( e, "/", 1 );
|
471
|
+
syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
|
472
|
+
}
|
473
|
+
} else {
|
474
|
+
/* TODO: Invalid tag (no colon after domain) */
|
475
|
+
return;
|
476
|
+
}
|
477
|
+
}
|
478
|
+
syck_emitter_write( e, " ", 1 );
|
479
|
+
|
480
|
+
/* private types */
|
481
|
+
} else if ( strncmp( tag, "x-private:", 10 ) == 0 ) {
|
482
|
+
syck_emitter_write( e, "!!", 2 );
|
483
|
+
syck_emitter_write( e, tag + 10, strlen( tag ) - 10 );
|
484
|
+
syck_emitter_write( e, " ", 1 );
|
485
|
+
}
|
486
|
+
lvl->anctag = 1;
|
487
|
+
}
|
488
|
+
|
489
|
+
/*
|
490
|
+
* Emit a newline and an appropriately spaced indent.
|
491
|
+
*/
|
492
|
+
void syck_emit_indent( SyckEmitter *e )
|
493
|
+
{
|
494
|
+
int i;
|
495
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
496
|
+
if ( e->bufpos == 0 && ( e->marker - e->buffer ) == 0 ) return;
|
497
|
+
if ( lvl->spaces >= 0 ) {
|
498
|
+
char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
|
499
|
+
|
500
|
+
spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
|
501
|
+
for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
|
502
|
+
syck_emitter_write( e, spcs, lvl->spaces + 1 );
|
503
|
+
free( spcs );
|
504
|
+
}
|
505
|
+
}
|
506
|
+
|
507
|
+
/* Clear the scan */
|
508
|
+
#define SCAN_NONE 0
|
509
|
+
/* All printable characters? */
|
510
|
+
#define SCAN_NONPRINT 1
|
511
|
+
/* Any indented lines? */
|
512
|
+
#define SCAN_INDENTED 2
|
513
|
+
/* Larger than the requested width? */
|
514
|
+
#define SCAN_WIDE 4
|
515
|
+
/* Opens or closes with whitespace? */
|
516
|
+
#define SCAN_WHITEEDGE 8
|
517
|
+
/* Contains a newline */
|
518
|
+
#define SCAN_NEWLINE 16
|
519
|
+
/* Contains a single quote */
|
520
|
+
#define SCAN_SINGLEQ 32
|
521
|
+
/* Contains a double quote */
|
522
|
+
#define SCAN_DOUBLEQ 64
|
523
|
+
/* Starts with a token */
|
524
|
+
#define SCAN_INDIC_S 128
|
525
|
+
/* Contains a flow indicator */
|
526
|
+
#define SCAN_INDIC_C 256
|
527
|
+
/* Ends without newlines */
|
528
|
+
#define SCAN_NONL_E 512
|
529
|
+
/* Ends with many newlines */
|
530
|
+
#define SCAN_MANYNL_E 1024
|
531
|
+
/* Contains flow map indicators */
|
532
|
+
#define SCAN_FLOWMAP 2048
|
533
|
+
/* Contains flow seq indicators */
|
534
|
+
#define SCAN_FLOWSEQ 4096
|
535
|
+
/* Contains a valid doc separator */
|
536
|
+
#define SCAN_DOCSEP 8192
|
537
|
+
|
538
|
+
/*
|
539
|
+
* Basic printable test for LATIN-1 characters.
|
540
|
+
*/
|
541
|
+
int
|
542
|
+
syck_scan_scalar( int req_width, char *cursor, long len )
|
543
|
+
{
|
544
|
+
long i = 0, start = 0;
|
545
|
+
int flags = SCAN_NONE;
|
546
|
+
|
547
|
+
if ( len < 1 ) return flags;
|
548
|
+
|
549
|
+
/* c-indicators from the spec */
|
550
|
+
if ( cursor[0] == '[' || cursor[0] == ']' ||
|
551
|
+
cursor[0] == '{' || cursor[0] == '}' ||
|
552
|
+
cursor[0] == '!' || cursor[0] == '*' ||
|
553
|
+
cursor[0] == '&' || cursor[0] == '|' ||
|
554
|
+
cursor[0] == '>' || cursor[0] == '\'' ||
|
555
|
+
cursor[0] == '"' || cursor[0] == '#' ||
|
556
|
+
cursor[0] == '%' || cursor[0] == '@' ||
|
557
|
+
cursor[0] == '&' ) {
|
558
|
+
flags |= SCAN_INDIC_S;
|
559
|
+
}
|
560
|
+
if ( ( cursor[0] == '-' || cursor[0] == ':' ||
|
561
|
+
cursor[0] == '?' || cursor[0] == ',' ) &&
|
562
|
+
( len == 1 || cursor[1] == ' ' || cursor[1] == '\n' ) )
|
563
|
+
{
|
564
|
+
flags |= SCAN_INDIC_S;
|
565
|
+
}
|
566
|
+
|
567
|
+
/* whitespace edges */
|
568
|
+
if ( cursor[len-1] != '\n' ) {
|
569
|
+
flags |= SCAN_NONL_E;
|
570
|
+
} else if ( len > 1 && cursor[len-2] == '\n' ) {
|
571
|
+
flags |= SCAN_MANYNL_E;
|
572
|
+
}
|
573
|
+
if (
|
574
|
+
( len > 0 && ( cursor[0] == ' ' || cursor[0] == '\t' ) ) ||
|
575
|
+
( len > 1 && ( cursor[len-1] == ' ' || cursor[len-1] == '\t' ) )
|
576
|
+
) {
|
577
|
+
flags |= SCAN_WHITEEDGE;
|
578
|
+
}
|
579
|
+
|
580
|
+
/* opening doc sep */
|
581
|
+
if ( len >= 3 && strncmp( cursor, "---", 3 ) == 0 )
|
582
|
+
flags |= SCAN_DOCSEP;
|
583
|
+
|
584
|
+
/* scan string */
|
585
|
+
for ( i = 0; i < len; i++ ) {
|
586
|
+
|
587
|
+
if ( ! ( cursor[i] == 0x9 ||
|
588
|
+
cursor[i] == 0xA ||
|
589
|
+
cursor[i] == 0xD ||
|
590
|
+
( cursor[i] >= 0x20 && cursor[i] <= 0x7E ) )
|
591
|
+
) {
|
592
|
+
flags |= SCAN_NONPRINT;
|
593
|
+
}
|
594
|
+
else if ( cursor[i] == '\n' ) {
|
595
|
+
flags |= SCAN_NEWLINE;
|
596
|
+
if ( len - i >= 3 && strncmp( &cursor[i+1], "---", 3 ) == 0 )
|
597
|
+
flags |= SCAN_DOCSEP;
|
598
|
+
if ( cursor[i+1] == ' ' || cursor[i+1] == '\t' )
|
599
|
+
flags |= SCAN_INDENTED;
|
600
|
+
if ( req_width > 0 && i - start > req_width )
|
601
|
+
flags |= SCAN_WIDE;
|
602
|
+
start = i;
|
603
|
+
}
|
604
|
+
else if ( cursor[i] == '\'' )
|
605
|
+
{
|
606
|
+
flags |= SCAN_SINGLEQ;
|
607
|
+
}
|
608
|
+
else if ( cursor[i] == '"' )
|
609
|
+
{
|
610
|
+
flags |= SCAN_DOUBLEQ;
|
611
|
+
}
|
612
|
+
else if ( cursor[i] == ']' )
|
613
|
+
{
|
614
|
+
flags |= SCAN_FLOWSEQ;
|
615
|
+
}
|
616
|
+
else if ( cursor[i] == '}' )
|
617
|
+
{
|
618
|
+
flags |= SCAN_FLOWMAP;
|
619
|
+
}
|
620
|
+
/* remember, if plain collections get implemented, to add nb-plain-flow-char */
|
621
|
+
else if ( ( cursor[i] == ' ' && cursor[i+1] == '#' ) ||
|
622
|
+
( cursor[i] == ':' &&
|
623
|
+
( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) ) )
|
624
|
+
{
|
625
|
+
flags |= SCAN_INDIC_C;
|
626
|
+
}
|
627
|
+
else if ( cursor[i] == ',' &&
|
628
|
+
( cursor[i+1] == ' ' || cursor[i+1] == '\n' || i == len - 1 ) )
|
629
|
+
{
|
630
|
+
flags |= SCAN_FLOWMAP;
|
631
|
+
flags |= SCAN_FLOWSEQ;
|
632
|
+
}
|
633
|
+
}
|
634
|
+
|
635
|
+
/* printf( "---STR---\n%s\nFLAGS: %d\n", cursor, flags ); */
|
636
|
+
return flags;
|
637
|
+
}
|
638
|
+
/*
|
639
|
+
* All scalars should be emitted through this function, which determines an appropriate style,
|
640
|
+
* tag and indent.
|
641
|
+
*/
|
642
|
+
void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style, int force_indent, int force_width,
|
643
|
+
char keep_nl, char *str, long len )
|
644
|
+
{
|
645
|
+
enum scalar_style favor_style = scalar_literal;
|
646
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
647
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
648
|
+
int scan = 0;
|
649
|
+
char *implicit;
|
650
|
+
|
651
|
+
if ( str == NULL ) str = "";
|
652
|
+
|
653
|
+
/* No empty nulls as map keys */
|
654
|
+
if ( len == 0 && ( parent->status == syck_lvl_map || parent->status == syck_lvl_imap ) &&
|
655
|
+
parent->ncount % 2 == 1 && syck_tagcmp( tag, "tag:yaml.org,2002:null" ) == 0 )
|
656
|
+
{
|
657
|
+
str = "~";
|
658
|
+
len = 1;
|
659
|
+
}
|
660
|
+
|
661
|
+
scan = syck_scan_scalar( force_width, str, len );
|
662
|
+
implicit = syck_match_implicit( str, len );
|
663
|
+
|
664
|
+
/* quote strings which default to implicits */
|
665
|
+
implicit = syck_taguri( YAML_DOMAIN, implicit, strlen( implicit ) );
|
666
|
+
if ( syck_tagcmp( tag, implicit ) != 0 && syck_tagcmp( tag, "tag:yaml.org,2002:str" ) == 0 ) {
|
667
|
+
force_style = scalar_2quote;
|
668
|
+
} else {
|
669
|
+
/* complex key */
|
670
|
+
if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 &&
|
671
|
+
( !( tag == NULL ||
|
672
|
+
( implicit != NULL && syck_tagcmp( tag, implicit ) == 0 && e->explicit_typing == 0 ) ) ) )
|
673
|
+
{
|
674
|
+
syck_emitter_write( e, "? ", 2 );
|
675
|
+
parent->status = syck_lvl_mapx;
|
676
|
+
}
|
677
|
+
syck_emit_tag( e, tag, implicit );
|
678
|
+
}
|
679
|
+
S_FREE( implicit );
|
680
|
+
|
681
|
+
/* if still arbitrary, sniff a good block style. */
|
682
|
+
if ( force_style == scalar_none ) {
|
683
|
+
if ( scan & SCAN_NEWLINE ) {
|
684
|
+
force_style = scalar_literal;
|
685
|
+
} else {
|
686
|
+
force_style = scalar_plain;
|
687
|
+
}
|
688
|
+
}
|
689
|
+
|
690
|
+
if ( e->style == scalar_fold ) {
|
691
|
+
favor_style = scalar_fold;
|
692
|
+
}
|
693
|
+
|
694
|
+
/* Determine block style */
|
695
|
+
if ( scan & SCAN_NONPRINT ) {
|
696
|
+
force_style = scalar_2quote;
|
697
|
+
} else if ( scan & SCAN_WHITEEDGE ) {
|
698
|
+
force_style = scalar_2quote;
|
699
|
+
} else if ( force_style != scalar_fold && ( scan & SCAN_INDENTED ) ) {
|
700
|
+
force_style = scalar_literal;
|
701
|
+
} else if ( force_style == scalar_plain && ( scan & SCAN_NEWLINE ) ) {
|
702
|
+
force_style = favor_style;
|
703
|
+
} else if ( force_style == scalar_plain && parent->status == syck_lvl_iseq && ( scan & SCAN_FLOWSEQ ) ) {
|
704
|
+
force_style = scalar_2quote;
|
705
|
+
} else if ( force_style == scalar_plain && parent->status == syck_lvl_imap && ( scan & SCAN_FLOWMAP ) ) {
|
706
|
+
force_style = scalar_2quote;
|
707
|
+
/* } else if ( force_style == scalar_fold && ( ! ( scan & SCAN_WIDE ) ) ) {
|
708
|
+
force_style = scalar_literal; */
|
709
|
+
} else if ( force_style == scalar_plain && ( scan & SCAN_INDIC_S || scan & SCAN_INDIC_C ) ) {
|
710
|
+
if ( scan & SCAN_NEWLINE ) {
|
711
|
+
force_style = favor_style;
|
712
|
+
} else {
|
713
|
+
force_style = scalar_2quote;
|
714
|
+
}
|
715
|
+
}
|
716
|
+
|
717
|
+
if ( force_indent > 0 ) {
|
718
|
+
lvl->spaces = parent->spaces + force_indent;
|
719
|
+
} else if ( scan & SCAN_DOCSEP ) {
|
720
|
+
lvl->spaces = parent->spaces + e->indent;
|
721
|
+
}
|
722
|
+
|
723
|
+
/* For now, all ambiguous keys are going to be double-quoted */
|
724
|
+
if ( ( parent->status == syck_lvl_map || parent->status == syck_lvl_mapx ) && parent->ncount % 2 == 1 ) {
|
725
|
+
if ( force_style != scalar_plain ) {
|
726
|
+
force_style = scalar_2quote;
|
727
|
+
}
|
728
|
+
}
|
729
|
+
|
730
|
+
/* If the parent is an inline, double quote anything complex */
|
731
|
+
if ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) {
|
732
|
+
if ( force_style != scalar_plain && force_style != scalar_1quote ) {
|
733
|
+
force_style = scalar_2quote;
|
734
|
+
}
|
735
|
+
}
|
736
|
+
|
737
|
+
/* Fix the ending newlines */
|
738
|
+
if ( scan & SCAN_NONL_E ) {
|
739
|
+
keep_nl = NL_CHOMP;
|
740
|
+
} else if ( scan & SCAN_MANYNL_E ) {
|
741
|
+
keep_nl = NL_KEEP;
|
742
|
+
}
|
743
|
+
|
744
|
+
/* Write the text node */
|
745
|
+
switch ( force_style )
|
746
|
+
{
|
747
|
+
case scalar_1quote:
|
748
|
+
syck_emit_1quoted( e, force_width, str, len );
|
749
|
+
break;
|
750
|
+
|
751
|
+
case scalar_none:
|
752
|
+
case scalar_2quote:
|
753
|
+
syck_emit_2quoted( e, force_width, str, len );
|
754
|
+
break;
|
755
|
+
|
756
|
+
case scalar_fold:
|
757
|
+
syck_emit_folded( e, force_width, keep_nl, str, len );
|
758
|
+
break;
|
759
|
+
|
760
|
+
case scalar_literal:
|
761
|
+
syck_emit_literal( e, keep_nl, str, len );
|
762
|
+
break;
|
763
|
+
|
764
|
+
case scalar_plain:
|
765
|
+
syck_emitter_write( e, str, len );
|
766
|
+
break;
|
767
|
+
}
|
768
|
+
|
769
|
+
if ( parent->status == syck_lvl_mapx )
|
770
|
+
{
|
771
|
+
syck_emitter_write( e, "\n", 1 );
|
772
|
+
}
|
773
|
+
}
|
774
|
+
|
775
|
+
void
|
776
|
+
syck_emitter_escape( SyckEmitter *e, char *src, long len )
|
777
|
+
{
|
778
|
+
int i;
|
779
|
+
for( i = 0; i < len; i++ )
|
780
|
+
{
|
781
|
+
if( (src[i] < 0x20) || (0x7E < src[i]) )
|
782
|
+
{
|
783
|
+
syck_emitter_write( e, "\\", 1 );
|
784
|
+
if( '\0' == src[i] )
|
785
|
+
syck_emitter_write( e, "0", 1 );
|
786
|
+
else
|
787
|
+
{
|
788
|
+
syck_emitter_write( e, "x", 1 );
|
789
|
+
syck_emitter_write( e, (char *)hex_table + ((src[i] & 0xF0) >> 4), 1 );
|
790
|
+
syck_emitter_write( e, (char *)hex_table + (src[i] & 0x0F), 1 );
|
791
|
+
}
|
792
|
+
}
|
793
|
+
else
|
794
|
+
{
|
795
|
+
syck_emitter_write( e, src + i, 1 );
|
796
|
+
if( '\\' == src[i] )
|
797
|
+
syck_emitter_write( e, "\\", 1 );
|
798
|
+
}
|
799
|
+
}
|
800
|
+
}
|
801
|
+
|
802
|
+
/*
|
803
|
+
* Outputs a single-quoted block.
|
804
|
+
*/
|
805
|
+
void syck_emit_1quoted( SyckEmitter *e, int width, char *str, long len )
|
806
|
+
{
|
807
|
+
char do_indent = 0;
|
808
|
+
char *mark = str;
|
809
|
+
char *start = str;
|
810
|
+
char *end = str;
|
811
|
+
syck_emitter_write( e, "'", 1 );
|
812
|
+
while ( mark < str + len ) {
|
813
|
+
if ( do_indent ) {
|
814
|
+
syck_emit_indent( e );
|
815
|
+
do_indent = 0;
|
816
|
+
}
|
817
|
+
switch ( *mark ) {
|
818
|
+
case '\'': syck_emitter_write( e, "'", 1 ); break;
|
819
|
+
|
820
|
+
case '\n':
|
821
|
+
end = mark + 1;
|
822
|
+
if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
|
823
|
+
syck_emitter_write( e, "\n\n", 2 );
|
824
|
+
} else {
|
825
|
+
syck_emitter_write( e, "\n", 1 );
|
826
|
+
}
|
827
|
+
do_indent = 1;
|
828
|
+
start = mark + 1;
|
829
|
+
break;
|
830
|
+
|
831
|
+
case ' ':
|
832
|
+
if ( width > 0 && *start != ' ' && mark - end > width ) {
|
833
|
+
do_indent = 1;
|
834
|
+
end = mark + 1;
|
835
|
+
} else {
|
836
|
+
syck_emitter_write( e, " ", 1 );
|
837
|
+
}
|
838
|
+
break;
|
839
|
+
|
840
|
+
default:
|
841
|
+
syck_emitter_write( e, mark, 1 );
|
842
|
+
break;
|
843
|
+
}
|
844
|
+
mark++;
|
845
|
+
}
|
846
|
+
syck_emitter_write( e, "'", 1 );
|
847
|
+
}
|
848
|
+
|
849
|
+
/*
|
850
|
+
* Outputs a double-quoted block.
|
851
|
+
*/
|
852
|
+
void syck_emit_2quoted( SyckEmitter *e, int width, char *str, long len )
|
853
|
+
{
|
854
|
+
char do_indent = 0;
|
855
|
+
char *mark = str;
|
856
|
+
char *start = str;
|
857
|
+
char *end = str;
|
858
|
+
syck_emitter_write( e, "\"", 1 );
|
859
|
+
while ( mark < str + len ) {
|
860
|
+
if ( do_indent > 0 ) {
|
861
|
+
if ( do_indent == 2 ) {
|
862
|
+
syck_emitter_write( e, "\\", 1 );
|
863
|
+
}
|
864
|
+
syck_emit_indent( e );
|
865
|
+
do_indent = 0;
|
866
|
+
}
|
867
|
+
switch ( *mark ) {
|
868
|
+
|
869
|
+
/* Escape sequences allowed within double quotes. */
|
870
|
+
case '"': syck_emitter_write( e, "\\\"", 2 ); break;
|
871
|
+
case '\\': syck_emitter_write( e, "\\\\", 2 ); break;
|
872
|
+
case '\0': syck_emitter_write( e, "\\0", 2 ); break;
|
873
|
+
case '\a': syck_emitter_write( e, "\\a", 2 ); break;
|
874
|
+
case '\b': syck_emitter_write( e, "\\b", 2 ); break;
|
875
|
+
case '\f': syck_emitter_write( e, "\\f", 2 ); break;
|
876
|
+
case '\r': syck_emitter_write( e, "\\r", 2 ); break;
|
877
|
+
case '\t': syck_emitter_write( e, "\\t", 2 ); break;
|
878
|
+
case '\v': syck_emitter_write( e, "\\v", 2 ); break;
|
879
|
+
case 0x1b: syck_emitter_write( e, "\\e", 2 ); break;
|
880
|
+
|
881
|
+
case '\n':
|
882
|
+
end = mark + 1;
|
883
|
+
syck_emitter_write( e, "\\n", 2 );
|
884
|
+
do_indent = 2;
|
885
|
+
start = mark + 1;
|
886
|
+
if ( start < str + len && ( *start == ' ' || *start == '\n' ) ) {
|
887
|
+
do_indent = 0;
|
888
|
+
}
|
889
|
+
break;
|
890
|
+
|
891
|
+
case ' ':
|
892
|
+
if ( width > 0 && *start != ' ' && mark - end > width ) {
|
893
|
+
do_indent = 1;
|
894
|
+
end = mark + 1;
|
895
|
+
} else {
|
896
|
+
syck_emitter_write( e, " ", 1 );
|
897
|
+
}
|
898
|
+
break;
|
899
|
+
|
900
|
+
default:
|
901
|
+
syck_emitter_escape( e, mark, 1 );
|
902
|
+
break;
|
903
|
+
}
|
904
|
+
mark++;
|
905
|
+
}
|
906
|
+
syck_emitter_write( e, "\"", 1 );
|
907
|
+
}
|
908
|
+
|
909
|
+
/*
|
910
|
+
* Outputs a literal block.
|
911
|
+
*/
|
912
|
+
void syck_emit_literal( SyckEmitter *e, char keep_nl, char *str, long len )
|
913
|
+
{
|
914
|
+
char *mark = str;
|
915
|
+
char *start = str;
|
916
|
+
char *end = str;
|
917
|
+
syck_emitter_write( e, "|", 1 );
|
918
|
+
if ( keep_nl == NL_CHOMP ) {
|
919
|
+
syck_emitter_write( e, "-", 1 );
|
920
|
+
} else if ( keep_nl == NL_KEEP ) {
|
921
|
+
syck_emitter_write( e, "+", 1 );
|
922
|
+
}
|
923
|
+
syck_emit_indent( e );
|
924
|
+
while ( mark < str + len ) {
|
925
|
+
if ( *mark == '\n' ) {
|
926
|
+
end = mark;
|
927
|
+
if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) end += 1;
|
928
|
+
syck_emitter_write( e, start, end - start );
|
929
|
+
if ( mark + 1 == str + len ) {
|
930
|
+
if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
|
931
|
+
} else {
|
932
|
+
syck_emit_indent( e );
|
933
|
+
}
|
934
|
+
start = mark + 1;
|
935
|
+
}
|
936
|
+
mark++;
|
937
|
+
}
|
938
|
+
end = str + len;
|
939
|
+
if ( start < end ) {
|
940
|
+
syck_emitter_write( e, start, end - start );
|
941
|
+
}
|
942
|
+
}
|
943
|
+
|
944
|
+
/*
|
945
|
+
* Outputs a folded block.
|
946
|
+
*/
|
947
|
+
void syck_emit_folded( SyckEmitter *e, int width, char keep_nl, char *str, long len )
|
948
|
+
{
|
949
|
+
char *mark = str;
|
950
|
+
char *start = str;
|
951
|
+
char *end = str;
|
952
|
+
syck_emitter_write( e, ">", 1 );
|
953
|
+
if ( keep_nl == NL_CHOMP ) {
|
954
|
+
syck_emitter_write( e, "-", 1 );
|
955
|
+
} else if ( keep_nl == NL_KEEP ) {
|
956
|
+
syck_emitter_write( e, "+", 1 );
|
957
|
+
}
|
958
|
+
syck_emit_indent( e );
|
959
|
+
if ( width <= 0 ) width = e->best_width;
|
960
|
+
while ( mark < str + len ) {
|
961
|
+
switch ( *mark ) {
|
962
|
+
case '\n':
|
963
|
+
syck_emitter_write( e, end, mark - end );
|
964
|
+
end = mark + 1;
|
965
|
+
if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
|
966
|
+
syck_emitter_write( e, "\n", 1 );
|
967
|
+
}
|
968
|
+
if ( mark + 1 == str + len ) {
|
969
|
+
if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
|
970
|
+
} else {
|
971
|
+
syck_emit_indent( e );
|
972
|
+
}
|
973
|
+
start = mark + 1;
|
974
|
+
break;
|
975
|
+
|
976
|
+
case ' ':
|
977
|
+
if ( *start != ' ' ) {
|
978
|
+
if ( mark - end > width ) {
|
979
|
+
syck_emitter_write( e, end, mark - end );
|
980
|
+
syck_emit_indent( e );
|
981
|
+
end = mark + 1;
|
982
|
+
}
|
983
|
+
}
|
984
|
+
break;
|
985
|
+
}
|
986
|
+
mark++;
|
987
|
+
}
|
988
|
+
if ( end < mark ) {
|
989
|
+
syck_emitter_write( e, end, mark - end );
|
990
|
+
}
|
991
|
+
}
|
992
|
+
|
993
|
+
/*
|
994
|
+
* Begins emission of a sequence.
|
995
|
+
*/
|
996
|
+
void syck_emit_seq( SyckEmitter *e, char *tag, enum seq_style style )
|
997
|
+
{
|
998
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
999
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
1000
|
+
syck_emit_tag( e, tag, "tag:yaml.org,2002:seq" );
|
1001
|
+
if ( style == seq_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
|
1002
|
+
syck_emitter_write( e, "[", 1 );
|
1003
|
+
lvl->status = syck_lvl_iseq;
|
1004
|
+
} else {
|
1005
|
+
/* complex key */
|
1006
|
+
if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
|
1007
|
+
syck_emitter_write( e, "? ", 2 );
|
1008
|
+
parent->status = syck_lvl_mapx;
|
1009
|
+
}
|
1010
|
+
lvl->status = syck_lvl_seq;
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
/*
|
1015
|
+
* Begins emission of a mapping.
|
1016
|
+
*/
|
1017
|
+
void syck_emit_map( SyckEmitter *e, char *tag, enum map_style style )
|
1018
|
+
{
|
1019
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
1020
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
1021
|
+
syck_emit_tag( e, tag, "tag:yaml.org,2002:map" );
|
1022
|
+
if ( style == map_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
|
1023
|
+
syck_emitter_write( e, "{", 1 );
|
1024
|
+
lvl->status = syck_lvl_imap;
|
1025
|
+
} else {
|
1026
|
+
/* complex key */
|
1027
|
+
if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
|
1028
|
+
syck_emitter_write( e, "? ", 2 );
|
1029
|
+
parent->status = syck_lvl_mapx;
|
1030
|
+
}
|
1031
|
+
lvl->status = syck_lvl_map;
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
/*
|
1036
|
+
* Handles emitting of a collection item (for both
|
1037
|
+
* sequences and maps)
|
1038
|
+
*/
|
1039
|
+
void syck_emit_item( SyckEmitter *e, st_data_t n )
|
1040
|
+
{
|
1041
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
1042
|
+
switch ( lvl->status )
|
1043
|
+
{
|
1044
|
+
case syck_lvl_seq:
|
1045
|
+
{
|
1046
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
1047
|
+
|
1048
|
+
/* seq-in-map shortcut -- the lvl->anctag check should be unneccesary but
|
1049
|
+
* there is a nasty shift/reduce in the parser on this point and
|
1050
|
+
* i'm not ready to tickle it. */
|
1051
|
+
if ( lvl->anctag == 0 && parent->status == syck_lvl_map && lvl->ncount == 0 ) {
|
1052
|
+
lvl->spaces = parent->spaces;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
/* seq-in-seq shortcut */
|
1056
|
+
else if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
|
1057
|
+
int spcs = ( lvl->spaces - parent->spaces ) - 2;
|
1058
|
+
if ( spcs >= 0 ) {
|
1059
|
+
int i = 0;
|
1060
|
+
for ( i = 0; i < spcs; i++ ) {
|
1061
|
+
syck_emitter_write( e, " ", 1 );
|
1062
|
+
}
|
1063
|
+
syck_emitter_write( e, "- ", 2 );
|
1064
|
+
break;
|
1065
|
+
}
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
syck_emit_indent( e );
|
1069
|
+
syck_emitter_write( e, "- ", 2 );
|
1070
|
+
}
|
1071
|
+
break;
|
1072
|
+
|
1073
|
+
case syck_lvl_iseq:
|
1074
|
+
{
|
1075
|
+
if ( lvl->ncount > 0 ) {
|
1076
|
+
syck_emitter_write( e, ", ", 2 );
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
break;
|
1080
|
+
|
1081
|
+
case syck_lvl_map:
|
1082
|
+
{
|
1083
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
1084
|
+
|
1085
|
+
/* map-in-seq shortcut */
|
1086
|
+
if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
|
1087
|
+
int spcs = ( lvl->spaces - parent->spaces ) - 2;
|
1088
|
+
if ( spcs >= 0 ) {
|
1089
|
+
int i = 0;
|
1090
|
+
for ( i = 0; i < spcs; i++ ) {
|
1091
|
+
syck_emitter_write( e, " ", 1 );
|
1092
|
+
}
|
1093
|
+
break;
|
1094
|
+
}
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
if ( lvl->ncount % 2 == 0 ) {
|
1098
|
+
syck_emit_indent( e );
|
1099
|
+
} else {
|
1100
|
+
syck_emitter_write( e, ": ", 2 );
|
1101
|
+
}
|
1102
|
+
}
|
1103
|
+
break;
|
1104
|
+
|
1105
|
+
case syck_lvl_mapx:
|
1106
|
+
{
|
1107
|
+
if ( lvl->ncount % 2 == 0 ) {
|
1108
|
+
syck_emit_indent( e );
|
1109
|
+
lvl->status = syck_lvl_map;
|
1110
|
+
} else {
|
1111
|
+
int i;
|
1112
|
+
if ( lvl->spaces > 0 ) {
|
1113
|
+
char *spcs = S_ALLOC_N( char, lvl->spaces + 1 );
|
1114
|
+
|
1115
|
+
spcs[lvl->spaces] = '\0';
|
1116
|
+
for ( i = 0; i < lvl->spaces; i++ ) spcs[i] = ' ';
|
1117
|
+
syck_emitter_write( e, spcs, lvl->spaces );
|
1118
|
+
S_FREE( spcs );
|
1119
|
+
}
|
1120
|
+
syck_emitter_write( e, ": ", 2 );
|
1121
|
+
}
|
1122
|
+
}
|
1123
|
+
break;
|
1124
|
+
|
1125
|
+
case syck_lvl_imap:
|
1126
|
+
{
|
1127
|
+
if ( lvl->ncount > 0 ) {
|
1128
|
+
if ( lvl->ncount % 2 == 0 ) {
|
1129
|
+
syck_emitter_write( e, ", ", 2 );
|
1130
|
+
} else {
|
1131
|
+
syck_emitter_write( e, ": ", 2 );
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
}
|
1135
|
+
break;
|
1136
|
+
|
1137
|
+
default: break;
|
1138
|
+
}
|
1139
|
+
lvl->ncount++;
|
1140
|
+
|
1141
|
+
syck_emit( e, n );
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
/*
|
1145
|
+
* Closes emission of a collection.
|
1146
|
+
*/
|
1147
|
+
void syck_emit_end( SyckEmitter *e )
|
1148
|
+
{
|
1149
|
+
SyckLevel *lvl = syck_emitter_current_level( e );
|
1150
|
+
SyckLevel *parent = syck_emitter_parent_level( e );
|
1151
|
+
switch ( lvl->status )
|
1152
|
+
{
|
1153
|
+
case syck_lvl_seq:
|
1154
|
+
if ( lvl->ncount == 0 ) {
|
1155
|
+
syck_emitter_write( e, "[]\n", 3 );
|
1156
|
+
} else if ( parent->status == syck_lvl_mapx ) {
|
1157
|
+
syck_emitter_write( e, "\n", 1 );
|
1158
|
+
}
|
1159
|
+
break;
|
1160
|
+
|
1161
|
+
case syck_lvl_iseq:
|
1162
|
+
syck_emitter_write( e, "]\n", 1 );
|
1163
|
+
break;
|
1164
|
+
|
1165
|
+
case syck_lvl_map:
|
1166
|
+
if ( lvl->ncount == 0 ) {
|
1167
|
+
syck_emitter_write( e, "{}\n", 3 );
|
1168
|
+
} else if ( lvl->ncount % 2 == 1 ) {
|
1169
|
+
syck_emitter_write( e, ":\n", 1 );
|
1170
|
+
} else if ( parent->status == syck_lvl_mapx ) {
|
1171
|
+
syck_emitter_write( e, "\n", 1 );
|
1172
|
+
}
|
1173
|
+
break;
|
1174
|
+
|
1175
|
+
case syck_lvl_imap:
|
1176
|
+
syck_emitter_write( e, "}\n", 1 );
|
1177
|
+
break;
|
1178
|
+
|
1179
|
+
default: break;
|
1180
|
+
}
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
/*
|
1184
|
+
* Fill markers table with emitter nodes in the
|
1185
|
+
* soon-to-be-emitted tree.
|
1186
|
+
*/
|
1187
|
+
SYMID
|
1188
|
+
syck_emitter_mark_node( SyckEmitter *e, st_data_t n )
|
1189
|
+
{
|
1190
|
+
SYMID oid = 0;
|
1191
|
+
char *anchor_name = NULL;
|
1192
|
+
|
1193
|
+
/*
|
1194
|
+
* Ensure markers table is initialized.
|
1195
|
+
*/
|
1196
|
+
if ( e->markers == NULL )
|
1197
|
+
{
|
1198
|
+
e->markers = st_init_numtable();
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
/*
|
1202
|
+
* Markers table initially marks the string position of the
|
1203
|
+
* object. Doesn't yet create an anchor, simply notes the
|
1204
|
+
* position.
|
1205
|
+
*/
|
1206
|
+
if ( ! st_lookup( e->markers, n, (st_data_t *)&oid ) )
|
1207
|
+
{
|
1208
|
+
/*
|
1209
|
+
* Store all markers
|
1210
|
+
*/
|
1211
|
+
oid = e->markers->num_entries + 1;
|
1212
|
+
st_insert( e->markers, n, (st_data_t)oid );
|
1213
|
+
}
|
1214
|
+
else
|
1215
|
+
{
|
1216
|
+
if ( e->anchors == NULL )
|
1217
|
+
{
|
1218
|
+
e->anchors = st_init_numtable();
|
1219
|
+
}
|
1220
|
+
|
1221
|
+
if ( ! st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
|
1222
|
+
{
|
1223
|
+
int idx = 0;
|
1224
|
+
char *anc = ( e->anchor_format == NULL ? DEFAULT_ANCHOR_FORMAT : e->anchor_format );
|
1225
|
+
|
1226
|
+
/*
|
1227
|
+
* Second time hitting this object, let's give it an anchor
|
1228
|
+
*/
|
1229
|
+
idx = e->anchors->num_entries + 1;
|
1230
|
+
anchor_name = S_ALLOC_N( char, strlen( anc ) + 10 );
|
1231
|
+
S_MEMZERO( anchor_name, char, strlen( anc ) + 10 );
|
1232
|
+
sprintf( anchor_name, anc, idx );
|
1233
|
+
|
1234
|
+
/*
|
1235
|
+
* Insert into anchors table
|
1236
|
+
*/
|
1237
|
+
st_insert( e->anchors, (st_data_t)oid, (st_data_t)anchor_name );
|
1238
|
+
}
|
1239
|
+
}
|
1240
|
+
return oid;
|
1241
|
+
}
|
1242
|
+
|