blob: 0f47c9ca8addf8e9d2e454e02842927ae825d0e9 [file] [log] [blame]
David K. Bainbridgebd6b2882021-08-26 13:31:02 +00001//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "bytes"
27 "fmt"
28)
29
30// Flush the buffer if needed.
31func flush(emitter *yaml_emitter_t) bool {
32 if emitter.buffer_pos+5 >= len(emitter.buffer) {
33 return yaml_emitter_flush(emitter)
34 }
35 return true
36}
37
38// Put a character to the output buffer.
39func put(emitter *yaml_emitter_t, value byte) bool {
40 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
41 return false
42 }
43 emitter.buffer[emitter.buffer_pos] = value
44 emitter.buffer_pos++
45 emitter.column++
46 return true
47}
48
49// Put a line break to the output buffer.
50func put_break(emitter *yaml_emitter_t) bool {
51 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
52 return false
53 }
54 switch emitter.line_break {
55 case yaml_CR_BREAK:
56 emitter.buffer[emitter.buffer_pos] = '\r'
57 emitter.buffer_pos += 1
58 case yaml_LN_BREAK:
59 emitter.buffer[emitter.buffer_pos] = '\n'
60 emitter.buffer_pos += 1
61 case yaml_CRLN_BREAK:
62 emitter.buffer[emitter.buffer_pos+0] = '\r'
63 emitter.buffer[emitter.buffer_pos+1] = '\n'
64 emitter.buffer_pos += 2
65 default:
66 panic("unknown line break setting")
67 }
68 if emitter.column == 0 {
69 emitter.space_above = true
70 }
71 emitter.column = 0
72 emitter.line++
73 // [Go] Do this here and below and drop from everywhere else (see commented lines).
74 emitter.indention = true
75 return true
76}
77
78// Copy a character from a string into buffer.
79func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
80 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
81 return false
82 }
83 p := emitter.buffer_pos
84 w := width(s[*i])
85 switch w {
86 case 4:
87 emitter.buffer[p+3] = s[*i+3]
88 fallthrough
89 case 3:
90 emitter.buffer[p+2] = s[*i+2]
91 fallthrough
92 case 2:
93 emitter.buffer[p+1] = s[*i+1]
94 fallthrough
95 case 1:
96 emitter.buffer[p+0] = s[*i+0]
97 default:
98 panic("unknown character width")
99 }
100 emitter.column++
101 emitter.buffer_pos += w
102 *i += w
103 return true
104}
105
106// Write a whole string into buffer.
107func write_all(emitter *yaml_emitter_t, s []byte) bool {
108 for i := 0; i < len(s); {
109 if !write(emitter, s, &i) {
110 return false
111 }
112 }
113 return true
114}
115
116// Copy a line break character from a string into buffer.
117func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
118 if s[*i] == '\n' {
119 if !put_break(emitter) {
120 return false
121 }
122 *i++
123 } else {
124 if !write(emitter, s, i) {
125 return false
126 }
127 if emitter.column == 0 {
128 emitter.space_above = true
129 }
130 emitter.column = 0
131 emitter.line++
132 // [Go] Do this here and above and drop from everywhere else (see commented lines).
133 emitter.indention = true
134 }
135 return true
136}
137
138// Set an emitter error and return false.
139func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
140 emitter.error = yaml_EMITTER_ERROR
141 emitter.problem = problem
142 return false
143}
144
145// Emit an event.
146func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
147 emitter.events = append(emitter.events, *event)
148 for !yaml_emitter_need_more_events(emitter) {
149 event := &emitter.events[emitter.events_head]
150 if !yaml_emitter_analyze_event(emitter, event) {
151 return false
152 }
153 if !yaml_emitter_state_machine(emitter, event) {
154 return false
155 }
156 yaml_event_delete(event)
157 emitter.events_head++
158 }
159 return true
160}
161
162// Check if we need to accumulate more events before emitting.
163//
164// We accumulate extra
165// - 1 event for DOCUMENT-START
166// - 2 events for SEQUENCE-START
167// - 3 events for MAPPING-START
168//
169func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
170 if emitter.events_head == len(emitter.events) {
171 return true
172 }
173 var accumulate int
174 switch emitter.events[emitter.events_head].typ {
175 case yaml_DOCUMENT_START_EVENT:
176 accumulate = 1
177 break
178 case yaml_SEQUENCE_START_EVENT:
179 accumulate = 2
180 break
181 case yaml_MAPPING_START_EVENT:
182 accumulate = 3
183 break
184 default:
185 return false
186 }
187 if len(emitter.events)-emitter.events_head > accumulate {
188 return false
189 }
190 var level int
191 for i := emitter.events_head; i < len(emitter.events); i++ {
192 switch emitter.events[i].typ {
193 case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
194 level++
195 case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
196 level--
197 }
198 if level == 0 {
199 return false
200 }
201 }
202 return true
203}
204
205// Append a directive to the directives stack.
206func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
207 for i := 0; i < len(emitter.tag_directives); i++ {
208 if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
209 if allow_duplicates {
210 return true
211 }
212 return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
213 }
214 }
215
216 // [Go] Do we actually need to copy this given garbage collection
217 // and the lack of deallocating destructors?
218 tag_copy := yaml_tag_directive_t{
219 handle: make([]byte, len(value.handle)),
220 prefix: make([]byte, len(value.prefix)),
221 }
222 copy(tag_copy.handle, value.handle)
223 copy(tag_copy.prefix, value.prefix)
224 emitter.tag_directives = append(emitter.tag_directives, tag_copy)
225 return true
226}
227
228// Increase the indentation level.
229func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
230 emitter.indents = append(emitter.indents, emitter.indent)
231 if emitter.indent < 0 {
232 if flow {
233 emitter.indent = emitter.best_indent
234 } else {
235 emitter.indent = 0
236 }
237 } else if !indentless {
238 // [Go] This was changed so that indentations are more regular.
239 if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
240 // The first indent inside a sequence will just skip the "- " indicator.
241 emitter.indent += 2
242 } else {
243 // Everything else aligns to the chosen indentation.
244 emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
245 }
246 }
247 return true
248}
249
250// State dispatcher.
251func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
252 switch emitter.state {
253 default:
254 case yaml_EMIT_STREAM_START_STATE:
255 return yaml_emitter_emit_stream_start(emitter, event)
256
257 case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
258 return yaml_emitter_emit_document_start(emitter, event, true)
259
260 case yaml_EMIT_DOCUMENT_START_STATE:
261 return yaml_emitter_emit_document_start(emitter, event, false)
262
263 case yaml_EMIT_DOCUMENT_CONTENT_STATE:
264 return yaml_emitter_emit_document_content(emitter, event)
265
266 case yaml_EMIT_DOCUMENT_END_STATE:
267 return yaml_emitter_emit_document_end(emitter, event)
268
269 case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
270 return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
271
272 case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
273 return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
274
275 case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
276 return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
277
278 case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
279 return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
280
281 case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
282 return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
283
284 case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
285 return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
286
287 case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
288 return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
289
290 case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
291 return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
292
293 case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
294 return yaml_emitter_emit_block_sequence_item(emitter, event, true)
295
296 case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
297 return yaml_emitter_emit_block_sequence_item(emitter, event, false)
298
299 case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
300 return yaml_emitter_emit_block_mapping_key(emitter, event, true)
301
302 case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
303 return yaml_emitter_emit_block_mapping_key(emitter, event, false)
304
305 case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
306 return yaml_emitter_emit_block_mapping_value(emitter, event, true)
307
308 case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
309 return yaml_emitter_emit_block_mapping_value(emitter, event, false)
310
311 case yaml_EMIT_END_STATE:
312 return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
313 }
314 panic("invalid emitter state")
315}
316
317// Expect STREAM-START.
318func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
319 if event.typ != yaml_STREAM_START_EVENT {
320 return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
321 }
322 if emitter.encoding == yaml_ANY_ENCODING {
323 emitter.encoding = event.encoding
324 if emitter.encoding == yaml_ANY_ENCODING {
325 emitter.encoding = yaml_UTF8_ENCODING
326 }
327 }
328 if emitter.best_indent < 2 || emitter.best_indent > 9 {
329 emitter.best_indent = 2
330 }
331 if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
332 emitter.best_width = 80
333 }
334 if emitter.best_width < 0 {
335 emitter.best_width = 1<<31 - 1
336 }
337 if emitter.line_break == yaml_ANY_BREAK {
338 emitter.line_break = yaml_LN_BREAK
339 }
340
341 emitter.indent = -1
342 emitter.line = 0
343 emitter.column = 0
344 emitter.whitespace = true
345 emitter.indention = true
346 emitter.space_above = true
347 emitter.foot_indent = -1
348
349 if emitter.encoding != yaml_UTF8_ENCODING {
350 if !yaml_emitter_write_bom(emitter) {
351 return false
352 }
353 }
354 emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
355 return true
356}
357
358// Expect DOCUMENT-START or STREAM-END.
359func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
360
361 if event.typ == yaml_DOCUMENT_START_EVENT {
362
363 if event.version_directive != nil {
364 if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
365 return false
366 }
367 }
368
369 for i := 0; i < len(event.tag_directives); i++ {
370 tag_directive := &event.tag_directives[i]
371 if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
372 return false
373 }
374 if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
375 return false
376 }
377 }
378
379 for i := 0; i < len(default_tag_directives); i++ {
380 tag_directive := &default_tag_directives[i]
381 if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
382 return false
383 }
384 }
385
386 implicit := event.implicit
387 if !first || emitter.canonical {
388 implicit = false
389 }
390
391 if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
392 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
393 return false
394 }
395 if !yaml_emitter_write_indent(emitter) {
396 return false
397 }
398 }
399
400 if event.version_directive != nil {
401 implicit = false
402 if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
403 return false
404 }
405 if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
406 return false
407 }
408 if !yaml_emitter_write_indent(emitter) {
409 return false
410 }
411 }
412
413 if len(event.tag_directives) > 0 {
414 implicit = false
415 for i := 0; i < len(event.tag_directives); i++ {
416 tag_directive := &event.tag_directives[i]
417 if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
418 return false
419 }
420 if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
421 return false
422 }
423 if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
424 return false
425 }
426 if !yaml_emitter_write_indent(emitter) {
427 return false
428 }
429 }
430 }
431
432 if yaml_emitter_check_empty_document(emitter) {
433 implicit = false
434 }
435 if !implicit {
436 if !yaml_emitter_write_indent(emitter) {
437 return false
438 }
439 if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
440 return false
441 }
442 if emitter.canonical || true {
443 if !yaml_emitter_write_indent(emitter) {
444 return false
445 }
446 }
447 }
448
449 if len(emitter.head_comment) > 0 {
450 if !yaml_emitter_process_head_comment(emitter) {
451 return false
452 }
453 if !put_break(emitter) {
454 return false
455 }
456 }
457
458 emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
459 return true
460 }
461
462 if event.typ == yaml_STREAM_END_EVENT {
463 if emitter.open_ended {
464 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
465 return false
466 }
467 if !yaml_emitter_write_indent(emitter) {
468 return false
469 }
470 }
471 if !yaml_emitter_flush(emitter) {
472 return false
473 }
474 emitter.state = yaml_EMIT_END_STATE
475 return true
476 }
477
478 return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
479}
480
481// Expect the root node.
482func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
483 emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
484
485 if !yaml_emitter_process_head_comment(emitter) {
486 return false
487 }
488 if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
489 return false
490 }
491 if !yaml_emitter_process_line_comment(emitter) {
492 return false
493 }
494 if !yaml_emitter_process_foot_comment(emitter) {
495 return false
496 }
497 return true
498}
499
500// Expect DOCUMENT-END.
501func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
502 if event.typ != yaml_DOCUMENT_END_EVENT {
503 return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
504 }
505 // [Go] Force document foot separation.
506 emitter.foot_indent = 0
507 if !yaml_emitter_process_foot_comment(emitter) {
508 return false
509 }
510 emitter.foot_indent = -1
511 if !yaml_emitter_write_indent(emitter) {
512 return false
513 }
514 if !event.implicit {
515 // [Go] Allocate the slice elsewhere.
516 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
517 return false
518 }
519 if !yaml_emitter_write_indent(emitter) {
520 return false
521 }
522 }
523 if !yaml_emitter_flush(emitter) {
524 return false
525 }
526 emitter.state = yaml_EMIT_DOCUMENT_START_STATE
527 emitter.tag_directives = emitter.tag_directives[:0]
528 return true
529}
530
531// Expect a flow item node.
532func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
533 if first {
534 if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
535 return false
536 }
537 if !yaml_emitter_increase_indent(emitter, true, false) {
538 return false
539 }
540 emitter.flow_level++
541 }
542
543 if event.typ == yaml_SEQUENCE_END_EVENT {
544 if emitter.canonical && !first && !trail {
545 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
546 return false
547 }
548 }
549 emitter.flow_level--
550 emitter.indent = emitter.indents[len(emitter.indents)-1]
551 emitter.indents = emitter.indents[:len(emitter.indents)-1]
552 if emitter.column == 0 || emitter.canonical && !first {
553 if !yaml_emitter_write_indent(emitter) {
554 return false
555 }
556 }
557 if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
558 return false
559 }
560 if !yaml_emitter_process_line_comment(emitter) {
561 return false
562 }
563 if !yaml_emitter_process_foot_comment(emitter) {
564 return false
565 }
566 emitter.state = emitter.states[len(emitter.states)-1]
567 emitter.states = emitter.states[:len(emitter.states)-1]
568
569 return true
570 }
571
572 if !first && !trail {
573 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
574 return false
575 }
576 }
577
578 if !yaml_emitter_process_head_comment(emitter) {
579 return false
580 }
581 if emitter.column == 0 {
582 if !yaml_emitter_write_indent(emitter) {
583 return false
584 }
585 }
586
587 if emitter.canonical || emitter.column > emitter.best_width {
588 if !yaml_emitter_write_indent(emitter) {
589 return false
590 }
591 }
592 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
593 emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
594 } else {
595 emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
596 }
597 if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
598 return false
599 }
600 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
601 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
602 return false
603 }
604 }
605 if !yaml_emitter_process_line_comment(emitter) {
606 return false
607 }
608 if !yaml_emitter_process_foot_comment(emitter) {
609 return false
610 }
611 return true
612}
613
614// Expect a flow key node.
615func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
616 if first {
617 if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
618 return false
619 }
620 if !yaml_emitter_increase_indent(emitter, true, false) {
621 return false
622 }
623 emitter.flow_level++
624 }
625
626 if event.typ == yaml_MAPPING_END_EVENT {
627 if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
628 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
629 return false
630 }
631 }
632 if !yaml_emitter_process_head_comment(emitter) {
633 return false
634 }
635 emitter.flow_level--
636 emitter.indent = emitter.indents[len(emitter.indents)-1]
637 emitter.indents = emitter.indents[:len(emitter.indents)-1]
638 if emitter.canonical && !first {
639 if !yaml_emitter_write_indent(emitter) {
640 return false
641 }
642 }
643 if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
644 return false
645 }
646 if !yaml_emitter_process_line_comment(emitter) {
647 return false
648 }
649 if !yaml_emitter_process_foot_comment(emitter) {
650 return false
651 }
652 emitter.state = emitter.states[len(emitter.states)-1]
653 emitter.states = emitter.states[:len(emitter.states)-1]
654 return true
655 }
656
657 if !first && !trail {
658 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
659 return false
660 }
661 }
662
663 if !yaml_emitter_process_head_comment(emitter) {
664 return false
665 }
666
667 if emitter.column == 0 {
668 if !yaml_emitter_write_indent(emitter) {
669 return false
670 }
671 }
672
673 if emitter.canonical || emitter.column > emitter.best_width {
674 if !yaml_emitter_write_indent(emitter) {
675 return false
676 }
677 }
678
679 if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
680 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
681 return yaml_emitter_emit_node(emitter, event, false, false, true, true)
682 }
683 if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
684 return false
685 }
686 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
687 return yaml_emitter_emit_node(emitter, event, false, false, true, false)
688}
689
690// Expect a flow value node.
691func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
692 if simple {
693 if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
694 return false
695 }
696 } else {
697 if emitter.canonical || emitter.column > emitter.best_width {
698 if !yaml_emitter_write_indent(emitter) {
699 return false
700 }
701 }
702 if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
703 return false
704 }
705 }
706 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
707 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
708 } else {
709 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
710 }
711 if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
712 return false
713 }
714 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
715 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
716 return false
717 }
718 }
719 if !yaml_emitter_process_line_comment(emitter) {
720 return false
721 }
722 if !yaml_emitter_process_foot_comment(emitter) {
723 return false
724 }
725 return true
726}
727
728// Expect a block item node.
729func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
730 if first {
731 if !yaml_emitter_increase_indent(emitter, false, false) {
732 return false
733 }
734 }
735 if event.typ == yaml_SEQUENCE_END_EVENT {
736 emitter.indent = emitter.indents[len(emitter.indents)-1]
737 emitter.indents = emitter.indents[:len(emitter.indents)-1]
738 emitter.state = emitter.states[len(emitter.states)-1]
739 emitter.states = emitter.states[:len(emitter.states)-1]
740 return true
741 }
742 if !yaml_emitter_process_head_comment(emitter) {
743 return false
744 }
745 if !yaml_emitter_write_indent(emitter) {
746 return false
747 }
748 if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
749 return false
750 }
751 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
752 if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
753 return false
754 }
755 if !yaml_emitter_process_line_comment(emitter) {
756 return false
757 }
758 if !yaml_emitter_process_foot_comment(emitter) {
759 return false
760 }
761 return true
762}
763
764// Expect a block key node.
765func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
766 if first {
767 if !yaml_emitter_increase_indent(emitter, false, false) {
768 return false
769 }
770 }
771 if !yaml_emitter_process_head_comment(emitter) {
772 return false
773 }
774 if event.typ == yaml_MAPPING_END_EVENT {
775 emitter.indent = emitter.indents[len(emitter.indents)-1]
776 emitter.indents = emitter.indents[:len(emitter.indents)-1]
777 emitter.state = emitter.states[len(emitter.states)-1]
778 emitter.states = emitter.states[:len(emitter.states)-1]
779 return true
780 }
781 if !yaml_emitter_write_indent(emitter) {
782 return false
783 }
784 if len(emitter.line_comment) > 0 {
785 // [Go] A line comment was provided for the key. That's unusual as the
786 // scanner associates line comments with the value. Either way,
787 // save the line comment and render it appropriately later.
788 emitter.key_line_comment = emitter.line_comment
789 emitter.line_comment = nil
790 }
791 if yaml_emitter_check_simple_key(emitter) {
792 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
793 return yaml_emitter_emit_node(emitter, event, false, false, true, true)
794 }
795 if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
796 return false
797 }
798 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
799 return yaml_emitter_emit_node(emitter, event, false, false, true, false)
800}
801
802// Expect a block value node.
803func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
804 if simple {
805 if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
806 return false
807 }
808 } else {
809 if !yaml_emitter_write_indent(emitter) {
810 return false
811 }
812 if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
813 return false
814 }
815 }
816 if len(emitter.key_line_comment) > 0 {
817 // [Go] Line comments are generally associated with the value, but when there's
818 // no value on the same line as a mapping key they end up attached to the
819 // key itself.
820 if event.typ == yaml_SCALAR_EVENT {
821 if len(emitter.line_comment) == 0 {
822 // A scalar is coming and it has no line comments by itself yet,
823 // so just let it handle the line comment as usual. If it has a
824 // line comment, we can't have both so the one from the key is lost.
825 emitter.line_comment = emitter.key_line_comment
826 emitter.key_line_comment = nil
827 }
828 } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
829 // An indented block follows, so write the comment right now.
830 emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
831 if !yaml_emitter_process_line_comment(emitter) {
832 return false
833 }
834 emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
835 }
836 }
837 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
838 if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
839 return false
840 }
841 if !yaml_emitter_process_line_comment(emitter) {
842 return false
843 }
844 if !yaml_emitter_process_foot_comment(emitter) {
845 return false
846 }
847 return true
848}
849
850func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
851 return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
852}
853
854// Expect a node.
855func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
856 root bool, sequence bool, mapping bool, simple_key bool) bool {
857
858 emitter.root_context = root
859 emitter.sequence_context = sequence
860 emitter.mapping_context = mapping
861 emitter.simple_key_context = simple_key
862
863 switch event.typ {
864 case yaml_ALIAS_EVENT:
865 return yaml_emitter_emit_alias(emitter, event)
866 case yaml_SCALAR_EVENT:
867 return yaml_emitter_emit_scalar(emitter, event)
868 case yaml_SEQUENCE_START_EVENT:
869 return yaml_emitter_emit_sequence_start(emitter, event)
870 case yaml_MAPPING_START_EVENT:
871 return yaml_emitter_emit_mapping_start(emitter, event)
872 default:
873 return yaml_emitter_set_emitter_error(emitter,
874 fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
875 }
876}
877
878// Expect ALIAS.
879func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
880 if !yaml_emitter_process_anchor(emitter) {
881 return false
882 }
883 emitter.state = emitter.states[len(emitter.states)-1]
884 emitter.states = emitter.states[:len(emitter.states)-1]
885 return true
886}
887
888// Expect SCALAR.
889func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
890 if !yaml_emitter_select_scalar_style(emitter, event) {
891 return false
892 }
893 if !yaml_emitter_process_anchor(emitter) {
894 return false
895 }
896 if !yaml_emitter_process_tag(emitter) {
897 return false
898 }
899 if !yaml_emitter_increase_indent(emitter, true, false) {
900 return false
901 }
902 if !yaml_emitter_process_scalar(emitter) {
903 return false
904 }
905 emitter.indent = emitter.indents[len(emitter.indents)-1]
906 emitter.indents = emitter.indents[:len(emitter.indents)-1]
907 emitter.state = emitter.states[len(emitter.states)-1]
908 emitter.states = emitter.states[:len(emitter.states)-1]
909 return true
910}
911
912// Expect SEQUENCE-START.
913func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
914 if !yaml_emitter_process_anchor(emitter) {
915 return false
916 }
917 if !yaml_emitter_process_tag(emitter) {
918 return false
919 }
920 if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
921 yaml_emitter_check_empty_sequence(emitter) {
922 emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
923 } else {
924 emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
925 }
926 return true
927}
928
929// Expect MAPPING-START.
930func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
931 if !yaml_emitter_process_anchor(emitter) {
932 return false
933 }
934 if !yaml_emitter_process_tag(emitter) {
935 return false
936 }
937 if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
938 yaml_emitter_check_empty_mapping(emitter) {
939 emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
940 } else {
941 emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
942 }
943 return true
944}
945
946// Check if the document content is an empty scalar.
947func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
948 return false // [Go] Huh?
949}
950
951// Check if the next events represent an empty sequence.
952func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
953 if len(emitter.events)-emitter.events_head < 2 {
954 return false
955 }
956 return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
957 emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
958}
959
960// Check if the next events represent an empty mapping.
961func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
962 if len(emitter.events)-emitter.events_head < 2 {
963 return false
964 }
965 return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
966 emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
967}
968
969// Check if the next node can be expressed as a simple key.
970func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
971 length := 0
972 switch emitter.events[emitter.events_head].typ {
973 case yaml_ALIAS_EVENT:
974 length += len(emitter.anchor_data.anchor)
975 case yaml_SCALAR_EVENT:
976 if emitter.scalar_data.multiline {
977 return false
978 }
979 length += len(emitter.anchor_data.anchor) +
980 len(emitter.tag_data.handle) +
981 len(emitter.tag_data.suffix) +
982 len(emitter.scalar_data.value)
983 case yaml_SEQUENCE_START_EVENT:
984 if !yaml_emitter_check_empty_sequence(emitter) {
985 return false
986 }
987 length += len(emitter.anchor_data.anchor) +
988 len(emitter.tag_data.handle) +
989 len(emitter.tag_data.suffix)
990 case yaml_MAPPING_START_EVENT:
991 if !yaml_emitter_check_empty_mapping(emitter) {
992 return false
993 }
994 length += len(emitter.anchor_data.anchor) +
995 len(emitter.tag_data.handle) +
996 len(emitter.tag_data.suffix)
997 default:
998 return false
999 }
1000 return length <= 128
1001}
1002
1003// Determine an acceptable scalar style.
1004func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
1005
1006 no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
1007 if no_tag && !event.implicit && !event.quoted_implicit {
1008 return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
1009 }
1010
1011 style := event.scalar_style()
1012 if style == yaml_ANY_SCALAR_STYLE {
1013 style = yaml_PLAIN_SCALAR_STYLE
1014 }
1015 if emitter.canonical {
1016 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1017 }
1018 if emitter.simple_key_context && emitter.scalar_data.multiline {
1019 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1020 }
1021
1022 if style == yaml_PLAIN_SCALAR_STYLE {
1023 if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
1024 emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
1025 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1026 }
1027 if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
1028 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1029 }
1030 if no_tag && !event.implicit {
1031 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1032 }
1033 }
1034 if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
1035 if !emitter.scalar_data.single_quoted_allowed {
1036 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1037 }
1038 }
1039 if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
1040 if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
1041 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1042 }
1043 }
1044
1045 if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
1046 emitter.tag_data.handle = []byte{'!'}
1047 }
1048 emitter.scalar_data.style = style
1049 return true
1050}
1051
1052// Write an anchor.
1053func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
1054 if emitter.anchor_data.anchor == nil {
1055 return true
1056 }
1057 c := []byte{'&'}
1058 if emitter.anchor_data.alias {
1059 c[0] = '*'
1060 }
1061 if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
1062 return false
1063 }
1064 return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
1065}
1066
1067// Write a tag.
1068func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
1069 if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
1070 return true
1071 }
1072 if len(emitter.tag_data.handle) > 0 {
1073 if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
1074 return false
1075 }
1076 if len(emitter.tag_data.suffix) > 0 {
1077 if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
1078 return false
1079 }
1080 }
1081 } else {
1082 // [Go] Allocate these slices elsewhere.
1083 if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
1084 return false
1085 }
1086 if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
1087 return false
1088 }
1089 if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
1090 return false
1091 }
1092 }
1093 return true
1094}
1095
1096// Write a scalar.
1097func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
1098 switch emitter.scalar_data.style {
1099 case yaml_PLAIN_SCALAR_STYLE:
1100 return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1101
1102 case yaml_SINGLE_QUOTED_SCALAR_STYLE:
1103 return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1104
1105 case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
1106 return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1107
1108 case yaml_LITERAL_SCALAR_STYLE:
1109 return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
1110
1111 case yaml_FOLDED_SCALAR_STYLE:
1112 return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
1113 }
1114 panic("unknown scalar style")
1115}
1116
1117// Write a head comment.
1118func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
1119 if len(emitter.tail_comment) > 0 {
1120 if !yaml_emitter_write_indent(emitter) {
1121 return false
1122 }
1123 if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
1124 return false
1125 }
1126 emitter.tail_comment = emitter.tail_comment[:0]
1127 emitter.foot_indent = emitter.indent
1128 if emitter.foot_indent < 0 {
1129 emitter.foot_indent = 0
1130 }
1131 }
1132
1133 if len(emitter.head_comment) == 0 {
1134 return true
1135 }
1136 if !yaml_emitter_write_indent(emitter) {
1137 return false
1138 }
1139 if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
1140 return false
1141 }
1142 emitter.head_comment = emitter.head_comment[:0]
1143 return true
1144}
1145
1146// Write an line comment.
1147func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
1148 if len(emitter.line_comment) == 0 {
1149 return true
1150 }
1151 if !emitter.whitespace {
1152 if !put(emitter, ' ') {
1153 return false
1154 }
1155 }
1156 if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
1157 return false
1158 }
1159 emitter.line_comment = emitter.line_comment[:0]
1160 return true
1161}
1162
1163// Write a foot comment.
1164func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
1165 if len(emitter.foot_comment) == 0 {
1166 return true
1167 }
1168 if !yaml_emitter_write_indent(emitter) {
1169 return false
1170 }
1171 if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
1172 return false
1173 }
1174 emitter.foot_comment = emitter.foot_comment[:0]
1175 emitter.foot_indent = emitter.indent
1176 if emitter.foot_indent < 0 {
1177 emitter.foot_indent = 0
1178 }
1179 return true
1180}
1181
1182// Check if a %YAML directive is valid.
1183func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
1184 if version_directive.major != 1 || version_directive.minor != 1 {
1185 return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
1186 }
1187 return true
1188}
1189
1190// Check if a %TAG directive is valid.
1191func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
1192 handle := tag_directive.handle
1193 prefix := tag_directive.prefix
1194 if len(handle) == 0 {
1195 return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
1196 }
1197 if handle[0] != '!' {
1198 return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
1199 }
1200 if handle[len(handle)-1] != '!' {
1201 return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
1202 }
1203 for i := 1; i < len(handle)-1; i += width(handle[i]) {
1204 if !is_alpha(handle, i) {
1205 return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
1206 }
1207 }
1208 if len(prefix) == 0 {
1209 return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
1210 }
1211 return true
1212}
1213
1214// Check if an anchor is valid.
1215func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
1216 if len(anchor) == 0 {
1217 problem := "anchor value must not be empty"
1218 if alias {
1219 problem = "alias value must not be empty"
1220 }
1221 return yaml_emitter_set_emitter_error(emitter, problem)
1222 }
1223 for i := 0; i < len(anchor); i += width(anchor[i]) {
1224 if !is_alpha(anchor, i) {
1225 problem := "anchor value must contain alphanumerical characters only"
1226 if alias {
1227 problem = "alias value must contain alphanumerical characters only"
1228 }
1229 return yaml_emitter_set_emitter_error(emitter, problem)
1230 }
1231 }
1232 emitter.anchor_data.anchor = anchor
1233 emitter.anchor_data.alias = alias
1234 return true
1235}
1236
1237// Check if a tag is valid.
1238func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
1239 if len(tag) == 0 {
1240 return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
1241 }
1242 for i := 0; i < len(emitter.tag_directives); i++ {
1243 tag_directive := &emitter.tag_directives[i]
1244 if bytes.HasPrefix(tag, tag_directive.prefix) {
1245 emitter.tag_data.handle = tag_directive.handle
1246 emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
1247 return true
1248 }
1249 }
1250 emitter.tag_data.suffix = tag
1251 return true
1252}
1253
1254// Check if a scalar is valid.
1255func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
1256 var (
1257 block_indicators = false
1258 flow_indicators = false
1259 line_breaks = false
1260 special_characters = false
1261 tab_characters = false
1262
1263 leading_space = false
1264 leading_break = false
1265 trailing_space = false
1266 trailing_break = false
1267 break_space = false
1268 space_break = false
1269
1270 preceded_by_whitespace = false
1271 followed_by_whitespace = false
1272 previous_space = false
1273 previous_break = false
1274 )
1275
1276 emitter.scalar_data.value = value
1277
1278 if len(value) == 0 {
1279 emitter.scalar_data.multiline = false
1280 emitter.scalar_data.flow_plain_allowed = false
1281 emitter.scalar_data.block_plain_allowed = true
1282 emitter.scalar_data.single_quoted_allowed = true
1283 emitter.scalar_data.block_allowed = false
1284 return true
1285 }
1286
1287 if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
1288 block_indicators = true
1289 flow_indicators = true
1290 }
1291
1292 preceded_by_whitespace = true
1293 for i, w := 0, 0; i < len(value); i += w {
1294 w = width(value[i])
1295 followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
1296
1297 if i == 0 {
1298 switch value[i] {
1299 case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
1300 flow_indicators = true
1301 block_indicators = true
1302 case '?', ':':
1303 flow_indicators = true
1304 if followed_by_whitespace {
1305 block_indicators = true
1306 }
1307 case '-':
1308 if followed_by_whitespace {
1309 flow_indicators = true
1310 block_indicators = true
1311 }
1312 }
1313 } else {
1314 switch value[i] {
1315 case ',', '?', '[', ']', '{', '}':
1316 flow_indicators = true
1317 case ':':
1318 flow_indicators = true
1319 if followed_by_whitespace {
1320 block_indicators = true
1321 }
1322 case '#':
1323 if preceded_by_whitespace {
1324 flow_indicators = true
1325 block_indicators = true
1326 }
1327 }
1328 }
1329
1330 if value[i] == '\t' {
1331 tab_characters = true
1332 } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
1333 special_characters = true
1334 }
1335 if is_space(value, i) {
1336 if i == 0 {
1337 leading_space = true
1338 }
1339 if i+width(value[i]) == len(value) {
1340 trailing_space = true
1341 }
1342 if previous_break {
1343 break_space = true
1344 }
1345 previous_space = true
1346 previous_break = false
1347 } else if is_break(value, i) {
1348 line_breaks = true
1349 if i == 0 {
1350 leading_break = true
1351 }
1352 if i+width(value[i]) == len(value) {
1353 trailing_break = true
1354 }
1355 if previous_space {
1356 space_break = true
1357 }
1358 previous_space = false
1359 previous_break = true
1360 } else {
1361 previous_space = false
1362 previous_break = false
1363 }
1364
1365 // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
1366 preceded_by_whitespace = is_blankz(value, i)
1367 }
1368
1369 emitter.scalar_data.multiline = line_breaks
1370 emitter.scalar_data.flow_plain_allowed = true
1371 emitter.scalar_data.block_plain_allowed = true
1372 emitter.scalar_data.single_quoted_allowed = true
1373 emitter.scalar_data.block_allowed = true
1374
1375 if leading_space || leading_break || trailing_space || trailing_break {
1376 emitter.scalar_data.flow_plain_allowed = false
1377 emitter.scalar_data.block_plain_allowed = false
1378 }
1379 if trailing_space {
1380 emitter.scalar_data.block_allowed = false
1381 }
1382 if break_space {
1383 emitter.scalar_data.flow_plain_allowed = false
1384 emitter.scalar_data.block_plain_allowed = false
1385 emitter.scalar_data.single_quoted_allowed = false
1386 }
1387 if space_break || tab_characters || special_characters {
1388 emitter.scalar_data.flow_plain_allowed = false
1389 emitter.scalar_data.block_plain_allowed = false
1390 emitter.scalar_data.single_quoted_allowed = false
1391 }
1392 if space_break || special_characters {
1393 emitter.scalar_data.block_allowed = false
1394 }
1395 if line_breaks {
1396 emitter.scalar_data.flow_plain_allowed = false
1397 emitter.scalar_data.block_plain_allowed = false
1398 }
1399 if flow_indicators {
1400 emitter.scalar_data.flow_plain_allowed = false
1401 }
1402 if block_indicators {
1403 emitter.scalar_data.block_plain_allowed = false
1404 }
1405 return true
1406}
1407
1408// Check if the event data is valid.
1409func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
1410
1411 emitter.anchor_data.anchor = nil
1412 emitter.tag_data.handle = nil
1413 emitter.tag_data.suffix = nil
1414 emitter.scalar_data.value = nil
1415
1416 if len(event.head_comment) > 0 {
1417 emitter.head_comment = event.head_comment
1418 }
1419 if len(event.line_comment) > 0 {
1420 emitter.line_comment = event.line_comment
1421 }
1422 if len(event.foot_comment) > 0 {
1423 emitter.foot_comment = event.foot_comment
1424 }
1425 if len(event.tail_comment) > 0 {
1426 emitter.tail_comment = event.tail_comment
1427 }
1428
1429 switch event.typ {
1430 case yaml_ALIAS_EVENT:
1431 if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
1432 return false
1433 }
1434
1435 case yaml_SCALAR_EVENT:
1436 if len(event.anchor) > 0 {
1437 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1438 return false
1439 }
1440 }
1441 if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
1442 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1443 return false
1444 }
1445 }
1446 if !yaml_emitter_analyze_scalar(emitter, event.value) {
1447 return false
1448 }
1449
1450 case yaml_SEQUENCE_START_EVENT:
1451 if len(event.anchor) > 0 {
1452 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1453 return false
1454 }
1455 }
1456 if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
1457 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1458 return false
1459 }
1460 }
1461
1462 case yaml_MAPPING_START_EVENT:
1463 if len(event.anchor) > 0 {
1464 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1465 return false
1466 }
1467 }
1468 if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
1469 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1470 return false
1471 }
1472 }
1473 }
1474 return true
1475}
1476
1477// Write the BOM character.
1478func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
1479 if !flush(emitter) {
1480 return false
1481 }
1482 pos := emitter.buffer_pos
1483 emitter.buffer[pos+0] = '\xEF'
1484 emitter.buffer[pos+1] = '\xBB'
1485 emitter.buffer[pos+2] = '\xBF'
1486 emitter.buffer_pos += 3
1487 return true
1488}
1489
1490func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
1491 indent := emitter.indent
1492 if indent < 0 {
1493 indent = 0
1494 }
1495 if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
1496 if !put_break(emitter) {
1497 return false
1498 }
1499 }
1500 if emitter.foot_indent == indent {
1501 if !put_break(emitter) {
1502 return false
1503 }
1504 }
1505 for emitter.column < indent {
1506 if !put(emitter, ' ') {
1507 return false
1508 }
1509 }
1510 emitter.whitespace = true
1511 //emitter.indention = true
1512 emitter.space_above = false
1513 emitter.foot_indent = -1
1514 return true
1515}
1516
1517func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
1518 if need_whitespace && !emitter.whitespace {
1519 if !put(emitter, ' ') {
1520 return false
1521 }
1522 }
1523 if !write_all(emitter, indicator) {
1524 return false
1525 }
1526 emitter.whitespace = is_whitespace
1527 emitter.indention = (emitter.indention && is_indention)
1528 emitter.open_ended = false
1529 return true
1530}
1531
1532func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
1533 if !write_all(emitter, value) {
1534 return false
1535 }
1536 emitter.whitespace = false
1537 emitter.indention = false
1538 return true
1539}
1540
1541func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
1542 if !emitter.whitespace {
1543 if !put(emitter, ' ') {
1544 return false
1545 }
1546 }
1547 if !write_all(emitter, value) {
1548 return false
1549 }
1550 emitter.whitespace = false
1551 emitter.indention = false
1552 return true
1553}
1554
1555func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
1556 if need_whitespace && !emitter.whitespace {
1557 if !put(emitter, ' ') {
1558 return false
1559 }
1560 }
1561 for i := 0; i < len(value); {
1562 var must_write bool
1563 switch value[i] {
1564 case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
1565 must_write = true
1566 default:
1567 must_write = is_alpha(value, i)
1568 }
1569 if must_write {
1570 if !write(emitter, value, &i) {
1571 return false
1572 }
1573 } else {
1574 w := width(value[i])
1575 for k := 0; k < w; k++ {
1576 octet := value[i]
1577 i++
1578 if !put(emitter, '%') {
1579 return false
1580 }
1581
1582 c := octet >> 4
1583 if c < 10 {
1584 c += '0'
1585 } else {
1586 c += 'A' - 10
1587 }
1588 if !put(emitter, c) {
1589 return false
1590 }
1591
1592 c = octet & 0x0f
1593 if c < 10 {
1594 c += '0'
1595 } else {
1596 c += 'A' - 10
1597 }
1598 if !put(emitter, c) {
1599 return false
1600 }
1601 }
1602 }
1603 }
1604 emitter.whitespace = false
1605 emitter.indention = false
1606 return true
1607}
1608
1609func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1610 if len(value) > 0 && !emitter.whitespace {
1611 if !put(emitter, ' ') {
1612 return false
1613 }
1614 }
1615
1616 spaces := false
1617 breaks := false
1618 for i := 0; i < len(value); {
1619 if is_space(value, i) {
1620 if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
1621 if !yaml_emitter_write_indent(emitter) {
1622 return false
1623 }
1624 i += width(value[i])
1625 } else {
1626 if !write(emitter, value, &i) {
1627 return false
1628 }
1629 }
1630 spaces = true
1631 } else if is_break(value, i) {
1632 if !breaks && value[i] == '\n' {
1633 if !put_break(emitter) {
1634 return false
1635 }
1636 }
1637 if !write_break(emitter, value, &i) {
1638 return false
1639 }
1640 //emitter.indention = true
1641 breaks = true
1642 } else {
1643 if breaks {
1644 if !yaml_emitter_write_indent(emitter) {
1645 return false
1646 }
1647 }
1648 if !write(emitter, value, &i) {
1649 return false
1650 }
1651 emitter.indention = false
1652 spaces = false
1653 breaks = false
1654 }
1655 }
1656
1657 if len(value) > 0 {
1658 emitter.whitespace = false
1659 }
1660 emitter.indention = false
1661 if emitter.root_context {
1662 emitter.open_ended = true
1663 }
1664
1665 return true
1666}
1667
1668func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1669
1670 if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
1671 return false
1672 }
1673
1674 spaces := false
1675 breaks := false
1676 for i := 0; i < len(value); {
1677 if is_space(value, i) {
1678 if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
1679 if !yaml_emitter_write_indent(emitter) {
1680 return false
1681 }
1682 i += width(value[i])
1683 } else {
1684 if !write(emitter, value, &i) {
1685 return false
1686 }
1687 }
1688 spaces = true
1689 } else if is_break(value, i) {
1690 if !breaks && value[i] == '\n' {
1691 if !put_break(emitter) {
1692 return false
1693 }
1694 }
1695 if !write_break(emitter, value, &i) {
1696 return false
1697 }
1698 //emitter.indention = true
1699 breaks = true
1700 } else {
1701 if breaks {
1702 if !yaml_emitter_write_indent(emitter) {
1703 return false
1704 }
1705 }
1706 if value[i] == '\'' {
1707 if !put(emitter, '\'') {
1708 return false
1709 }
1710 }
1711 if !write(emitter, value, &i) {
1712 return false
1713 }
1714 emitter.indention = false
1715 spaces = false
1716 breaks = false
1717 }
1718 }
1719 if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
1720 return false
1721 }
1722 emitter.whitespace = false
1723 emitter.indention = false
1724 return true
1725}
1726
1727func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1728 spaces := false
1729 if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
1730 return false
1731 }
1732
1733 for i := 0; i < len(value); {
1734 if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
1735 is_bom(value, i) || is_break(value, i) ||
1736 value[i] == '"' || value[i] == '\\' {
1737
1738 octet := value[i]
1739
1740 var w int
1741 var v rune
1742 switch {
1743 case octet&0x80 == 0x00:
1744 w, v = 1, rune(octet&0x7F)
1745 case octet&0xE0 == 0xC0:
1746 w, v = 2, rune(octet&0x1F)
1747 case octet&0xF0 == 0xE0:
1748 w, v = 3, rune(octet&0x0F)
1749 case octet&0xF8 == 0xF0:
1750 w, v = 4, rune(octet&0x07)
1751 }
1752 for k := 1; k < w; k++ {
1753 octet = value[i+k]
1754 v = (v << 6) + (rune(octet) & 0x3F)
1755 }
1756 i += w
1757
1758 if !put(emitter, '\\') {
1759 return false
1760 }
1761
1762 var ok bool
1763 switch v {
1764 case 0x00:
1765 ok = put(emitter, '0')
1766 case 0x07:
1767 ok = put(emitter, 'a')
1768 case 0x08:
1769 ok = put(emitter, 'b')
1770 case 0x09:
1771 ok = put(emitter, 't')
1772 case 0x0A:
1773 ok = put(emitter, 'n')
1774 case 0x0b:
1775 ok = put(emitter, 'v')
1776 case 0x0c:
1777 ok = put(emitter, 'f')
1778 case 0x0d:
1779 ok = put(emitter, 'r')
1780 case 0x1b:
1781 ok = put(emitter, 'e')
1782 case 0x22:
1783 ok = put(emitter, '"')
1784 case 0x5c:
1785 ok = put(emitter, '\\')
1786 case 0x85:
1787 ok = put(emitter, 'N')
1788 case 0xA0:
1789 ok = put(emitter, '_')
1790 case 0x2028:
1791 ok = put(emitter, 'L')
1792 case 0x2029:
1793 ok = put(emitter, 'P')
1794 default:
1795 if v <= 0xFF {
1796 ok = put(emitter, 'x')
1797 w = 2
1798 } else if v <= 0xFFFF {
1799 ok = put(emitter, 'u')
1800 w = 4
1801 } else {
1802 ok = put(emitter, 'U')
1803 w = 8
1804 }
1805 for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
1806 digit := byte((v >> uint(k)) & 0x0F)
1807 if digit < 10 {
1808 ok = put(emitter, digit+'0')
1809 } else {
1810 ok = put(emitter, digit+'A'-10)
1811 }
1812 }
1813 }
1814 if !ok {
1815 return false
1816 }
1817 spaces = false
1818 } else if is_space(value, i) {
1819 if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
1820 if !yaml_emitter_write_indent(emitter) {
1821 return false
1822 }
1823 if is_space(value, i+1) {
1824 if !put(emitter, '\\') {
1825 return false
1826 }
1827 }
1828 i += width(value[i])
1829 } else if !write(emitter, value, &i) {
1830 return false
1831 }
1832 spaces = true
1833 } else {
1834 if !write(emitter, value, &i) {
1835 return false
1836 }
1837 spaces = false
1838 }
1839 }
1840 if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
1841 return false
1842 }
1843 emitter.whitespace = false
1844 emitter.indention = false
1845 return true
1846}
1847
1848func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
1849 if is_space(value, 0) || is_break(value, 0) {
1850 indent_hint := []byte{'0' + byte(emitter.best_indent)}
1851 if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
1852 return false
1853 }
1854 }
1855
1856 emitter.open_ended = false
1857
1858 var chomp_hint [1]byte
1859 if len(value) == 0 {
1860 chomp_hint[0] = '-'
1861 } else {
1862 i := len(value) - 1
1863 for value[i]&0xC0 == 0x80 {
1864 i--
1865 }
1866 if !is_break(value, i) {
1867 chomp_hint[0] = '-'
1868 } else if i == 0 {
1869 chomp_hint[0] = '+'
1870 emitter.open_ended = true
1871 } else {
1872 i--
1873 for value[i]&0xC0 == 0x80 {
1874 i--
1875 }
1876 if is_break(value, i) {
1877 chomp_hint[0] = '+'
1878 emitter.open_ended = true
1879 }
1880 }
1881 }
1882 if chomp_hint[0] != 0 {
1883 if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
1884 return false
1885 }
1886 }
1887 return true
1888}
1889
1890func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
1891 if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
1892 return false
1893 }
1894 if !yaml_emitter_write_block_scalar_hints(emitter, value) {
1895 return false
1896 }
1897 if !yaml_emitter_process_line_comment(emitter) {
1898 return false
1899 }
1900 //emitter.indention = true
1901 emitter.whitespace = true
1902 breaks := true
1903 for i := 0; i < len(value); {
1904 if is_break(value, i) {
1905 if !write_break(emitter, value, &i) {
1906 return false
1907 }
1908 //emitter.indention = true
1909 breaks = true
1910 } else {
1911 if breaks {
1912 if !yaml_emitter_write_indent(emitter) {
1913 return false
1914 }
1915 }
1916 if !write(emitter, value, &i) {
1917 return false
1918 }
1919 emitter.indention = false
1920 breaks = false
1921 }
1922 }
1923
1924 return true
1925}
1926
1927func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
1928 if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
1929 return false
1930 }
1931 if !yaml_emitter_write_block_scalar_hints(emitter, value) {
1932 return false
1933 }
1934 if !yaml_emitter_process_line_comment(emitter) {
1935 return false
1936 }
1937
1938 //emitter.indention = true
1939 emitter.whitespace = true
1940
1941 breaks := true
1942 leading_spaces := true
1943 for i := 0; i < len(value); {
1944 if is_break(value, i) {
1945 if !breaks && !leading_spaces && value[i] == '\n' {
1946 k := 0
1947 for is_break(value, k) {
1948 k += width(value[k])
1949 }
1950 if !is_blankz(value, k) {
1951 if !put_break(emitter) {
1952 return false
1953 }
1954 }
1955 }
1956 if !write_break(emitter, value, &i) {
1957 return false
1958 }
1959 //emitter.indention = true
1960 breaks = true
1961 } else {
1962 if breaks {
1963 if !yaml_emitter_write_indent(emitter) {
1964 return false
1965 }
1966 leading_spaces = is_blank(value, i)
1967 }
1968 if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
1969 if !yaml_emitter_write_indent(emitter) {
1970 return false
1971 }
1972 i += width(value[i])
1973 } else {
1974 if !write(emitter, value, &i) {
1975 return false
1976 }
1977 }
1978 emitter.indention = false
1979 breaks = false
1980 }
1981 }
1982 return true
1983}
1984
1985func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
1986 breaks := false
1987 pound := false
1988 for i := 0; i < len(comment); {
1989 if is_break(comment, i) {
1990 if !write_break(emitter, comment, &i) {
1991 return false
1992 }
1993 //emitter.indention = true
1994 breaks = true
1995 pound = false
1996 } else {
1997 if breaks && !yaml_emitter_write_indent(emitter) {
1998 return false
1999 }
2000 if !pound {
2001 if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
2002 return false
2003 }
2004 pound = true
2005 }
2006 if !write(emitter, comment, &i) {
2007 return false
2008 }
2009 emitter.indention = false
2010 breaks = false
2011 }
2012 }
2013 if !breaks && !put_break(emitter) {
2014 return false
2015 }
2016
2017 emitter.whitespace = true
2018 //emitter.indention = true
2019 return true
2020}