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