rubysl-yaml 2.0.4 → 2.1.0

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