rubysl-yaml 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1242 +0,0 @@
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
-