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