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