aboutsummaryrefslogtreecommitdiff
path: root/vendor/gopkg.in/yaml.v3
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gopkg.in/yaml.v3')
-rw-r--r--vendor/gopkg.in/yaml.v3/LICENSE50
-rw-r--r--vendor/gopkg.in/yaml.v3/NOTICE13
-rw-r--r--vendor/gopkg.in/yaml.v3/README.md150
-rw-r--r--vendor/gopkg.in/yaml.v3/apic.go747
-rw-r--r--vendor/gopkg.in/yaml.v3/decode.go1000
-rw-r--r--vendor/gopkg.in/yaml.v3/emitterc.go2020
-rw-r--r--vendor/gopkg.in/yaml.v3/encode.go577
-rw-r--r--vendor/gopkg.in/yaml.v3/parserc.go1258
-rw-r--r--vendor/gopkg.in/yaml.v3/readerc.go434
-rw-r--r--vendor/gopkg.in/yaml.v3/resolve.go326
-rw-r--r--vendor/gopkg.in/yaml.v3/scannerc.go3038
-rw-r--r--vendor/gopkg.in/yaml.v3/sorter.go134
-rw-r--r--vendor/gopkg.in/yaml.v3/writerc.go48
-rw-r--r--vendor/gopkg.in/yaml.v3/yaml.go698
-rw-r--r--vendor/gopkg.in/yaml.v3/yamlh.go807
-rw-r--r--vendor/gopkg.in/yaml.v3/yamlprivateh.go198
16 files changed, 11498 insertions, 0 deletions
diff --git a/vendor/gopkg.in/yaml.v3/LICENSE b/vendor/gopkg.in/yaml.v3/LICENSE
new file mode 100644
index 0000000..2683e4b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/LICENSE
@@ -0,0 +1,50 @@
1
2This project is covered by two different licenses: MIT and Apache.
3
4#### MIT License ####
5
6The following files were ported to Go from C files of libyaml, and thus
7are still covered by their original MIT license, with the additional
8copyright staring in 2011 when the project was ported over:
9
10 apic.go emitterc.go parserc.go readerc.go scannerc.go
11 writerc.go yamlh.go yamlprivateh.go
12
13Copyright (c) 2006-2010 Kirill Simonov
14Copyright (c) 2006-2011 Kirill Simonov
15
16Permission is hereby granted, free of charge, to any person obtaining a copy of
17this software and associated documentation files (the "Software"), to deal in
18the Software without restriction, including without limitation the rights to
19use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
20of the Software, and to permit persons to whom the Software is furnished to do
21so, subject to the following conditions:
22
23The above copyright notice and this permission notice shall be included in all
24copies or substantial portions of the Software.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32SOFTWARE.
33
34### Apache License ###
35
36All the remaining project files are covered by the Apache license:
37
38Copyright (c) 2011-2019 Canonical Ltd
39
40Licensed under the Apache License, Version 2.0 (the "License");
41you may not use this file except in compliance with the License.
42You may obtain a copy of the License at
43
44 http://www.apache.org/licenses/LICENSE-2.0
45
46Unless required by applicable law or agreed to in writing, software
47distributed under the License is distributed on an "AS IS" BASIS,
48WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49See the License for the specific language governing permissions and
50limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v3/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE
new file mode 100644
index 0000000..866d74a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/NOTICE
@@ -0,0 +1,13 @@
1Copyright 2011-2016 Canonical Ltd.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v3/README.md b/vendor/gopkg.in/yaml.v3/README.md
new file mode 100644
index 0000000..08eb1ba
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/README.md
@@ -0,0 +1,150 @@
1# YAML support for the Go language
2
3Introduction
4------------
5
6The yaml package enables Go programs to comfortably encode and decode YAML
7values. It was developed within [Canonical](https://www.canonical.com) as
8part of the [juju](https://juju.ubuntu.com) project, and is based on a
9pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
10C library to parse and generate YAML data quickly and reliably.
11
12Compatibility
13-------------
14
15The yaml package supports most of YAML 1.2, but preserves some behavior
16from 1.1 for backwards compatibility.
17
18Specifically, as of v3 of the yaml package:
19
20 - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
21 decoded into a typed bool value. Otherwise they behave as a string. Booleans
22 in YAML 1.2 are _true/false_ only.
23 - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
24 as specified in YAML 1.2, because most parsers still use the old format.
25 Octals in the _0o777_ format are supported though, so new files work.
26 - Does not support base-60 floats. These are gone from YAML 1.2, and were
27 actually never supported by this package as it's clearly a poor choice.
28
29and offers backwards
30compatibility with YAML 1.1 in some cases.
311.2, including support for
32anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
33implemented, and base-60 floats from YAML 1.1 are purposefully not
34supported since they're a poor design and are gone in YAML 1.2.
35
36Installation and usage
37----------------------
38
39The import path for the package is *gopkg.in/yaml.v3*.
40
41To install it, run:
42
43 go get gopkg.in/yaml.v3
44
45API documentation
46-----------------
47
48If opened in a browser, the import path itself leads to the API documentation:
49
50 - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
51
52API stability
53-------------
54
55The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
56
57
58License
59-------
60
61The yaml package is licensed under the MIT and Apache License 2.0 licenses.
62Please see the LICENSE file for details.
63
64
65Example
66-------
67
68```Go
69package main
70
71import (
72 "fmt"
73 "log"
74
75 "gopkg.in/yaml.v3"
76)
77
78var data = `
79a: Easy!
80b:
81 c: 2
82 d: [3, 4]
83`
84
85// Note: struct fields must be public in order for unmarshal to
86// correctly populate the data.
87type T struct {
88 A string
89 B struct {
90 RenamedC int `yaml:"c"`
91 D []int `yaml:",flow"`
92 }
93}
94
95func main() {
96 t := T{}
97
98 err := yaml.Unmarshal([]byte(data), &t)
99 if err != nil {
100 log.Fatalf("error: %v", err)
101 }
102 fmt.Printf("--- t:\n%v\n\n", t)
103
104 d, err := yaml.Marshal(&t)
105 if err != nil {
106 log.Fatalf("error: %v", err)
107 }
108 fmt.Printf("--- t dump:\n%s\n\n", string(d))
109
110 m := make(map[interface{}]interface{})
111
112 err = yaml.Unmarshal([]byte(data), &m)
113 if err != nil {
114 log.Fatalf("error: %v", err)
115 }
116 fmt.Printf("--- m:\n%v\n\n", m)
117
118 d, err = yaml.Marshal(&m)
119 if err != nil {
120 log.Fatalf("error: %v", err)
121 }
122 fmt.Printf("--- m dump:\n%s\n\n", string(d))
123}
124```
125
126This example will generate the following output:
127
128```
129--- t:
130{Easy! {2 [3 4]}}
131
132--- t dump:
133a: Easy!
134b:
135 c: 2
136 d: [3, 4]
137
138
139--- m:
140map[a:Easy! b:map[c:2 d:[3 4]]]
141
142--- m dump:
143a: Easy!
144b:
145 c: 2
146 d:
147 - 3
148 - 4
149```
150
diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go
new file mode 100644
index 0000000..ae7d049
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/apic.go
@@ -0,0 +1,747 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "io"
27)
28
29func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
30 //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
31
32 // Check if we can move the queue at the beginning of the buffer.
33 if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
34 if parser.tokens_head != len(parser.tokens) {
35 copy(parser.tokens, parser.tokens[parser.tokens_head:])
36 }
37 parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
38 parser.tokens_head = 0
39 }
40 parser.tokens = append(parser.tokens, *token)
41 if pos < 0 {
42 return
43 }
44 copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
45 parser.tokens[parser.tokens_head+pos] = *token
46}
47
48// Create a new parser object.
49func yaml_parser_initialize(parser *yaml_parser_t) bool {
50 *parser = yaml_parser_t{
51 raw_buffer: make([]byte, 0, input_raw_buffer_size),
52 buffer: make([]byte, 0, input_buffer_size),
53 }
54 return true
55}
56
57// Destroy a parser object.
58func yaml_parser_delete(parser *yaml_parser_t) {
59 *parser = yaml_parser_t{}
60}
61
62// String read handler.
63func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
64 if parser.input_pos == len(parser.input) {
65 return 0, io.EOF
66 }
67 n = copy(buffer, parser.input[parser.input_pos:])
68 parser.input_pos += n
69 return n, nil
70}
71
72// Reader read handler.
73func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
74 return parser.input_reader.Read(buffer)
75}
76
77// Set a string input.
78func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
79 if parser.read_handler != nil {
80 panic("must set the input source only once")
81 }
82 parser.read_handler = yaml_string_read_handler
83 parser.input = input
84 parser.input_pos = 0
85}
86
87// Set a file input.
88func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
89 if parser.read_handler != nil {
90 panic("must set the input source only once")
91 }
92 parser.read_handler = yaml_reader_read_handler
93 parser.input_reader = r
94}
95
96// Set the source encoding.
97func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
98 if parser.encoding != yaml_ANY_ENCODING {
99 panic("must set the encoding only once")
100 }
101 parser.encoding = encoding
102}
103
104// Create a new emitter object.
105func yaml_emitter_initialize(emitter *yaml_emitter_t) {
106 *emitter = yaml_emitter_t{
107 buffer: make([]byte, output_buffer_size),
108 raw_buffer: make([]byte, 0, output_raw_buffer_size),
109 states: make([]yaml_emitter_state_t, 0, initial_stack_size),
110 events: make([]yaml_event_t, 0, initial_queue_size),
111 best_width: -1,
112 }
113}
114
115// Destroy an emitter object.
116func yaml_emitter_delete(emitter *yaml_emitter_t) {
117 *emitter = yaml_emitter_t{}
118}
119
120// String write handler.
121func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
122 *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
123 return nil
124}
125
126// yaml_writer_write_handler uses emitter.output_writer to write the
127// emitted text.
128func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
129 _, err := emitter.output_writer.Write(buffer)
130 return err
131}
132
133// Set a string output.
134func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
135 if emitter.write_handler != nil {
136 panic("must set the output target only once")
137 }
138 emitter.write_handler = yaml_string_write_handler
139 emitter.output_buffer = output_buffer
140}
141
142// Set a file output.
143func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
144 if emitter.write_handler != nil {
145 panic("must set the output target only once")
146 }
147 emitter.write_handler = yaml_writer_write_handler
148 emitter.output_writer = w
149}
150
151// Set the output encoding.
152func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
153 if emitter.encoding != yaml_ANY_ENCODING {
154 panic("must set the output encoding only once")
155 }
156 emitter.encoding = encoding
157}
158
159// Set the canonical output style.
160func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
161 emitter.canonical = canonical
162}
163
164// Set the indentation increment.
165func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
166 if indent < 2 || indent > 9 {
167 indent = 2
168 }
169 emitter.best_indent = indent
170}
171
172// Set the preferred line width.
173func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
174 if width < 0 {
175 width = -1
176 }
177 emitter.best_width = width
178}
179
180// Set if unescaped non-ASCII characters are allowed.
181func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
182 emitter.unicode = unicode
183}
184
185// Set the preferred line break character.
186func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
187 emitter.line_break = line_break
188}
189
190///*
191// * Destroy a token object.
192// */
193//
194//YAML_DECLARE(void)
195//yaml_token_delete(yaml_token_t *token)
196//{
197// assert(token); // Non-NULL token object expected.
198//
199// switch (token.type)
200// {
201// case YAML_TAG_DIRECTIVE_TOKEN:
202// yaml_free(token.data.tag_directive.handle);
203// yaml_free(token.data.tag_directive.prefix);
204// break;
205//
206// case YAML_ALIAS_TOKEN:
207// yaml_free(token.data.alias.value);
208// break;
209//
210// case YAML_ANCHOR_TOKEN:
211// yaml_free(token.data.anchor.value);
212// break;
213//
214// case YAML_TAG_TOKEN:
215// yaml_free(token.data.tag.handle);
216// yaml_free(token.data.tag.suffix);
217// break;
218//
219// case YAML_SCALAR_TOKEN:
220// yaml_free(token.data.scalar.value);
221// break;
222//
223// default:
224// break;
225// }
226//
227// memset(token, 0, sizeof(yaml_token_t));
228//}
229//
230///*
231// * Check if a string is a valid UTF-8 sequence.
232// *
233// * Check 'reader.c' for more details on UTF-8 encoding.
234// */
235//
236//static int
237//yaml_check_utf8(yaml_char_t *start, size_t length)
238//{
239// yaml_char_t *end = start+length;
240// yaml_char_t *pointer = start;
241//
242// while (pointer < end) {
243// unsigned char octet;
244// unsigned int width;
245// unsigned int value;
246// size_t k;
247//
248// octet = pointer[0];
249// width = (octet & 0x80) == 0x00 ? 1 :
250// (octet & 0xE0) == 0xC0 ? 2 :
251// (octet & 0xF0) == 0xE0 ? 3 :
252// (octet & 0xF8) == 0xF0 ? 4 : 0;
253// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
254// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
255// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
256// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
257// if (!width) return 0;
258// if (pointer+width > end) return 0;
259// for (k = 1; k < width; k ++) {
260// octet = pointer[k];
261// if ((octet & 0xC0) != 0x80) return 0;
262// value = (value << 6) + (octet & 0x3F);
263// }
264// if (!((width == 1) ||
265// (width == 2 && value >= 0x80) ||
266// (width == 3 && value >= 0x800) ||
267// (width == 4 && value >= 0x10000))) return 0;
268//
269// pointer += width;
270// }
271//
272// return 1;
273//}
274//
275
276// Create STREAM-START.
277func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
278 *event = yaml_event_t{
279 typ: yaml_STREAM_START_EVENT,
280 encoding: encoding,
281 }
282}
283
284// Create STREAM-END.
285func yaml_stream_end_event_initialize(event *yaml_event_t) {
286 *event = yaml_event_t{
287 typ: yaml_STREAM_END_EVENT,
288 }
289}
290
291// Create DOCUMENT-START.
292func yaml_document_start_event_initialize(
293 event *yaml_event_t,
294 version_directive *yaml_version_directive_t,
295 tag_directives []yaml_tag_directive_t,
296 implicit bool,
297) {
298 *event = yaml_event_t{
299 typ: yaml_DOCUMENT_START_EVENT,
300 version_directive: version_directive,
301 tag_directives: tag_directives,
302 implicit: implicit,
303 }
304}
305
306// Create DOCUMENT-END.
307func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
308 *event = yaml_event_t{
309 typ: yaml_DOCUMENT_END_EVENT,
310 implicit: implicit,
311 }
312}
313
314// Create ALIAS.
315func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
316 *event = yaml_event_t{
317 typ: yaml_ALIAS_EVENT,
318 anchor: anchor,
319 }
320 return true
321}
322
323// Create SCALAR.
324func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
325 *event = yaml_event_t{
326 typ: yaml_SCALAR_EVENT,
327 anchor: anchor,
328 tag: tag,
329 value: value,
330 implicit: plain_implicit,
331 quoted_implicit: quoted_implicit,
332 style: yaml_style_t(style),
333 }
334 return true
335}
336
337// Create SEQUENCE-START.
338func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
339 *event = yaml_event_t{
340 typ: yaml_SEQUENCE_START_EVENT,
341 anchor: anchor,
342 tag: tag,
343 implicit: implicit,
344 style: yaml_style_t(style),
345 }
346 return true
347}
348
349// Create SEQUENCE-END.
350func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
351 *event = yaml_event_t{
352 typ: yaml_SEQUENCE_END_EVENT,
353 }
354 return true
355}
356
357// Create MAPPING-START.
358func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
359 *event = yaml_event_t{
360 typ: yaml_MAPPING_START_EVENT,
361 anchor: anchor,
362 tag: tag,
363 implicit: implicit,
364 style: yaml_style_t(style),
365 }
366}
367
368// Create MAPPING-END.
369func yaml_mapping_end_event_initialize(event *yaml_event_t) {
370 *event = yaml_event_t{
371 typ: yaml_MAPPING_END_EVENT,
372 }
373}
374
375// Destroy an event object.
376func yaml_event_delete(event *yaml_event_t) {
377 *event = yaml_event_t{}
378}
379
380///*
381// * Create a document object.
382// */
383//
384//YAML_DECLARE(int)
385//yaml_document_initialize(document *yaml_document_t,
386// version_directive *yaml_version_directive_t,
387// tag_directives_start *yaml_tag_directive_t,
388// tag_directives_end *yaml_tag_directive_t,
389// start_implicit int, end_implicit int)
390//{
391// struct {
392// error yaml_error_type_t
393// } context
394// struct {
395// start *yaml_node_t
396// end *yaml_node_t
397// top *yaml_node_t
398// } nodes = { NULL, NULL, NULL }
399// version_directive_copy *yaml_version_directive_t = NULL
400// struct {
401// start *yaml_tag_directive_t
402// end *yaml_tag_directive_t
403// top *yaml_tag_directive_t
404// } tag_directives_copy = { NULL, NULL, NULL }
405// value yaml_tag_directive_t = { NULL, NULL }
406// mark yaml_mark_t = { 0, 0, 0 }
407//
408// assert(document) // Non-NULL document object is expected.
409// assert((tag_directives_start && tag_directives_end) ||
410// (tag_directives_start == tag_directives_end))
411// // Valid tag directives are expected.
412//
413// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
414//
415// if (version_directive) {
416// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
417// if (!version_directive_copy) goto error
418// version_directive_copy.major = version_directive.major
419// version_directive_copy.minor = version_directive.minor
420// }
421//
422// if (tag_directives_start != tag_directives_end) {
423// tag_directive *yaml_tag_directive_t
424// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
425// goto error
426// for (tag_directive = tag_directives_start
427// tag_directive != tag_directives_end; tag_directive ++) {
428// assert(tag_directive.handle)
429// assert(tag_directive.prefix)
430// if (!yaml_check_utf8(tag_directive.handle,
431// strlen((char *)tag_directive.handle)))
432// goto error
433// if (!yaml_check_utf8(tag_directive.prefix,
434// strlen((char *)tag_directive.prefix)))
435// goto error
436// value.handle = yaml_strdup(tag_directive.handle)
437// value.prefix = yaml_strdup(tag_directive.prefix)
438// if (!value.handle || !value.prefix) goto error
439// if (!PUSH(&context, tag_directives_copy, value))
440// goto error
441// value.handle = NULL
442// value.prefix = NULL
443// }
444// }
445//
446// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
447// tag_directives_copy.start, tag_directives_copy.top,
448// start_implicit, end_implicit, mark, mark)
449//
450// return 1
451//
452//error:
453// STACK_DEL(&context, nodes)
454// yaml_free(version_directive_copy)
455// while (!STACK_EMPTY(&context, tag_directives_copy)) {
456// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
457// yaml_free(value.handle)
458// yaml_free(value.prefix)
459// }
460// STACK_DEL(&context, tag_directives_copy)
461// yaml_free(value.handle)
462// yaml_free(value.prefix)
463//
464// return 0
465//}
466//
467///*
468// * Destroy a document object.
469// */
470//
471//YAML_DECLARE(void)
472//yaml_document_delete(document *yaml_document_t)
473//{
474// struct {
475// error yaml_error_type_t
476// } context
477// tag_directive *yaml_tag_directive_t
478//
479// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
480//
481// assert(document) // Non-NULL document object is expected.
482//
483// while (!STACK_EMPTY(&context, document.nodes)) {
484// node yaml_node_t = POP(&context, document.nodes)
485// yaml_free(node.tag)
486// switch (node.type) {
487// case YAML_SCALAR_NODE:
488// yaml_free(node.data.scalar.value)
489// break
490// case YAML_SEQUENCE_NODE:
491// STACK_DEL(&context, node.data.sequence.items)
492// break
493// case YAML_MAPPING_NODE:
494// STACK_DEL(&context, node.data.mapping.pairs)
495// break
496// default:
497// assert(0) // Should not happen.
498// }
499// }
500// STACK_DEL(&context, document.nodes)
501//
502// yaml_free(document.version_directive)
503// for (tag_directive = document.tag_directives.start
504// tag_directive != document.tag_directives.end
505// tag_directive++) {
506// yaml_free(tag_directive.handle)
507// yaml_free(tag_directive.prefix)
508// }
509// yaml_free(document.tag_directives.start)
510//
511// memset(document, 0, sizeof(yaml_document_t))
512//}
513//
514///**
515// * Get a document node.
516// */
517//
518//YAML_DECLARE(yaml_node_t *)
519//yaml_document_get_node(document *yaml_document_t, index int)
520//{
521// assert(document) // Non-NULL document object is expected.
522//
523// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
524// return document.nodes.start + index - 1
525// }
526// return NULL
527//}
528//
529///**
530// * Get the root object.
531// */
532//
533//YAML_DECLARE(yaml_node_t *)
534//yaml_document_get_root_node(document *yaml_document_t)
535//{
536// assert(document) // Non-NULL document object is expected.
537//
538// if (document.nodes.top != document.nodes.start) {
539// return document.nodes.start
540// }
541// return NULL
542//}
543//
544///*
545// * Add a scalar node to a document.
546// */
547//
548//YAML_DECLARE(int)
549//yaml_document_add_scalar(document *yaml_document_t,
550// tag *yaml_char_t, value *yaml_char_t, length int,
551// style yaml_scalar_style_t)
552//{
553// struct {
554// error yaml_error_type_t
555// } context
556// mark yaml_mark_t = { 0, 0, 0 }
557// tag_copy *yaml_char_t = NULL
558// value_copy *yaml_char_t = NULL
559// node yaml_node_t
560//
561// assert(document) // Non-NULL document object is expected.
562// assert(value) // Non-NULL value is expected.
563//
564// if (!tag) {
565// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
566// }
567//
568// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
569// tag_copy = yaml_strdup(tag)
570// if (!tag_copy) goto error
571//
572// if (length < 0) {
573// length = strlen((char *)value)
574// }
575//
576// if (!yaml_check_utf8(value, length)) goto error
577// value_copy = yaml_malloc(length+1)
578// if (!value_copy) goto error
579// memcpy(value_copy, value, length)
580// value_copy[length] = '\0'
581//
582// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
583// if (!PUSH(&context, document.nodes, node)) goto error
584//
585// return document.nodes.top - document.nodes.start
586//
587//error:
588// yaml_free(tag_copy)
589// yaml_free(value_copy)
590//
591// return 0
592//}
593//
594///*
595// * Add a sequence node to a document.
596// */
597//
598//YAML_DECLARE(int)
599//yaml_document_add_sequence(document *yaml_document_t,
600// tag *yaml_char_t, style yaml_sequence_style_t)
601//{
602// struct {
603// error yaml_error_type_t
604// } context
605// mark yaml_mark_t = { 0, 0, 0 }
606// tag_copy *yaml_char_t = NULL
607// struct {
608// start *yaml_node_item_t
609// end *yaml_node_item_t
610// top *yaml_node_item_t
611// } items = { NULL, NULL, NULL }
612// node yaml_node_t
613//
614// assert(document) // Non-NULL document object is expected.
615//
616// if (!tag) {
617// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
618// }
619//
620// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
621// tag_copy = yaml_strdup(tag)
622// if (!tag_copy) goto error
623//
624// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
625//
626// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
627// style, mark, mark)
628// if (!PUSH(&context, document.nodes, node)) goto error
629//
630// return document.nodes.top - document.nodes.start
631//
632//error:
633// STACK_DEL(&context, items)
634// yaml_free(tag_copy)
635//
636// return 0
637//}
638//
639///*
640// * Add a mapping node to a document.
641// */
642//
643//YAML_DECLARE(int)
644//yaml_document_add_mapping(document *yaml_document_t,
645// tag *yaml_char_t, style yaml_mapping_style_t)
646//{
647// struct {
648// error yaml_error_type_t
649// } context
650// mark yaml_mark_t = { 0, 0, 0 }
651// tag_copy *yaml_char_t = NULL
652// struct {
653// start *yaml_node_pair_t
654// end *yaml_node_pair_t
655// top *yaml_node_pair_t
656// } pairs = { NULL, NULL, NULL }
657// node yaml_node_t
658//
659// assert(document) // Non-NULL document object is expected.
660//
661// if (!tag) {
662// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
663// }
664//
665// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
666// tag_copy = yaml_strdup(tag)
667// if (!tag_copy) goto error
668//
669// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
670//
671// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
672// style, mark, mark)
673// if (!PUSH(&context, document.nodes, node)) goto error
674//
675// return document.nodes.top - document.nodes.start
676//
677//error:
678// STACK_DEL(&context, pairs)
679// yaml_free(tag_copy)
680//
681// return 0
682//}
683//
684///*
685// * Append an item to a sequence node.
686// */
687//
688//YAML_DECLARE(int)
689//yaml_document_append_sequence_item(document *yaml_document_t,
690// sequence int, item int)
691//{
692// struct {
693// error yaml_error_type_t
694// } context
695//
696// assert(document) // Non-NULL document is required.
697// assert(sequence > 0
698// && document.nodes.start + sequence <= document.nodes.top)
699// // Valid sequence id is required.
700// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
701// // A sequence node is required.
702// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
703// // Valid item id is required.
704//
705// if (!PUSH(&context,
706// document.nodes.start[sequence-1].data.sequence.items, item))
707// return 0
708//
709// return 1
710//}
711//
712///*
713// * Append a pair of a key and a value to a mapping node.
714// */
715//
716//YAML_DECLARE(int)
717//yaml_document_append_mapping_pair(document *yaml_document_t,
718// mapping int, key int, value int)
719//{
720// struct {
721// error yaml_error_type_t
722// } context
723//
724// pair yaml_node_pair_t
725//
726// assert(document) // Non-NULL document is required.
727// assert(mapping > 0
728// && document.nodes.start + mapping <= document.nodes.top)
729// // Valid mapping id is required.
730// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
731// // A mapping node is required.
732// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
733// // Valid key id is required.
734// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
735// // Valid value id is required.
736//
737// pair.key = key
738// pair.value = value
739//
740// if (!PUSH(&context,
741// document.nodes.start[mapping-1].data.mapping.pairs, pair))
742// return 0
743//
744// return 1
745//}
746//
747//
diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go
new file mode 100644
index 0000000..0173b69
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/decode.go
@@ -0,0 +1,1000 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package yaml
17
18import (
19 "encoding"
20 "encoding/base64"
21 "fmt"
22 "io"
23 "math"
24 "reflect"
25 "strconv"
26 "time"
27)
28
29// ----------------------------------------------------------------------------
30// Parser, produces a node tree out of a libyaml event stream.
31
32type parser struct {
33 parser yaml_parser_t
34 event yaml_event_t
35 doc *Node
36 anchors map[string]*Node
37 doneInit bool
38 textless bool
39}
40
41func newParser(b []byte) *parser {
42 p := parser{}
43 if !yaml_parser_initialize(&p.parser) {
44 panic("failed to initialize YAML emitter")
45 }
46 if len(b) == 0 {
47 b = []byte{'\n'}
48 }
49 yaml_parser_set_input_string(&p.parser, b)
50 return &p
51}
52
53func newParserFromReader(r io.Reader) *parser {
54 p := parser{}
55 if !yaml_parser_initialize(&p.parser) {
56 panic("failed to initialize YAML emitter")
57 }
58 yaml_parser_set_input_reader(&p.parser, r)
59 return &p
60}
61
62func (p *parser) init() {
63 if p.doneInit {
64 return
65 }
66 p.anchors = make(map[string]*Node)
67 p.expect(yaml_STREAM_START_EVENT)
68 p.doneInit = true
69}
70
71func (p *parser) destroy() {
72 if p.event.typ != yaml_NO_EVENT {
73 yaml_event_delete(&p.event)
74 }
75 yaml_parser_delete(&p.parser)
76}
77
78// expect consumes an event from the event stream and
79// checks that it's of the expected type.
80func (p *parser) expect(e yaml_event_type_t) {
81 if p.event.typ == yaml_NO_EVENT {
82 if !yaml_parser_parse(&p.parser, &p.event) {
83 p.fail()
84 }
85 }
86 if p.event.typ == yaml_STREAM_END_EVENT {
87 failf("attempted to go past the end of stream; corrupted value?")
88 }
89 if p.event.typ != e {
90 p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
91 p.fail()
92 }
93 yaml_event_delete(&p.event)
94 p.event.typ = yaml_NO_EVENT
95}
96
97// peek peeks at the next event in the event stream,
98// puts the results into p.event and returns the event type.
99func (p *parser) peek() yaml_event_type_t {
100 if p.event.typ != yaml_NO_EVENT {
101 return p.event.typ
102 }
103 // It's curious choice from the underlying API to generally return a
104 // positive result on success, but on this case return true in an error
105 // scenario. This was the source of bugs in the past (issue #666).
106 if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
107 p.fail()
108 }
109 return p.event.typ
110}
111
112func (p *parser) fail() {
113 var where string
114 var line int
115 if p.parser.context_mark.line != 0 {
116 line = p.parser.context_mark.line
117 // Scanner errors don't iterate line before returning error
118 if p.parser.error == yaml_SCANNER_ERROR {
119 line++
120 }
121 } else if p.parser.problem_mark.line != 0 {
122 line = p.parser.problem_mark.line
123 // Scanner errors don't iterate line before returning error
124 if p.parser.error == yaml_SCANNER_ERROR {
125 line++
126 }
127 }
128 if line != 0 {
129 where = "line " + strconv.Itoa(line) + ": "
130 }
131 var msg string
132 if len(p.parser.problem) > 0 {
133 msg = p.parser.problem
134 } else {
135 msg = "unknown problem parsing YAML content"
136 }
137 failf("%s%s", where, msg)
138}
139
140func (p *parser) anchor(n *Node, anchor []byte) {
141 if anchor != nil {
142 n.Anchor = string(anchor)
143 p.anchors[n.Anchor] = n
144 }
145}
146
147func (p *parser) parse() *Node {
148 p.init()
149 switch p.peek() {
150 case yaml_SCALAR_EVENT:
151 return p.scalar()
152 case yaml_ALIAS_EVENT:
153 return p.alias()
154 case yaml_MAPPING_START_EVENT:
155 return p.mapping()
156 case yaml_SEQUENCE_START_EVENT:
157 return p.sequence()
158 case yaml_DOCUMENT_START_EVENT:
159 return p.document()
160 case yaml_STREAM_END_EVENT:
161 // Happens when attempting to decode an empty buffer.
162 return nil
163 case yaml_TAIL_COMMENT_EVENT:
164 panic("internal error: unexpected tail comment event (please report)")
165 default:
166 panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
167 }
168}
169
170func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
171 var style Style
172 if tag != "" && tag != "!" {
173 tag = shortTag(tag)
174 style = TaggedStyle
175 } else if defaultTag != "" {
176 tag = defaultTag
177 } else if kind == ScalarNode {
178 tag, _ = resolve("", value)
179 }
180 n := &Node{
181 Kind: kind,
182 Tag: tag,
183 Value: value,
184 Style: style,
185 }
186 if !p.textless {
187 n.Line = p.event.start_mark.line + 1
188 n.Column = p.event.start_mark.column + 1
189 n.HeadComment = string(p.event.head_comment)
190 n.LineComment = string(p.event.line_comment)
191 n.FootComment = string(p.event.foot_comment)
192 }
193 return n
194}
195
196func (p *parser) parseChild(parent *Node) *Node {
197 child := p.parse()
198 parent.Content = append(parent.Content, child)
199 return child
200}
201
202func (p *parser) document() *Node {
203 n := p.node(DocumentNode, "", "", "")
204 p.doc = n
205 p.expect(yaml_DOCUMENT_START_EVENT)
206 p.parseChild(n)
207 if p.peek() == yaml_DOCUMENT_END_EVENT {
208 n.FootComment = string(p.event.foot_comment)
209 }
210 p.expect(yaml_DOCUMENT_END_EVENT)
211 return n
212}
213
214func (p *parser) alias() *Node {
215 n := p.node(AliasNode, "", "", string(p.event.anchor))
216 n.Alias = p.anchors[n.Value]
217 if n.Alias == nil {
218 failf("unknown anchor '%s' referenced", n.Value)
219 }
220 p.expect(yaml_ALIAS_EVENT)
221 return n
222}
223
224func (p *parser) scalar() *Node {
225 var parsedStyle = p.event.scalar_style()
226 var nodeStyle Style
227 switch {
228 case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
229 nodeStyle = DoubleQuotedStyle
230 case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
231 nodeStyle = SingleQuotedStyle
232 case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
233 nodeStyle = LiteralStyle
234 case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
235 nodeStyle = FoldedStyle
236 }
237 var nodeValue = string(p.event.value)
238 var nodeTag = string(p.event.tag)
239 var defaultTag string
240 if nodeStyle == 0 {
241 if nodeValue == "<<" {
242 defaultTag = mergeTag
243 }
244 } else {
245 defaultTag = strTag
246 }
247 n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
248 n.Style |= nodeStyle
249 p.anchor(n, p.event.anchor)
250 p.expect(yaml_SCALAR_EVENT)
251 return n
252}
253
254func (p *parser) sequence() *Node {
255 n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
256 if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
257 n.Style |= FlowStyle
258 }
259 p.anchor(n, p.event.anchor)
260 p.expect(yaml_SEQUENCE_START_EVENT)
261 for p.peek() != yaml_SEQUENCE_END_EVENT {
262 p.parseChild(n)
263 }
264 n.LineComment = string(p.event.line_comment)
265 n.FootComment = string(p.event.foot_comment)
266 p.expect(yaml_SEQUENCE_END_EVENT)
267 return n
268}
269
270func (p *parser) mapping() *Node {
271 n := p.node(MappingNode, mapTag, string(p.event.tag), "")
272 block := true
273 if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
274 block = false
275 n.Style |= FlowStyle
276 }
277 p.anchor(n, p.event.anchor)
278 p.expect(yaml_MAPPING_START_EVENT)
279 for p.peek() != yaml_MAPPING_END_EVENT {
280 k := p.parseChild(n)
281 if block && k.FootComment != "" {
282 // Must be a foot comment for the prior value when being dedented.
283 if len(n.Content) > 2 {
284 n.Content[len(n.Content)-3].FootComment = k.FootComment
285 k.FootComment = ""
286 }
287 }
288 v := p.parseChild(n)
289 if k.FootComment == "" && v.FootComment != "" {
290 k.FootComment = v.FootComment
291 v.FootComment = ""
292 }
293 if p.peek() == yaml_TAIL_COMMENT_EVENT {
294 if k.FootComment == "" {
295 k.FootComment = string(p.event.foot_comment)
296 }
297 p.expect(yaml_TAIL_COMMENT_EVENT)
298 }
299 }
300 n.LineComment = string(p.event.line_comment)
301 n.FootComment = string(p.event.foot_comment)
302 if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
303 n.Content[len(n.Content)-2].FootComment = n.FootComment
304 n.FootComment = ""
305 }
306 p.expect(yaml_MAPPING_END_EVENT)
307 return n
308}
309
310// ----------------------------------------------------------------------------
311// Decoder, unmarshals a node into a provided value.
312
313type decoder struct {
314 doc *Node
315 aliases map[*Node]bool
316 terrors []string
317
318 stringMapType reflect.Type
319 generalMapType reflect.Type
320
321 knownFields bool
322 uniqueKeys bool
323 decodeCount int
324 aliasCount int
325 aliasDepth int
326
327 mergedFields map[interface{}]bool
328}
329
330var (
331 nodeType = reflect.TypeOf(Node{})
332 durationType = reflect.TypeOf(time.Duration(0))
333 stringMapType = reflect.TypeOf(map[string]interface{}{})
334 generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
335 ifaceType = generalMapType.Elem()
336 timeType = reflect.TypeOf(time.Time{})
337 ptrTimeType = reflect.TypeOf(&time.Time{})
338)
339
340func newDecoder() *decoder {
341 d := &decoder{
342 stringMapType: stringMapType,
343 generalMapType: generalMapType,
344 uniqueKeys: true,
345 }
346 d.aliases = make(map[*Node]bool)
347 return d
348}
349
350func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
351 if n.Tag != "" {
352 tag = n.Tag
353 }
354 value := n.Value
355 if tag != seqTag && tag != mapTag {
356 if len(value) > 10 {
357 value = " `" + value[:7] + "...`"
358 } else {
359 value = " `" + value + "`"
360 }
361 }
362 d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
363}
364
365func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
366 err := u.UnmarshalYAML(n)
367 if e, ok := err.(*TypeError); ok {
368 d.terrors = append(d.terrors, e.Errors...)
369 return false
370 }
371 if err != nil {
372 fail(err)
373 }
374 return true
375}
376
377func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
378 terrlen := len(d.terrors)
379 err := u.UnmarshalYAML(func(v interface{}) (err error) {
380 defer handleErr(&err)
381 d.unmarshal(n, reflect.ValueOf(v))
382 if len(d.terrors) > terrlen {
383 issues := d.terrors[terrlen:]
384 d.terrors = d.terrors[:terrlen]
385 return &TypeError{issues}
386 }
387 return nil
388 })
389 if e, ok := err.(*TypeError); ok {
390 d.terrors = append(d.terrors, e.Errors...)
391 return false
392 }
393 if err != nil {
394 fail(err)
395 }
396 return true
397}
398
399// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
400// if a value is found to implement it.
401// It returns the initialized and dereferenced out value, whether
402// unmarshalling was already done by UnmarshalYAML, and if so whether
403// its types unmarshalled appropriately.
404//
405// If n holds a null value, prepare returns before doing anything.
406func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
407 if n.ShortTag() == nullTag {
408 return out, false, false
409 }
410 again := true
411 for again {
412 again = false
413 if out.Kind() == reflect.Ptr {
414 if out.IsNil() {
415 out.Set(reflect.New(out.Type().Elem()))
416 }
417 out = out.Elem()
418 again = true
419 }
420 if out.CanAddr() {
421 outi := out.Addr().Interface()
422 if u, ok := outi.(Unmarshaler); ok {
423 good = d.callUnmarshaler(n, u)
424 return out, true, good
425 }
426 if u, ok := outi.(obsoleteUnmarshaler); ok {
427 good = d.callObsoleteUnmarshaler(n, u)
428 return out, true, good
429 }
430 }
431 }
432 return out, false, false
433}
434
435func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
436 if n.ShortTag() == nullTag {
437 return reflect.Value{}
438 }
439 for _, num := range index {
440 for {
441 if v.Kind() == reflect.Ptr {
442 if v.IsNil() {
443 v.Set(reflect.New(v.Type().Elem()))
444 }
445 v = v.Elem()
446 continue
447 }
448 break
449 }
450 v = v.Field(num)
451 }
452 return v
453}
454
455const (
456 // 400,000 decode operations is ~500kb of dense object declarations, or
457 // ~5kb of dense object declarations with 10000% alias expansion
458 alias_ratio_range_low = 400000
459
460 // 4,000,000 decode operations is ~5MB of dense object declarations, or
461 // ~4.5MB of dense object declarations with 10% alias expansion
462 alias_ratio_range_high = 4000000
463
464 // alias_ratio_range is the range over which we scale allowed alias ratios
465 alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
466)
467
468func allowedAliasRatio(decodeCount int) float64 {
469 switch {
470 case decodeCount <= alias_ratio_range_low:
471 // allow 99% to come from alias expansion for small-to-medium documents
472 return 0.99
473 case decodeCount >= alias_ratio_range_high:
474 // allow 10% to come from alias expansion for very large documents
475 return 0.10
476 default:
477 // scale smoothly from 99% down to 10% over the range.
478 // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
479 // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
480 return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
481 }
482}
483
484func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
485 d.decodeCount++
486 if d.aliasDepth > 0 {
487 d.aliasCount++
488 }
489 if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
490 failf("document contains excessive aliasing")
491 }
492 if out.Type() == nodeType {
493 out.Set(reflect.ValueOf(n).Elem())
494 return true
495 }
496 switch n.Kind {
497 case DocumentNode:
498 return d.document(n, out)
499 case AliasNode:
500 return d.alias(n, out)
501 }
502 out, unmarshaled, good := d.prepare(n, out)
503 if unmarshaled {
504 return good
505 }
506 switch n.Kind {
507 case ScalarNode:
508 good = d.scalar(n, out)
509 case MappingNode:
510 good = d.mapping(n, out)
511 case SequenceNode:
512 good = d.sequence(n, out)
513 case 0:
514 if n.IsZero() {
515 return d.null(out)
516 }
517 fallthrough
518 default:
519 failf("cannot decode node with unknown kind %d", n.Kind)
520 }
521 return good
522}
523
524func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
525 if len(n.Content) == 1 {
526 d.doc = n
527 d.unmarshal(n.Content[0], out)
528 return true
529 }
530 return false
531}
532
533func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
534 if d.aliases[n] {
535 // TODO this could actually be allowed in some circumstances.
536 failf("anchor '%s' value contains itself", n.Value)
537 }
538 d.aliases[n] = true
539 d.aliasDepth++
540 good = d.unmarshal(n.Alias, out)
541 d.aliasDepth--
542 delete(d.aliases, n)
543 return good
544}
545
546var zeroValue reflect.Value
547
548func resetMap(out reflect.Value) {
549 for _, k := range out.MapKeys() {
550 out.SetMapIndex(k, zeroValue)
551 }
552}
553
554func (d *decoder) null(out reflect.Value) bool {
555 if out.CanAddr() {
556 switch out.Kind() {
557 case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
558 out.Set(reflect.Zero(out.Type()))
559 return true
560 }
561 }
562 return false
563}
564
565func (d *decoder) scalar(n *Node, out reflect.Value) bool {
566 var tag string
567 var resolved interface{}
568 if n.indicatedString() {
569 tag = strTag
570 resolved = n.Value
571 } else {
572 tag, resolved = resolve(n.Tag, n.Value)
573 if tag == binaryTag {
574 data, err := base64.StdEncoding.DecodeString(resolved.(string))
575 if err != nil {
576 failf("!!binary value contains invalid base64 data")
577 }
578 resolved = string(data)
579 }
580 }
581 if resolved == nil {
582 return d.null(out)
583 }
584 if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
585 // We've resolved to exactly the type we want, so use that.
586 out.Set(resolvedv)
587 return true
588 }
589 // Perhaps we can use the value as a TextUnmarshaler to
590 // set its value.
591 if out.CanAddr() {
592 u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
593 if ok {
594 var text []byte
595 if tag == binaryTag {
596 text = []byte(resolved.(string))
597 } else {
598 // We let any value be unmarshaled into TextUnmarshaler.
599 // That might be more lax than we'd like, but the
600 // TextUnmarshaler itself should bowl out any dubious values.
601 text = []byte(n.Value)
602 }
603 err := u.UnmarshalText(text)
604 if err != nil {
605 fail(err)
606 }
607 return true
608 }
609 }
610 switch out.Kind() {
611 case reflect.String:
612 if tag == binaryTag {
613 out.SetString(resolved.(string))
614 return true
615 }
616 out.SetString(n.Value)
617 return true
618 case reflect.Interface:
619 out.Set(reflect.ValueOf(resolved))
620 return true
621 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
622 // This used to work in v2, but it's very unfriendly.
623 isDuration := out.Type() == durationType
624
625 switch resolved := resolved.(type) {
626 case int:
627 if !isDuration && !out.OverflowInt(int64(resolved)) {
628 out.SetInt(int64(resolved))
629 return true
630 }
631 case int64:
632 if !isDuration && !out.OverflowInt(resolved) {
633 out.SetInt(resolved)
634 return true
635 }
636 case uint64:
637 if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
638 out.SetInt(int64(resolved))
639 return true
640 }
641 case float64:
642 if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
643 out.SetInt(int64(resolved))
644 return true
645 }
646 case string:
647 if out.Type() == durationType {
648 d, err := time.ParseDuration(resolved)
649 if err == nil {
650 out.SetInt(int64(d))
651 return true
652 }
653 }
654 }
655 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
656 switch resolved := resolved.(type) {
657 case int:
658 if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
659 out.SetUint(uint64(resolved))
660 return true
661 }
662 case int64:
663 if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
664 out.SetUint(uint64(resolved))
665 return true
666 }
667 case uint64:
668 if !out.OverflowUint(uint64(resolved)) {
669 out.SetUint(uint64(resolved))
670 return true
671 }
672 case float64:
673 if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
674 out.SetUint(uint64(resolved))
675 return true
676 }
677 }
678 case reflect.Bool:
679 switch resolved := resolved.(type) {
680 case bool:
681 out.SetBool(resolved)
682 return true
683 case string:
684 // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
685 // It only works if explicitly attempting to unmarshal into a typed bool value.
686 switch resolved {
687 case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
688 out.SetBool(true)
689 return true
690 case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
691 out.SetBool(false)
692 return true
693 }
694 }
695 case reflect.Float32, reflect.Float64:
696 switch resolved := resolved.(type) {
697 case int:
698 out.SetFloat(float64(resolved))
699 return true
700 case int64:
701 out.SetFloat(float64(resolved))
702 return true
703 case uint64:
704 out.SetFloat(float64(resolved))
705 return true
706 case float64:
707 out.SetFloat(resolved)
708 return true
709 }
710 case reflect.Struct:
711 if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
712 out.Set(resolvedv)
713 return true
714 }
715 case reflect.Ptr:
716 panic("yaml internal error: please report the issue")
717 }
718 d.terror(n, tag, out)
719 return false
720}
721
722func settableValueOf(i interface{}) reflect.Value {
723 v := reflect.ValueOf(i)
724 sv := reflect.New(v.Type()).Elem()
725 sv.Set(v)
726 return sv
727}
728
729func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
730 l := len(n.Content)
731
732 var iface reflect.Value
733 switch out.Kind() {
734 case reflect.Slice:
735 out.Set(reflect.MakeSlice(out.Type(), l, l))
736 case reflect.Array:
737 if l != out.Len() {
738 failf("invalid array: want %d elements but got %d", out.Len(), l)
739 }
740 case reflect.Interface:
741 // No type hints. Will have to use a generic sequence.
742 iface = out
743 out = settableValueOf(make([]interface{}, l))
744 default:
745 d.terror(n, seqTag, out)
746 return false
747 }
748 et := out.Type().Elem()
749
750 j := 0
751 for i := 0; i < l; i++ {
752 e := reflect.New(et).Elem()
753 if ok := d.unmarshal(n.Content[i], e); ok {
754 out.Index(j).Set(e)
755 j++
756 }
757 }
758 if out.Kind() != reflect.Array {
759 out.Set(out.Slice(0, j))
760 }
761 if iface.IsValid() {
762 iface.Set(out)
763 }
764 return true
765}
766
767func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
768 l := len(n.Content)
769 if d.uniqueKeys {
770 nerrs := len(d.terrors)
771 for i := 0; i < l; i += 2 {
772 ni := n.Content[i]
773 for j := i + 2; j < l; j += 2 {
774 nj := n.Content[j]
775 if ni.Kind == nj.Kind && ni.Value == nj.Value {
776 d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
777 }
778 }
779 }
780 if len(d.terrors) > nerrs {
781 return false
782 }
783 }
784 switch out.Kind() {
785 case reflect.Struct:
786 return d.mappingStruct(n, out)
787 case reflect.Map:
788 // okay
789 case reflect.Interface:
790 iface := out
791 if isStringMap(n) {
792 out = reflect.MakeMap(d.stringMapType)
793 } else {
794 out = reflect.MakeMap(d.generalMapType)
795 }
796 iface.Set(out)
797 default:
798 d.terror(n, mapTag, out)
799 return false
800 }
801
802 outt := out.Type()
803 kt := outt.Key()
804 et := outt.Elem()
805
806 stringMapType := d.stringMapType
807 generalMapType := d.generalMapType
808 if outt.Elem() == ifaceType {
809 if outt.Key().Kind() == reflect.String {
810 d.stringMapType = outt
811 } else if outt.Key() == ifaceType {
812 d.generalMapType = outt
813 }
814 }
815
816 mergedFields := d.mergedFields
817 d.mergedFields = nil
818
819 var mergeNode *Node
820
821 mapIsNew := false
822 if out.IsNil() {
823 out.Set(reflect.MakeMap(outt))
824 mapIsNew = true
825 }
826 for i := 0; i < l; i += 2 {
827 if isMerge(n.Content[i]) {
828 mergeNode = n.Content[i+1]
829 continue
830 }
831 k := reflect.New(kt).Elem()
832 if d.unmarshal(n.Content[i], k) {
833 if mergedFields != nil {
834 ki := k.Interface()
835 if mergedFields[ki] {
836 continue
837 }
838 mergedFields[ki] = true
839 }
840 kkind := k.Kind()
841 if kkind == reflect.Interface {
842 kkind = k.Elem().Kind()
843 }
844 if kkind == reflect.Map || kkind == reflect.Slice {
845 failf("invalid map key: %#v", k.Interface())
846 }
847 e := reflect.New(et).Elem()
848 if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
849 out.SetMapIndex(k, e)
850 }
851 }
852 }
853
854 d.mergedFields = mergedFields
855 if mergeNode != nil {
856 d.merge(n, mergeNode, out)
857 }
858
859 d.stringMapType = stringMapType
860 d.generalMapType = generalMapType
861 return true
862}
863
864func isStringMap(n *Node) bool {
865 if n.Kind != MappingNode {
866 return false
867 }
868 l := len(n.Content)
869 for i := 0; i < l; i += 2 {
870 shortTag := n.Content[i].ShortTag()
871 if shortTag != strTag && shortTag != mergeTag {
872 return false
873 }
874 }
875 return true
876}
877
878func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
879 sinfo, err := getStructInfo(out.Type())
880 if err != nil {
881 panic(err)
882 }
883
884 var inlineMap reflect.Value
885 var elemType reflect.Type
886 if sinfo.InlineMap != -1 {
887 inlineMap = out.Field(sinfo.InlineMap)
888 elemType = inlineMap.Type().Elem()
889 }
890
891 for _, index := range sinfo.InlineUnmarshalers {
892 field := d.fieldByIndex(n, out, index)
893 d.prepare(n, field)
894 }
895
896 mergedFields := d.mergedFields
897 d.mergedFields = nil
898 var mergeNode *Node
899 var doneFields []bool
900 if d.uniqueKeys {
901 doneFields = make([]bool, len(sinfo.FieldsList))
902 }
903 name := settableValueOf("")
904 l := len(n.Content)
905 for i := 0; i < l; i += 2 {
906 ni := n.Content[i]
907 if isMerge(ni) {
908 mergeNode = n.Content[i+1]
909 continue
910 }
911 if !d.unmarshal(ni, name) {
912 continue
913 }
914 sname := name.String()
915 if mergedFields != nil {
916 if mergedFields[sname] {
917 continue
918 }
919 mergedFields[sname] = true
920 }
921 if info, ok := sinfo.FieldsMap[sname]; ok {
922 if d.uniqueKeys {
923 if doneFields[info.Id] {
924 d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
925 continue
926 }
927 doneFields[info.Id] = true
928 }
929 var field reflect.Value
930 if info.Inline == nil {
931 field = out.Field(info.Num)
932 } else {
933 field = d.fieldByIndex(n, out, info.Inline)
934 }
935 d.unmarshal(n.Content[i+1], field)
936 } else if sinfo.InlineMap != -1 {
937 if inlineMap.IsNil() {
938 inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
939 }
940 value := reflect.New(elemType).Elem()
941 d.unmarshal(n.Content[i+1], value)
942 inlineMap.SetMapIndex(name, value)
943 } else if d.knownFields {
944 d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
945 }
946 }
947
948 d.mergedFields = mergedFields
949 if mergeNode != nil {
950 d.merge(n, mergeNode, out)
951 }
952 return true
953}
954
955func failWantMap() {
956 failf("map merge requires map or sequence of maps as the value")
957}
958
959func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
960 mergedFields := d.mergedFields
961 if mergedFields == nil {
962 d.mergedFields = make(map[interface{}]bool)
963 for i := 0; i < len(parent.Content); i += 2 {
964 k := reflect.New(ifaceType).Elem()
965 if d.unmarshal(parent.Content[i], k) {
966 d.mergedFields[k.Interface()] = true
967 }
968 }
969 }
970
971 switch merge.Kind {
972 case MappingNode:
973 d.unmarshal(merge, out)
974 case AliasNode:
975 if merge.Alias != nil && merge.Alias.Kind != MappingNode {
976 failWantMap()
977 }
978 d.unmarshal(merge, out)
979 case SequenceNode:
980 for i := 0; i < len(merge.Content); i++ {
981 ni := merge.Content[i]
982 if ni.Kind == AliasNode {
983 if ni.Alias != nil && ni.Alias.Kind != MappingNode {
984 failWantMap()
985 }
986 } else if ni.Kind != MappingNode {
987 failWantMap()
988 }
989 d.unmarshal(ni, out)
990 }
991 default:
992 failWantMap()
993 }
994
995 d.mergedFields = mergedFields
996}
997
998func isMerge(n *Node) bool {
999 return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
1000}
diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go
new file mode 100644
index 0000000..0f47c9c
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/emitterc.go
@@ -0,0 +1,2020 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "bytes"
27 "fmt"
28)
29
30// Flush the buffer if needed.
31func flush(emitter *yaml_emitter_t) bool {
32 if emitter.buffer_pos+5 >= len(emitter.buffer) {
33 return yaml_emitter_flush(emitter)
34 }
35 return true
36}
37
38// Put a character to the output buffer.
39func put(emitter *yaml_emitter_t, value byte) bool {
40 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
41 return false
42 }
43 emitter.buffer[emitter.buffer_pos] = value
44 emitter.buffer_pos++
45 emitter.column++
46 return true
47}
48
49// Put a line break to the output buffer.
50func put_break(emitter *yaml_emitter_t) bool {
51 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
52 return false
53 }
54 switch emitter.line_break {
55 case yaml_CR_BREAK:
56 emitter.buffer[emitter.buffer_pos] = '\r'
57 emitter.buffer_pos += 1
58 case yaml_LN_BREAK:
59 emitter.buffer[emitter.buffer_pos] = '\n'
60 emitter.buffer_pos += 1
61 case yaml_CRLN_BREAK:
62 emitter.buffer[emitter.buffer_pos+0] = '\r'
63 emitter.buffer[emitter.buffer_pos+1] = '\n'
64 emitter.buffer_pos += 2
65 default:
66 panic("unknown line break setting")
67 }
68 if emitter.column == 0 {
69 emitter.space_above = true
70 }
71 emitter.column = 0
72 emitter.line++
73 // [Go] Do this here and below and drop from everywhere else (see commented lines).
74 emitter.indention = true
75 return true
76}
77
78// Copy a character from a string into buffer.
79func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
80 if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
81 return false
82 }
83 p := emitter.buffer_pos
84 w := width(s[*i])
85 switch w {
86 case 4:
87 emitter.buffer[p+3] = s[*i+3]
88 fallthrough
89 case 3:
90 emitter.buffer[p+2] = s[*i+2]
91 fallthrough
92 case 2:
93 emitter.buffer[p+1] = s[*i+1]
94 fallthrough
95 case 1:
96 emitter.buffer[p+0] = s[*i+0]
97 default:
98 panic("unknown character width")
99 }
100 emitter.column++
101 emitter.buffer_pos += w
102 *i += w
103 return true
104}
105
106// Write a whole string into buffer.
107func write_all(emitter *yaml_emitter_t, s []byte) bool {
108 for i := 0; i < len(s); {
109 if !write(emitter, s, &i) {
110 return false
111 }
112 }
113 return true
114}
115
116// Copy a line break character from a string into buffer.
117func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
118 if s[*i] == '\n' {
119 if !put_break(emitter) {
120 return false
121 }
122 *i++
123 } else {
124 if !write(emitter, s, i) {
125 return false
126 }
127 if emitter.column == 0 {
128 emitter.space_above = true
129 }
130 emitter.column = 0
131 emitter.line++
132 // [Go] Do this here and above and drop from everywhere else (see commented lines).
133 emitter.indention = true
134 }
135 return true
136}
137
138// Set an emitter error and return false.
139func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
140 emitter.error = yaml_EMITTER_ERROR
141 emitter.problem = problem
142 return false
143}
144
145// Emit an event.
146func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
147 emitter.events = append(emitter.events, *event)
148 for !yaml_emitter_need_more_events(emitter) {
149 event := &emitter.events[emitter.events_head]
150 if !yaml_emitter_analyze_event(emitter, event) {
151 return false
152 }
153 if !yaml_emitter_state_machine(emitter, event) {
154 return false
155 }
156 yaml_event_delete(event)
157 emitter.events_head++
158 }
159 return true
160}
161
162// Check if we need to accumulate more events before emitting.
163//
164// We accumulate extra
165// - 1 event for DOCUMENT-START
166// - 2 events for SEQUENCE-START
167// - 3 events for MAPPING-START
168//
169func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
170 if emitter.events_head == len(emitter.events) {
171 return true
172 }
173 var accumulate int
174 switch emitter.events[emitter.events_head].typ {
175 case yaml_DOCUMENT_START_EVENT:
176 accumulate = 1
177 break
178 case yaml_SEQUENCE_START_EVENT:
179 accumulate = 2
180 break
181 case yaml_MAPPING_START_EVENT:
182 accumulate = 3
183 break
184 default:
185 return false
186 }
187 if len(emitter.events)-emitter.events_head > accumulate {
188 return false
189 }
190 var level int
191 for i := emitter.events_head; i < len(emitter.events); i++ {
192 switch emitter.events[i].typ {
193 case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
194 level++
195 case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
196 level--
197 }
198 if level == 0 {
199 return false
200 }
201 }
202 return true
203}
204
205// Append a directive to the directives stack.
206func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
207 for i := 0; i < len(emitter.tag_directives); i++ {
208 if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
209 if allow_duplicates {
210 return true
211 }
212 return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
213 }
214 }
215
216 // [Go] Do we actually need to copy this given garbage collection
217 // and the lack of deallocating destructors?
218 tag_copy := yaml_tag_directive_t{
219 handle: make([]byte, len(value.handle)),
220 prefix: make([]byte, len(value.prefix)),
221 }
222 copy(tag_copy.handle, value.handle)
223 copy(tag_copy.prefix, value.prefix)
224 emitter.tag_directives = append(emitter.tag_directives, tag_copy)
225 return true
226}
227
228// Increase the indentation level.
229func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
230 emitter.indents = append(emitter.indents, emitter.indent)
231 if emitter.indent < 0 {
232 if flow {
233 emitter.indent = emitter.best_indent
234 } else {
235 emitter.indent = 0
236 }
237 } else if !indentless {
238 // [Go] This was changed so that indentations are more regular.
239 if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
240 // The first indent inside a sequence will just skip the "- " indicator.
241 emitter.indent += 2
242 } else {
243 // Everything else aligns to the chosen indentation.
244 emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
245 }
246 }
247 return true
248}
249
250// State dispatcher.
251func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
252 switch emitter.state {
253 default:
254 case yaml_EMIT_STREAM_START_STATE:
255 return yaml_emitter_emit_stream_start(emitter, event)
256
257 case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
258 return yaml_emitter_emit_document_start(emitter, event, true)
259
260 case yaml_EMIT_DOCUMENT_START_STATE:
261 return yaml_emitter_emit_document_start(emitter, event, false)
262
263 case yaml_EMIT_DOCUMENT_CONTENT_STATE:
264 return yaml_emitter_emit_document_content(emitter, event)
265
266 case yaml_EMIT_DOCUMENT_END_STATE:
267 return yaml_emitter_emit_document_end(emitter, event)
268
269 case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
270 return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
271
272 case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
273 return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
274
275 case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
276 return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
277
278 case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
279 return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
280
281 case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
282 return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
283
284 case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
285 return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
286
287 case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
288 return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
289
290 case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
291 return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
292
293 case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
294 return yaml_emitter_emit_block_sequence_item(emitter, event, true)
295
296 case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
297 return yaml_emitter_emit_block_sequence_item(emitter, event, false)
298
299 case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
300 return yaml_emitter_emit_block_mapping_key(emitter, event, true)
301
302 case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
303 return yaml_emitter_emit_block_mapping_key(emitter, event, false)
304
305 case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
306 return yaml_emitter_emit_block_mapping_value(emitter, event, true)
307
308 case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
309 return yaml_emitter_emit_block_mapping_value(emitter, event, false)
310
311 case yaml_EMIT_END_STATE:
312 return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
313 }
314 panic("invalid emitter state")
315}
316
317// Expect STREAM-START.
318func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
319 if event.typ != yaml_STREAM_START_EVENT {
320 return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
321 }
322 if emitter.encoding == yaml_ANY_ENCODING {
323 emitter.encoding = event.encoding
324 if emitter.encoding == yaml_ANY_ENCODING {
325 emitter.encoding = yaml_UTF8_ENCODING
326 }
327 }
328 if emitter.best_indent < 2 || emitter.best_indent > 9 {
329 emitter.best_indent = 2
330 }
331 if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
332 emitter.best_width = 80
333 }
334 if emitter.best_width < 0 {
335 emitter.best_width = 1<<31 - 1
336 }
337 if emitter.line_break == yaml_ANY_BREAK {
338 emitter.line_break = yaml_LN_BREAK
339 }
340
341 emitter.indent = -1
342 emitter.line = 0
343 emitter.column = 0
344 emitter.whitespace = true
345 emitter.indention = true
346 emitter.space_above = true
347 emitter.foot_indent = -1
348
349 if emitter.encoding != yaml_UTF8_ENCODING {
350 if !yaml_emitter_write_bom(emitter) {
351 return false
352 }
353 }
354 emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
355 return true
356}
357
358// Expect DOCUMENT-START or STREAM-END.
359func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
360
361 if event.typ == yaml_DOCUMENT_START_EVENT {
362
363 if event.version_directive != nil {
364 if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
365 return false
366 }
367 }
368
369 for i := 0; i < len(event.tag_directives); i++ {
370 tag_directive := &event.tag_directives[i]
371 if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
372 return false
373 }
374 if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
375 return false
376 }
377 }
378
379 for i := 0; i < len(default_tag_directives); i++ {
380 tag_directive := &default_tag_directives[i]
381 if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
382 return false
383 }
384 }
385
386 implicit := event.implicit
387 if !first || emitter.canonical {
388 implicit = false
389 }
390
391 if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
392 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
393 return false
394 }
395 if !yaml_emitter_write_indent(emitter) {
396 return false
397 }
398 }
399
400 if event.version_directive != nil {
401 implicit = false
402 if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
403 return false
404 }
405 if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
406 return false
407 }
408 if !yaml_emitter_write_indent(emitter) {
409 return false
410 }
411 }
412
413 if len(event.tag_directives) > 0 {
414 implicit = false
415 for i := 0; i < len(event.tag_directives); i++ {
416 tag_directive := &event.tag_directives[i]
417 if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
418 return false
419 }
420 if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
421 return false
422 }
423 if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
424 return false
425 }
426 if !yaml_emitter_write_indent(emitter) {
427 return false
428 }
429 }
430 }
431
432 if yaml_emitter_check_empty_document(emitter) {
433 implicit = false
434 }
435 if !implicit {
436 if !yaml_emitter_write_indent(emitter) {
437 return false
438 }
439 if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
440 return false
441 }
442 if emitter.canonical || true {
443 if !yaml_emitter_write_indent(emitter) {
444 return false
445 }
446 }
447 }
448
449 if len(emitter.head_comment) > 0 {
450 if !yaml_emitter_process_head_comment(emitter) {
451 return false
452 }
453 if !put_break(emitter) {
454 return false
455 }
456 }
457
458 emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
459 return true
460 }
461
462 if event.typ == yaml_STREAM_END_EVENT {
463 if emitter.open_ended {
464 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
465 return false
466 }
467 if !yaml_emitter_write_indent(emitter) {
468 return false
469 }
470 }
471 if !yaml_emitter_flush(emitter) {
472 return false
473 }
474 emitter.state = yaml_EMIT_END_STATE
475 return true
476 }
477
478 return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
479}
480
481// Expect the root node.
482func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
483 emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
484
485 if !yaml_emitter_process_head_comment(emitter) {
486 return false
487 }
488 if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
489 return false
490 }
491 if !yaml_emitter_process_line_comment(emitter) {
492 return false
493 }
494 if !yaml_emitter_process_foot_comment(emitter) {
495 return false
496 }
497 return true
498}
499
500// Expect DOCUMENT-END.
501func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
502 if event.typ != yaml_DOCUMENT_END_EVENT {
503 return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
504 }
505 // [Go] Force document foot separation.
506 emitter.foot_indent = 0
507 if !yaml_emitter_process_foot_comment(emitter) {
508 return false
509 }
510 emitter.foot_indent = -1
511 if !yaml_emitter_write_indent(emitter) {
512 return false
513 }
514 if !event.implicit {
515 // [Go] Allocate the slice elsewhere.
516 if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
517 return false
518 }
519 if !yaml_emitter_write_indent(emitter) {
520 return false
521 }
522 }
523 if !yaml_emitter_flush(emitter) {
524 return false
525 }
526 emitter.state = yaml_EMIT_DOCUMENT_START_STATE
527 emitter.tag_directives = emitter.tag_directives[:0]
528 return true
529}
530
531// Expect a flow item node.
532func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
533 if first {
534 if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
535 return false
536 }
537 if !yaml_emitter_increase_indent(emitter, true, false) {
538 return false
539 }
540 emitter.flow_level++
541 }
542
543 if event.typ == yaml_SEQUENCE_END_EVENT {
544 if emitter.canonical && !first && !trail {
545 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
546 return false
547 }
548 }
549 emitter.flow_level--
550 emitter.indent = emitter.indents[len(emitter.indents)-1]
551 emitter.indents = emitter.indents[:len(emitter.indents)-1]
552 if emitter.column == 0 || emitter.canonical && !first {
553 if !yaml_emitter_write_indent(emitter) {
554 return false
555 }
556 }
557 if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
558 return false
559 }
560 if !yaml_emitter_process_line_comment(emitter) {
561 return false
562 }
563 if !yaml_emitter_process_foot_comment(emitter) {
564 return false
565 }
566 emitter.state = emitter.states[len(emitter.states)-1]
567 emitter.states = emitter.states[:len(emitter.states)-1]
568
569 return true
570 }
571
572 if !first && !trail {
573 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
574 return false
575 }
576 }
577
578 if !yaml_emitter_process_head_comment(emitter) {
579 return false
580 }
581 if emitter.column == 0 {
582 if !yaml_emitter_write_indent(emitter) {
583 return false
584 }
585 }
586
587 if emitter.canonical || emitter.column > emitter.best_width {
588 if !yaml_emitter_write_indent(emitter) {
589 return false
590 }
591 }
592 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
593 emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
594 } else {
595 emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
596 }
597 if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
598 return false
599 }
600 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
601 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
602 return false
603 }
604 }
605 if !yaml_emitter_process_line_comment(emitter) {
606 return false
607 }
608 if !yaml_emitter_process_foot_comment(emitter) {
609 return false
610 }
611 return true
612}
613
614// Expect a flow key node.
615func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
616 if first {
617 if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
618 return false
619 }
620 if !yaml_emitter_increase_indent(emitter, true, false) {
621 return false
622 }
623 emitter.flow_level++
624 }
625
626 if event.typ == yaml_MAPPING_END_EVENT {
627 if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
628 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
629 return false
630 }
631 }
632 if !yaml_emitter_process_head_comment(emitter) {
633 return false
634 }
635 emitter.flow_level--
636 emitter.indent = emitter.indents[len(emitter.indents)-1]
637 emitter.indents = emitter.indents[:len(emitter.indents)-1]
638 if emitter.canonical && !first {
639 if !yaml_emitter_write_indent(emitter) {
640 return false
641 }
642 }
643 if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
644 return false
645 }
646 if !yaml_emitter_process_line_comment(emitter) {
647 return false
648 }
649 if !yaml_emitter_process_foot_comment(emitter) {
650 return false
651 }
652 emitter.state = emitter.states[len(emitter.states)-1]
653 emitter.states = emitter.states[:len(emitter.states)-1]
654 return true
655 }
656
657 if !first && !trail {
658 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
659 return false
660 }
661 }
662
663 if !yaml_emitter_process_head_comment(emitter) {
664 return false
665 }
666
667 if emitter.column == 0 {
668 if !yaml_emitter_write_indent(emitter) {
669 return false
670 }
671 }
672
673 if emitter.canonical || emitter.column > emitter.best_width {
674 if !yaml_emitter_write_indent(emitter) {
675 return false
676 }
677 }
678
679 if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
680 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
681 return yaml_emitter_emit_node(emitter, event, false, false, true, true)
682 }
683 if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
684 return false
685 }
686 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
687 return yaml_emitter_emit_node(emitter, event, false, false, true, false)
688}
689
690// Expect a flow value node.
691func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
692 if simple {
693 if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
694 return false
695 }
696 } else {
697 if emitter.canonical || emitter.column > emitter.best_width {
698 if !yaml_emitter_write_indent(emitter) {
699 return false
700 }
701 }
702 if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
703 return false
704 }
705 }
706 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
707 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
708 } else {
709 emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
710 }
711 if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
712 return false
713 }
714 if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
715 if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
716 return false
717 }
718 }
719 if !yaml_emitter_process_line_comment(emitter) {
720 return false
721 }
722 if !yaml_emitter_process_foot_comment(emitter) {
723 return false
724 }
725 return true
726}
727
728// Expect a block item node.
729func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
730 if first {
731 if !yaml_emitter_increase_indent(emitter, false, false) {
732 return false
733 }
734 }
735 if event.typ == yaml_SEQUENCE_END_EVENT {
736 emitter.indent = emitter.indents[len(emitter.indents)-1]
737 emitter.indents = emitter.indents[:len(emitter.indents)-1]
738 emitter.state = emitter.states[len(emitter.states)-1]
739 emitter.states = emitter.states[:len(emitter.states)-1]
740 return true
741 }
742 if !yaml_emitter_process_head_comment(emitter) {
743 return false
744 }
745 if !yaml_emitter_write_indent(emitter) {
746 return false
747 }
748 if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
749 return false
750 }
751 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
752 if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
753 return false
754 }
755 if !yaml_emitter_process_line_comment(emitter) {
756 return false
757 }
758 if !yaml_emitter_process_foot_comment(emitter) {
759 return false
760 }
761 return true
762}
763
764// Expect a block key node.
765func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
766 if first {
767 if !yaml_emitter_increase_indent(emitter, false, false) {
768 return false
769 }
770 }
771 if !yaml_emitter_process_head_comment(emitter) {
772 return false
773 }
774 if event.typ == yaml_MAPPING_END_EVENT {
775 emitter.indent = emitter.indents[len(emitter.indents)-1]
776 emitter.indents = emitter.indents[:len(emitter.indents)-1]
777 emitter.state = emitter.states[len(emitter.states)-1]
778 emitter.states = emitter.states[:len(emitter.states)-1]
779 return true
780 }
781 if !yaml_emitter_write_indent(emitter) {
782 return false
783 }
784 if len(emitter.line_comment) > 0 {
785 // [Go] A line comment was provided for the key. That's unusual as the
786 // scanner associates line comments with the value. Either way,
787 // save the line comment and render it appropriately later.
788 emitter.key_line_comment = emitter.line_comment
789 emitter.line_comment = nil
790 }
791 if yaml_emitter_check_simple_key(emitter) {
792 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
793 return yaml_emitter_emit_node(emitter, event, false, false, true, true)
794 }
795 if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
796 return false
797 }
798 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
799 return yaml_emitter_emit_node(emitter, event, false, false, true, false)
800}
801
802// Expect a block value node.
803func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
804 if simple {
805 if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
806 return false
807 }
808 } else {
809 if !yaml_emitter_write_indent(emitter) {
810 return false
811 }
812 if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
813 return false
814 }
815 }
816 if len(emitter.key_line_comment) > 0 {
817 // [Go] Line comments are generally associated with the value, but when there's
818 // no value on the same line as a mapping key they end up attached to the
819 // key itself.
820 if event.typ == yaml_SCALAR_EVENT {
821 if len(emitter.line_comment) == 0 {
822 // A scalar is coming and it has no line comments by itself yet,
823 // so just let it handle the line comment as usual. If it has a
824 // line comment, we can't have both so the one from the key is lost.
825 emitter.line_comment = emitter.key_line_comment
826 emitter.key_line_comment = nil
827 }
828 } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
829 // An indented block follows, so write the comment right now.
830 emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
831 if !yaml_emitter_process_line_comment(emitter) {
832 return false
833 }
834 emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
835 }
836 }
837 emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
838 if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
839 return false
840 }
841 if !yaml_emitter_process_line_comment(emitter) {
842 return false
843 }
844 if !yaml_emitter_process_foot_comment(emitter) {
845 return false
846 }
847 return true
848}
849
850func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
851 return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
852}
853
854// Expect a node.
855func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
856 root bool, sequence bool, mapping bool, simple_key bool) bool {
857
858 emitter.root_context = root
859 emitter.sequence_context = sequence
860 emitter.mapping_context = mapping
861 emitter.simple_key_context = simple_key
862
863 switch event.typ {
864 case yaml_ALIAS_EVENT:
865 return yaml_emitter_emit_alias(emitter, event)
866 case yaml_SCALAR_EVENT:
867 return yaml_emitter_emit_scalar(emitter, event)
868 case yaml_SEQUENCE_START_EVENT:
869 return yaml_emitter_emit_sequence_start(emitter, event)
870 case yaml_MAPPING_START_EVENT:
871 return yaml_emitter_emit_mapping_start(emitter, event)
872 default:
873 return yaml_emitter_set_emitter_error(emitter,
874 fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
875 }
876}
877
878// Expect ALIAS.
879func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
880 if !yaml_emitter_process_anchor(emitter) {
881 return false
882 }
883 emitter.state = emitter.states[len(emitter.states)-1]
884 emitter.states = emitter.states[:len(emitter.states)-1]
885 return true
886}
887
888// Expect SCALAR.
889func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
890 if !yaml_emitter_select_scalar_style(emitter, event) {
891 return false
892 }
893 if !yaml_emitter_process_anchor(emitter) {
894 return false
895 }
896 if !yaml_emitter_process_tag(emitter) {
897 return false
898 }
899 if !yaml_emitter_increase_indent(emitter, true, false) {
900 return false
901 }
902 if !yaml_emitter_process_scalar(emitter) {
903 return false
904 }
905 emitter.indent = emitter.indents[len(emitter.indents)-1]
906 emitter.indents = emitter.indents[:len(emitter.indents)-1]
907 emitter.state = emitter.states[len(emitter.states)-1]
908 emitter.states = emitter.states[:len(emitter.states)-1]
909 return true
910}
911
912// Expect SEQUENCE-START.
913func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
914 if !yaml_emitter_process_anchor(emitter) {
915 return false
916 }
917 if !yaml_emitter_process_tag(emitter) {
918 return false
919 }
920 if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
921 yaml_emitter_check_empty_sequence(emitter) {
922 emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
923 } else {
924 emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
925 }
926 return true
927}
928
929// Expect MAPPING-START.
930func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
931 if !yaml_emitter_process_anchor(emitter) {
932 return false
933 }
934 if !yaml_emitter_process_tag(emitter) {
935 return false
936 }
937 if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
938 yaml_emitter_check_empty_mapping(emitter) {
939 emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
940 } else {
941 emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
942 }
943 return true
944}
945
946// Check if the document content is an empty scalar.
947func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
948 return false // [Go] Huh?
949}
950
951// Check if the next events represent an empty sequence.
952func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
953 if len(emitter.events)-emitter.events_head < 2 {
954 return false
955 }
956 return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
957 emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
958}
959
960// Check if the next events represent an empty mapping.
961func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
962 if len(emitter.events)-emitter.events_head < 2 {
963 return false
964 }
965 return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
966 emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
967}
968
969// Check if the next node can be expressed as a simple key.
970func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
971 length := 0
972 switch emitter.events[emitter.events_head].typ {
973 case yaml_ALIAS_EVENT:
974 length += len(emitter.anchor_data.anchor)
975 case yaml_SCALAR_EVENT:
976 if emitter.scalar_data.multiline {
977 return false
978 }
979 length += len(emitter.anchor_data.anchor) +
980 len(emitter.tag_data.handle) +
981 len(emitter.tag_data.suffix) +
982 len(emitter.scalar_data.value)
983 case yaml_SEQUENCE_START_EVENT:
984 if !yaml_emitter_check_empty_sequence(emitter) {
985 return false
986 }
987 length += len(emitter.anchor_data.anchor) +
988 len(emitter.tag_data.handle) +
989 len(emitter.tag_data.suffix)
990 case yaml_MAPPING_START_EVENT:
991 if !yaml_emitter_check_empty_mapping(emitter) {
992 return false
993 }
994 length += len(emitter.anchor_data.anchor) +
995 len(emitter.tag_data.handle) +
996 len(emitter.tag_data.suffix)
997 default:
998 return false
999 }
1000 return length <= 128
1001}
1002
1003// Determine an acceptable scalar style.
1004func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
1005
1006 no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
1007 if no_tag && !event.implicit && !event.quoted_implicit {
1008 return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
1009 }
1010
1011 style := event.scalar_style()
1012 if style == yaml_ANY_SCALAR_STYLE {
1013 style = yaml_PLAIN_SCALAR_STYLE
1014 }
1015 if emitter.canonical {
1016 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1017 }
1018 if emitter.simple_key_context && emitter.scalar_data.multiline {
1019 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1020 }
1021
1022 if style == yaml_PLAIN_SCALAR_STYLE {
1023 if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
1024 emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
1025 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1026 }
1027 if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
1028 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1029 }
1030 if no_tag && !event.implicit {
1031 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
1032 }
1033 }
1034 if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
1035 if !emitter.scalar_data.single_quoted_allowed {
1036 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1037 }
1038 }
1039 if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
1040 if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
1041 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
1042 }
1043 }
1044
1045 if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
1046 emitter.tag_data.handle = []byte{'!'}
1047 }
1048 emitter.scalar_data.style = style
1049 return true
1050}
1051
1052// Write an anchor.
1053func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
1054 if emitter.anchor_data.anchor == nil {
1055 return true
1056 }
1057 c := []byte{'&'}
1058 if emitter.anchor_data.alias {
1059 c[0] = '*'
1060 }
1061 if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
1062 return false
1063 }
1064 return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
1065}
1066
1067// Write a tag.
1068func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
1069 if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
1070 return true
1071 }
1072 if len(emitter.tag_data.handle) > 0 {
1073 if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
1074 return false
1075 }
1076 if len(emitter.tag_data.suffix) > 0 {
1077 if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
1078 return false
1079 }
1080 }
1081 } else {
1082 // [Go] Allocate these slices elsewhere.
1083 if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
1084 return false
1085 }
1086 if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
1087 return false
1088 }
1089 if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
1090 return false
1091 }
1092 }
1093 return true
1094}
1095
1096// Write a scalar.
1097func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
1098 switch emitter.scalar_data.style {
1099 case yaml_PLAIN_SCALAR_STYLE:
1100 return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1101
1102 case yaml_SINGLE_QUOTED_SCALAR_STYLE:
1103 return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1104
1105 case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
1106 return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
1107
1108 case yaml_LITERAL_SCALAR_STYLE:
1109 return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
1110
1111 case yaml_FOLDED_SCALAR_STYLE:
1112 return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
1113 }
1114 panic("unknown scalar style")
1115}
1116
1117// Write a head comment.
1118func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
1119 if len(emitter.tail_comment) > 0 {
1120 if !yaml_emitter_write_indent(emitter) {
1121 return false
1122 }
1123 if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
1124 return false
1125 }
1126 emitter.tail_comment = emitter.tail_comment[:0]
1127 emitter.foot_indent = emitter.indent
1128 if emitter.foot_indent < 0 {
1129 emitter.foot_indent = 0
1130 }
1131 }
1132
1133 if len(emitter.head_comment) == 0 {
1134 return true
1135 }
1136 if !yaml_emitter_write_indent(emitter) {
1137 return false
1138 }
1139 if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
1140 return false
1141 }
1142 emitter.head_comment = emitter.head_comment[:0]
1143 return true
1144}
1145
1146// Write an line comment.
1147func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
1148 if len(emitter.line_comment) == 0 {
1149 return true
1150 }
1151 if !emitter.whitespace {
1152 if !put(emitter, ' ') {
1153 return false
1154 }
1155 }
1156 if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
1157 return false
1158 }
1159 emitter.line_comment = emitter.line_comment[:0]
1160 return true
1161}
1162
1163// Write a foot comment.
1164func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
1165 if len(emitter.foot_comment) == 0 {
1166 return true
1167 }
1168 if !yaml_emitter_write_indent(emitter) {
1169 return false
1170 }
1171 if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
1172 return false
1173 }
1174 emitter.foot_comment = emitter.foot_comment[:0]
1175 emitter.foot_indent = emitter.indent
1176 if emitter.foot_indent < 0 {
1177 emitter.foot_indent = 0
1178 }
1179 return true
1180}
1181
1182// Check if a %YAML directive is valid.
1183func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
1184 if version_directive.major != 1 || version_directive.minor != 1 {
1185 return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
1186 }
1187 return true
1188}
1189
1190// Check if a %TAG directive is valid.
1191func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
1192 handle := tag_directive.handle
1193 prefix := tag_directive.prefix
1194 if len(handle) == 0 {
1195 return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
1196 }
1197 if handle[0] != '!' {
1198 return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
1199 }
1200 if handle[len(handle)-1] != '!' {
1201 return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
1202 }
1203 for i := 1; i < len(handle)-1; i += width(handle[i]) {
1204 if !is_alpha(handle, i) {
1205 return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
1206 }
1207 }
1208 if len(prefix) == 0 {
1209 return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
1210 }
1211 return true
1212}
1213
1214// Check if an anchor is valid.
1215func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
1216 if len(anchor) == 0 {
1217 problem := "anchor value must not be empty"
1218 if alias {
1219 problem = "alias value must not be empty"
1220 }
1221 return yaml_emitter_set_emitter_error(emitter, problem)
1222 }
1223 for i := 0; i < len(anchor); i += width(anchor[i]) {
1224 if !is_alpha(anchor, i) {
1225 problem := "anchor value must contain alphanumerical characters only"
1226 if alias {
1227 problem = "alias value must contain alphanumerical characters only"
1228 }
1229 return yaml_emitter_set_emitter_error(emitter, problem)
1230 }
1231 }
1232 emitter.anchor_data.anchor = anchor
1233 emitter.anchor_data.alias = alias
1234 return true
1235}
1236
1237// Check if a tag is valid.
1238func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
1239 if len(tag) == 0 {
1240 return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
1241 }
1242 for i := 0; i < len(emitter.tag_directives); i++ {
1243 tag_directive := &emitter.tag_directives[i]
1244 if bytes.HasPrefix(tag, tag_directive.prefix) {
1245 emitter.tag_data.handle = tag_directive.handle
1246 emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
1247 return true
1248 }
1249 }
1250 emitter.tag_data.suffix = tag
1251 return true
1252}
1253
1254// Check if a scalar is valid.
1255func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
1256 var (
1257 block_indicators = false
1258 flow_indicators = false
1259 line_breaks = false
1260 special_characters = false
1261 tab_characters = false
1262
1263 leading_space = false
1264 leading_break = false
1265 trailing_space = false
1266 trailing_break = false
1267 break_space = false
1268 space_break = false
1269
1270 preceded_by_whitespace = false
1271 followed_by_whitespace = false
1272 previous_space = false
1273 previous_break = false
1274 )
1275
1276 emitter.scalar_data.value = value
1277
1278 if len(value) == 0 {
1279 emitter.scalar_data.multiline = false
1280 emitter.scalar_data.flow_plain_allowed = false
1281 emitter.scalar_data.block_plain_allowed = true
1282 emitter.scalar_data.single_quoted_allowed = true
1283 emitter.scalar_data.block_allowed = false
1284 return true
1285 }
1286
1287 if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
1288 block_indicators = true
1289 flow_indicators = true
1290 }
1291
1292 preceded_by_whitespace = true
1293 for i, w := 0, 0; i < len(value); i += w {
1294 w = width(value[i])
1295 followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
1296
1297 if i == 0 {
1298 switch value[i] {
1299 case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
1300 flow_indicators = true
1301 block_indicators = true
1302 case '?', ':':
1303 flow_indicators = true
1304 if followed_by_whitespace {
1305 block_indicators = true
1306 }
1307 case '-':
1308 if followed_by_whitespace {
1309 flow_indicators = true
1310 block_indicators = true
1311 }
1312 }
1313 } else {
1314 switch value[i] {
1315 case ',', '?', '[', ']', '{', '}':
1316 flow_indicators = true
1317 case ':':
1318 flow_indicators = true
1319 if followed_by_whitespace {
1320 block_indicators = true
1321 }
1322 case '#':
1323 if preceded_by_whitespace {
1324 flow_indicators = true
1325 block_indicators = true
1326 }
1327 }
1328 }
1329
1330 if value[i] == '\t' {
1331 tab_characters = true
1332 } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
1333 special_characters = true
1334 }
1335 if is_space(value, i) {
1336 if i == 0 {
1337 leading_space = true
1338 }
1339 if i+width(value[i]) == len(value) {
1340 trailing_space = true
1341 }
1342 if previous_break {
1343 break_space = true
1344 }
1345 previous_space = true
1346 previous_break = false
1347 } else if is_break(value, i) {
1348 line_breaks = true
1349 if i == 0 {
1350 leading_break = true
1351 }
1352 if i+width(value[i]) == len(value) {
1353 trailing_break = true
1354 }
1355 if previous_space {
1356 space_break = true
1357 }
1358 previous_space = false
1359 previous_break = true
1360 } else {
1361 previous_space = false
1362 previous_break = false
1363 }
1364
1365 // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
1366 preceded_by_whitespace = is_blankz(value, i)
1367 }
1368
1369 emitter.scalar_data.multiline = line_breaks
1370 emitter.scalar_data.flow_plain_allowed = true
1371 emitter.scalar_data.block_plain_allowed = true
1372 emitter.scalar_data.single_quoted_allowed = true
1373 emitter.scalar_data.block_allowed = true
1374
1375 if leading_space || leading_break || trailing_space || trailing_break {
1376 emitter.scalar_data.flow_plain_allowed = false
1377 emitter.scalar_data.block_plain_allowed = false
1378 }
1379 if trailing_space {
1380 emitter.scalar_data.block_allowed = false
1381 }
1382 if break_space {
1383 emitter.scalar_data.flow_plain_allowed = false
1384 emitter.scalar_data.block_plain_allowed = false
1385 emitter.scalar_data.single_quoted_allowed = false
1386 }
1387 if space_break || tab_characters || special_characters {
1388 emitter.scalar_data.flow_plain_allowed = false
1389 emitter.scalar_data.block_plain_allowed = false
1390 emitter.scalar_data.single_quoted_allowed = false
1391 }
1392 if space_break || special_characters {
1393 emitter.scalar_data.block_allowed = false
1394 }
1395 if line_breaks {
1396 emitter.scalar_data.flow_plain_allowed = false
1397 emitter.scalar_data.block_plain_allowed = false
1398 }
1399 if flow_indicators {
1400 emitter.scalar_data.flow_plain_allowed = false
1401 }
1402 if block_indicators {
1403 emitter.scalar_data.block_plain_allowed = false
1404 }
1405 return true
1406}
1407
1408// Check if the event data is valid.
1409func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
1410
1411 emitter.anchor_data.anchor = nil
1412 emitter.tag_data.handle = nil
1413 emitter.tag_data.suffix = nil
1414 emitter.scalar_data.value = nil
1415
1416 if len(event.head_comment) > 0 {
1417 emitter.head_comment = event.head_comment
1418 }
1419 if len(event.line_comment) > 0 {
1420 emitter.line_comment = event.line_comment
1421 }
1422 if len(event.foot_comment) > 0 {
1423 emitter.foot_comment = event.foot_comment
1424 }
1425 if len(event.tail_comment) > 0 {
1426 emitter.tail_comment = event.tail_comment
1427 }
1428
1429 switch event.typ {
1430 case yaml_ALIAS_EVENT:
1431 if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
1432 return false
1433 }
1434
1435 case yaml_SCALAR_EVENT:
1436 if len(event.anchor) > 0 {
1437 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1438 return false
1439 }
1440 }
1441 if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
1442 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1443 return false
1444 }
1445 }
1446 if !yaml_emitter_analyze_scalar(emitter, event.value) {
1447 return false
1448 }
1449
1450 case yaml_SEQUENCE_START_EVENT:
1451 if len(event.anchor) > 0 {
1452 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1453 return false
1454 }
1455 }
1456 if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
1457 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1458 return false
1459 }
1460 }
1461
1462 case yaml_MAPPING_START_EVENT:
1463 if len(event.anchor) > 0 {
1464 if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
1465 return false
1466 }
1467 }
1468 if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
1469 if !yaml_emitter_analyze_tag(emitter, event.tag) {
1470 return false
1471 }
1472 }
1473 }
1474 return true
1475}
1476
1477// Write the BOM character.
1478func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
1479 if !flush(emitter) {
1480 return false
1481 }
1482 pos := emitter.buffer_pos
1483 emitter.buffer[pos+0] = '\xEF'
1484 emitter.buffer[pos+1] = '\xBB'
1485 emitter.buffer[pos+2] = '\xBF'
1486 emitter.buffer_pos += 3
1487 return true
1488}
1489
1490func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
1491 indent := emitter.indent
1492 if indent < 0 {
1493 indent = 0
1494 }
1495 if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
1496 if !put_break(emitter) {
1497 return false
1498 }
1499 }
1500 if emitter.foot_indent == indent {
1501 if !put_break(emitter) {
1502 return false
1503 }
1504 }
1505 for emitter.column < indent {
1506 if !put(emitter, ' ') {
1507 return false
1508 }
1509 }
1510 emitter.whitespace = true
1511 //emitter.indention = true
1512 emitter.space_above = false
1513 emitter.foot_indent = -1
1514 return true
1515}
1516
1517func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
1518 if need_whitespace && !emitter.whitespace {
1519 if !put(emitter, ' ') {
1520 return false
1521 }
1522 }
1523 if !write_all(emitter, indicator) {
1524 return false
1525 }
1526 emitter.whitespace = is_whitespace
1527 emitter.indention = (emitter.indention && is_indention)
1528 emitter.open_ended = false
1529 return true
1530}
1531
1532func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
1533 if !write_all(emitter, value) {
1534 return false
1535 }
1536 emitter.whitespace = false
1537 emitter.indention = false
1538 return true
1539}
1540
1541func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
1542 if !emitter.whitespace {
1543 if !put(emitter, ' ') {
1544 return false
1545 }
1546 }
1547 if !write_all(emitter, value) {
1548 return false
1549 }
1550 emitter.whitespace = false
1551 emitter.indention = false
1552 return true
1553}
1554
1555func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
1556 if need_whitespace && !emitter.whitespace {
1557 if !put(emitter, ' ') {
1558 return false
1559 }
1560 }
1561 for i := 0; i < len(value); {
1562 var must_write bool
1563 switch value[i] {
1564 case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
1565 must_write = true
1566 default:
1567 must_write = is_alpha(value, i)
1568 }
1569 if must_write {
1570 if !write(emitter, value, &i) {
1571 return false
1572 }
1573 } else {
1574 w := width(value[i])
1575 for k := 0; k < w; k++ {
1576 octet := value[i]
1577 i++
1578 if !put(emitter, '%') {
1579 return false
1580 }
1581
1582 c := octet >> 4
1583 if c < 10 {
1584 c += '0'
1585 } else {
1586 c += 'A' - 10
1587 }
1588 if !put(emitter, c) {
1589 return false
1590 }
1591
1592 c = octet & 0x0f
1593 if c < 10 {
1594 c += '0'
1595 } else {
1596 c += 'A' - 10
1597 }
1598 if !put(emitter, c) {
1599 return false
1600 }
1601 }
1602 }
1603 }
1604 emitter.whitespace = false
1605 emitter.indention = false
1606 return true
1607}
1608
1609func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1610 if len(value) > 0 && !emitter.whitespace {
1611 if !put(emitter, ' ') {
1612 return false
1613 }
1614 }
1615
1616 spaces := false
1617 breaks := false
1618 for i := 0; i < len(value); {
1619 if is_space(value, i) {
1620 if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
1621 if !yaml_emitter_write_indent(emitter) {
1622 return false
1623 }
1624 i += width(value[i])
1625 } else {
1626 if !write(emitter, value, &i) {
1627 return false
1628 }
1629 }
1630 spaces = true
1631 } else if is_break(value, i) {
1632 if !breaks && value[i] == '\n' {
1633 if !put_break(emitter) {
1634 return false
1635 }
1636 }
1637 if !write_break(emitter, value, &i) {
1638 return false
1639 }
1640 //emitter.indention = true
1641 breaks = true
1642 } else {
1643 if breaks {
1644 if !yaml_emitter_write_indent(emitter) {
1645 return false
1646 }
1647 }
1648 if !write(emitter, value, &i) {
1649 return false
1650 }
1651 emitter.indention = false
1652 spaces = false
1653 breaks = false
1654 }
1655 }
1656
1657 if len(value) > 0 {
1658 emitter.whitespace = false
1659 }
1660 emitter.indention = false
1661 if emitter.root_context {
1662 emitter.open_ended = true
1663 }
1664
1665 return true
1666}
1667
1668func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1669
1670 if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
1671 return false
1672 }
1673
1674 spaces := false
1675 breaks := false
1676 for i := 0; i < len(value); {
1677 if is_space(value, i) {
1678 if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
1679 if !yaml_emitter_write_indent(emitter) {
1680 return false
1681 }
1682 i += width(value[i])
1683 } else {
1684 if !write(emitter, value, &i) {
1685 return false
1686 }
1687 }
1688 spaces = true
1689 } else if is_break(value, i) {
1690 if !breaks && value[i] == '\n' {
1691 if !put_break(emitter) {
1692 return false
1693 }
1694 }
1695 if !write_break(emitter, value, &i) {
1696 return false
1697 }
1698 //emitter.indention = true
1699 breaks = true
1700 } else {
1701 if breaks {
1702 if !yaml_emitter_write_indent(emitter) {
1703 return false
1704 }
1705 }
1706 if value[i] == '\'' {
1707 if !put(emitter, '\'') {
1708 return false
1709 }
1710 }
1711 if !write(emitter, value, &i) {
1712 return false
1713 }
1714 emitter.indention = false
1715 spaces = false
1716 breaks = false
1717 }
1718 }
1719 if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
1720 return false
1721 }
1722 emitter.whitespace = false
1723 emitter.indention = false
1724 return true
1725}
1726
1727func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
1728 spaces := false
1729 if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
1730 return false
1731 }
1732
1733 for i := 0; i < len(value); {
1734 if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
1735 is_bom(value, i) || is_break(value, i) ||
1736 value[i] == '"' || value[i] == '\\' {
1737
1738 octet := value[i]
1739
1740 var w int
1741 var v rune
1742 switch {
1743 case octet&0x80 == 0x00:
1744 w, v = 1, rune(octet&0x7F)
1745 case octet&0xE0 == 0xC0:
1746 w, v = 2, rune(octet&0x1F)
1747 case octet&0xF0 == 0xE0:
1748 w, v = 3, rune(octet&0x0F)
1749 case octet&0xF8 == 0xF0:
1750 w, v = 4, rune(octet&0x07)
1751 }
1752 for k := 1; k < w; k++ {
1753 octet = value[i+k]
1754 v = (v << 6) + (rune(octet) & 0x3F)
1755 }
1756 i += w
1757
1758 if !put(emitter, '\\') {
1759 return false
1760 }
1761
1762 var ok bool
1763 switch v {
1764 case 0x00:
1765 ok = put(emitter, '0')
1766 case 0x07:
1767 ok = put(emitter, 'a')
1768 case 0x08:
1769 ok = put(emitter, 'b')
1770 case 0x09:
1771 ok = put(emitter, 't')
1772 case 0x0A:
1773 ok = put(emitter, 'n')
1774 case 0x0b:
1775 ok = put(emitter, 'v')
1776 case 0x0c:
1777 ok = put(emitter, 'f')
1778 case 0x0d:
1779 ok = put(emitter, 'r')
1780 case 0x1b:
1781 ok = put(emitter, 'e')
1782 case 0x22:
1783 ok = put(emitter, '"')
1784 case 0x5c:
1785 ok = put(emitter, '\\')
1786 case 0x85:
1787 ok = put(emitter, 'N')
1788 case 0xA0:
1789 ok = put(emitter, '_')
1790 case 0x2028:
1791 ok = put(emitter, 'L')
1792 case 0x2029:
1793 ok = put(emitter, 'P')
1794 default:
1795 if v <= 0xFF {
1796 ok = put(emitter, 'x')
1797 w = 2
1798 } else if v <= 0xFFFF {
1799 ok = put(emitter, 'u')
1800 w = 4
1801 } else {
1802 ok = put(emitter, 'U')
1803 w = 8
1804 }
1805 for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
1806 digit := byte((v >> uint(k)) & 0x0F)
1807 if digit < 10 {
1808 ok = put(emitter, digit+'0')
1809 } else {
1810 ok = put(emitter, digit+'A'-10)
1811 }
1812 }
1813 }
1814 if !ok {
1815 return false
1816 }
1817 spaces = false
1818 } else if is_space(value, i) {
1819 if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
1820 if !yaml_emitter_write_indent(emitter) {
1821 return false
1822 }
1823 if is_space(value, i+1) {
1824 if !put(emitter, '\\') {
1825 return false
1826 }
1827 }
1828 i += width(value[i])
1829 } else if !write(emitter, value, &i) {
1830 return false
1831 }
1832 spaces = true
1833 } else {
1834 if !write(emitter, value, &i) {
1835 return false
1836 }
1837 spaces = false
1838 }
1839 }
1840 if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
1841 return false
1842 }
1843 emitter.whitespace = false
1844 emitter.indention = false
1845 return true
1846}
1847
1848func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
1849 if is_space(value, 0) || is_break(value, 0) {
1850 indent_hint := []byte{'0' + byte(emitter.best_indent)}
1851 if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
1852 return false
1853 }
1854 }
1855
1856 emitter.open_ended = false
1857
1858 var chomp_hint [1]byte
1859 if len(value) == 0 {
1860 chomp_hint[0] = '-'
1861 } else {
1862 i := len(value) - 1
1863 for value[i]&0xC0 == 0x80 {
1864 i--
1865 }
1866 if !is_break(value, i) {
1867 chomp_hint[0] = '-'
1868 } else if i == 0 {
1869 chomp_hint[0] = '+'
1870 emitter.open_ended = true
1871 } else {
1872 i--
1873 for value[i]&0xC0 == 0x80 {
1874 i--
1875 }
1876 if is_break(value, i) {
1877 chomp_hint[0] = '+'
1878 emitter.open_ended = true
1879 }
1880 }
1881 }
1882 if chomp_hint[0] != 0 {
1883 if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
1884 return false
1885 }
1886 }
1887 return true
1888}
1889
1890func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
1891 if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
1892 return false
1893 }
1894 if !yaml_emitter_write_block_scalar_hints(emitter, value) {
1895 return false
1896 }
1897 if !yaml_emitter_process_line_comment(emitter) {
1898 return false
1899 }
1900 //emitter.indention = true
1901 emitter.whitespace = true
1902 breaks := true
1903 for i := 0; i < len(value); {
1904 if is_break(value, i) {
1905 if !write_break(emitter, value, &i) {
1906 return false
1907 }
1908 //emitter.indention = true
1909 breaks = true
1910 } else {
1911 if breaks {
1912 if !yaml_emitter_write_indent(emitter) {
1913 return false
1914 }
1915 }
1916 if !write(emitter, value, &i) {
1917 return false
1918 }
1919 emitter.indention = false
1920 breaks = false
1921 }
1922 }
1923
1924 return true
1925}
1926
1927func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
1928 if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
1929 return false
1930 }
1931 if !yaml_emitter_write_block_scalar_hints(emitter, value) {
1932 return false
1933 }
1934 if !yaml_emitter_process_line_comment(emitter) {
1935 return false
1936 }
1937
1938 //emitter.indention = true
1939 emitter.whitespace = true
1940
1941 breaks := true
1942 leading_spaces := true
1943 for i := 0; i < len(value); {
1944 if is_break(value, i) {
1945 if !breaks && !leading_spaces && value[i] == '\n' {
1946 k := 0
1947 for is_break(value, k) {
1948 k += width(value[k])
1949 }
1950 if !is_blankz(value, k) {
1951 if !put_break(emitter) {
1952 return false
1953 }
1954 }
1955 }
1956 if !write_break(emitter, value, &i) {
1957 return false
1958 }
1959 //emitter.indention = true
1960 breaks = true
1961 } else {
1962 if breaks {
1963 if !yaml_emitter_write_indent(emitter) {
1964 return false
1965 }
1966 leading_spaces = is_blank(value, i)
1967 }
1968 if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
1969 if !yaml_emitter_write_indent(emitter) {
1970 return false
1971 }
1972 i += width(value[i])
1973 } else {
1974 if !write(emitter, value, &i) {
1975 return false
1976 }
1977 }
1978 emitter.indention = false
1979 breaks = false
1980 }
1981 }
1982 return true
1983}
1984
1985func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
1986 breaks := false
1987 pound := false
1988 for i := 0; i < len(comment); {
1989 if is_break(comment, i) {
1990 if !write_break(emitter, comment, &i) {
1991 return false
1992 }
1993 //emitter.indention = true
1994 breaks = true
1995 pound = false
1996 } else {
1997 if breaks && !yaml_emitter_write_indent(emitter) {
1998 return false
1999 }
2000 if !pound {
2001 if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
2002 return false
2003 }
2004 pound = true
2005 }
2006 if !write(emitter, comment, &i) {
2007 return false
2008 }
2009 emitter.indention = false
2010 breaks = false
2011 }
2012 }
2013 if !breaks && !put_break(emitter) {
2014 return false
2015 }
2016
2017 emitter.whitespace = true
2018 //emitter.indention = true
2019 return true
2020}
diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go
new file mode 100644
index 0000000..de9e72a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/encode.go
@@ -0,0 +1,577 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package yaml
17
18import (
19 "encoding"
20 "fmt"
21 "io"
22 "reflect"
23 "regexp"
24 "sort"
25 "strconv"
26 "strings"
27 "time"
28 "unicode/utf8"
29)
30
31type encoder struct {
32 emitter yaml_emitter_t
33 event yaml_event_t
34 out []byte
35 flow bool
36 indent int
37 doneInit bool
38}
39
40func newEncoder() *encoder {
41 e := &encoder{}
42 yaml_emitter_initialize(&e.emitter)
43 yaml_emitter_set_output_string(&e.emitter, &e.out)
44 yaml_emitter_set_unicode(&e.emitter, true)
45 return e
46}
47
48func newEncoderWithWriter(w io.Writer) *encoder {
49 e := &encoder{}
50 yaml_emitter_initialize(&e.emitter)
51 yaml_emitter_set_output_writer(&e.emitter, w)
52 yaml_emitter_set_unicode(&e.emitter, true)
53 return e
54}
55
56func (e *encoder) init() {
57 if e.doneInit {
58 return
59 }
60 if e.indent == 0 {
61 e.indent = 4
62 }
63 e.emitter.best_indent = e.indent
64 yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
65 e.emit()
66 e.doneInit = true
67}
68
69func (e *encoder) finish() {
70 e.emitter.open_ended = false
71 yaml_stream_end_event_initialize(&e.event)
72 e.emit()
73}
74
75func (e *encoder) destroy() {
76 yaml_emitter_delete(&e.emitter)
77}
78
79func (e *encoder) emit() {
80 // This will internally delete the e.event value.
81 e.must(yaml_emitter_emit(&e.emitter, &e.event))
82}
83
84func (e *encoder) must(ok bool) {
85 if !ok {
86 msg := e.emitter.problem
87 if msg == "" {
88 msg = "unknown problem generating YAML content"
89 }
90 failf("%s", msg)
91 }
92}
93
94func (e *encoder) marshalDoc(tag string, in reflect.Value) {
95 e.init()
96 var node *Node
97 if in.IsValid() {
98 node, _ = in.Interface().(*Node)
99 }
100 if node != nil && node.Kind == DocumentNode {
101 e.nodev(in)
102 } else {
103 yaml_document_start_event_initialize(&e.event, nil, nil, true)
104 e.emit()
105 e.marshal(tag, in)
106 yaml_document_end_event_initialize(&e.event, true)
107 e.emit()
108 }
109}
110
111func (e *encoder) marshal(tag string, in reflect.Value) {
112 tag = shortTag(tag)
113 if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
114 e.nilv()
115 return
116 }
117 iface := in.Interface()
118 switch value := iface.(type) {
119 case *Node:
120 e.nodev(in)
121 return
122 case Node:
123 if !in.CanAddr() {
124 var n = reflect.New(in.Type()).Elem()
125 n.Set(in)
126 in = n
127 }
128 e.nodev(in.Addr())
129 return
130 case time.Time:
131 e.timev(tag, in)
132 return
133 case *time.Time:
134 e.timev(tag, in.Elem())
135 return
136 case time.Duration:
137 e.stringv(tag, reflect.ValueOf(value.String()))
138 return
139 case Marshaler:
140 v, err := value.MarshalYAML()
141 if err != nil {
142 fail(err)
143 }
144 if v == nil {
145 e.nilv()
146 return
147 }
148 e.marshal(tag, reflect.ValueOf(v))
149 return
150 case encoding.TextMarshaler:
151 text, err := value.MarshalText()
152 if err != nil {
153 fail(err)
154 }
155 in = reflect.ValueOf(string(text))
156 case nil:
157 e.nilv()
158 return
159 }
160 switch in.Kind() {
161 case reflect.Interface:
162 e.marshal(tag, in.Elem())
163 case reflect.Map:
164 e.mapv(tag, in)
165 case reflect.Ptr:
166 e.marshal(tag, in.Elem())
167 case reflect.Struct:
168 e.structv(tag, in)
169 case reflect.Slice, reflect.Array:
170 e.slicev(tag, in)
171 case reflect.String:
172 e.stringv(tag, in)
173 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
174 e.intv(tag, in)
175 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
176 e.uintv(tag, in)
177 case reflect.Float32, reflect.Float64:
178 e.floatv(tag, in)
179 case reflect.Bool:
180 e.boolv(tag, in)
181 default:
182 panic("cannot marshal type: " + in.Type().String())
183 }
184}
185
186func (e *encoder) mapv(tag string, in reflect.Value) {
187 e.mappingv(tag, func() {
188 keys := keyList(in.MapKeys())
189 sort.Sort(keys)
190 for _, k := range keys {
191 e.marshal("", k)
192 e.marshal("", in.MapIndex(k))
193 }
194 })
195}
196
197func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
198 for _, num := range index {
199 for {
200 if v.Kind() == reflect.Ptr {
201 if v.IsNil() {
202 return reflect.Value{}
203 }
204 v = v.Elem()
205 continue
206 }
207 break
208 }
209 v = v.Field(num)
210 }
211 return v
212}
213
214func (e *encoder) structv(tag string, in reflect.Value) {
215 sinfo, err := getStructInfo(in.Type())
216 if err != nil {
217 panic(err)
218 }
219 e.mappingv(tag, func() {
220 for _, info := range sinfo.FieldsList {
221 var value reflect.Value
222 if info.Inline == nil {
223 value = in.Field(info.Num)
224 } else {
225 value = e.fieldByIndex(in, info.Inline)
226 if !value.IsValid() {
227 continue
228 }
229 }
230 if info.OmitEmpty && isZero(value) {
231 continue
232 }
233 e.marshal("", reflect.ValueOf(info.Key))
234 e.flow = info.Flow
235 e.marshal("", value)
236 }
237 if sinfo.InlineMap >= 0 {
238 m := in.Field(sinfo.InlineMap)
239 if m.Len() > 0 {
240 e.flow = false
241 keys := keyList(m.MapKeys())
242 sort.Sort(keys)
243 for _, k := range keys {
244 if _, found := sinfo.FieldsMap[k.String()]; found {
245 panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
246 }
247 e.marshal("", k)
248 e.flow = false
249 e.marshal("", m.MapIndex(k))
250 }
251 }
252 }
253 })
254}
255
256func (e *encoder) mappingv(tag string, f func()) {
257 implicit := tag == ""
258 style := yaml_BLOCK_MAPPING_STYLE
259 if e.flow {
260 e.flow = false
261 style = yaml_FLOW_MAPPING_STYLE
262 }
263 yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
264 e.emit()
265 f()
266 yaml_mapping_end_event_initialize(&e.event)
267 e.emit()
268}
269
270func (e *encoder) slicev(tag string, in reflect.Value) {
271 implicit := tag == ""
272 style := yaml_BLOCK_SEQUENCE_STYLE
273 if e.flow {
274 e.flow = false
275 style = yaml_FLOW_SEQUENCE_STYLE
276 }
277 e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
278 e.emit()
279 n := in.Len()
280 for i := 0; i < n; i++ {
281 e.marshal("", in.Index(i))
282 }
283 e.must(yaml_sequence_end_event_initialize(&e.event))
284 e.emit()
285}
286
287// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
288//
289// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
290// in YAML 1.2 and by this package, but these should be marshalled quoted for
291// the time being for compatibility with other parsers.
292func isBase60Float(s string) (result bool) {
293 // Fast path.
294 if s == "" {
295 return false
296 }
297 c := s[0]
298 if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
299 return false
300 }
301 // Do the full match.
302 return base60float.MatchString(s)
303}
304
305// From http://yaml.org/type/float.html, except the regular expression there
306// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
307var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
308
309// isOldBool returns whether s is bool notation as defined in YAML 1.1.
310//
311// We continue to force strings that YAML 1.1 would interpret as booleans to be
312// rendered as quotes strings so that the marshalled output valid for YAML 1.1
313// parsing.
314func isOldBool(s string) (result bool) {
315 switch s {
316 case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
317 "n", "N", "no", "No", "NO", "off", "Off", "OFF":
318 return true
319 default:
320 return false
321 }
322}
323
324func (e *encoder) stringv(tag string, in reflect.Value) {
325 var style yaml_scalar_style_t
326 s := in.String()
327 canUsePlain := true
328 switch {
329 case !utf8.ValidString(s):
330 if tag == binaryTag {
331 failf("explicitly tagged !!binary data must be base64-encoded")
332 }
333 if tag != "" {
334 failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
335 }
336 // It can't be encoded directly as YAML so use a binary tag
337 // and encode it as base64.
338 tag = binaryTag
339 s = encodeBase64(s)
340 case tag == "":
341 // Check to see if it would resolve to a specific
342 // tag when encoded unquoted. If it doesn't,
343 // there's no need to quote it.
344 rtag, _ := resolve("", s)
345 canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
346 }
347 // Note: it's possible for user code to emit invalid YAML
348 // if they explicitly specify a tag and a string containing
349 // text that's incompatible with that tag.
350 switch {
351 case strings.Contains(s, "\n"):
352 if e.flow {
353 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
354 } else {
355 style = yaml_LITERAL_SCALAR_STYLE
356 }
357 case canUsePlain:
358 style = yaml_PLAIN_SCALAR_STYLE
359 default:
360 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
361 }
362 e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
363}
364
365func (e *encoder) boolv(tag string, in reflect.Value) {
366 var s string
367 if in.Bool() {
368 s = "true"
369 } else {
370 s = "false"
371 }
372 e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
373}
374
375func (e *encoder) intv(tag string, in reflect.Value) {
376 s := strconv.FormatInt(in.Int(), 10)
377 e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
378}
379
380func (e *encoder) uintv(tag string, in reflect.Value) {
381 s := strconv.FormatUint(in.Uint(), 10)
382 e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
383}
384
385func (e *encoder) timev(tag string, in reflect.Value) {
386 t := in.Interface().(time.Time)
387 s := t.Format(time.RFC3339Nano)
388 e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
389}
390
391func (e *encoder) floatv(tag string, in reflect.Value) {
392 // Issue #352: When formatting, use the precision of the underlying value
393 precision := 64
394 if in.Kind() == reflect.Float32 {
395 precision = 32
396 }
397
398 s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
399 switch s {
400 case "+Inf":
401 s = ".inf"
402 case "-Inf":
403 s = "-.inf"
404 case "NaN":
405 s = ".nan"
406 }
407 e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
408}
409
410func (e *encoder) nilv() {
411 e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
412}
413
414func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
415 // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
416 implicit := tag == ""
417 if !implicit {
418 tag = longTag(tag)
419 }
420 e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
421 e.event.head_comment = head
422 e.event.line_comment = line
423 e.event.foot_comment = foot
424 e.event.tail_comment = tail
425 e.emit()
426}
427
428func (e *encoder) nodev(in reflect.Value) {
429 e.node(in.Interface().(*Node), "")
430}
431
432func (e *encoder) node(node *Node, tail string) {
433 // Zero nodes behave as nil.
434 if node.Kind == 0 && node.IsZero() {
435 e.nilv()
436 return
437 }
438
439 // If the tag was not explicitly requested, and dropping it won't change the
440 // implicit tag of the value, don't include it in the presentation.
441 var tag = node.Tag
442 var stag = shortTag(tag)
443 var forceQuoting bool
444 if tag != "" && node.Style&TaggedStyle == 0 {
445 if node.Kind == ScalarNode {
446 if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
447 tag = ""
448 } else {
449 rtag, _ := resolve("", node.Value)
450 if rtag == stag {
451 tag = ""
452 } else if stag == strTag {
453 tag = ""
454 forceQuoting = true
455 }
456 }
457 } else {
458 var rtag string
459 switch node.Kind {
460 case MappingNode:
461 rtag = mapTag
462 case SequenceNode:
463 rtag = seqTag
464 }
465 if rtag == stag {
466 tag = ""
467 }
468 }
469 }
470
471 switch node.Kind {
472 case DocumentNode:
473 yaml_document_start_event_initialize(&e.event, nil, nil, true)
474 e.event.head_comment = []byte(node.HeadComment)
475 e.emit()
476 for _, node := range node.Content {
477 e.node(node, "")
478 }
479 yaml_document_end_event_initialize(&e.event, true)
480 e.event.foot_comment = []byte(node.FootComment)
481 e.emit()
482
483 case SequenceNode:
484 style := yaml_BLOCK_SEQUENCE_STYLE
485 if node.Style&FlowStyle != 0 {
486 style = yaml_FLOW_SEQUENCE_STYLE
487 }
488 e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
489 e.event.head_comment = []byte(node.HeadComment)
490 e.emit()
491 for _, node := range node.Content {
492 e.node(node, "")
493 }
494 e.must(yaml_sequence_end_event_initialize(&e.event))
495 e.event.line_comment = []byte(node.LineComment)
496 e.event.foot_comment = []byte(node.FootComment)
497 e.emit()
498
499 case MappingNode:
500 style := yaml_BLOCK_MAPPING_STYLE
501 if node.Style&FlowStyle != 0 {
502 style = yaml_FLOW_MAPPING_STYLE
503 }
504 yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
505 e.event.tail_comment = []byte(tail)
506 e.event.head_comment = []byte(node.HeadComment)
507 e.emit()
508
509 // The tail logic below moves the foot comment of prior keys to the following key,
510 // since the value for each key may be a nested structure and the foot needs to be
511 // processed only the entirety of the value is streamed. The last tail is processed
512 // with the mapping end event.
513 var tail string
514 for i := 0; i+1 < len(node.Content); i += 2 {
515 k := node.Content[i]
516 foot := k.FootComment
517 if foot != "" {
518 kopy := *k
519 kopy.FootComment = ""
520 k = &kopy
521 }
522 e.node(k, tail)
523 tail = foot
524
525 v := node.Content[i+1]
526 e.node(v, "")
527 }
528
529 yaml_mapping_end_event_initialize(&e.event)
530 e.event.tail_comment = []byte(tail)
531 e.event.line_comment = []byte(node.LineComment)
532 e.event.foot_comment = []byte(node.FootComment)
533 e.emit()
534
535 case AliasNode:
536 yaml_alias_event_initialize(&e.event, []byte(node.Value))
537 e.event.head_comment = []byte(node.HeadComment)
538 e.event.line_comment = []byte(node.LineComment)
539 e.event.foot_comment = []byte(node.FootComment)
540 e.emit()
541
542 case ScalarNode:
543 value := node.Value
544 if !utf8.ValidString(value) {
545 if stag == binaryTag {
546 failf("explicitly tagged !!binary data must be base64-encoded")
547 }
548 if stag != "" {
549 failf("cannot marshal invalid UTF-8 data as %s", stag)
550 }
551 // It can't be encoded directly as YAML so use a binary tag
552 // and encode it as base64.
553 tag = binaryTag
554 value = encodeBase64(value)
555 }
556
557 style := yaml_PLAIN_SCALAR_STYLE
558 switch {
559 case node.Style&DoubleQuotedStyle != 0:
560 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
561 case node.Style&SingleQuotedStyle != 0:
562 style = yaml_SINGLE_QUOTED_SCALAR_STYLE
563 case node.Style&LiteralStyle != 0:
564 style = yaml_LITERAL_SCALAR_STYLE
565 case node.Style&FoldedStyle != 0:
566 style = yaml_FOLDED_SCALAR_STYLE
567 case strings.Contains(value, "\n"):
568 style = yaml_LITERAL_SCALAR_STYLE
569 case forceQuoting:
570 style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
571 }
572
573 e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
574 default:
575 failf("cannot encode node with unknown kind %d", node.Kind)
576 }
577}
diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go
new file mode 100644
index 0000000..268558a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/parserc.go
@@ -0,0 +1,1258 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "bytes"
27)
28
29// The parser implements the following grammar:
30//
31// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
32// implicit_document ::= block_node DOCUMENT-END*
33// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
34// block_node_or_indentless_sequence ::=
35// ALIAS
36// | properties (block_content | indentless_block_sequence)?
37// | block_content
38// | indentless_block_sequence
39// block_node ::= ALIAS
40// | properties block_content?
41// | block_content
42// flow_node ::= ALIAS
43// | properties flow_content?
44// | flow_content
45// properties ::= TAG ANCHOR? | ANCHOR TAG?
46// block_content ::= block_collection | flow_collection | SCALAR
47// flow_content ::= flow_collection | SCALAR
48// block_collection ::= block_sequence | block_mapping
49// flow_collection ::= flow_sequence | flow_mapping
50// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
51// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
52// block_mapping ::= BLOCK-MAPPING_START
53// ((KEY block_node_or_indentless_sequence?)?
54// (VALUE block_node_or_indentless_sequence?)?)*
55// BLOCK-END
56// flow_sequence ::= FLOW-SEQUENCE-START
57// (flow_sequence_entry FLOW-ENTRY)*
58// flow_sequence_entry?
59// FLOW-SEQUENCE-END
60// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
61// flow_mapping ::= FLOW-MAPPING-START
62// (flow_mapping_entry FLOW-ENTRY)*
63// flow_mapping_entry?
64// FLOW-MAPPING-END
65// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
66
67// Peek the next token in the token queue.
68func peek_token(parser *yaml_parser_t) *yaml_token_t {
69 if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
70 token := &parser.tokens[parser.tokens_head]
71 yaml_parser_unfold_comments(parser, token)
72 return token
73 }
74 return nil
75}
76
77// yaml_parser_unfold_comments walks through the comments queue and joins all
78// comments behind the position of the provided token into the respective
79// top-level comment slices in the parser.
80func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
81 for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
82 comment := &parser.comments[parser.comments_head]
83 if len(comment.head) > 0 {
84 if token.typ == yaml_BLOCK_END_TOKEN {
85 // No heads on ends, so keep comment.head for a follow up token.
86 break
87 }
88 if len(parser.head_comment) > 0 {
89 parser.head_comment = append(parser.head_comment, '\n')
90 }
91 parser.head_comment = append(parser.head_comment, comment.head...)
92 }
93 if len(comment.foot) > 0 {
94 if len(parser.foot_comment) > 0 {
95 parser.foot_comment = append(parser.foot_comment, '\n')
96 }
97 parser.foot_comment = append(parser.foot_comment, comment.foot...)
98 }
99 if len(comment.line) > 0 {
100 if len(parser.line_comment) > 0 {
101 parser.line_comment = append(parser.line_comment, '\n')
102 }
103 parser.line_comment = append(parser.line_comment, comment.line...)
104 }
105 *comment = yaml_comment_t{}
106 parser.comments_head++
107 }
108}
109
110// Remove the next token from the queue (must be called after peek_token).
111func skip_token(parser *yaml_parser_t) {
112 parser.token_available = false
113 parser.tokens_parsed++
114 parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
115 parser.tokens_head++
116}
117
118// Get the next event.
119func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
120 // Erase the event object.
121 *event = yaml_event_t{}
122
123 // No events after the end of the stream or error.
124 if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
125 return true
126 }
127
128 // Generate the next event.
129 return yaml_parser_state_machine(parser, event)
130}
131
132// Set parser error.
133func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
134 parser.error = yaml_PARSER_ERROR
135 parser.problem = problem
136 parser.problem_mark = problem_mark
137 return false
138}
139
140func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
141 parser.error = yaml_PARSER_ERROR
142 parser.context = context
143 parser.context_mark = context_mark
144 parser.problem = problem
145 parser.problem_mark = problem_mark
146 return false
147}
148
149// State dispatcher.
150func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
151 //trace("yaml_parser_state_machine", "state:", parser.state.String())
152
153 switch parser.state {
154 case yaml_PARSE_STREAM_START_STATE:
155 return yaml_parser_parse_stream_start(parser, event)
156
157 case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
158 return yaml_parser_parse_document_start(parser, event, true)
159
160 case yaml_PARSE_DOCUMENT_START_STATE:
161 return yaml_parser_parse_document_start(parser, event, false)
162
163 case yaml_PARSE_DOCUMENT_CONTENT_STATE:
164 return yaml_parser_parse_document_content(parser, event)
165
166 case yaml_PARSE_DOCUMENT_END_STATE:
167 return yaml_parser_parse_document_end(parser, event)
168
169 case yaml_PARSE_BLOCK_NODE_STATE:
170 return yaml_parser_parse_node(parser, event, true, false)
171
172 case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
173 return yaml_parser_parse_node(parser, event, true, true)
174
175 case yaml_PARSE_FLOW_NODE_STATE:
176 return yaml_parser_parse_node(parser, event, false, false)
177
178 case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
179 return yaml_parser_parse_block_sequence_entry(parser, event, true)
180
181 case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
182 return yaml_parser_parse_block_sequence_entry(parser, event, false)
183
184 case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
185 return yaml_parser_parse_indentless_sequence_entry(parser, event)
186
187 case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
188 return yaml_parser_parse_block_mapping_key(parser, event, true)
189
190 case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
191 return yaml_parser_parse_block_mapping_key(parser, event, false)
192
193 case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
194 return yaml_parser_parse_block_mapping_value(parser, event)
195
196 case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
197 return yaml_parser_parse_flow_sequence_entry(parser, event, true)
198
199 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
200 return yaml_parser_parse_flow_sequence_entry(parser, event, false)
201
202 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
203 return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
204
205 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
206 return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
207
208 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
209 return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
210
211 case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
212 return yaml_parser_parse_flow_mapping_key(parser, event, true)
213
214 case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
215 return yaml_parser_parse_flow_mapping_key(parser, event, false)
216
217 case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
218 return yaml_parser_parse_flow_mapping_value(parser, event, false)
219
220 case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
221 return yaml_parser_parse_flow_mapping_value(parser, event, true)
222
223 default:
224 panic("invalid parser state")
225 }
226}
227
228// Parse the production:
229// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
230// ************
231func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
232 token := peek_token(parser)
233 if token == nil {
234 return false
235 }
236 if token.typ != yaml_STREAM_START_TOKEN {
237 return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark)
238 }
239 parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
240 *event = yaml_event_t{
241 typ: yaml_STREAM_START_EVENT,
242 start_mark: token.start_mark,
243 end_mark: token.end_mark,
244 encoding: token.encoding,
245 }
246 skip_token(parser)
247 return true
248}
249
250// Parse the productions:
251// implicit_document ::= block_node DOCUMENT-END*
252// *
253// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
254// *************************
255func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
256
257 token := peek_token(parser)
258 if token == nil {
259 return false
260 }
261
262 // Parse extra document end indicators.
263 if !implicit {
264 for token.typ == yaml_DOCUMENT_END_TOKEN {
265 skip_token(parser)
266 token = peek_token(parser)
267 if token == nil {
268 return false
269 }
270 }
271 }
272
273 if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
274 token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
275 token.typ != yaml_DOCUMENT_START_TOKEN &&
276 token.typ != yaml_STREAM_END_TOKEN {
277 // Parse an implicit document.
278 if !yaml_parser_process_directives(parser, nil, nil) {
279 return false
280 }
281 parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
282 parser.state = yaml_PARSE_BLOCK_NODE_STATE
283
284 var head_comment []byte
285 if len(parser.head_comment) > 0 {
286 // [Go] Scan the header comment backwards, and if an empty line is found, break
287 // the header so the part before the last empty line goes into the
288 // document header, while the bottom of it goes into a follow up event.
289 for i := len(parser.head_comment) - 1; i > 0; i-- {
290 if parser.head_comment[i] == '\n' {
291 if i == len(parser.head_comment)-1 {
292 head_comment = parser.head_comment[:i]
293 parser.head_comment = parser.head_comment[i+1:]
294 break
295 } else if parser.head_comment[i-1] == '\n' {
296 head_comment = parser.head_comment[:i-1]
297 parser.head_comment = parser.head_comment[i+1:]
298 break
299 }
300 }
301 }
302 }
303
304 *event = yaml_event_t{
305 typ: yaml_DOCUMENT_START_EVENT,
306 start_mark: token.start_mark,
307 end_mark: token.end_mark,
308
309 head_comment: head_comment,
310 }
311
312 } else if token.typ != yaml_STREAM_END_TOKEN {
313 // Parse an explicit document.
314 var version_directive *yaml_version_directive_t
315 var tag_directives []yaml_tag_directive_t
316 start_mark := token.start_mark
317 if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
318 return false
319 }
320 token = peek_token(parser)
321 if token == nil {
322 return false
323 }
324 if token.typ != yaml_DOCUMENT_START_TOKEN {
325 yaml_parser_set_parser_error(parser,
326 "did not find expected <document start>", token.start_mark)
327 return false
328 }
329 parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
330 parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
331 end_mark := token.end_mark
332
333 *event = yaml_event_t{
334 typ: yaml_DOCUMENT_START_EVENT,
335 start_mark: start_mark,
336 end_mark: end_mark,
337 version_directive: version_directive,
338 tag_directives: tag_directives,
339 implicit: false,
340 }
341 skip_token(parser)
342
343 } else {
344 // Parse the stream end.
345 parser.state = yaml_PARSE_END_STATE
346 *event = yaml_event_t{
347 typ: yaml_STREAM_END_EVENT,
348 start_mark: token.start_mark,
349 end_mark: token.end_mark,
350 }
351 skip_token(parser)
352 }
353
354 return true
355}
356
357// Parse the productions:
358// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
359// ***********
360//
361func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
362 token := peek_token(parser)
363 if token == nil {
364 return false
365 }
366
367 if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
368 token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
369 token.typ == yaml_DOCUMENT_START_TOKEN ||
370 token.typ == yaml_DOCUMENT_END_TOKEN ||
371 token.typ == yaml_STREAM_END_TOKEN {
372 parser.state = parser.states[len(parser.states)-1]
373 parser.states = parser.states[:len(parser.states)-1]
374 return yaml_parser_process_empty_scalar(parser, event,
375 token.start_mark)
376 }
377 return yaml_parser_parse_node(parser, event, true, false)
378}
379
380// Parse the productions:
381// implicit_document ::= block_node DOCUMENT-END*
382// *************
383// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
384//
385func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
386 token := peek_token(parser)
387 if token == nil {
388 return false
389 }
390
391 start_mark := token.start_mark
392 end_mark := token.start_mark
393
394 implicit := true
395 if token.typ == yaml_DOCUMENT_END_TOKEN {
396 end_mark = token.end_mark
397 skip_token(parser)
398 implicit = false
399 }
400
401 parser.tag_directives = parser.tag_directives[:0]
402
403 parser.state = yaml_PARSE_DOCUMENT_START_STATE
404 *event = yaml_event_t{
405 typ: yaml_DOCUMENT_END_EVENT,
406 start_mark: start_mark,
407 end_mark: end_mark,
408 implicit: implicit,
409 }
410 yaml_parser_set_event_comments(parser, event)
411 if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
412 event.foot_comment = event.head_comment
413 event.head_comment = nil
414 }
415 return true
416}
417
418func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
419 event.head_comment = parser.head_comment
420 event.line_comment = parser.line_comment
421 event.foot_comment = parser.foot_comment
422 parser.head_comment = nil
423 parser.line_comment = nil
424 parser.foot_comment = nil
425 parser.tail_comment = nil
426 parser.stem_comment = nil
427}
428
429// Parse the productions:
430// block_node_or_indentless_sequence ::=
431// ALIAS
432// *****
433// | properties (block_content | indentless_block_sequence)?
434// ********** *
435// | block_content | indentless_block_sequence
436// *
437// block_node ::= ALIAS
438// *****
439// | properties block_content?
440// ********** *
441// | block_content
442// *
443// flow_node ::= ALIAS
444// *****
445// | properties flow_content?
446// ********** *
447// | flow_content
448// *
449// properties ::= TAG ANCHOR? | ANCHOR TAG?
450// *************************
451// block_content ::= block_collection | flow_collection | SCALAR
452// ******
453// flow_content ::= flow_collection | SCALAR
454// ******
455func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
456 //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
457
458 token := peek_token(parser)
459 if token == nil {
460 return false
461 }
462
463 if token.typ == yaml_ALIAS_TOKEN {
464 parser.state = parser.states[len(parser.states)-1]
465 parser.states = parser.states[:len(parser.states)-1]
466 *event = yaml_event_t{
467 typ: yaml_ALIAS_EVENT,
468 start_mark: token.start_mark,
469 end_mark: token.end_mark,
470 anchor: token.value,
471 }
472 yaml_parser_set_event_comments(parser, event)
473 skip_token(parser)
474 return true
475 }
476
477 start_mark := token.start_mark
478 end_mark := token.start_mark
479
480 var tag_token bool
481 var tag_handle, tag_suffix, anchor []byte
482 var tag_mark yaml_mark_t
483 if token.typ == yaml_ANCHOR_TOKEN {
484 anchor = token.value
485 start_mark = token.start_mark
486 end_mark = token.end_mark
487 skip_token(parser)
488 token = peek_token(parser)
489 if token == nil {
490 return false
491 }
492 if token.typ == yaml_TAG_TOKEN {
493 tag_token = true
494 tag_handle = token.value
495 tag_suffix = token.suffix
496 tag_mark = token.start_mark
497 end_mark = token.end_mark
498 skip_token(parser)
499 token = peek_token(parser)
500 if token == nil {
501 return false
502 }
503 }
504 } else if token.typ == yaml_TAG_TOKEN {
505 tag_token = true
506 tag_handle = token.value
507 tag_suffix = token.suffix
508 start_mark = token.start_mark
509 tag_mark = token.start_mark
510 end_mark = token.end_mark
511 skip_token(parser)
512 token = peek_token(parser)
513 if token == nil {
514 return false
515 }
516 if token.typ == yaml_ANCHOR_TOKEN {
517 anchor = token.value
518 end_mark = token.end_mark
519 skip_token(parser)
520 token = peek_token(parser)
521 if token == nil {
522 return false
523 }
524 }
525 }
526
527 var tag []byte
528 if tag_token {
529 if len(tag_handle) == 0 {
530 tag = tag_suffix
531 tag_suffix = nil
532 } else {
533 for i := range parser.tag_directives {
534 if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
535 tag = append([]byte(nil), parser.tag_directives[i].prefix...)
536 tag = append(tag, tag_suffix...)
537 break
538 }
539 }
540 if len(tag) == 0 {
541 yaml_parser_set_parser_error_context(parser,
542 "while parsing a node", start_mark,
543 "found undefined tag handle", tag_mark)
544 return false
545 }
546 }
547 }
548
549 implicit := len(tag) == 0
550 if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
551 end_mark = token.end_mark
552 parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
553 *event = yaml_event_t{
554 typ: yaml_SEQUENCE_START_EVENT,
555 start_mark: start_mark,
556 end_mark: end_mark,
557 anchor: anchor,
558 tag: tag,
559 implicit: implicit,
560 style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
561 }
562 return true
563 }
564 if token.typ == yaml_SCALAR_TOKEN {
565 var plain_implicit, quoted_implicit bool
566 end_mark = token.end_mark
567 if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
568 plain_implicit = true
569 } else if len(tag) == 0 {
570 quoted_implicit = true
571 }
572 parser.state = parser.states[len(parser.states)-1]
573 parser.states = parser.states[:len(parser.states)-1]
574
575 *event = yaml_event_t{
576 typ: yaml_SCALAR_EVENT,
577 start_mark: start_mark,
578 end_mark: end_mark,
579 anchor: anchor,
580 tag: tag,
581 value: token.value,
582 implicit: plain_implicit,
583 quoted_implicit: quoted_implicit,
584 style: yaml_style_t(token.style),
585 }
586 yaml_parser_set_event_comments(parser, event)
587 skip_token(parser)
588 return true
589 }
590 if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
591 // [Go] Some of the events below can be merged as they differ only on style.
592 end_mark = token.end_mark
593 parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
594 *event = yaml_event_t{
595 typ: yaml_SEQUENCE_START_EVENT,
596 start_mark: start_mark,
597 end_mark: end_mark,
598 anchor: anchor,
599 tag: tag,
600 implicit: implicit,
601 style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
602 }
603 yaml_parser_set_event_comments(parser, event)
604 return true
605 }
606 if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
607 end_mark = token.end_mark
608 parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
609 *event = yaml_event_t{
610 typ: yaml_MAPPING_START_EVENT,
611 start_mark: start_mark,
612 end_mark: end_mark,
613 anchor: anchor,
614 tag: tag,
615 implicit: implicit,
616 style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
617 }
618 yaml_parser_set_event_comments(parser, event)
619 return true
620 }
621 if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
622 end_mark = token.end_mark
623 parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
624 *event = yaml_event_t{
625 typ: yaml_SEQUENCE_START_EVENT,
626 start_mark: start_mark,
627 end_mark: end_mark,
628 anchor: anchor,
629 tag: tag,
630 implicit: implicit,
631 style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
632 }
633 if parser.stem_comment != nil {
634 event.head_comment = parser.stem_comment
635 parser.stem_comment = nil
636 }
637 return true
638 }
639 if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
640 end_mark = token.end_mark
641 parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
642 *event = yaml_event_t{
643 typ: yaml_MAPPING_START_EVENT,
644 start_mark: start_mark,
645 end_mark: end_mark,
646 anchor: anchor,
647 tag: tag,
648 implicit: implicit,
649 style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
650 }
651 if parser.stem_comment != nil {
652 event.head_comment = parser.stem_comment
653 parser.stem_comment = nil
654 }
655 return true
656 }
657 if len(anchor) > 0 || len(tag) > 0 {
658 parser.state = parser.states[len(parser.states)-1]
659 parser.states = parser.states[:len(parser.states)-1]
660
661 *event = yaml_event_t{
662 typ: yaml_SCALAR_EVENT,
663 start_mark: start_mark,
664 end_mark: end_mark,
665 anchor: anchor,
666 tag: tag,
667 implicit: implicit,
668 quoted_implicit: false,
669 style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
670 }
671 return true
672 }
673
674 context := "while parsing a flow node"
675 if block {
676 context = "while parsing a block node"
677 }
678 yaml_parser_set_parser_error_context(parser, context, start_mark,
679 "did not find expected node content", token.start_mark)
680 return false
681}
682
683// Parse the productions:
684// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
685// ******************** *********** * *********
686//
687func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
688 if first {
689 token := peek_token(parser)
690 if token == nil {
691 return false
692 }
693 parser.marks = append(parser.marks, token.start_mark)
694 skip_token(parser)
695 }
696
697 token := peek_token(parser)
698 if token == nil {
699 return false
700 }
701
702 if token.typ == yaml_BLOCK_ENTRY_TOKEN {
703 mark := token.end_mark
704 prior_head_len := len(parser.head_comment)
705 skip_token(parser)
706 yaml_parser_split_stem_comment(parser, prior_head_len)
707 token = peek_token(parser)
708 if token == nil {
709 return false
710 }
711 if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
712 parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
713 return yaml_parser_parse_node(parser, event, true, false)
714 } else {
715 parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
716 return yaml_parser_process_empty_scalar(parser, event, mark)
717 }
718 }
719 if token.typ == yaml_BLOCK_END_TOKEN {
720 parser.state = parser.states[len(parser.states)-1]
721 parser.states = parser.states[:len(parser.states)-1]
722 parser.marks = parser.marks[:len(parser.marks)-1]
723
724 *event = yaml_event_t{
725 typ: yaml_SEQUENCE_END_EVENT,
726 start_mark: token.start_mark,
727 end_mark: token.end_mark,
728 }
729
730 skip_token(parser)
731 return true
732 }
733
734 context_mark := parser.marks[len(parser.marks)-1]
735 parser.marks = parser.marks[:len(parser.marks)-1]
736 return yaml_parser_set_parser_error_context(parser,
737 "while parsing a block collection", context_mark,
738 "did not find expected '-' indicator", token.start_mark)
739}
740
741// Parse the productions:
742// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
743// *********** *
744func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
745 token := peek_token(parser)
746 if token == nil {
747 return false
748 }
749
750 if token.typ == yaml_BLOCK_ENTRY_TOKEN {
751 mark := token.end_mark
752 prior_head_len := len(parser.head_comment)
753 skip_token(parser)
754 yaml_parser_split_stem_comment(parser, prior_head_len)
755 token = peek_token(parser)
756 if token == nil {
757 return false
758 }
759 if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
760 token.typ != yaml_KEY_TOKEN &&
761 token.typ != yaml_VALUE_TOKEN &&
762 token.typ != yaml_BLOCK_END_TOKEN {
763 parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
764 return yaml_parser_parse_node(parser, event, true, false)
765 }
766 parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
767 return yaml_parser_process_empty_scalar(parser, event, mark)
768 }
769 parser.state = parser.states[len(parser.states)-1]
770 parser.states = parser.states[:len(parser.states)-1]
771
772 *event = yaml_event_t{
773 typ: yaml_SEQUENCE_END_EVENT,
774 start_mark: token.start_mark,
775 end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?
776 }
777 return true
778}
779
780// Split stem comment from head comment.
781//
782// When a sequence or map is found under a sequence entry, the former head comment
783// is assigned to the underlying sequence or map as a whole, not the individual
784// sequence or map entry as would be expected otherwise. To handle this case the
785// previous head comment is moved aside as the stem comment.
786func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
787 if stem_len == 0 {
788 return
789 }
790
791 token := peek_token(parser)
792 if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
793 return
794 }
795
796 parser.stem_comment = parser.head_comment[:stem_len]
797 if len(parser.head_comment) == stem_len {
798 parser.head_comment = nil
799 } else {
800 // Copy suffix to prevent very strange bugs if someone ever appends
801 // further bytes to the prefix in the stem_comment slice above.
802 parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
803 }
804}
805
806// Parse the productions:
807// block_mapping ::= BLOCK-MAPPING_START
808// *******************
809// ((KEY block_node_or_indentless_sequence?)?
810// *** *
811// (VALUE block_node_or_indentless_sequence?)?)*
812//
813// BLOCK-END
814// *********
815//
816func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
817 if first {
818 token := peek_token(parser)
819 if token == nil {
820 return false
821 }
822 parser.marks = append(parser.marks, token.start_mark)
823 skip_token(parser)
824 }
825
826 token := peek_token(parser)
827 if token == nil {
828 return false
829 }
830
831 // [Go] A tail comment was left from the prior mapping value processed. Emit an event
832 // as it needs to be processed with that value and not the following key.
833 if len(parser.tail_comment) > 0 {
834 *event = yaml_event_t{
835 typ: yaml_TAIL_COMMENT_EVENT,
836 start_mark: token.start_mark,
837 end_mark: token.end_mark,
838 foot_comment: parser.tail_comment,
839 }
840 parser.tail_comment = nil
841 return true
842 }
843
844 if token.typ == yaml_KEY_TOKEN {
845 mark := token.end_mark
846 skip_token(parser)
847 token = peek_token(parser)
848 if token == nil {
849 return false
850 }
851 if token.typ != yaml_KEY_TOKEN &&
852 token.typ != yaml_VALUE_TOKEN &&
853 token.typ != yaml_BLOCK_END_TOKEN {
854 parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
855 return yaml_parser_parse_node(parser, event, true, true)
856 } else {
857 parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
858 return yaml_parser_process_empty_scalar(parser, event, mark)
859 }
860 } else if token.typ == yaml_BLOCK_END_TOKEN {
861 parser.state = parser.states[len(parser.states)-1]
862 parser.states = parser.states[:len(parser.states)-1]
863 parser.marks = parser.marks[:len(parser.marks)-1]
864 *event = yaml_event_t{
865 typ: yaml_MAPPING_END_EVENT,
866 start_mark: token.start_mark,
867 end_mark: token.end_mark,
868 }
869 yaml_parser_set_event_comments(parser, event)
870 skip_token(parser)
871 return true
872 }
873
874 context_mark := parser.marks[len(parser.marks)-1]
875 parser.marks = parser.marks[:len(parser.marks)-1]
876 return yaml_parser_set_parser_error_context(parser,
877 "while parsing a block mapping", context_mark,
878 "did not find expected key", token.start_mark)
879}
880
881// Parse the productions:
882// block_mapping ::= BLOCK-MAPPING_START
883//
884// ((KEY block_node_or_indentless_sequence?)?
885//
886// (VALUE block_node_or_indentless_sequence?)?)*
887// ***** *
888// BLOCK-END
889//
890//
891func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
892 token := peek_token(parser)
893 if token == nil {
894 return false
895 }
896 if token.typ == yaml_VALUE_TOKEN {
897 mark := token.end_mark
898 skip_token(parser)
899 token = peek_token(parser)
900 if token == nil {
901 return false
902 }
903 if token.typ != yaml_KEY_TOKEN &&
904 token.typ != yaml_VALUE_TOKEN &&
905 token.typ != yaml_BLOCK_END_TOKEN {
906 parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
907 return yaml_parser_parse_node(parser, event, true, true)
908 }
909 parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
910 return yaml_parser_process_empty_scalar(parser, event, mark)
911 }
912 parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
913 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
914}
915
916// Parse the productions:
917// flow_sequence ::= FLOW-SEQUENCE-START
918// *******************
919// (flow_sequence_entry FLOW-ENTRY)*
920// * **********
921// flow_sequence_entry?
922// *
923// FLOW-SEQUENCE-END
924// *****************
925// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
926// *
927//
928func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
929 if first {
930 token := peek_token(parser)
931 if token == nil {
932 return false
933 }
934 parser.marks = append(parser.marks, token.start_mark)
935 skip_token(parser)
936 }
937 token := peek_token(parser)
938 if token == nil {
939 return false
940 }
941 if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
942 if !first {
943 if token.typ == yaml_FLOW_ENTRY_TOKEN {
944 skip_token(parser)
945 token = peek_token(parser)
946 if token == nil {
947 return false
948 }
949 } else {
950 context_mark := parser.marks[len(parser.marks)-1]
951 parser.marks = parser.marks[:len(parser.marks)-1]
952 return yaml_parser_set_parser_error_context(parser,
953 "while parsing a flow sequence", context_mark,
954 "did not find expected ',' or ']'", token.start_mark)
955 }
956 }
957
958 if token.typ == yaml_KEY_TOKEN {
959 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
960 *event = yaml_event_t{
961 typ: yaml_MAPPING_START_EVENT,
962 start_mark: token.start_mark,
963 end_mark: token.end_mark,
964 implicit: true,
965 style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
966 }
967 skip_token(parser)
968 return true
969 } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
970 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
971 return yaml_parser_parse_node(parser, event, false, false)
972 }
973 }
974
975 parser.state = parser.states[len(parser.states)-1]
976 parser.states = parser.states[:len(parser.states)-1]
977 parser.marks = parser.marks[:len(parser.marks)-1]
978
979 *event = yaml_event_t{
980 typ: yaml_SEQUENCE_END_EVENT,
981 start_mark: token.start_mark,
982 end_mark: token.end_mark,
983 }
984 yaml_parser_set_event_comments(parser, event)
985
986 skip_token(parser)
987 return true
988}
989
990//
991// Parse the productions:
992// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
993// *** *
994//
995func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
996 token := peek_token(parser)
997 if token == nil {
998 return false
999 }
1000 if token.typ != yaml_VALUE_TOKEN &&
1001 token.typ != yaml_FLOW_ENTRY_TOKEN &&
1002 token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1003 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
1004 return yaml_parser_parse_node(parser, event, false, false)
1005 }
1006 mark := token.end_mark
1007 skip_token(parser)
1008 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
1009 return yaml_parser_process_empty_scalar(parser, event, mark)
1010}
1011
1012// Parse the productions:
1013// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1014// ***** *
1015//
1016func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
1017 token := peek_token(parser)
1018 if token == nil {
1019 return false
1020 }
1021 if token.typ == yaml_VALUE_TOKEN {
1022 skip_token(parser)
1023 token := peek_token(parser)
1024 if token == nil {
1025 return false
1026 }
1027 if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
1028 parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
1029 return yaml_parser_parse_node(parser, event, false, false)
1030 }
1031 }
1032 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
1033 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1034}
1035
1036// Parse the productions:
1037// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1038// *
1039//
1040func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
1041 token := peek_token(parser)
1042 if token == nil {
1043 return false
1044 }
1045 parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
1046 *event = yaml_event_t{
1047 typ: yaml_MAPPING_END_EVENT,
1048 start_mark: token.start_mark,
1049 end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?
1050 }
1051 return true
1052}
1053
1054// Parse the productions:
1055// flow_mapping ::= FLOW-MAPPING-START
1056// ******************
1057// (flow_mapping_entry FLOW-ENTRY)*
1058// * **********
1059// flow_mapping_entry?
1060// ******************
1061// FLOW-MAPPING-END
1062// ****************
1063// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1064// * *** *
1065//
1066func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
1067 if first {
1068 token := peek_token(parser)
1069 parser.marks = append(parser.marks, token.start_mark)
1070 skip_token(parser)
1071 }
1072
1073 token := peek_token(parser)
1074 if token == nil {
1075 return false
1076 }
1077
1078 if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1079 if !first {
1080 if token.typ == yaml_FLOW_ENTRY_TOKEN {
1081 skip_token(parser)
1082 token = peek_token(parser)
1083 if token == nil {
1084 return false
1085 }
1086 } else {
1087 context_mark := parser.marks[len(parser.marks)-1]
1088 parser.marks = parser.marks[:len(parser.marks)-1]
1089 return yaml_parser_set_parser_error_context(parser,
1090 "while parsing a flow mapping", context_mark,
1091 "did not find expected ',' or '}'", token.start_mark)
1092 }
1093 }
1094
1095 if token.typ == yaml_KEY_TOKEN {
1096 skip_token(parser)
1097 token = peek_token(parser)
1098 if token == nil {
1099 return false
1100 }
1101 if token.typ != yaml_VALUE_TOKEN &&
1102 token.typ != yaml_FLOW_ENTRY_TOKEN &&
1103 token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1104 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
1105 return yaml_parser_parse_node(parser, event, false, false)
1106 } else {
1107 parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
1108 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1109 }
1110 } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1111 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
1112 return yaml_parser_parse_node(parser, event, false, false)
1113 }
1114 }
1115
1116 parser.state = parser.states[len(parser.states)-1]
1117 parser.states = parser.states[:len(parser.states)-1]
1118 parser.marks = parser.marks[:len(parser.marks)-1]
1119 *event = yaml_event_t{
1120 typ: yaml_MAPPING_END_EVENT,
1121 start_mark: token.start_mark,
1122 end_mark: token.end_mark,
1123 }
1124 yaml_parser_set_event_comments(parser, event)
1125 skip_token(parser)
1126 return true
1127}
1128
1129// Parse the productions:
1130// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1131// * ***** *
1132//
1133func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
1134 token := peek_token(parser)
1135 if token == nil {
1136 return false
1137 }
1138 if empty {
1139 parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1140 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1141 }
1142 if token.typ == yaml_VALUE_TOKEN {
1143 skip_token(parser)
1144 token = peek_token(parser)
1145 if token == nil {
1146 return false
1147 }
1148 if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
1149 parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
1150 return yaml_parser_parse_node(parser, event, false, false)
1151 }
1152 }
1153 parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
1154 return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
1155}
1156
1157// Generate an empty scalar event.
1158func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
1159 *event = yaml_event_t{
1160 typ: yaml_SCALAR_EVENT,
1161 start_mark: mark,
1162 end_mark: mark,
1163 value: nil, // Empty
1164 implicit: true,
1165 style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
1166 }
1167 return true
1168}
1169
1170var default_tag_directives = []yaml_tag_directive_t{
1171 {[]byte("!"), []byte("!")},
1172 {[]byte("!!"), []byte("tag:yaml.org,2002:")},
1173}
1174
1175// Parse directives.
1176func yaml_parser_process_directives(parser *yaml_parser_t,
1177 version_directive_ref **yaml_version_directive_t,
1178 tag_directives_ref *[]yaml_tag_directive_t) bool {
1179
1180 var version_directive *yaml_version_directive_t
1181 var tag_directives []yaml_tag_directive_t
1182
1183 token := peek_token(parser)
1184 if token == nil {
1185 return false
1186 }
1187
1188 for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1189 if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
1190 if version_directive != nil {
1191 yaml_parser_set_parser_error(parser,
1192 "found duplicate %YAML directive", token.start_mark)
1193 return false
1194 }
1195 if token.major != 1 || token.minor != 1 {
1196 yaml_parser_set_parser_error(parser,
1197 "found incompatible YAML document", token.start_mark)
1198 return false
1199 }
1200 version_directive = &yaml_version_directive_t{
1201 major: token.major,
1202 minor: token.minor,
1203 }
1204 } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
1205 value := yaml_tag_directive_t{
1206 handle: token.value,
1207 prefix: token.prefix,
1208 }
1209 if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
1210 return false
1211 }
1212 tag_directives = append(tag_directives, value)
1213 }
1214
1215 skip_token(parser)
1216 token = peek_token(parser)
1217 if token == nil {
1218 return false
1219 }
1220 }
1221
1222 for i := range default_tag_directives {
1223 if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
1224 return false
1225 }
1226 }
1227
1228 if version_directive_ref != nil {
1229 *version_directive_ref = version_directive
1230 }
1231 if tag_directives_ref != nil {
1232 *tag_directives_ref = tag_directives
1233 }
1234 return true
1235}
1236
1237// Append a tag directive to the directives stack.
1238func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
1239 for i := range parser.tag_directives {
1240 if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
1241 if allow_duplicates {
1242 return true
1243 }
1244 return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
1245 }
1246 }
1247
1248 // [Go] I suspect the copy is unnecessary. This was likely done
1249 // because there was no way to track ownership of the data.
1250 value_copy := yaml_tag_directive_t{
1251 handle: make([]byte, len(value.handle)),
1252 prefix: make([]byte, len(value.prefix)),
1253 }
1254 copy(value_copy.handle, value.handle)
1255 copy(value_copy.prefix, value.prefix)
1256 parser.tag_directives = append(parser.tag_directives, value_copy)
1257 return true
1258}
diff --git a/vendor/gopkg.in/yaml.v3/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go
new file mode 100644
index 0000000..b7de0a8
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/readerc.go
@@ -0,0 +1,434 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "io"
27)
28
29// Set the reader error and return 0.
30func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
31 parser.error = yaml_READER_ERROR
32 parser.problem = problem
33 parser.problem_offset = offset
34 parser.problem_value = value
35 return false
36}
37
38// Byte order marks.
39const (
40 bom_UTF8 = "\xef\xbb\xbf"
41 bom_UTF16LE = "\xff\xfe"
42 bom_UTF16BE = "\xfe\xff"
43)
44
45// Determine the input stream encoding by checking the BOM symbol. If no BOM is
46// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
47func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
48 // Ensure that we had enough bytes in the raw buffer.
49 for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
50 if !yaml_parser_update_raw_buffer(parser) {
51 return false
52 }
53 }
54
55 // Determine the encoding.
56 buf := parser.raw_buffer
57 pos := parser.raw_buffer_pos
58 avail := len(buf) - pos
59 if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
60 parser.encoding = yaml_UTF16LE_ENCODING
61 parser.raw_buffer_pos += 2
62 parser.offset += 2
63 } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
64 parser.encoding = yaml_UTF16BE_ENCODING
65 parser.raw_buffer_pos += 2
66 parser.offset += 2
67 } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
68 parser.encoding = yaml_UTF8_ENCODING
69 parser.raw_buffer_pos += 3
70 parser.offset += 3
71 } else {
72 parser.encoding = yaml_UTF8_ENCODING
73 }
74 return true
75}
76
77// Update the raw buffer.
78func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
79 size_read := 0
80
81 // Return if the raw buffer is full.
82 if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
83 return true
84 }
85
86 // Return on EOF.
87 if parser.eof {
88 return true
89 }
90
91 // Move the remaining bytes in the raw buffer to the beginning.
92 if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
93 copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
94 }
95 parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
96 parser.raw_buffer_pos = 0
97
98 // Call the read handler to fill the buffer.
99 size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
100 parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
101 if err == io.EOF {
102 parser.eof = true
103 } else if err != nil {
104 return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
105 }
106 return true
107}
108
109// Ensure that the buffer contains at least `length` characters.
110// Return true on success, false on failure.
111//
112// The length is supposed to be significantly less that the buffer size.
113func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
114 if parser.read_handler == nil {
115 panic("read handler must be set")
116 }
117
118 // [Go] This function was changed to guarantee the requested length size at EOF.
119 // The fact we need to do this is pretty awful, but the description above implies
120 // for that to be the case, and there are tests
121
122 // If the EOF flag is set and the raw buffer is empty, do nothing.
123 if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
124 // [Go] ACTUALLY! Read the documentation of this function above.
125 // This is just broken. To return true, we need to have the
126 // given length in the buffer. Not doing that means every single
127 // check that calls this function to make sure the buffer has a
128 // given length is Go) panicking; or C) accessing invalid memory.
129 //return true
130 }
131
132 // Return if the buffer contains enough characters.
133 if parser.unread >= length {
134 return true
135 }
136
137 // Determine the input encoding if it is not known yet.
138 if parser.encoding == yaml_ANY_ENCODING {
139 if !yaml_parser_determine_encoding(parser) {
140 return false
141 }
142 }
143
144 // Move the unread characters to the beginning of the buffer.
145 buffer_len := len(parser.buffer)
146 if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
147 copy(parser.buffer, parser.buffer[parser.buffer_pos:])
148 buffer_len -= parser.buffer_pos
149 parser.buffer_pos = 0
150 } else if parser.buffer_pos == buffer_len {
151 buffer_len = 0
152 parser.buffer_pos = 0
153 }
154
155 // Open the whole buffer for writing, and cut it before returning.
156 parser.buffer = parser.buffer[:cap(parser.buffer)]
157
158 // Fill the buffer until it has enough characters.
159 first := true
160 for parser.unread < length {
161
162 // Fill the raw buffer if necessary.
163 if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
164 if !yaml_parser_update_raw_buffer(parser) {
165 parser.buffer = parser.buffer[:buffer_len]
166 return false
167 }
168 }
169 first = false
170
171 // Decode the raw buffer.
172 inner:
173 for parser.raw_buffer_pos != len(parser.raw_buffer) {
174 var value rune
175 var width int
176
177 raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
178
179 // Decode the next character.
180 switch parser.encoding {
181 case yaml_UTF8_ENCODING:
182 // Decode a UTF-8 character. Check RFC 3629
183 // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
184 //
185 // The following table (taken from the RFC) is used for
186 // decoding.
187 //
188 // Char. number range | UTF-8 octet sequence
189 // (hexadecimal) | (binary)
190 // --------------------+------------------------------------
191 // 0000 0000-0000 007F | 0xxxxxxx
192 // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
193 // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
194 // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
195 //
196 // Additionally, the characters in the range 0xD800-0xDFFF
197 // are prohibited as they are reserved for use with UTF-16
198 // surrogate pairs.
199
200 // Determine the length of the UTF-8 sequence.
201 octet := parser.raw_buffer[parser.raw_buffer_pos]
202 switch {
203 case octet&0x80 == 0x00:
204 width = 1
205 case octet&0xE0 == 0xC0:
206 width = 2
207 case octet&0xF0 == 0xE0:
208 width = 3
209 case octet&0xF8 == 0xF0:
210 width = 4
211 default:
212 // The leading octet is invalid.
213 return yaml_parser_set_reader_error(parser,
214 "invalid leading UTF-8 octet",
215 parser.offset, int(octet))
216 }
217
218 // Check if the raw buffer contains an incomplete character.
219 if width > raw_unread {
220 if parser.eof {
221 return yaml_parser_set_reader_error(parser,
222 "incomplete UTF-8 octet sequence",
223 parser.offset, -1)
224 }
225 break inner
226 }
227
228 // Decode the leading octet.
229 switch {
230 case octet&0x80 == 0x00:
231 value = rune(octet & 0x7F)
232 case octet&0xE0 == 0xC0:
233 value = rune(octet & 0x1F)
234 case octet&0xF0 == 0xE0:
235 value = rune(octet & 0x0F)
236 case octet&0xF8 == 0xF0:
237 value = rune(octet & 0x07)
238 default:
239 value = 0
240 }
241
242 // Check and decode the trailing octets.
243 for k := 1; k < width; k++ {
244 octet = parser.raw_buffer[parser.raw_buffer_pos+k]
245
246 // Check if the octet is valid.
247 if (octet & 0xC0) != 0x80 {
248 return yaml_parser_set_reader_error(parser,
249 "invalid trailing UTF-8 octet",
250 parser.offset+k, int(octet))
251 }
252
253 // Decode the octet.
254 value = (value << 6) + rune(octet&0x3F)
255 }
256
257 // Check the length of the sequence against the value.
258 switch {
259 case width == 1:
260 case width == 2 && value >= 0x80:
261 case width == 3 && value >= 0x800:
262 case width == 4 && value >= 0x10000:
263 default:
264 return yaml_parser_set_reader_error(parser,
265 "invalid length of a UTF-8 sequence",
266 parser.offset, -1)
267 }
268
269 // Check the range of the value.
270 if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
271 return yaml_parser_set_reader_error(parser,
272 "invalid Unicode character",
273 parser.offset, int(value))
274 }
275
276 case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
277 var low, high int
278 if parser.encoding == yaml_UTF16LE_ENCODING {
279 low, high = 0, 1
280 } else {
281 low, high = 1, 0
282 }
283
284 // The UTF-16 encoding is not as simple as one might
285 // naively think. Check RFC 2781
286 // (http://www.ietf.org/rfc/rfc2781.txt).
287 //
288 // Normally, two subsequent bytes describe a Unicode
289 // character. However a special technique (called a
290 // surrogate pair) is used for specifying character
291 // values larger than 0xFFFF.
292 //
293 // A surrogate pair consists of two pseudo-characters:
294 // high surrogate area (0xD800-0xDBFF)
295 // low surrogate area (0xDC00-0xDFFF)
296 //
297 // The following formulas are used for decoding
298 // and encoding characters using surrogate pairs:
299 //
300 // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
301 // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
302 // W1 = 110110yyyyyyyyyy
303 // W2 = 110111xxxxxxxxxx
304 //
305 // where U is the character value, W1 is the high surrogate
306 // area, W2 is the low surrogate area.
307
308 // Check for incomplete UTF-16 character.
309 if raw_unread < 2 {
310 if parser.eof {
311 return yaml_parser_set_reader_error(parser,
312 "incomplete UTF-16 character",
313 parser.offset, -1)
314 }
315 break inner
316 }
317
318 // Get the character.
319 value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
320 (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
321
322 // Check for unexpected low surrogate area.
323 if value&0xFC00 == 0xDC00 {
324 return yaml_parser_set_reader_error(parser,
325 "unexpected low surrogate area",
326 parser.offset, int(value))
327 }
328
329 // Check for a high surrogate area.
330 if value&0xFC00 == 0xD800 {
331 width = 4
332
333 // Check for incomplete surrogate pair.
334 if raw_unread < 4 {
335 if parser.eof {
336 return yaml_parser_set_reader_error(parser,
337 "incomplete UTF-16 surrogate pair",
338 parser.offset, -1)
339 }
340 break inner
341 }
342
343 // Get the next character.
344 value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
345 (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
346
347 // Check for a low surrogate area.
348 if value2&0xFC00 != 0xDC00 {
349 return yaml_parser_set_reader_error(parser,
350 "expected low surrogate area",
351 parser.offset+2, int(value2))
352 }
353
354 // Generate the value of the surrogate pair.
355 value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
356 } else {
357 width = 2
358 }
359
360 default:
361 panic("impossible")
362 }
363
364 // Check if the character is in the allowed range:
365 // #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
366 // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
367 // | [#x10000-#x10FFFF] (32 bit)
368 switch {
369 case value == 0x09:
370 case value == 0x0A:
371 case value == 0x0D:
372 case value >= 0x20 && value <= 0x7E:
373 case value == 0x85:
374 case value >= 0xA0 && value <= 0xD7FF:
375 case value >= 0xE000 && value <= 0xFFFD:
376 case value >= 0x10000 && value <= 0x10FFFF:
377 default:
378 return yaml_parser_set_reader_error(parser,
379 "control characters are not allowed",
380 parser.offset, int(value))
381 }
382
383 // Move the raw pointers.
384 parser.raw_buffer_pos += width
385 parser.offset += width
386
387 // Finally put the character into the buffer.
388 if value <= 0x7F {
389 // 0000 0000-0000 007F . 0xxxxxxx
390 parser.buffer[buffer_len+0] = byte(value)
391 buffer_len += 1
392 } else if value <= 0x7FF {
393 // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
394 parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
395 parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
396 buffer_len += 2
397 } else if value <= 0xFFFF {
398 // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
399 parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
400 parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
401 parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
402 buffer_len += 3
403 } else {
404 // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
405 parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
406 parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
407 parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
408 parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
409 buffer_len += 4
410 }
411
412 parser.unread++
413 }
414
415 // On EOF, put NUL into the buffer and return.
416 if parser.eof {
417 parser.buffer[buffer_len] = 0
418 buffer_len++
419 parser.unread++
420 break
421 }
422 }
423 // [Go] Read the documentation of this function above. To return true,
424 // we need to have the given length in the buffer. Not doing that means
425 // every single check that calls this function to make sure the buffer
426 // has a given length is Go) panicking; or C) accessing invalid memory.
427 // This happens here due to the EOF above breaking early.
428 for buffer_len < length {
429 parser.buffer[buffer_len] = 0
430 buffer_len++
431 }
432 parser.buffer = parser.buffer[:buffer_len]
433 return true
434}
diff --git a/vendor/gopkg.in/yaml.v3/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go
new file mode 100644
index 0000000..64ae888
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/resolve.go
@@ -0,0 +1,326 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package yaml
17
18import (
19 "encoding/base64"
20 "math"
21 "regexp"
22 "strconv"
23 "strings"
24 "time"
25)
26
27type resolveMapItem struct {
28 value interface{}
29 tag string
30}
31
32var resolveTable = make([]byte, 256)
33var resolveMap = make(map[string]resolveMapItem)
34
35func init() {
36 t := resolveTable
37 t[int('+')] = 'S' // Sign
38 t[int('-')] = 'S'
39 for _, c := range "0123456789" {
40 t[int(c)] = 'D' // Digit
41 }
42 for _, c := range "yYnNtTfFoO~" {
43 t[int(c)] = 'M' // In map
44 }
45 t[int('.')] = '.' // Float (potentially in map)
46
47 var resolveMapList = []struct {
48 v interface{}
49 tag string
50 l []string
51 }{
52 {true, boolTag, []string{"true", "True", "TRUE"}},
53 {false, boolTag, []string{"false", "False", "FALSE"}},
54 {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
55 {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
56 {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
57 {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
58 {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
59 {"<<", mergeTag, []string{"<<"}},
60 }
61
62 m := resolveMap
63 for _, item := range resolveMapList {
64 for _, s := range item.l {
65 m[s] = resolveMapItem{item.v, item.tag}
66 }
67 }
68}
69
70const (
71 nullTag = "!!null"
72 boolTag = "!!bool"
73 strTag = "!!str"
74 intTag = "!!int"
75 floatTag = "!!float"
76 timestampTag = "!!timestamp"
77 seqTag = "!!seq"
78 mapTag = "!!map"
79 binaryTag = "!!binary"
80 mergeTag = "!!merge"
81)
82
83var longTags = make(map[string]string)
84var shortTags = make(map[string]string)
85
86func init() {
87 for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
88 ltag := longTag(stag)
89 longTags[stag] = ltag
90 shortTags[ltag] = stag
91 }
92}
93
94const longTagPrefix = "tag:yaml.org,2002:"
95
96func shortTag(tag string) string {
97 if strings.HasPrefix(tag, longTagPrefix) {
98 if stag, ok := shortTags[tag]; ok {
99 return stag
100 }
101 return "!!" + tag[len(longTagPrefix):]
102 }
103 return tag
104}
105
106func longTag(tag string) string {
107 if strings.HasPrefix(tag, "!!") {
108 if ltag, ok := longTags[tag]; ok {
109 return ltag
110 }
111 return longTagPrefix + tag[2:]
112 }
113 return tag
114}
115
116func resolvableTag(tag string) bool {
117 switch tag {
118 case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
119 return true
120 }
121 return false
122}
123
124var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
125
126func resolve(tag string, in string) (rtag string, out interface{}) {
127 tag = shortTag(tag)
128 if !resolvableTag(tag) {
129 return tag, in
130 }
131
132 defer func() {
133 switch tag {
134 case "", rtag, strTag, binaryTag:
135 return
136 case floatTag:
137 if rtag == intTag {
138 switch v := out.(type) {
139 case int64:
140 rtag = floatTag
141 out = float64(v)
142 return
143 case int:
144 rtag = floatTag
145 out = float64(v)
146 return
147 }
148 }
149 }
150 failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
151 }()
152
153 // Any data is accepted as a !!str or !!binary.
154 // Otherwise, the prefix is enough of a hint about what it might be.
155 hint := byte('N')
156 if in != "" {
157 hint = resolveTable[in[0]]
158 }
159 if hint != 0 && tag != strTag && tag != binaryTag {
160 // Handle things we can lookup in a map.
161 if item, ok := resolveMap[in]; ok {
162 return item.tag, item.value
163 }
164
165 // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
166 // are purposefully unsupported here. They're still quoted on
167 // the way out for compatibility with other parser, though.
168
169 switch hint {
170 case 'M':
171 // We've already checked the map above.
172
173 case '.':
174 // Not in the map, so maybe a normal float.
175 floatv, err := strconv.ParseFloat(in, 64)
176 if err == nil {
177 return floatTag, floatv
178 }
179
180 case 'D', 'S':
181 // Int, float, or timestamp.
182 // Only try values as a timestamp if the value is unquoted or there's an explicit
183 // !!timestamp tag.
184 if tag == "" || tag == timestampTag {
185 t, ok := parseTimestamp(in)
186 if ok {
187 return timestampTag, t
188 }
189 }
190
191 plain := strings.Replace(in, "_", "", -1)
192 intv, err := strconv.ParseInt(plain, 0, 64)
193 if err == nil {
194 if intv == int64(int(intv)) {
195 return intTag, int(intv)
196 } else {
197 return intTag, intv
198 }
199 }
200 uintv, err := strconv.ParseUint(plain, 0, 64)
201 if err == nil {
202 return intTag, uintv
203 }
204 if yamlStyleFloat.MatchString(plain) {
205 floatv, err := strconv.ParseFloat(plain, 64)
206 if err == nil {
207 return floatTag, floatv
208 }
209 }
210 if strings.HasPrefix(plain, "0b") {
211 intv, err := strconv.ParseInt(plain[2:], 2, 64)
212 if err == nil {
213 if intv == int64(int(intv)) {
214 return intTag, int(intv)
215 } else {
216 return intTag, intv
217 }
218 }
219 uintv, err := strconv.ParseUint(plain[2:], 2, 64)
220 if err == nil {
221 return intTag, uintv
222 }
223 } else if strings.HasPrefix(plain, "-0b") {
224 intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
225 if err == nil {
226 if true || intv == int64(int(intv)) {
227 return intTag, int(intv)
228 } else {
229 return intTag, intv
230 }
231 }
232 }
233 // Octals as introduced in version 1.2 of the spec.
234 // Octals from the 1.1 spec, spelled as 0777, are still
235 // decoded by default in v3 as well for compatibility.
236 // May be dropped in v4 depending on how usage evolves.
237 if strings.HasPrefix(plain, "0o") {
238 intv, err := strconv.ParseInt(plain[2:], 8, 64)
239 if err == nil {
240 if intv == int64(int(intv)) {
241 return intTag, int(intv)
242 } else {
243 return intTag, intv
244 }
245 }
246 uintv, err := strconv.ParseUint(plain[2:], 8, 64)
247 if err == nil {
248 return intTag, uintv
249 }
250 } else if strings.HasPrefix(plain, "-0o") {
251 intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
252 if err == nil {
253 if true || intv == int64(int(intv)) {
254 return intTag, int(intv)
255 } else {
256 return intTag, intv
257 }
258 }
259 }
260 default:
261 panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
262 }
263 }
264 return strTag, in
265}
266
267// encodeBase64 encodes s as base64 that is broken up into multiple lines
268// as appropriate for the resulting length.
269func encodeBase64(s string) string {
270 const lineLen = 70
271 encLen := base64.StdEncoding.EncodedLen(len(s))
272 lines := encLen/lineLen + 1
273 buf := make([]byte, encLen*2+lines)
274 in := buf[0:encLen]
275 out := buf[encLen:]
276 base64.StdEncoding.Encode(in, []byte(s))
277 k := 0
278 for i := 0; i < len(in); i += lineLen {
279 j := i + lineLen
280 if j > len(in) {
281 j = len(in)
282 }
283 k += copy(out[k:], in[i:j])
284 if lines > 1 {
285 out[k] = '\n'
286 k++
287 }
288 }
289 return string(out[:k])
290}
291
292// This is a subset of the formats allowed by the regular expression
293// defined at http://yaml.org/type/timestamp.html.
294var allowedTimestampFormats = []string{
295 "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
296 "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
297 "2006-1-2 15:4:5.999999999", // space separated with no time zone
298 "2006-1-2", // date only
299 // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
300 // from the set of examples.
301}
302
303// parseTimestamp parses s as a timestamp string and
304// returns the timestamp and reports whether it succeeded.
305// Timestamp formats are defined at http://yaml.org/type/timestamp.html
306func parseTimestamp(s string) (time.Time, bool) {
307 // TODO write code to check all the formats supported by
308 // http://yaml.org/type/timestamp.html instead of using time.Parse.
309
310 // Quick check: all date formats start with YYYY-.
311 i := 0
312 for ; i < len(s); i++ {
313 if c := s[i]; c < '0' || c > '9' {
314 break
315 }
316 }
317 if i != 4 || i == len(s) || s[i] != '-' {
318 return time.Time{}, false
319 }
320 for _, format := range allowedTimestampFormats {
321 if t, err := time.Parse(format, s); err == nil {
322 return t, true
323 }
324 }
325 return time.Time{}, false
326}
diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go
new file mode 100644
index 0000000..ca00701
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/scannerc.go
@@ -0,0 +1,3038 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "bytes"
27 "fmt"
28)
29
30// Introduction
31// ************
32//
33// The following notes assume that you are familiar with the YAML specification
34// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
35// some cases we are less restrictive that it requires.
36//
37// The process of transforming a YAML stream into a sequence of events is
38// divided on two steps: Scanning and Parsing.
39//
40// The Scanner transforms the input stream into a sequence of tokens, while the
41// parser transform the sequence of tokens produced by the Scanner into a
42// sequence of parsing events.
43//
44// The Scanner is rather clever and complicated. The Parser, on the contrary,
45// is a straightforward implementation of a recursive-descendant parser (or,
46// LL(1) parser, as it is usually called).
47//
48// Actually there are two issues of Scanning that might be called "clever", the
49// rest is quite straightforward. The issues are "block collection start" and
50// "simple keys". Both issues are explained below in details.
51//
52// Here the Scanning step is explained and implemented. We start with the list
53// of all the tokens produced by the Scanner together with short descriptions.
54//
55// Now, tokens:
56//
57// STREAM-START(encoding) # The stream start.
58// STREAM-END # The stream end.
59// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
60// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
61// DOCUMENT-START # '---'
62// DOCUMENT-END # '...'
63// BLOCK-SEQUENCE-START # Indentation increase denoting a block
64// BLOCK-MAPPING-START # sequence or a block mapping.
65// BLOCK-END # Indentation decrease.
66// FLOW-SEQUENCE-START # '['
67// FLOW-SEQUENCE-END # ']'
68// BLOCK-SEQUENCE-START # '{'
69// BLOCK-SEQUENCE-END # '}'
70// BLOCK-ENTRY # '-'
71// FLOW-ENTRY # ','
72// KEY # '?' or nothing (simple keys).
73// VALUE # ':'
74// ALIAS(anchor) # '*anchor'
75// ANCHOR(anchor) # '&anchor'
76// TAG(handle,suffix) # '!handle!suffix'
77// SCALAR(value,style) # A scalar.
78//
79// The following two tokens are "virtual" tokens denoting the beginning and the
80// end of the stream:
81//
82// STREAM-START(encoding)
83// STREAM-END
84//
85// We pass the information about the input stream encoding with the
86// STREAM-START token.
87//
88// The next two tokens are responsible for tags:
89//
90// VERSION-DIRECTIVE(major,minor)
91// TAG-DIRECTIVE(handle,prefix)
92//
93// Example:
94//
95// %YAML 1.1
96// %TAG ! !foo
97// %TAG !yaml! tag:yaml.org,2002:
98// ---
99//
100// The correspoding sequence of tokens:
101//
102// STREAM-START(utf-8)
103// VERSION-DIRECTIVE(1,1)
104// TAG-DIRECTIVE("!","!foo")
105// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
106// DOCUMENT-START
107// STREAM-END
108//
109// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
110// line.
111//
112// The document start and end indicators are represented by:
113//
114// DOCUMENT-START
115// DOCUMENT-END
116//
117// Note that if a YAML stream contains an implicit document (without '---'
118// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
119// produced.
120//
121// In the following examples, we present whole documents together with the
122// produced tokens.
123//
124// 1. An implicit document:
125//
126// 'a scalar'
127//
128// Tokens:
129//
130// STREAM-START(utf-8)
131// SCALAR("a scalar",single-quoted)
132// STREAM-END
133//
134// 2. An explicit document:
135//
136// ---
137// 'a scalar'
138// ...
139//
140// Tokens:
141//
142// STREAM-START(utf-8)
143// DOCUMENT-START
144// SCALAR("a scalar",single-quoted)
145// DOCUMENT-END
146// STREAM-END
147//
148// 3. Several documents in a stream:
149//
150// 'a scalar'
151// ---
152// 'another scalar'
153// ---
154// 'yet another scalar'
155//
156// Tokens:
157//
158// STREAM-START(utf-8)
159// SCALAR("a scalar",single-quoted)
160// DOCUMENT-START
161// SCALAR("another scalar",single-quoted)
162// DOCUMENT-START
163// SCALAR("yet another scalar",single-quoted)
164// STREAM-END
165//
166// We have already introduced the SCALAR token above. The following tokens are
167// used to describe aliases, anchors, tag, and scalars:
168//
169// ALIAS(anchor)
170// ANCHOR(anchor)
171// TAG(handle,suffix)
172// SCALAR(value,style)
173//
174// The following series of examples illustrate the usage of these tokens:
175//
176// 1. A recursive sequence:
177//
178// &A [ *A ]
179//
180// Tokens:
181//
182// STREAM-START(utf-8)
183// ANCHOR("A")
184// FLOW-SEQUENCE-START
185// ALIAS("A")
186// FLOW-SEQUENCE-END
187// STREAM-END
188//
189// 2. A tagged scalar:
190//
191// !!float "3.14" # A good approximation.
192//
193// Tokens:
194//
195// STREAM-START(utf-8)
196// TAG("!!","float")
197// SCALAR("3.14",double-quoted)
198// STREAM-END
199//
200// 3. Various scalar styles:
201//
202// --- # Implicit empty plain scalars do not produce tokens.
203// --- a plain scalar
204// --- 'a single-quoted scalar'
205// --- "a double-quoted scalar"
206// --- |-
207// a literal scalar
208// --- >-
209// a folded
210// scalar
211//
212// Tokens:
213//
214// STREAM-START(utf-8)
215// DOCUMENT-START
216// DOCUMENT-START
217// SCALAR("a plain scalar",plain)
218// DOCUMENT-START
219// SCALAR("a single-quoted scalar",single-quoted)
220// DOCUMENT-START
221// SCALAR("a double-quoted scalar",double-quoted)
222// DOCUMENT-START
223// SCALAR("a literal scalar",literal)
224// DOCUMENT-START
225// SCALAR("a folded scalar",folded)
226// STREAM-END
227//
228// Now it's time to review collection-related tokens. We will start with
229// flow collections:
230//
231// FLOW-SEQUENCE-START
232// FLOW-SEQUENCE-END
233// FLOW-MAPPING-START
234// FLOW-MAPPING-END
235// FLOW-ENTRY
236// KEY
237// VALUE
238//
239// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
240// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
241// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
242// indicators '?' and ':', which are used for denoting mapping keys and values,
243// are represented by the KEY and VALUE tokens.
244//
245// The following examples show flow collections:
246//
247// 1. A flow sequence:
248//
249// [item 1, item 2, item 3]
250//
251// Tokens:
252//
253// STREAM-START(utf-8)
254// FLOW-SEQUENCE-START
255// SCALAR("item 1",plain)
256// FLOW-ENTRY
257// SCALAR("item 2",plain)
258// FLOW-ENTRY
259// SCALAR("item 3",plain)
260// FLOW-SEQUENCE-END
261// STREAM-END
262//
263// 2. A flow mapping:
264//
265// {
266// a simple key: a value, # Note that the KEY token is produced.
267// ? a complex key: another value,
268// }
269//
270// Tokens:
271//
272// STREAM-START(utf-8)
273// FLOW-MAPPING-START
274// KEY
275// SCALAR("a simple key",plain)
276// VALUE
277// SCALAR("a value",plain)
278// FLOW-ENTRY
279// KEY
280// SCALAR("a complex key",plain)
281// VALUE
282// SCALAR("another value",plain)
283// FLOW-ENTRY
284// FLOW-MAPPING-END
285// STREAM-END
286//
287// A simple key is a key which is not denoted by the '?' indicator. Note that
288// the Scanner still produce the KEY token whenever it encounters a simple key.
289//
290// For scanning block collections, the following tokens are used (note that we
291// repeat KEY and VALUE here):
292//
293// BLOCK-SEQUENCE-START
294// BLOCK-MAPPING-START
295// BLOCK-END
296// BLOCK-ENTRY
297// KEY
298// VALUE
299//
300// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
301// increase that precedes a block collection (cf. the INDENT token in Python).
302// The token BLOCK-END denote indentation decrease that ends a block collection
303// (cf. the DEDENT token in Python). However YAML has some syntax pecularities
304// that makes detections of these tokens more complex.
305//
306// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
307// '-', '?', and ':' correspondingly.
308//
309// The following examples show how the tokens BLOCK-SEQUENCE-START,
310// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
311//
312// 1. Block sequences:
313//
314// - item 1
315// - item 2
316// -
317// - item 3.1
318// - item 3.2
319// -
320// key 1: value 1
321// key 2: value 2
322//
323// Tokens:
324//
325// STREAM-START(utf-8)
326// BLOCK-SEQUENCE-START
327// BLOCK-ENTRY
328// SCALAR("item 1",plain)
329// BLOCK-ENTRY
330// SCALAR("item 2",plain)
331// BLOCK-ENTRY
332// BLOCK-SEQUENCE-START
333// BLOCK-ENTRY
334// SCALAR("item 3.1",plain)
335// BLOCK-ENTRY
336// SCALAR("item 3.2",plain)
337// BLOCK-END
338// BLOCK-ENTRY
339// BLOCK-MAPPING-START
340// KEY
341// SCALAR("key 1",plain)
342// VALUE
343// SCALAR("value 1",plain)
344// KEY
345// SCALAR("key 2",plain)
346// VALUE
347// SCALAR("value 2",plain)
348// BLOCK-END
349// BLOCK-END
350// STREAM-END
351//
352// 2. Block mappings:
353//
354// a simple key: a value # The KEY token is produced here.
355// ? a complex key
356// : another value
357// a mapping:
358// key 1: value 1
359// key 2: value 2
360// a sequence:
361// - item 1
362// - item 2
363//
364// Tokens:
365//
366// STREAM-START(utf-8)
367// BLOCK-MAPPING-START
368// KEY
369// SCALAR("a simple key",plain)
370// VALUE
371// SCALAR("a value",plain)
372// KEY
373// SCALAR("a complex key",plain)
374// VALUE
375// SCALAR("another value",plain)
376// KEY
377// SCALAR("a mapping",plain)
378// BLOCK-MAPPING-START
379// KEY
380// SCALAR("key 1",plain)
381// VALUE
382// SCALAR("value 1",plain)
383// KEY
384// SCALAR("key 2",plain)
385// VALUE
386// SCALAR("value 2",plain)
387// BLOCK-END
388// KEY
389// SCALAR("a sequence",plain)
390// VALUE
391// BLOCK-SEQUENCE-START
392// BLOCK-ENTRY
393// SCALAR("item 1",plain)
394// BLOCK-ENTRY
395// SCALAR("item 2",plain)
396// BLOCK-END
397// BLOCK-END
398// STREAM-END
399//
400// YAML does not always require to start a new block collection from a new
401// line. If the current line contains only '-', '?', and ':' indicators, a new
402// block collection may start at the current line. The following examples
403// illustrate this case:
404//
405// 1. Collections in a sequence:
406//
407// - - item 1
408// - item 2
409// - key 1: value 1
410// key 2: value 2
411// - ? complex key
412// : complex value
413//
414// Tokens:
415//
416// STREAM-START(utf-8)
417// BLOCK-SEQUENCE-START
418// BLOCK-ENTRY
419// BLOCK-SEQUENCE-START
420// BLOCK-ENTRY
421// SCALAR("item 1",plain)
422// BLOCK-ENTRY
423// SCALAR("item 2",plain)
424// BLOCK-END
425// BLOCK-ENTRY
426// BLOCK-MAPPING-START
427// KEY
428// SCALAR("key 1",plain)
429// VALUE
430// SCALAR("value 1",plain)
431// KEY
432// SCALAR("key 2",plain)
433// VALUE
434// SCALAR("value 2",plain)
435// BLOCK-END
436// BLOCK-ENTRY
437// BLOCK-MAPPING-START
438// KEY
439// SCALAR("complex key")
440// VALUE
441// SCALAR("complex value")
442// BLOCK-END
443// BLOCK-END
444// STREAM-END
445//
446// 2. Collections in a mapping:
447//
448// ? a sequence
449// : - item 1
450// - item 2
451// ? a mapping
452// : key 1: value 1
453// key 2: value 2
454//
455// Tokens:
456//
457// STREAM-START(utf-8)
458// BLOCK-MAPPING-START
459// KEY
460// SCALAR("a sequence",plain)
461// VALUE
462// BLOCK-SEQUENCE-START
463// BLOCK-ENTRY
464// SCALAR("item 1",plain)
465// BLOCK-ENTRY
466// SCALAR("item 2",plain)
467// BLOCK-END
468// KEY
469// SCALAR("a mapping",plain)
470// VALUE
471// BLOCK-MAPPING-START
472// KEY
473// SCALAR("key 1",plain)
474// VALUE
475// SCALAR("value 1",plain)
476// KEY
477// SCALAR("key 2",plain)
478// VALUE
479// SCALAR("value 2",plain)
480// BLOCK-END
481// BLOCK-END
482// STREAM-END
483//
484// YAML also permits non-indented sequences if they are included into a block
485// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
486//
487// key:
488// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
489// - item 2
490//
491// Tokens:
492//
493// STREAM-START(utf-8)
494// BLOCK-MAPPING-START
495// KEY
496// SCALAR("key",plain)
497// VALUE
498// BLOCK-ENTRY
499// SCALAR("item 1",plain)
500// BLOCK-ENTRY
501// SCALAR("item 2",plain)
502// BLOCK-END
503//
504
505// Ensure that the buffer contains the required number of characters.
506// Return true on success, false on failure (reader error or memory error).
507func cache(parser *yaml_parser_t, length int) bool {
508 // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
509 return parser.unread >= length || yaml_parser_update_buffer(parser, length)
510}
511
512// Advance the buffer pointer.
513func skip(parser *yaml_parser_t) {
514 if !is_blank(parser.buffer, parser.buffer_pos) {
515 parser.newlines = 0
516 }
517 parser.mark.index++
518 parser.mark.column++
519 parser.unread--
520 parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
521}
522
523func skip_line(parser *yaml_parser_t) {
524 if is_crlf(parser.buffer, parser.buffer_pos) {
525 parser.mark.index += 2
526 parser.mark.column = 0
527 parser.mark.line++
528 parser.unread -= 2
529 parser.buffer_pos += 2
530 parser.newlines++
531 } else if is_break(parser.buffer, parser.buffer_pos) {
532 parser.mark.index++
533 parser.mark.column = 0
534 parser.mark.line++
535 parser.unread--
536 parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
537 parser.newlines++
538 }
539}
540
541// Copy a character to a string buffer and advance pointers.
542func read(parser *yaml_parser_t, s []byte) []byte {
543 if !is_blank(parser.buffer, parser.buffer_pos) {
544 parser.newlines = 0
545 }
546 w := width(parser.buffer[parser.buffer_pos])
547 if w == 0 {
548 panic("invalid character sequence")
549 }
550 if len(s) == 0 {
551 s = make([]byte, 0, 32)
552 }
553 if w == 1 && len(s)+w <= cap(s) {
554 s = s[:len(s)+1]
555 s[len(s)-1] = parser.buffer[parser.buffer_pos]
556 parser.buffer_pos++
557 } else {
558 s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
559 parser.buffer_pos += w
560 }
561 parser.mark.index++
562 parser.mark.column++
563 parser.unread--
564 return s
565}
566
567// Copy a line break character to a string buffer and advance pointers.
568func read_line(parser *yaml_parser_t, s []byte) []byte {
569 buf := parser.buffer
570 pos := parser.buffer_pos
571 switch {
572 case buf[pos] == '\r' && buf[pos+1] == '\n':
573 // CR LF . LF
574 s = append(s, '\n')
575 parser.buffer_pos += 2
576 parser.mark.index++
577 parser.unread--
578 case buf[pos] == '\r' || buf[pos] == '\n':
579 // CR|LF . LF
580 s = append(s, '\n')
581 parser.buffer_pos += 1
582 case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
583 // NEL . LF
584 s = append(s, '\n')
585 parser.buffer_pos += 2
586 case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
587 // LS|PS . LS|PS
588 s = append(s, buf[parser.buffer_pos:pos+3]...)
589 parser.buffer_pos += 3
590 default:
591 return s
592 }
593 parser.mark.index++
594 parser.mark.column = 0
595 parser.mark.line++
596 parser.unread--
597 parser.newlines++
598 return s
599}
600
601// Get the next token.
602func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
603 // Erase the token object.
604 *token = yaml_token_t{} // [Go] Is this necessary?
605
606 // No tokens after STREAM-END or error.
607 if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
608 return true
609 }
610
611 // Ensure that the tokens queue contains enough tokens.
612 if !parser.token_available {
613 if !yaml_parser_fetch_more_tokens(parser) {
614 return false
615 }
616 }
617
618 // Fetch the next token from the queue.
619 *token = parser.tokens[parser.tokens_head]
620 parser.tokens_head++
621 parser.tokens_parsed++
622 parser.token_available = false
623
624 if token.typ == yaml_STREAM_END_TOKEN {
625 parser.stream_end_produced = true
626 }
627 return true
628}
629
630// Set the scanner error and return false.
631func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
632 parser.error = yaml_SCANNER_ERROR
633 parser.context = context
634 parser.context_mark = context_mark
635 parser.problem = problem
636 parser.problem_mark = parser.mark
637 return false
638}
639
640func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
641 context := "while parsing a tag"
642 if directive {
643 context = "while parsing a %TAG directive"
644 }
645 return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
646}
647
648func trace(args ...interface{}) func() {
649 pargs := append([]interface{}{"+++"}, args...)
650 fmt.Println(pargs...)
651 pargs = append([]interface{}{"---"}, args...)
652 return func() { fmt.Println(pargs...) }
653}
654
655// Ensure that the tokens queue contains at least one token which can be
656// returned to the Parser.
657func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
658 // While we need more tokens to fetch, do it.
659 for {
660 // [Go] The comment parsing logic requires a lookahead of two tokens
661 // so that foot comments may be parsed in time of associating them
662 // with the tokens that are parsed before them, and also for line
663 // comments to be transformed into head comments in some edge cases.
664 if parser.tokens_head < len(parser.tokens)-2 {
665 // If a potential simple key is at the head position, we need to fetch
666 // the next token to disambiguate it.
667 head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
668 if !ok {
669 break
670 } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
671 return false
672 } else if !valid {
673 break
674 }
675 }
676 // Fetch the next token.
677 if !yaml_parser_fetch_next_token(parser) {
678 return false
679 }
680 }
681
682 parser.token_available = true
683 return true
684}
685
686// The dispatcher for token fetchers.
687func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
688 // Ensure that the buffer is initialized.
689 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
690 return false
691 }
692
693 // Check if we just started scanning. Fetch STREAM-START then.
694 if !parser.stream_start_produced {
695 return yaml_parser_fetch_stream_start(parser)
696 }
697
698 scan_mark := parser.mark
699
700 // Eat whitespaces and comments until we reach the next token.
701 if !yaml_parser_scan_to_next_token(parser) {
702 return false
703 }
704
705 // [Go] While unrolling indents, transform the head comments of prior
706 // indentation levels observed after scan_start into foot comments at
707 // the respective indexes.
708
709 // Check the indentation level against the current column.
710 if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
711 return false
712 }
713
714 // Ensure that the buffer contains at least 4 characters. 4 is the length
715 // of the longest indicators ('--- ' and '... ').
716 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
717 return false
718 }
719
720 // Is it the end of the stream?
721 if is_z(parser.buffer, parser.buffer_pos) {
722 return yaml_parser_fetch_stream_end(parser)
723 }
724
725 // Is it a directive?
726 if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
727 return yaml_parser_fetch_directive(parser)
728 }
729
730 buf := parser.buffer
731 pos := parser.buffer_pos
732
733 // Is it the document start indicator?
734 if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
735 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
736 }
737
738 // Is it the document end indicator?
739 if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
740 return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
741 }
742
743 comment_mark := parser.mark
744 if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
745 // Associate any following comments with the prior token.
746 comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
747 }
748 defer func() {
749 if !ok {
750 return
751 }
752 if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
753 // Sequence indicators alone have no line comments. It becomes
754 // a head comment for whatever follows.
755 return
756 }
757 if !yaml_parser_scan_line_comment(parser, comment_mark) {
758 ok = false
759 return
760 }
761 }()
762
763 // Is it the flow sequence start indicator?
764 if buf[pos] == '[' {
765 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
766 }
767
768 // Is it the flow mapping start indicator?
769 if parser.buffer[parser.buffer_pos] == '{' {
770 return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
771 }
772
773 // Is it the flow sequence end indicator?
774 if parser.buffer[parser.buffer_pos] == ']' {
775 return yaml_parser_fetch_flow_collection_end(parser,
776 yaml_FLOW_SEQUENCE_END_TOKEN)
777 }
778
779 // Is it the flow mapping end indicator?
780 if parser.buffer[parser.buffer_pos] == '}' {
781 return yaml_parser_fetch_flow_collection_end(parser,
782 yaml_FLOW_MAPPING_END_TOKEN)
783 }
784
785 // Is it the flow entry indicator?
786 if parser.buffer[parser.buffer_pos] == ',' {
787 return yaml_parser_fetch_flow_entry(parser)
788 }
789
790 // Is it the block entry indicator?
791 if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
792 return yaml_parser_fetch_block_entry(parser)
793 }
794
795 // Is it the key indicator?
796 if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
797 return yaml_parser_fetch_key(parser)
798 }
799
800 // Is it the value indicator?
801 if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
802 return yaml_parser_fetch_value(parser)
803 }
804
805 // Is it an alias?
806 if parser.buffer[parser.buffer_pos] == '*' {
807 return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
808 }
809
810 // Is it an anchor?
811 if parser.buffer[parser.buffer_pos] == '&' {
812 return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
813 }
814
815 // Is it a tag?
816 if parser.buffer[parser.buffer_pos] == '!' {
817 return yaml_parser_fetch_tag(parser)
818 }
819
820 // Is it a literal scalar?
821 if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
822 return yaml_parser_fetch_block_scalar(parser, true)
823 }
824
825 // Is it a folded scalar?
826 if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
827 return yaml_parser_fetch_block_scalar(parser, false)
828 }
829
830 // Is it a single-quoted scalar?
831 if parser.buffer[parser.buffer_pos] == '\'' {
832 return yaml_parser_fetch_flow_scalar(parser, true)
833 }
834
835 // Is it a double-quoted scalar?
836 if parser.buffer[parser.buffer_pos] == '"' {
837 return yaml_parser_fetch_flow_scalar(parser, false)
838 }
839
840 // Is it a plain scalar?
841 //
842 // A plain scalar may start with any non-blank characters except
843 //
844 // '-', '?', ':', ',', '[', ']', '{', '}',
845 // '#', '&', '*', '!', '|', '>', '\'', '\"',
846 // '%', '@', '`'.
847 //
848 // In the block context (and, for the '-' indicator, in the flow context
849 // too), it may also start with the characters
850 //
851 // '-', '?', ':'
852 //
853 // if it is followed by a non-space character.
854 //
855 // The last rule is more restrictive than the specification requires.
856 // [Go] TODO Make this logic more reasonable.
857 //switch parser.buffer[parser.buffer_pos] {
858 //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
859 //}
860 if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
861 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
862 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
863 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
864 parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
865 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
866 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
867 parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
868 parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
869 parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
870 (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
871 (parser.flow_level == 0 &&
872 (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
873 !is_blankz(parser.buffer, parser.buffer_pos+1)) {
874 return yaml_parser_fetch_plain_scalar(parser)
875 }
876
877 // If we don't determine the token type so far, it is an error.
878 return yaml_parser_set_scanner_error(parser,
879 "while scanning for the next token", parser.mark,
880 "found character that cannot start any token")
881}
882
883func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
884 if !simple_key.possible {
885 return false, true
886 }
887
888 // The 1.2 specification says:
889 //
890 // "If the ? indicator is omitted, parsing needs to see past the
891 // implicit key to recognize it as such. To limit the amount of
892 // lookahead required, the “:” indicator must appear at most 1024
893 // Unicode characters beyond the start of the key. In addition, the key
894 // is restricted to a single line."
895 //
896 if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
897 // Check if the potential simple key to be removed is required.
898 if simple_key.required {
899 return false, yaml_parser_set_scanner_error(parser,
900 "while scanning a simple key", simple_key.mark,
901 "could not find expected ':'")
902 }
903 simple_key.possible = false
904 return false, true
905 }
906 return true, true
907}
908
909// Check if a simple key may start at the current position and add it if
910// needed.
911func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
912 // A simple key is required at the current position if the scanner is in
913 // the block context and the current column coincides with the indentation
914 // level.
915
916 required := parser.flow_level == 0 && parser.indent == parser.mark.column
917
918 //
919 // If the current position may start a simple key, save it.
920 //
921 if parser.simple_key_allowed {
922 simple_key := yaml_simple_key_t{
923 possible: true,
924 required: required,
925 token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
926 mark: parser.mark,
927 }
928
929 if !yaml_parser_remove_simple_key(parser) {
930 return false
931 }
932 parser.simple_keys[len(parser.simple_keys)-1] = simple_key
933 parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
934 }
935 return true
936}
937
938// Remove a potential simple key at the current flow level.
939func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
940 i := len(parser.simple_keys) - 1
941 if parser.simple_keys[i].possible {
942 // If the key is required, it is an error.
943 if parser.simple_keys[i].required {
944 return yaml_parser_set_scanner_error(parser,
945 "while scanning a simple key", parser.simple_keys[i].mark,
946 "could not find expected ':'")
947 }
948 // Remove the key from the stack.
949 parser.simple_keys[i].possible = false
950 delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
951 }
952 return true
953}
954
955// max_flow_level limits the flow_level
956const max_flow_level = 10000
957
958// Increase the flow level and resize the simple key list if needed.
959func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
960 // Reset the simple key on the next level.
961 parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
962 possible: false,
963 required: false,
964 token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
965 mark: parser.mark,
966 })
967
968 // Increase the flow level.
969 parser.flow_level++
970 if parser.flow_level > max_flow_level {
971 return yaml_parser_set_scanner_error(parser,
972 "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
973 fmt.Sprintf("exceeded max depth of %d", max_flow_level))
974 }
975 return true
976}
977
978// Decrease the flow level.
979func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
980 if parser.flow_level > 0 {
981 parser.flow_level--
982 last := len(parser.simple_keys) - 1
983 delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
984 parser.simple_keys = parser.simple_keys[:last]
985 }
986 return true
987}
988
989// max_indents limits the indents stack size
990const max_indents = 10000
991
992// Push the current indentation level to the stack and set the new level
993// the current column is greater than the indentation level. In this case,
994// append or insert the specified token into the token queue.
995func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
996 // In the flow context, do nothing.
997 if parser.flow_level > 0 {
998 return true
999 }
1000
1001 if parser.indent < column {
1002 // Push the current indentation level to the stack and set the new
1003 // indentation level.
1004 parser.indents = append(parser.indents, parser.indent)
1005 parser.indent = column
1006 if len(parser.indents) > max_indents {
1007 return yaml_parser_set_scanner_error(parser,
1008 "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
1009 fmt.Sprintf("exceeded max depth of %d", max_indents))
1010 }
1011
1012 // Create a token and insert it into the queue.
1013 token := yaml_token_t{
1014 typ: typ,
1015 start_mark: mark,
1016 end_mark: mark,
1017 }
1018 if number > -1 {
1019 number -= parser.tokens_parsed
1020 }
1021 yaml_insert_token(parser, number, &token)
1022 }
1023 return true
1024}
1025
1026// Pop indentation levels from the indents stack until the current level
1027// becomes less or equal to the column. For each indentation level, append
1028// the BLOCK-END token.
1029func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
1030 // In the flow context, do nothing.
1031 if parser.flow_level > 0 {
1032 return true
1033 }
1034
1035 block_mark := scan_mark
1036 block_mark.index--
1037
1038 // Loop through the indentation levels in the stack.
1039 for parser.indent > column {
1040
1041 // [Go] Reposition the end token before potential following
1042 // foot comments of parent blocks. For that, search
1043 // backwards for recent comments that were at the same
1044 // indent as the block that is ending now.
1045 stop_index := block_mark.index
1046 for i := len(parser.comments) - 1; i >= 0; i-- {
1047 comment := &parser.comments[i]
1048
1049 if comment.end_mark.index < stop_index {
1050 // Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
1051 // If requested indent column is < 0, then the document is over and everything else
1052 // is a foot anyway.
1053 break
1054 }
1055 if comment.start_mark.column == parser.indent+1 {
1056 // This is a good match. But maybe there's a former comment
1057 // at that same indent level, so keep searching.
1058 block_mark = comment.start_mark
1059 }
1060
1061 // While the end of the former comment matches with
1062 // the start of the following one, we know there's
1063 // nothing in between and scanning is still safe.
1064 stop_index = comment.scan_mark.index
1065 }
1066
1067 // Create a token and append it to the queue.
1068 token := yaml_token_t{
1069 typ: yaml_BLOCK_END_TOKEN,
1070 start_mark: block_mark,
1071 end_mark: block_mark,
1072 }
1073 yaml_insert_token(parser, -1, &token)
1074
1075 // Pop the indentation level.
1076 parser.indent = parser.indents[len(parser.indents)-1]
1077 parser.indents = parser.indents[:len(parser.indents)-1]
1078 }
1079 return true
1080}
1081
1082// Initialize the scanner and produce the STREAM-START token.
1083func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
1084
1085 // Set the initial indentation.
1086 parser.indent = -1
1087
1088 // Initialize the simple key stack.
1089 parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
1090
1091 parser.simple_keys_by_tok = make(map[int]int)
1092
1093 // A simple key is allowed at the beginning of the stream.
1094 parser.simple_key_allowed = true
1095
1096 // We have started.
1097 parser.stream_start_produced = true
1098
1099 // Create the STREAM-START token and append it to the queue.
1100 token := yaml_token_t{
1101 typ: yaml_STREAM_START_TOKEN,
1102 start_mark: parser.mark,
1103 end_mark: parser.mark,
1104 encoding: parser.encoding,
1105 }
1106 yaml_insert_token(parser, -1, &token)
1107 return true
1108}
1109
1110// Produce the STREAM-END token and shut down the scanner.
1111func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
1112
1113 // Force new line.
1114 if parser.mark.column != 0 {
1115 parser.mark.column = 0
1116 parser.mark.line++
1117 }
1118
1119 // Reset the indentation level.
1120 if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
1121 return false
1122 }
1123
1124 // Reset simple keys.
1125 if !yaml_parser_remove_simple_key(parser) {
1126 return false
1127 }
1128
1129 parser.simple_key_allowed = false
1130
1131 // Create the STREAM-END token and append it to the queue.
1132 token := yaml_token_t{
1133 typ: yaml_STREAM_END_TOKEN,
1134 start_mark: parser.mark,
1135 end_mark: parser.mark,
1136 }
1137 yaml_insert_token(parser, -1, &token)
1138 return true
1139}
1140
1141// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
1142func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
1143 // Reset the indentation level.
1144 if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
1145 return false
1146 }
1147
1148 // Reset simple keys.
1149 if !yaml_parser_remove_simple_key(parser) {
1150 return false
1151 }
1152
1153 parser.simple_key_allowed = false
1154
1155 // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
1156 token := yaml_token_t{}
1157 if !yaml_parser_scan_directive(parser, &token) {
1158 return false
1159 }
1160 // Append the token to the queue.
1161 yaml_insert_token(parser, -1, &token)
1162 return true
1163}
1164
1165// Produce the DOCUMENT-START or DOCUMENT-END token.
1166func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1167 // Reset the indentation level.
1168 if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
1169 return false
1170 }
1171
1172 // Reset simple keys.
1173 if !yaml_parser_remove_simple_key(parser) {
1174 return false
1175 }
1176
1177 parser.simple_key_allowed = false
1178
1179 // Consume the token.
1180 start_mark := parser.mark
1181
1182 skip(parser)
1183 skip(parser)
1184 skip(parser)
1185
1186 end_mark := parser.mark
1187
1188 // Create the DOCUMENT-START or DOCUMENT-END token.
1189 token := yaml_token_t{
1190 typ: typ,
1191 start_mark: start_mark,
1192 end_mark: end_mark,
1193 }
1194 // Append the token to the queue.
1195 yaml_insert_token(parser, -1, &token)
1196 return true
1197}
1198
1199// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1200func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1201
1202 // The indicators '[' and '{' may start a simple key.
1203 if !yaml_parser_save_simple_key(parser) {
1204 return false
1205 }
1206
1207 // Increase the flow level.
1208 if !yaml_parser_increase_flow_level(parser) {
1209 return false
1210 }
1211
1212 // A simple key may follow the indicators '[' and '{'.
1213 parser.simple_key_allowed = true
1214
1215 // Consume the token.
1216 start_mark := parser.mark
1217 skip(parser)
1218 end_mark := parser.mark
1219
1220 // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
1221 token := yaml_token_t{
1222 typ: typ,
1223 start_mark: start_mark,
1224 end_mark: end_mark,
1225 }
1226 // Append the token to the queue.
1227 yaml_insert_token(parser, -1, &token)
1228 return true
1229}
1230
1231// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1232func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1233 // Reset any potential simple key on the current flow level.
1234 if !yaml_parser_remove_simple_key(parser) {
1235 return false
1236 }
1237
1238 // Decrease the flow level.
1239 if !yaml_parser_decrease_flow_level(parser) {
1240 return false
1241 }
1242
1243 // No simple keys after the indicators ']' and '}'.
1244 parser.simple_key_allowed = false
1245
1246 // Consume the token.
1247
1248 start_mark := parser.mark
1249 skip(parser)
1250 end_mark := parser.mark
1251
1252 // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
1253 token := yaml_token_t{
1254 typ: typ,
1255 start_mark: start_mark,
1256 end_mark: end_mark,
1257 }
1258 // Append the token to the queue.
1259 yaml_insert_token(parser, -1, &token)
1260 return true
1261}
1262
1263// Produce the FLOW-ENTRY token.
1264func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
1265 // Reset any potential simple keys on the current flow level.
1266 if !yaml_parser_remove_simple_key(parser) {
1267 return false
1268 }
1269
1270 // Simple keys are allowed after ','.
1271 parser.simple_key_allowed = true
1272
1273 // Consume the token.
1274 start_mark := parser.mark
1275 skip(parser)
1276 end_mark := parser.mark
1277
1278 // Create the FLOW-ENTRY token and append it to the queue.
1279 token := yaml_token_t{
1280 typ: yaml_FLOW_ENTRY_TOKEN,
1281 start_mark: start_mark,
1282 end_mark: end_mark,
1283 }
1284 yaml_insert_token(parser, -1, &token)
1285 return true
1286}
1287
1288// Produce the BLOCK-ENTRY token.
1289func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
1290 // Check if the scanner is in the block context.
1291 if parser.flow_level == 0 {
1292 // Check if we are allowed to start a new entry.
1293 if !parser.simple_key_allowed {
1294 return yaml_parser_set_scanner_error(parser, "", parser.mark,
1295 "block sequence entries are not allowed in this context")
1296 }
1297 // Add the BLOCK-SEQUENCE-START token if needed.
1298 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
1299 return false
1300 }
1301 } else {
1302 // It is an error for the '-' indicator to occur in the flow context,
1303 // but we let the Parser detect and report about it because the Parser
1304 // is able to point to the context.
1305 }
1306
1307 // Reset any potential simple keys on the current flow level.
1308 if !yaml_parser_remove_simple_key(parser) {
1309 return false
1310 }
1311
1312 // Simple keys are allowed after '-'.
1313 parser.simple_key_allowed = true
1314
1315 // Consume the token.
1316 start_mark := parser.mark
1317 skip(parser)
1318 end_mark := parser.mark
1319
1320 // Create the BLOCK-ENTRY token and append it to the queue.
1321 token := yaml_token_t{
1322 typ: yaml_BLOCK_ENTRY_TOKEN,
1323 start_mark: start_mark,
1324 end_mark: end_mark,
1325 }
1326 yaml_insert_token(parser, -1, &token)
1327 return true
1328}
1329
1330// Produce the KEY token.
1331func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
1332
1333 // In the block context, additional checks are required.
1334 if parser.flow_level == 0 {
1335 // Check if we are allowed to start a new key (not nessesary simple).
1336 if !parser.simple_key_allowed {
1337 return yaml_parser_set_scanner_error(parser, "", parser.mark,
1338 "mapping keys are not allowed in this context")
1339 }
1340 // Add the BLOCK-MAPPING-START token if needed.
1341 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
1342 return false
1343 }
1344 }
1345
1346 // Reset any potential simple keys on the current flow level.
1347 if !yaml_parser_remove_simple_key(parser) {
1348 return false
1349 }
1350
1351 // Simple keys are allowed after '?' in the block context.
1352 parser.simple_key_allowed = parser.flow_level == 0
1353
1354 // Consume the token.
1355 start_mark := parser.mark
1356 skip(parser)
1357 end_mark := parser.mark
1358
1359 // Create the KEY token and append it to the queue.
1360 token := yaml_token_t{
1361 typ: yaml_KEY_TOKEN,
1362 start_mark: start_mark,
1363 end_mark: end_mark,
1364 }
1365 yaml_insert_token(parser, -1, &token)
1366 return true
1367}
1368
1369// Produce the VALUE token.
1370func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
1371
1372 simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
1373
1374 // Have we found a simple key?
1375 if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
1376 return false
1377
1378 } else if valid {
1379
1380 // Create the KEY token and insert it into the queue.
1381 token := yaml_token_t{
1382 typ: yaml_KEY_TOKEN,
1383 start_mark: simple_key.mark,
1384 end_mark: simple_key.mark,
1385 }
1386 yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
1387
1388 // In the block context, we may need to add the BLOCK-MAPPING-START token.
1389 if !yaml_parser_roll_indent(parser, simple_key.mark.column,
1390 simple_key.token_number,
1391 yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
1392 return false
1393 }
1394
1395 // Remove the simple key.
1396 simple_key.possible = false
1397 delete(parser.simple_keys_by_tok, simple_key.token_number)
1398
1399 // A simple key cannot follow another simple key.
1400 parser.simple_key_allowed = false
1401
1402 } else {
1403 // The ':' indicator follows a complex key.
1404
1405 // In the block context, extra checks are required.
1406 if parser.flow_level == 0 {
1407
1408 // Check if we are allowed to start a complex value.
1409 if !parser.simple_key_allowed {
1410 return yaml_parser_set_scanner_error(parser, "", parser.mark,
1411 "mapping values are not allowed in this context")
1412 }
1413
1414 // Add the BLOCK-MAPPING-START token if needed.
1415 if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
1416 return false
1417 }
1418 }
1419
1420 // Simple keys after ':' are allowed in the block context.
1421 parser.simple_key_allowed = parser.flow_level == 0
1422 }
1423
1424 // Consume the token.
1425 start_mark := parser.mark
1426 skip(parser)
1427 end_mark := parser.mark
1428
1429 // Create the VALUE token and append it to the queue.
1430 token := yaml_token_t{
1431 typ: yaml_VALUE_TOKEN,
1432 start_mark: start_mark,
1433 end_mark: end_mark,
1434 }
1435 yaml_insert_token(parser, -1, &token)
1436 return true
1437}
1438
1439// Produce the ALIAS or ANCHOR token.
1440func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
1441 // An anchor or an alias could be a simple key.
1442 if !yaml_parser_save_simple_key(parser) {
1443 return false
1444 }
1445
1446 // A simple key cannot follow an anchor or an alias.
1447 parser.simple_key_allowed = false
1448
1449 // Create the ALIAS or ANCHOR token and append it to the queue.
1450 var token yaml_token_t
1451 if !yaml_parser_scan_anchor(parser, &token, typ) {
1452 return false
1453 }
1454 yaml_insert_token(parser, -1, &token)
1455 return true
1456}
1457
1458// Produce the TAG token.
1459func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
1460 // A tag could be a simple key.
1461 if !yaml_parser_save_simple_key(parser) {
1462 return false
1463 }
1464
1465 // A simple key cannot follow a tag.
1466 parser.simple_key_allowed = false
1467
1468 // Create the TAG token and append it to the queue.
1469 var token yaml_token_t
1470 if !yaml_parser_scan_tag(parser, &token) {
1471 return false
1472 }
1473 yaml_insert_token(parser, -1, &token)
1474 return true
1475}
1476
1477// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
1478func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
1479 // Remove any potential simple keys.
1480 if !yaml_parser_remove_simple_key(parser) {
1481 return false
1482 }
1483
1484 // A simple key may follow a block scalar.
1485 parser.simple_key_allowed = true
1486
1487 // Create the SCALAR token and append it to the queue.
1488 var token yaml_token_t
1489 if !yaml_parser_scan_block_scalar(parser, &token, literal) {
1490 return false
1491 }
1492 yaml_insert_token(parser, -1, &token)
1493 return true
1494}
1495
1496// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
1497func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
1498 // A plain scalar could be a simple key.
1499 if !yaml_parser_save_simple_key(parser) {
1500 return false
1501 }
1502
1503 // A simple key cannot follow a flow scalar.
1504 parser.simple_key_allowed = false
1505
1506 // Create the SCALAR token and append it to the queue.
1507 var token yaml_token_t
1508 if !yaml_parser_scan_flow_scalar(parser, &token, single) {
1509 return false
1510 }
1511 yaml_insert_token(parser, -1, &token)
1512 return true
1513}
1514
1515// Produce the SCALAR(...,plain) token.
1516func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
1517 // A plain scalar could be a simple key.
1518 if !yaml_parser_save_simple_key(parser) {
1519 return false
1520 }
1521
1522 // A simple key cannot follow a flow scalar.
1523 parser.simple_key_allowed = false
1524
1525 // Create the SCALAR token and append it to the queue.
1526 var token yaml_token_t
1527 if !yaml_parser_scan_plain_scalar(parser, &token) {
1528 return false
1529 }
1530 yaml_insert_token(parser, -1, &token)
1531 return true
1532}
1533
1534// Eat whitespaces and comments until the next token is found.
1535func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
1536
1537 scan_mark := parser.mark
1538
1539 // Until the next token is not found.
1540 for {
1541 // Allow the BOM mark to start a line.
1542 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1543 return false
1544 }
1545 if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
1546 skip(parser)
1547 }
1548
1549 // Eat whitespaces.
1550 // Tabs are allowed:
1551 // - in the flow context
1552 // - in the block context, but not at the beginning of the line or
1553 // after '-', '?', or ':' (complex value).
1554 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1555 return false
1556 }
1557
1558 for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
1559 skip(parser)
1560 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1561 return false
1562 }
1563 }
1564
1565 // Check if we just had a line comment under a sequence entry that
1566 // looks more like a header to the following content. Similar to this:
1567 //
1568 // - # The comment
1569 // - Some data
1570 //
1571 // If so, transform the line comment to a head comment and reposition.
1572 if len(parser.comments) > 0 && len(parser.tokens) > 1 {
1573 tokenA := parser.tokens[len(parser.tokens)-2]
1574 tokenB := parser.tokens[len(parser.tokens)-1]
1575 comment := &parser.comments[len(parser.comments)-1]
1576 if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
1577 // If it was in the prior line, reposition so it becomes a
1578 // header of the follow up token. Otherwise, keep it in place
1579 // so it becomes a header of the former.
1580 comment.head = comment.line
1581 comment.line = nil
1582 if comment.start_mark.line == parser.mark.line-1 {
1583 comment.token_mark = parser.mark
1584 }
1585 }
1586 }
1587
1588 // Eat a comment until a line break.
1589 if parser.buffer[parser.buffer_pos] == '#' {
1590 if !yaml_parser_scan_comments(parser, scan_mark) {
1591 return false
1592 }
1593 }
1594
1595 // If it is a line break, eat it.
1596 if is_break(parser.buffer, parser.buffer_pos) {
1597 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1598 return false
1599 }
1600 skip_line(parser)
1601
1602 // In the block context, a new line may start a simple key.
1603 if parser.flow_level == 0 {
1604 parser.simple_key_allowed = true
1605 }
1606 } else {
1607 break // We have found a token.
1608 }
1609 }
1610
1611 return true
1612}
1613
1614// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
1615//
1616// Scope:
1617// %YAML 1.1 # a comment \n
1618// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1619// %TAG !yaml! tag:yaml.org,2002: \n
1620// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1621//
1622func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
1623 // Eat '%'.
1624 start_mark := parser.mark
1625 skip(parser)
1626
1627 // Scan the directive name.
1628 var name []byte
1629 if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
1630 return false
1631 }
1632
1633 // Is it a YAML directive?
1634 if bytes.Equal(name, []byte("YAML")) {
1635 // Scan the VERSION directive value.
1636 var major, minor int8
1637 if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
1638 return false
1639 }
1640 end_mark := parser.mark
1641
1642 // Create a VERSION-DIRECTIVE token.
1643 *token = yaml_token_t{
1644 typ: yaml_VERSION_DIRECTIVE_TOKEN,
1645 start_mark: start_mark,
1646 end_mark: end_mark,
1647 major: major,
1648 minor: minor,
1649 }
1650
1651 // Is it a TAG directive?
1652 } else if bytes.Equal(name, []byte("TAG")) {
1653 // Scan the TAG directive value.
1654 var handle, prefix []byte
1655 if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
1656 return false
1657 }
1658 end_mark := parser.mark
1659
1660 // Create a TAG-DIRECTIVE token.
1661 *token = yaml_token_t{
1662 typ: yaml_TAG_DIRECTIVE_TOKEN,
1663 start_mark: start_mark,
1664 end_mark: end_mark,
1665 value: handle,
1666 prefix: prefix,
1667 }
1668
1669 // Unknown directive.
1670 } else {
1671 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1672 start_mark, "found unknown directive name")
1673 return false
1674 }
1675
1676 // Eat the rest of the line including any comments.
1677 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1678 return false
1679 }
1680
1681 for is_blank(parser.buffer, parser.buffer_pos) {
1682 skip(parser)
1683 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1684 return false
1685 }
1686 }
1687
1688 if parser.buffer[parser.buffer_pos] == '#' {
1689 // [Go] Discard this inline comment for the time being.
1690 //if !yaml_parser_scan_line_comment(parser, start_mark) {
1691 // return false
1692 //}
1693 for !is_breakz(parser.buffer, parser.buffer_pos) {
1694 skip(parser)
1695 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1696 return false
1697 }
1698 }
1699 }
1700
1701 // Check if we are at the end of the line.
1702 if !is_breakz(parser.buffer, parser.buffer_pos) {
1703 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1704 start_mark, "did not find expected comment or line break")
1705 return false
1706 }
1707
1708 // Eat a line break.
1709 if is_break(parser.buffer, parser.buffer_pos) {
1710 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1711 return false
1712 }
1713 skip_line(parser)
1714 }
1715
1716 return true
1717}
1718
1719// Scan the directive name.
1720//
1721// Scope:
1722// %YAML 1.1 # a comment \n
1723// ^^^^
1724// %TAG !yaml! tag:yaml.org,2002: \n
1725// ^^^
1726//
1727func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
1728 // Consume the directive name.
1729 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1730 return false
1731 }
1732
1733 var s []byte
1734 for is_alpha(parser.buffer, parser.buffer_pos) {
1735 s = read(parser, s)
1736 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1737 return false
1738 }
1739 }
1740
1741 // Check if the name is empty.
1742 if len(s) == 0 {
1743 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1744 start_mark, "could not find expected directive name")
1745 return false
1746 }
1747
1748 // Check for an blank character after the name.
1749 if !is_blankz(parser.buffer, parser.buffer_pos) {
1750 yaml_parser_set_scanner_error(parser, "while scanning a directive",
1751 start_mark, "found unexpected non-alphabetical character")
1752 return false
1753 }
1754 *name = s
1755 return true
1756}
1757
1758// Scan the value of VERSION-DIRECTIVE.
1759//
1760// Scope:
1761// %YAML 1.1 # a comment \n
1762// ^^^^^^
1763func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
1764 // Eat whitespaces.
1765 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1766 return false
1767 }
1768 for is_blank(parser.buffer, parser.buffer_pos) {
1769 skip(parser)
1770 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1771 return false
1772 }
1773 }
1774
1775 // Consume the major version number.
1776 if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
1777 return false
1778 }
1779
1780 // Eat '.'.
1781 if parser.buffer[parser.buffer_pos] != '.' {
1782 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1783 start_mark, "did not find expected digit or '.' character")
1784 }
1785
1786 skip(parser)
1787
1788 // Consume the minor version number.
1789 if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
1790 return false
1791 }
1792 return true
1793}
1794
1795const max_number_length = 2
1796
1797// Scan the version number of VERSION-DIRECTIVE.
1798//
1799// Scope:
1800// %YAML 1.1 # a comment \n
1801// ^
1802// %YAML 1.1 # a comment \n
1803// ^
1804func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
1805
1806 // Repeat while the next character is digit.
1807 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1808 return false
1809 }
1810 var value, length int8
1811 for is_digit(parser.buffer, parser.buffer_pos) {
1812 // Check if the number is too long.
1813 length++
1814 if length > max_number_length {
1815 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1816 start_mark, "found extremely long version number")
1817 }
1818 value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
1819 skip(parser)
1820 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1821 return false
1822 }
1823 }
1824
1825 // Check if the number was present.
1826 if length == 0 {
1827 return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
1828 start_mark, "did not find expected version number")
1829 }
1830 *number = value
1831 return true
1832}
1833
1834// Scan the value of a TAG-DIRECTIVE token.
1835//
1836// Scope:
1837// %TAG !yaml! tag:yaml.org,2002: \n
1838// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1839//
1840func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
1841 var handle_value, prefix_value []byte
1842
1843 // Eat whitespaces.
1844 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1845 return false
1846 }
1847
1848 for is_blank(parser.buffer, parser.buffer_pos) {
1849 skip(parser)
1850 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1851 return false
1852 }
1853 }
1854
1855 // Scan a handle.
1856 if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
1857 return false
1858 }
1859
1860 // Expect a whitespace.
1861 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1862 return false
1863 }
1864 if !is_blank(parser.buffer, parser.buffer_pos) {
1865 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
1866 start_mark, "did not find expected whitespace")
1867 return false
1868 }
1869
1870 // Eat whitespaces.
1871 for is_blank(parser.buffer, parser.buffer_pos) {
1872 skip(parser)
1873 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1874 return false
1875 }
1876 }
1877
1878 // Scan a prefix.
1879 if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
1880 return false
1881 }
1882
1883 // Expect a whitespace or line break.
1884 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1885 return false
1886 }
1887 if !is_blankz(parser.buffer, parser.buffer_pos) {
1888 yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
1889 start_mark, "did not find expected whitespace or line break")
1890 return false
1891 }
1892
1893 *handle = handle_value
1894 *prefix = prefix_value
1895 return true
1896}
1897
1898func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
1899 var s []byte
1900
1901 // Eat the indicator character.
1902 start_mark := parser.mark
1903 skip(parser)
1904
1905 // Consume the value.
1906 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1907 return false
1908 }
1909
1910 for is_alpha(parser.buffer, parser.buffer_pos) {
1911 s = read(parser, s)
1912 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
1913 return false
1914 }
1915 }
1916
1917 end_mark := parser.mark
1918
1919 /*
1920 * Check if length of the anchor is greater than 0 and it is followed by
1921 * a whitespace character or one of the indicators:
1922 *
1923 * '?', ':', ',', ']', '}', '%', '@', '`'.
1924 */
1925
1926 if len(s) == 0 ||
1927 !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
1928 parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
1929 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
1930 parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
1931 parser.buffer[parser.buffer_pos] == '`') {
1932 context := "while scanning an alias"
1933 if typ == yaml_ANCHOR_TOKEN {
1934 context = "while scanning an anchor"
1935 }
1936 yaml_parser_set_scanner_error(parser, context, start_mark,
1937 "did not find expected alphabetic or numeric character")
1938 return false
1939 }
1940
1941 // Create a token.
1942 *token = yaml_token_t{
1943 typ: typ,
1944 start_mark: start_mark,
1945 end_mark: end_mark,
1946 value: s,
1947 }
1948
1949 return true
1950}
1951
1952/*
1953 * Scan a TAG token.
1954 */
1955
1956func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
1957 var handle, suffix []byte
1958
1959 start_mark := parser.mark
1960
1961 // Check if the tag is in the canonical form.
1962 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
1963 return false
1964 }
1965
1966 if parser.buffer[parser.buffer_pos+1] == '<' {
1967 // Keep the handle as ''
1968
1969 // Eat '!<'
1970 skip(parser)
1971 skip(parser)
1972
1973 // Consume the tag value.
1974 if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
1975 return false
1976 }
1977
1978 // Check for '>' and eat it.
1979 if parser.buffer[parser.buffer_pos] != '>' {
1980 yaml_parser_set_scanner_error(parser, "while scanning a tag",
1981 start_mark, "did not find the expected '>'")
1982 return false
1983 }
1984
1985 skip(parser)
1986 } else {
1987 // The tag has either the '!suffix' or the '!handle!suffix' form.
1988
1989 // First, try to scan a handle.
1990 if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
1991 return false
1992 }
1993
1994 // Check if it is, indeed, handle.
1995 if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
1996 // Scan the suffix now.
1997 if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
1998 return false
1999 }
2000 } else {
2001 // It wasn't a handle after all. Scan the rest of the tag.
2002 if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
2003 return false
2004 }
2005
2006 // Set the handle to '!'.
2007 handle = []byte{'!'}
2008
2009 // A special case: the '!' tag. Set the handle to '' and the
2010 // suffix to '!'.
2011 if len(suffix) == 0 {
2012 handle, suffix = suffix, handle
2013 }
2014 }
2015 }
2016
2017 // Check the character which ends the tag.
2018 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2019 return false
2020 }
2021 if !is_blankz(parser.buffer, parser.buffer_pos) {
2022 yaml_parser_set_scanner_error(parser, "while scanning a tag",
2023 start_mark, "did not find expected whitespace or line break")
2024 return false
2025 }
2026
2027 end_mark := parser.mark
2028
2029 // Create a token.
2030 *token = yaml_token_t{
2031 typ: yaml_TAG_TOKEN,
2032 start_mark: start_mark,
2033 end_mark: end_mark,
2034 value: handle,
2035 suffix: suffix,
2036 }
2037 return true
2038}
2039
2040// Scan a tag handle.
2041func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
2042 // Check the initial '!' character.
2043 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2044 return false
2045 }
2046 if parser.buffer[parser.buffer_pos] != '!' {
2047 yaml_parser_set_scanner_tag_error(parser, directive,
2048 start_mark, "did not find expected '!'")
2049 return false
2050 }
2051
2052 var s []byte
2053
2054 // Copy the '!' character.
2055 s = read(parser, s)
2056
2057 // Copy all subsequent alphabetical and numerical characters.
2058 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2059 return false
2060 }
2061 for is_alpha(parser.buffer, parser.buffer_pos) {
2062 s = read(parser, s)
2063 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2064 return false
2065 }
2066 }
2067
2068 // Check if the trailing character is '!' and copy it.
2069 if parser.buffer[parser.buffer_pos] == '!' {
2070 s = read(parser, s)
2071 } else {
2072 // It's either the '!' tag or not really a tag handle. If it's a %TAG
2073 // directive, it's an error. If it's a tag token, it must be a part of URI.
2074 if directive && string(s) != "!" {
2075 yaml_parser_set_scanner_tag_error(parser, directive,
2076 start_mark, "did not find expected '!'")
2077 return false
2078 }
2079 }
2080
2081 *handle = s
2082 return true
2083}
2084
2085// Scan a tag.
2086func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
2087 //size_t length = head ? strlen((char *)head) : 0
2088 var s []byte
2089 hasTag := len(head) > 0
2090
2091 // Copy the head if needed.
2092 //
2093 // Note that we don't copy the leading '!' character.
2094 if len(head) > 1 {
2095 s = append(s, head[1:]...)
2096 }
2097
2098 // Scan the tag.
2099 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2100 return false
2101 }
2102
2103 // The set of characters that may appear in URI is as follows:
2104 //
2105 // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
2106 // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
2107 // '%'.
2108 // [Go] TODO Convert this into more reasonable logic.
2109 for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
2110 parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
2111 parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
2112 parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
2113 parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
2114 parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
2115 parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
2116 parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
2117 parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
2118 parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
2119 parser.buffer[parser.buffer_pos] == '%' {
2120 // Check if it is a URI-escape sequence.
2121 if parser.buffer[parser.buffer_pos] == '%' {
2122 if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
2123 return false
2124 }
2125 } else {
2126 s = read(parser, s)
2127 }
2128 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2129 return false
2130 }
2131 hasTag = true
2132 }
2133
2134 if !hasTag {
2135 yaml_parser_set_scanner_tag_error(parser, directive,
2136 start_mark, "did not find expected tag URI")
2137 return false
2138 }
2139 *uri = s
2140 return true
2141}
2142
2143// Decode an URI-escape sequence corresponding to a single UTF-8 character.
2144func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
2145
2146 // Decode the required number of characters.
2147 w := 1024
2148 for w > 0 {
2149 // Check for a URI-escaped octet.
2150 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
2151 return false
2152 }
2153
2154 if !(parser.buffer[parser.buffer_pos] == '%' &&
2155 is_hex(parser.buffer, parser.buffer_pos+1) &&
2156 is_hex(parser.buffer, parser.buffer_pos+2)) {
2157 return yaml_parser_set_scanner_tag_error(parser, directive,
2158 start_mark, "did not find URI escaped octet")
2159 }
2160
2161 // Get the octet.
2162 octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
2163
2164 // If it is the leading octet, determine the length of the UTF-8 sequence.
2165 if w == 1024 {
2166 w = width(octet)
2167 if w == 0 {
2168 return yaml_parser_set_scanner_tag_error(parser, directive,
2169 start_mark, "found an incorrect leading UTF-8 octet")
2170 }
2171 } else {
2172 // Check if the trailing octet is correct.
2173 if octet&0xC0 != 0x80 {
2174 return yaml_parser_set_scanner_tag_error(parser, directive,
2175 start_mark, "found an incorrect trailing UTF-8 octet")
2176 }
2177 }
2178
2179 // Copy the octet and move the pointers.
2180 *s = append(*s, octet)
2181 skip(parser)
2182 skip(parser)
2183 skip(parser)
2184 w--
2185 }
2186 return true
2187}
2188
2189// Scan a block scalar.
2190func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
2191 // Eat the indicator '|' or '>'.
2192 start_mark := parser.mark
2193 skip(parser)
2194
2195 // Scan the additional block scalar indicators.
2196 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2197 return false
2198 }
2199
2200 // Check for a chomping indicator.
2201 var chomping, increment int
2202 if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
2203 // Set the chomping method and eat the indicator.
2204 if parser.buffer[parser.buffer_pos] == '+' {
2205 chomping = +1
2206 } else {
2207 chomping = -1
2208 }
2209 skip(parser)
2210
2211 // Check for an indentation indicator.
2212 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2213 return false
2214 }
2215 if is_digit(parser.buffer, parser.buffer_pos) {
2216 // Check that the indentation is greater than 0.
2217 if parser.buffer[parser.buffer_pos] == '0' {
2218 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2219 start_mark, "found an indentation indicator equal to 0")
2220 return false
2221 }
2222
2223 // Get the indentation level and eat the indicator.
2224 increment = as_digit(parser.buffer, parser.buffer_pos)
2225 skip(parser)
2226 }
2227
2228 } else if is_digit(parser.buffer, parser.buffer_pos) {
2229 // Do the same as above, but in the opposite order.
2230
2231 if parser.buffer[parser.buffer_pos] == '0' {
2232 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2233 start_mark, "found an indentation indicator equal to 0")
2234 return false
2235 }
2236 increment = as_digit(parser.buffer, parser.buffer_pos)
2237 skip(parser)
2238
2239 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2240 return false
2241 }
2242 if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
2243 if parser.buffer[parser.buffer_pos] == '+' {
2244 chomping = +1
2245 } else {
2246 chomping = -1
2247 }
2248 skip(parser)
2249 }
2250 }
2251
2252 // Eat whitespaces and comments to the end of the line.
2253 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2254 return false
2255 }
2256 for is_blank(parser.buffer, parser.buffer_pos) {
2257 skip(parser)
2258 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2259 return false
2260 }
2261 }
2262 if parser.buffer[parser.buffer_pos] == '#' {
2263 if !yaml_parser_scan_line_comment(parser, start_mark) {
2264 return false
2265 }
2266 for !is_breakz(parser.buffer, parser.buffer_pos) {
2267 skip(parser)
2268 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2269 return false
2270 }
2271 }
2272 }
2273
2274 // Check if we are at the end of the line.
2275 if !is_breakz(parser.buffer, parser.buffer_pos) {
2276 yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2277 start_mark, "did not find expected comment or line break")
2278 return false
2279 }
2280
2281 // Eat a line break.
2282 if is_break(parser.buffer, parser.buffer_pos) {
2283 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2284 return false
2285 }
2286 skip_line(parser)
2287 }
2288
2289 end_mark := parser.mark
2290
2291 // Set the indentation level if it was specified.
2292 var indent int
2293 if increment > 0 {
2294 if parser.indent >= 0 {
2295 indent = parser.indent + increment
2296 } else {
2297 indent = increment
2298 }
2299 }
2300
2301 // Scan the leading line breaks and determine the indentation level if needed.
2302 var s, leading_break, trailing_breaks []byte
2303 if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
2304 return false
2305 }
2306
2307 // Scan the block scalar content.
2308 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2309 return false
2310 }
2311 var leading_blank, trailing_blank bool
2312 for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
2313 // We are at the beginning of a non-empty line.
2314
2315 // Is it a trailing whitespace?
2316 trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
2317
2318 // Check if we need to fold the leading line break.
2319 if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
2320 // Do we need to join the lines by space?
2321 if len(trailing_breaks) == 0 {
2322 s = append(s, ' ')
2323 }
2324 } else {
2325 s = append(s, leading_break...)
2326 }
2327 leading_break = leading_break[:0]
2328
2329 // Append the remaining line breaks.
2330 s = append(s, trailing_breaks...)
2331 trailing_breaks = trailing_breaks[:0]
2332
2333 // Is it a leading whitespace?
2334 leading_blank = is_blank(parser.buffer, parser.buffer_pos)
2335
2336 // Consume the current line.
2337 for !is_breakz(parser.buffer, parser.buffer_pos) {
2338 s = read(parser, s)
2339 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2340 return false
2341 }
2342 }
2343
2344 // Consume the line break.
2345 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2346 return false
2347 }
2348
2349 leading_break = read_line(parser, leading_break)
2350
2351 // Eat the following indentation spaces and line breaks.
2352 if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
2353 return false
2354 }
2355 }
2356
2357 // Chomp the tail.
2358 if chomping != -1 {
2359 s = append(s, leading_break...)
2360 }
2361 if chomping == 1 {
2362 s = append(s, trailing_breaks...)
2363 }
2364
2365 // Create a token.
2366 *token = yaml_token_t{
2367 typ: yaml_SCALAR_TOKEN,
2368 start_mark: start_mark,
2369 end_mark: end_mark,
2370 value: s,
2371 style: yaml_LITERAL_SCALAR_STYLE,
2372 }
2373 if !literal {
2374 token.style = yaml_FOLDED_SCALAR_STYLE
2375 }
2376 return true
2377}
2378
2379// Scan indentation spaces and line breaks for a block scalar. Determine the
2380// indentation level if needed.
2381func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
2382 *end_mark = parser.mark
2383
2384 // Eat the indentation spaces and line breaks.
2385 max_indent := 0
2386 for {
2387 // Eat the indentation spaces.
2388 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2389 return false
2390 }
2391 for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
2392 skip(parser)
2393 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2394 return false
2395 }
2396 }
2397 if parser.mark.column > max_indent {
2398 max_indent = parser.mark.column
2399 }
2400
2401 // Check for a tab character messing the indentation.
2402 if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
2403 return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2404 start_mark, "found a tab character where an indentation space is expected")
2405 }
2406
2407 // Have we found a non-empty line?
2408 if !is_break(parser.buffer, parser.buffer_pos) {
2409 break
2410 }
2411
2412 // Consume the line break.
2413 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2414 return false
2415 }
2416 // [Go] Should really be returning breaks instead.
2417 *breaks = read_line(parser, *breaks)
2418 *end_mark = parser.mark
2419 }
2420
2421 // Determine the indentation level if needed.
2422 if *indent == 0 {
2423 *indent = max_indent
2424 if *indent < parser.indent+1 {
2425 *indent = parser.indent + 1
2426 }
2427 if *indent < 1 {
2428 *indent = 1
2429 }
2430 }
2431 return true
2432}
2433
2434// Scan a quoted scalar.
2435func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
2436 // Eat the left quote.
2437 start_mark := parser.mark
2438 skip(parser)
2439
2440 // Consume the content of the quoted scalar.
2441 var s, leading_break, trailing_breaks, whitespaces []byte
2442 for {
2443 // Check that there are no document indicators at the beginning of the line.
2444 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
2445 return false
2446 }
2447
2448 if parser.mark.column == 0 &&
2449 ((parser.buffer[parser.buffer_pos+0] == '-' &&
2450 parser.buffer[parser.buffer_pos+1] == '-' &&
2451 parser.buffer[parser.buffer_pos+2] == '-') ||
2452 (parser.buffer[parser.buffer_pos+0] == '.' &&
2453 parser.buffer[parser.buffer_pos+1] == '.' &&
2454 parser.buffer[parser.buffer_pos+2] == '.')) &&
2455 is_blankz(parser.buffer, parser.buffer_pos+3) {
2456 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
2457 start_mark, "found unexpected document indicator")
2458 return false
2459 }
2460
2461 // Check for EOF.
2462 if is_z(parser.buffer, parser.buffer_pos) {
2463 yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
2464 start_mark, "found unexpected end of stream")
2465 return false
2466 }
2467
2468 // Consume non-blank characters.
2469 leading_blanks := false
2470 for !is_blankz(parser.buffer, parser.buffer_pos) {
2471 if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
2472 // Is is an escaped single quote.
2473 s = append(s, '\'')
2474 skip(parser)
2475 skip(parser)
2476
2477 } else if single && parser.buffer[parser.buffer_pos] == '\'' {
2478 // It is a right single quote.
2479 break
2480 } else if !single && parser.buffer[parser.buffer_pos] == '"' {
2481 // It is a right double quote.
2482 break
2483
2484 } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
2485 // It is an escaped line break.
2486 if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
2487 return false
2488 }
2489 skip(parser)
2490 skip_line(parser)
2491 leading_blanks = true
2492 break
2493
2494 } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
2495 // It is an escape sequence.
2496 code_length := 0
2497
2498 // Check the escape character.
2499 switch parser.buffer[parser.buffer_pos+1] {
2500 case '0':
2501 s = append(s, 0)
2502 case 'a':
2503 s = append(s, '\x07')
2504 case 'b':
2505 s = append(s, '\x08')
2506 case 't', '\t':
2507 s = append(s, '\x09')
2508 case 'n':
2509 s = append(s, '\x0A')
2510 case 'v':
2511 s = append(s, '\x0B')
2512 case 'f':
2513 s = append(s, '\x0C')
2514 case 'r':
2515 s = append(s, '\x0D')
2516 case 'e':
2517 s = append(s, '\x1B')
2518 case ' ':
2519 s = append(s, '\x20')
2520 case '"':
2521 s = append(s, '"')
2522 case '\'':
2523 s = append(s, '\'')
2524 case '\\':
2525 s = append(s, '\\')
2526 case 'N': // NEL (#x85)
2527 s = append(s, '\xC2')
2528 s = append(s, '\x85')
2529 case '_': // #xA0
2530 s = append(s, '\xC2')
2531 s = append(s, '\xA0')
2532 case 'L': // LS (#x2028)
2533 s = append(s, '\xE2')
2534 s = append(s, '\x80')
2535 s = append(s, '\xA8')
2536 case 'P': // PS (#x2029)
2537 s = append(s, '\xE2')
2538 s = append(s, '\x80')
2539 s = append(s, '\xA9')
2540 case 'x':
2541 code_length = 2
2542 case 'u':
2543 code_length = 4
2544 case 'U':
2545 code_length = 8
2546 default:
2547 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2548 start_mark, "found unknown escape character")
2549 return false
2550 }
2551
2552 skip(parser)
2553 skip(parser)
2554
2555 // Consume an arbitrary escape code.
2556 if code_length > 0 {
2557 var value int
2558
2559 // Scan the character value.
2560 if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
2561 return false
2562 }
2563 for k := 0; k < code_length; k++ {
2564 if !is_hex(parser.buffer, parser.buffer_pos+k) {
2565 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2566 start_mark, "did not find expected hexdecimal number")
2567 return false
2568 }
2569 value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
2570 }
2571
2572 // Check the value and write the character.
2573 if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
2574 yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
2575 start_mark, "found invalid Unicode character escape code")
2576 return false
2577 }
2578 if value <= 0x7F {
2579 s = append(s, byte(value))
2580 } else if value <= 0x7FF {
2581 s = append(s, byte(0xC0+(value>>6)))
2582 s = append(s, byte(0x80+(value&0x3F)))
2583 } else if value <= 0xFFFF {
2584 s = append(s, byte(0xE0+(value>>12)))
2585 s = append(s, byte(0x80+((value>>6)&0x3F)))
2586 s = append(s, byte(0x80+(value&0x3F)))
2587 } else {
2588 s = append(s, byte(0xF0+(value>>18)))
2589 s = append(s, byte(0x80+((value>>12)&0x3F)))
2590 s = append(s, byte(0x80+((value>>6)&0x3F)))
2591 s = append(s, byte(0x80+(value&0x3F)))
2592 }
2593
2594 // Advance the pointer.
2595 for k := 0; k < code_length; k++ {
2596 skip(parser)
2597 }
2598 }
2599 } else {
2600 // It is a non-escaped non-blank character.
2601 s = read(parser, s)
2602 }
2603 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2604 return false
2605 }
2606 }
2607
2608 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2609 return false
2610 }
2611
2612 // Check if we are at the end of the scalar.
2613 if single {
2614 if parser.buffer[parser.buffer_pos] == '\'' {
2615 break
2616 }
2617 } else {
2618 if parser.buffer[parser.buffer_pos] == '"' {
2619 break
2620 }
2621 }
2622
2623 // Consume blank characters.
2624 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
2625 if is_blank(parser.buffer, parser.buffer_pos) {
2626 // Consume a space or a tab character.
2627 if !leading_blanks {
2628 whitespaces = read(parser, whitespaces)
2629 } else {
2630 skip(parser)
2631 }
2632 } else {
2633 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2634 return false
2635 }
2636
2637 // Check if it is a first line break.
2638 if !leading_blanks {
2639 whitespaces = whitespaces[:0]
2640 leading_break = read_line(parser, leading_break)
2641 leading_blanks = true
2642 } else {
2643 trailing_breaks = read_line(parser, trailing_breaks)
2644 }
2645 }
2646 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2647 return false
2648 }
2649 }
2650
2651 // Join the whitespaces or fold line breaks.
2652 if leading_blanks {
2653 // Do we need to fold line breaks?
2654 if len(leading_break) > 0 && leading_break[0] == '\n' {
2655 if len(trailing_breaks) == 0 {
2656 s = append(s, ' ')
2657 } else {
2658 s = append(s, trailing_breaks...)
2659 }
2660 } else {
2661 s = append(s, leading_break...)
2662 s = append(s, trailing_breaks...)
2663 }
2664 trailing_breaks = trailing_breaks[:0]
2665 leading_break = leading_break[:0]
2666 } else {
2667 s = append(s, whitespaces...)
2668 whitespaces = whitespaces[:0]
2669 }
2670 }
2671
2672 // Eat the right quote.
2673 skip(parser)
2674 end_mark := parser.mark
2675
2676 // Create a token.
2677 *token = yaml_token_t{
2678 typ: yaml_SCALAR_TOKEN,
2679 start_mark: start_mark,
2680 end_mark: end_mark,
2681 value: s,
2682 style: yaml_SINGLE_QUOTED_SCALAR_STYLE,
2683 }
2684 if !single {
2685 token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
2686 }
2687 return true
2688}
2689
2690// Scan a plain scalar.
2691func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
2692
2693 var s, leading_break, trailing_breaks, whitespaces []byte
2694 var leading_blanks bool
2695 var indent = parser.indent + 1
2696
2697 start_mark := parser.mark
2698 end_mark := parser.mark
2699
2700 // Consume the content of the plain scalar.
2701 for {
2702 // Check for a document indicator.
2703 if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
2704 return false
2705 }
2706 if parser.mark.column == 0 &&
2707 ((parser.buffer[parser.buffer_pos+0] == '-' &&
2708 parser.buffer[parser.buffer_pos+1] == '-' &&
2709 parser.buffer[parser.buffer_pos+2] == '-') ||
2710 (parser.buffer[parser.buffer_pos+0] == '.' &&
2711 parser.buffer[parser.buffer_pos+1] == '.' &&
2712 parser.buffer[parser.buffer_pos+2] == '.')) &&
2713 is_blankz(parser.buffer, parser.buffer_pos+3) {
2714 break
2715 }
2716
2717 // Check for a comment.
2718 if parser.buffer[parser.buffer_pos] == '#' {
2719 break
2720 }
2721
2722 // Consume non-blank characters.
2723 for !is_blankz(parser.buffer, parser.buffer_pos) {
2724
2725 // Check for indicators that may end a plain scalar.
2726 if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
2727 (parser.flow_level > 0 &&
2728 (parser.buffer[parser.buffer_pos] == ',' ||
2729 parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
2730 parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
2731 parser.buffer[parser.buffer_pos] == '}')) {
2732 break
2733 }
2734
2735 // Check if we need to join whitespaces and breaks.
2736 if leading_blanks || len(whitespaces) > 0 {
2737 if leading_blanks {
2738 // Do we need to fold line breaks?
2739 if leading_break[0] == '\n' {
2740 if len(trailing_breaks) == 0 {
2741 s = append(s, ' ')
2742 } else {
2743 s = append(s, trailing_breaks...)
2744 }
2745 } else {
2746 s = append(s, leading_break...)
2747 s = append(s, trailing_breaks...)
2748 }
2749 trailing_breaks = trailing_breaks[:0]
2750 leading_break = leading_break[:0]
2751 leading_blanks = false
2752 } else {
2753 s = append(s, whitespaces...)
2754 whitespaces = whitespaces[:0]
2755 }
2756 }
2757
2758 // Copy the character.
2759 s = read(parser, s)
2760
2761 end_mark = parser.mark
2762 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2763 return false
2764 }
2765 }
2766
2767 // Is it the end?
2768 if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
2769 break
2770 }
2771
2772 // Consume blank characters.
2773 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2774 return false
2775 }
2776
2777 for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
2778 if is_blank(parser.buffer, parser.buffer_pos) {
2779
2780 // Check for tab characters that abuse indentation.
2781 if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
2782 yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
2783 start_mark, "found a tab character that violates indentation")
2784 return false
2785 }
2786
2787 // Consume a space or a tab character.
2788 if !leading_blanks {
2789 whitespaces = read(parser, whitespaces)
2790 } else {
2791 skip(parser)
2792 }
2793 } else {
2794 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2795 return false
2796 }
2797
2798 // Check if it is a first line break.
2799 if !leading_blanks {
2800 whitespaces = whitespaces[:0]
2801 leading_break = read_line(parser, leading_break)
2802 leading_blanks = true
2803 } else {
2804 trailing_breaks = read_line(parser, trailing_breaks)
2805 }
2806 }
2807 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2808 return false
2809 }
2810 }
2811
2812 // Check indentation level.
2813 if parser.flow_level == 0 && parser.mark.column < indent {
2814 break
2815 }
2816 }
2817
2818 // Create a token.
2819 *token = yaml_token_t{
2820 typ: yaml_SCALAR_TOKEN,
2821 start_mark: start_mark,
2822 end_mark: end_mark,
2823 value: s,
2824 style: yaml_PLAIN_SCALAR_STYLE,
2825 }
2826
2827 // Note that we change the 'simple_key_allowed' flag.
2828 if leading_blanks {
2829 parser.simple_key_allowed = true
2830 }
2831 return true
2832}
2833
2834func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
2835 if parser.newlines > 0 {
2836 return true
2837 }
2838
2839 var start_mark yaml_mark_t
2840 var text []byte
2841
2842 for peek := 0; peek < 512; peek++ {
2843 if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
2844 break
2845 }
2846 if is_blank(parser.buffer, parser.buffer_pos+peek) {
2847 continue
2848 }
2849 if parser.buffer[parser.buffer_pos+peek] == '#' {
2850 seen := parser.mark.index+peek
2851 for {
2852 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
2853 return false
2854 }
2855 if is_breakz(parser.buffer, parser.buffer_pos) {
2856 if parser.mark.index >= seen {
2857 break
2858 }
2859 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
2860 return false
2861 }
2862 skip_line(parser)
2863 } else if parser.mark.index >= seen {
2864 if len(text) == 0 {
2865 start_mark = parser.mark
2866 }
2867 text = read(parser, text)
2868 } else {
2869 skip(parser)
2870 }
2871 }
2872 }
2873 break
2874 }
2875 if len(text) > 0 {
2876 parser.comments = append(parser.comments, yaml_comment_t{
2877 token_mark: token_mark,
2878 start_mark: start_mark,
2879 line: text,
2880 })
2881 }
2882 return true
2883}
2884
2885func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
2886 token := parser.tokens[len(parser.tokens)-1]
2887
2888 if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
2889 token = parser.tokens[len(parser.tokens)-2]
2890 }
2891
2892 var token_mark = token.start_mark
2893 var start_mark yaml_mark_t
2894 var next_indent = parser.indent
2895 if next_indent < 0 {
2896 next_indent = 0
2897 }
2898
2899 var recent_empty = false
2900 var first_empty = parser.newlines <= 1
2901
2902 var line = parser.mark.line
2903 var column = parser.mark.column
2904
2905 var text []byte
2906
2907 // The foot line is the place where a comment must start to
2908 // still be considered as a foot of the prior content.
2909 // If there's some content in the currently parsed line, then
2910 // the foot is the line below it.
2911 var foot_line = -1
2912 if scan_mark.line > 0 {
2913 foot_line = parser.mark.line-parser.newlines+1
2914 if parser.newlines == 0 && parser.mark.column > 1 {
2915 foot_line++
2916 }
2917 }
2918
2919 var peek = 0
2920 for ; peek < 512; peek++ {
2921 if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
2922 break
2923 }
2924 column++
2925 if is_blank(parser.buffer, parser.buffer_pos+peek) {
2926 continue
2927 }
2928 c := parser.buffer[parser.buffer_pos+peek]
2929 var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
2930 if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
2931 // Got line break or terminator.
2932 if close_flow || !recent_empty {
2933 if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
2934 // This is the first empty line and there were no empty lines before,
2935 // so this initial part of the comment is a foot of the prior token
2936 // instead of being a head for the following one. Split it up.
2937 // Alternatively, this might also be the last comment inside a flow
2938 // scope, so it must be a footer.
2939 if len(text) > 0 {
2940 if start_mark.column-1 < next_indent {
2941 // If dedented it's unrelated to the prior token.
2942 token_mark = start_mark
2943 }
2944 parser.comments = append(parser.comments, yaml_comment_t{
2945 scan_mark: scan_mark,
2946 token_mark: token_mark,
2947 start_mark: start_mark,
2948 end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
2949 foot: text,
2950 })
2951 scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
2952 token_mark = scan_mark
2953 text = nil
2954 }
2955 } else {
2956 if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
2957 text = append(text, '\n')
2958 }
2959 }
2960 }
2961 if !is_break(parser.buffer, parser.buffer_pos+peek) {
2962 break
2963 }
2964 first_empty = false
2965 recent_empty = true
2966 column = 0
2967 line++
2968 continue
2969 }
2970
2971 if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
2972 // The comment at the different indentation is a foot of the
2973 // preceding data rather than a head of the upcoming one.
2974 parser.comments = append(parser.comments, yaml_comment_t{
2975 scan_mark: scan_mark,
2976 token_mark: token_mark,
2977 start_mark: start_mark,
2978 end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
2979 foot: text,
2980 })
2981 scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
2982 token_mark = scan_mark
2983 text = nil
2984 }
2985
2986 if parser.buffer[parser.buffer_pos+peek] != '#' {
2987 break
2988 }
2989
2990 if len(text) == 0 {
2991 start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
2992 } else {
2993 text = append(text, '\n')
2994 }
2995
2996 recent_empty = false
2997
2998 // Consume until after the consumed comment line.
2999 seen := parser.mark.index+peek
3000 for {
3001 if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
3002 return false
3003 }
3004 if is_breakz(parser.buffer, parser.buffer_pos) {
3005 if parser.mark.index >= seen {
3006 break
3007 }
3008 if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
3009 return false
3010 }
3011 skip_line(parser)
3012 } else if parser.mark.index >= seen {
3013 text = read(parser, text)
3014 } else {
3015 skip(parser)
3016 }
3017 }
3018
3019 peek = 0
3020 column = 0
3021 line = parser.mark.line
3022 next_indent = parser.indent
3023 if next_indent < 0 {
3024 next_indent = 0
3025 }
3026 }
3027
3028 if len(text) > 0 {
3029 parser.comments = append(parser.comments, yaml_comment_t{
3030 scan_mark: scan_mark,
3031 token_mark: start_mark,
3032 start_mark: start_mark,
3033 end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column},
3034 head: text,
3035 })
3036 }
3037 return true
3038}
diff --git a/vendor/gopkg.in/yaml.v3/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go
new file mode 100644
index 0000000..9210ece
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/sorter.go
@@ -0,0 +1,134 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package yaml
17
18import (
19 "reflect"
20 "unicode"
21)
22
23type keyList []reflect.Value
24
25func (l keyList) Len() int { return len(l) }
26func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
27func (l keyList) Less(i, j int) bool {
28 a := l[i]
29 b := l[j]
30 ak := a.Kind()
31 bk := b.Kind()
32 for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
33 a = a.Elem()
34 ak = a.Kind()
35 }
36 for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
37 b = b.Elem()
38 bk = b.Kind()
39 }
40 af, aok := keyFloat(a)
41 bf, bok := keyFloat(b)
42 if aok && bok {
43 if af != bf {
44 return af < bf
45 }
46 if ak != bk {
47 return ak < bk
48 }
49 return numLess(a, b)
50 }
51 if ak != reflect.String || bk != reflect.String {
52 return ak < bk
53 }
54 ar, br := []rune(a.String()), []rune(b.String())
55 digits := false
56 for i := 0; i < len(ar) && i < len(br); i++ {
57 if ar[i] == br[i] {
58 digits = unicode.IsDigit(ar[i])
59 continue
60 }
61 al := unicode.IsLetter(ar[i])
62 bl := unicode.IsLetter(br[i])
63 if al && bl {
64 return ar[i] < br[i]
65 }
66 if al || bl {
67 if digits {
68 return al
69 } else {
70 return bl
71 }
72 }
73 var ai, bi int
74 var an, bn int64
75 if ar[i] == '0' || br[i] == '0' {
76 for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
77 if ar[j] != '0' {
78 an = 1
79 bn = 1
80 break
81 }
82 }
83 }
84 for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
85 an = an*10 + int64(ar[ai]-'0')
86 }
87 for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
88 bn = bn*10 + int64(br[bi]-'0')
89 }
90 if an != bn {
91 return an < bn
92 }
93 if ai != bi {
94 return ai < bi
95 }
96 return ar[i] < br[i]
97 }
98 return len(ar) < len(br)
99}
100
101// keyFloat returns a float value for v if it is a number/bool
102// and whether it is a number/bool or not.
103func keyFloat(v reflect.Value) (f float64, ok bool) {
104 switch v.Kind() {
105 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
106 return float64(v.Int()), true
107 case reflect.Float32, reflect.Float64:
108 return v.Float(), true
109 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
110 return float64(v.Uint()), true
111 case reflect.Bool:
112 if v.Bool() {
113 return 1, true
114 }
115 return 0, true
116 }
117 return 0, false
118}
119
120// numLess returns whether a < b.
121// a and b must necessarily have the same kind.
122func numLess(a, b reflect.Value) bool {
123 switch a.Kind() {
124 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
125 return a.Int() < b.Int()
126 case reflect.Float32, reflect.Float64:
127 return a.Float() < b.Float()
128 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
129 return a.Uint() < b.Uint()
130 case reflect.Bool:
131 return !a.Bool() && b.Bool()
132 }
133 panic("not a number")
134}
diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go
new file mode 100644
index 0000000..b8a116b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/writerc.go
@@ -0,0 +1,48 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25// Set the writer error and return false.
26func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
27 emitter.error = yaml_WRITER_ERROR
28 emitter.problem = problem
29 return false
30}
31
32// Flush the output buffer.
33func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
34 if emitter.write_handler == nil {
35 panic("write handler not set")
36 }
37
38 // Check if the buffer is empty.
39 if emitter.buffer_pos == 0 {
40 return true
41 }
42
43 if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
44 return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
45 }
46 emitter.buffer_pos = 0
47 return true
48}
diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go
new file mode 100644
index 0000000..8cec6da
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yaml.go
@@ -0,0 +1,698 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// Package yaml implements YAML support for the Go language.
17//
18// Source code and other details for the project are available at GitHub:
19//
20// https://github.com/go-yaml/yaml
21//
22package yaml
23
24import (
25 "errors"
26 "fmt"
27 "io"
28 "reflect"
29 "strings"
30 "sync"
31 "unicode/utf8"
32)
33
34// The Unmarshaler interface may be implemented by types to customize their
35// behavior when being unmarshaled from a YAML document.
36type Unmarshaler interface {
37 UnmarshalYAML(value *Node) error
38}
39
40type obsoleteUnmarshaler interface {
41 UnmarshalYAML(unmarshal func(interface{}) error) error
42}
43
44// The Marshaler interface may be implemented by types to customize their
45// behavior when being marshaled into a YAML document. The returned value
46// is marshaled in place of the original value implementing Marshaler.
47//
48// If an error is returned by MarshalYAML, the marshaling procedure stops
49// and returns with the provided error.
50type Marshaler interface {
51 MarshalYAML() (interface{}, error)
52}
53
54// Unmarshal decodes the first document found within the in byte slice
55// and assigns decoded values into the out value.
56//
57// Maps and pointers (to a struct, string, int, etc) are accepted as out
58// values. If an internal pointer within a struct is not initialized,
59// the yaml package will initialize it if necessary for unmarshalling
60// the provided data. The out parameter must not be nil.
61//
62// The type of the decoded values should be compatible with the respective
63// values in out. If one or more values cannot be decoded due to a type
64// mismatches, decoding continues partially until the end of the YAML
65// content, and a *yaml.TypeError is returned with details for all
66// missed values.
67//
68// Struct fields are only unmarshalled if they are exported (have an
69// upper case first letter), and are unmarshalled using the field name
70// lowercased as the default key. Custom keys may be defined via the
71// "yaml" name in the field tag: the content preceding the first comma
72// is used as the key, and the following comma-separated options are
73// used to tweak the marshalling process (see Marshal).
74// Conflicting names result in a runtime error.
75//
76// For example:
77//
78// type T struct {
79// F int `yaml:"a,omitempty"`
80// B int
81// }
82// var t T
83// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
84//
85// See the documentation of Marshal for the format of tags and a list of
86// supported tag options.
87//
88func Unmarshal(in []byte, out interface{}) (err error) {
89 return unmarshal(in, out, false)
90}
91
92// A Decoder reads and decodes YAML values from an input stream.
93type Decoder struct {
94 parser *parser
95 knownFields bool
96}
97
98// NewDecoder returns a new decoder that reads from r.
99//
100// The decoder introduces its own buffering and may read
101// data from r beyond the YAML values requested.
102func NewDecoder(r io.Reader) *Decoder {
103 return &Decoder{
104 parser: newParserFromReader(r),
105 }
106}
107
108// KnownFields ensures that the keys in decoded mappings to
109// exist as fields in the struct being decoded into.
110func (dec *Decoder) KnownFields(enable bool) {
111 dec.knownFields = enable
112}
113
114// Decode reads the next YAML-encoded value from its input
115// and stores it in the value pointed to by v.
116//
117// See the documentation for Unmarshal for details about the
118// conversion of YAML into a Go value.
119func (dec *Decoder) Decode(v interface{}) (err error) {
120 d := newDecoder()
121 d.knownFields = dec.knownFields
122 defer handleErr(&err)
123 node := dec.parser.parse()
124 if node == nil {
125 return io.EOF
126 }
127 out := reflect.ValueOf(v)
128 if out.Kind() == reflect.Ptr && !out.IsNil() {
129 out = out.Elem()
130 }
131 d.unmarshal(node, out)
132 if len(d.terrors) > 0 {
133 return &TypeError{d.terrors}
134 }
135 return nil
136}
137
138// Decode decodes the node and stores its data into the value pointed to by v.
139//
140// See the documentation for Unmarshal for details about the
141// conversion of YAML into a Go value.
142func (n *Node) Decode(v interface{}) (err error) {
143 d := newDecoder()
144 defer handleErr(&err)
145 out := reflect.ValueOf(v)
146 if out.Kind() == reflect.Ptr && !out.IsNil() {
147 out = out.Elem()
148 }
149 d.unmarshal(n, out)
150 if len(d.terrors) > 0 {
151 return &TypeError{d.terrors}
152 }
153 return nil
154}
155
156func unmarshal(in []byte, out interface{}, strict bool) (err error) {
157 defer handleErr(&err)
158 d := newDecoder()
159 p := newParser(in)
160 defer p.destroy()
161 node := p.parse()
162 if node != nil {
163 v := reflect.ValueOf(out)
164 if v.Kind() == reflect.Ptr && !v.IsNil() {
165 v = v.Elem()
166 }
167 d.unmarshal(node, v)
168 }
169 if len(d.terrors) > 0 {
170 return &TypeError{d.terrors}
171 }
172 return nil
173}
174
175// Marshal serializes the value provided into a YAML document. The structure
176// of the generated document will reflect the structure of the value itself.
177// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
178//
179// Struct fields are only marshalled if they are exported (have an upper case
180// first letter), and are marshalled using the field name lowercased as the
181// default key. Custom keys may be defined via the "yaml" name in the field
182// tag: the content preceding the first comma is used as the key, and the
183// following comma-separated options are used to tweak the marshalling process.
184// Conflicting names result in a runtime error.
185//
186// The field tag format accepted is:
187//
188// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
189//
190// The following flags are currently supported:
191//
192// omitempty Only include the field if it's not set to the zero
193// value for the type or to empty slices or maps.
194// Zero valued structs will be omitted if all their public
195// fields are zero, unless they implement an IsZero
196// method (see the IsZeroer interface type), in which
197// case the field will be excluded if IsZero returns true.
198//
199// flow Marshal using a flow style (useful for structs,
200// sequences and maps).
201//
202// inline Inline the field, which must be a struct or a map,
203// causing all of its fields or keys to be processed as if
204// they were part of the outer struct. For maps, keys must
205// not conflict with the yaml keys of other struct fields.
206//
207// In addition, if the key is "-", the field is ignored.
208//
209// For example:
210//
211// type T struct {
212// F int `yaml:"a,omitempty"`
213// B int
214// }
215// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
216// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
217//
218func Marshal(in interface{}) (out []byte, err error) {
219 defer handleErr(&err)
220 e := newEncoder()
221 defer e.destroy()
222 e.marshalDoc("", reflect.ValueOf(in))
223 e.finish()
224 out = e.out
225 return
226}
227
228// An Encoder writes YAML values to an output stream.
229type Encoder struct {
230 encoder *encoder
231}
232
233// NewEncoder returns a new encoder that writes to w.
234// The Encoder should be closed after use to flush all data
235// to w.
236func NewEncoder(w io.Writer) *Encoder {
237 return &Encoder{
238 encoder: newEncoderWithWriter(w),
239 }
240}
241
242// Encode writes the YAML encoding of v to the stream.
243// If multiple items are encoded to the stream, the
244// second and subsequent document will be preceded
245// with a "---" document separator, but the first will not.
246//
247// See the documentation for Marshal for details about the conversion of Go
248// values to YAML.
249func (e *Encoder) Encode(v interface{}) (err error) {
250 defer handleErr(&err)
251 e.encoder.marshalDoc("", reflect.ValueOf(v))
252 return nil
253}
254
255// Encode encodes value v and stores its representation in n.
256//
257// See the documentation for Marshal for details about the
258// conversion of Go values into YAML.
259func (n *Node) Encode(v interface{}) (err error) {
260 defer handleErr(&err)
261 e := newEncoder()
262 defer e.destroy()
263 e.marshalDoc("", reflect.ValueOf(v))
264 e.finish()
265 p := newParser(e.out)
266 p.textless = true
267 defer p.destroy()
268 doc := p.parse()
269 *n = *doc.Content[0]
270 return nil
271}
272
273// SetIndent changes the used indentation used when encoding.
274func (e *Encoder) SetIndent(spaces int) {
275 if spaces < 0 {
276 panic("yaml: cannot indent to a negative number of spaces")
277 }
278 e.encoder.indent = spaces
279}
280
281// Close closes the encoder by writing any remaining data.
282// It does not write a stream terminating string "...".
283func (e *Encoder) Close() (err error) {
284 defer handleErr(&err)
285 e.encoder.finish()
286 return nil
287}
288
289func handleErr(err *error) {
290 if v := recover(); v != nil {
291 if e, ok := v.(yamlError); ok {
292 *err = e.err
293 } else {
294 panic(v)
295 }
296 }
297}
298
299type yamlError struct {
300 err error
301}
302
303func fail(err error) {
304 panic(yamlError{err})
305}
306
307func failf(format string, args ...interface{}) {
308 panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
309}
310
311// A TypeError is returned by Unmarshal when one or more fields in
312// the YAML document cannot be properly decoded into the requested
313// types. When this error is returned, the value is still
314// unmarshaled partially.
315type TypeError struct {
316 Errors []string
317}
318
319func (e *TypeError) Error() string {
320 return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
321}
322
323type Kind uint32
324
325const (
326 DocumentNode Kind = 1 << iota
327 SequenceNode
328 MappingNode
329 ScalarNode
330 AliasNode
331)
332
333type Style uint32
334
335const (
336 TaggedStyle Style = 1 << iota
337 DoubleQuotedStyle
338 SingleQuotedStyle
339 LiteralStyle
340 FoldedStyle
341 FlowStyle
342)
343
344// Node represents an element in the YAML document hierarchy. While documents
345// are typically encoded and decoded into higher level types, such as structs
346// and maps, Node is an intermediate representation that allows detailed
347// control over the content being decoded or encoded.
348//
349// It's worth noting that although Node offers access into details such as
350// line numbers, colums, and comments, the content when re-encoded will not
351// have its original textual representation preserved. An effort is made to
352// render the data plesantly, and to preserve comments near the data they
353// describe, though.
354//
355// Values that make use of the Node type interact with the yaml package in the
356// same way any other type would do, by encoding and decoding yaml data
357// directly or indirectly into them.
358//
359// For example:
360//
361// var person struct {
362// Name string
363// Address yaml.Node
364// }
365// err := yaml.Unmarshal(data, &person)
366//
367// Or by itself:
368//
369// var person Node
370// err := yaml.Unmarshal(data, &person)
371//
372type Node struct {
373 // Kind defines whether the node is a document, a mapping, a sequence,
374 // a scalar value, or an alias to another node. The specific data type of
375 // scalar nodes may be obtained via the ShortTag and LongTag methods.
376 Kind Kind
377
378 // Style allows customizing the apperance of the node in the tree.
379 Style Style
380
381 // Tag holds the YAML tag defining the data type for the value.
382 // When decoding, this field will always be set to the resolved tag,
383 // even when it wasn't explicitly provided in the YAML content.
384 // When encoding, if this field is unset the value type will be
385 // implied from the node properties, and if it is set, it will only
386 // be serialized into the representation if TaggedStyle is used or
387 // the implicit tag diverges from the provided one.
388 Tag string
389
390 // Value holds the unescaped and unquoted represenation of the value.
391 Value string
392
393 // Anchor holds the anchor name for this node, which allows aliases to point to it.
394 Anchor string
395
396 // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
397 Alias *Node
398
399 // Content holds contained nodes for documents, mappings, and sequences.
400 Content []*Node
401
402 // HeadComment holds any comments in the lines preceding the node and
403 // not separated by an empty line.
404 HeadComment string
405
406 // LineComment holds any comments at the end of the line where the node is in.
407 LineComment string
408
409 // FootComment holds any comments following the node and before empty lines.
410 FootComment string
411
412 // Line and Column hold the node position in the decoded YAML text.
413 // These fields are not respected when encoding the node.
414 Line int
415 Column int
416}
417
418// IsZero returns whether the node has all of its fields unset.
419func (n *Node) IsZero() bool {
420 return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
421 n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
422}
423
424
425// LongTag returns the long form of the tag that indicates the data type for
426// the node. If the Tag field isn't explicitly defined, one will be computed
427// based on the node properties.
428func (n *Node) LongTag() string {
429 return longTag(n.ShortTag())
430}
431
432// ShortTag returns the short form of the YAML tag that indicates data type for
433// the node. If the Tag field isn't explicitly defined, one will be computed
434// based on the node properties.
435func (n *Node) ShortTag() string {
436 if n.indicatedString() {
437 return strTag
438 }
439 if n.Tag == "" || n.Tag == "!" {
440 switch n.Kind {
441 case MappingNode:
442 return mapTag
443 case SequenceNode:
444 return seqTag
445 case AliasNode:
446 if n.Alias != nil {
447 return n.Alias.ShortTag()
448 }
449 case ScalarNode:
450 tag, _ := resolve("", n.Value)
451 return tag
452 case 0:
453 // Special case to make the zero value convenient.
454 if n.IsZero() {
455 return nullTag
456 }
457 }
458 return ""
459 }
460 return shortTag(n.Tag)
461}
462
463func (n *Node) indicatedString() bool {
464 return n.Kind == ScalarNode &&
465 (shortTag(n.Tag) == strTag ||
466 (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
467}
468
469// SetString is a convenience function that sets the node to a string value
470// and defines its style in a pleasant way depending on its content.
471func (n *Node) SetString(s string) {
472 n.Kind = ScalarNode
473 if utf8.ValidString(s) {
474 n.Value = s
475 n.Tag = strTag
476 } else {
477 n.Value = encodeBase64(s)
478 n.Tag = binaryTag
479 }
480 if strings.Contains(n.Value, "\n") {
481 n.Style = LiteralStyle
482 }
483}
484
485// --------------------------------------------------------------------------
486// Maintain a mapping of keys to structure field indexes
487
488// The code in this section was copied from mgo/bson.
489
490// structInfo holds details for the serialization of fields of
491// a given struct.
492type structInfo struct {
493 FieldsMap map[string]fieldInfo
494 FieldsList []fieldInfo
495
496 // InlineMap is the number of the field in the struct that
497 // contains an ,inline map, or -1 if there's none.
498 InlineMap int
499
500 // InlineUnmarshalers holds indexes to inlined fields that
501 // contain unmarshaler values.
502 InlineUnmarshalers [][]int
503}
504
505type fieldInfo struct {
506 Key string
507 Num int
508 OmitEmpty bool
509 Flow bool
510 // Id holds the unique field identifier, so we can cheaply
511 // check for field duplicates without maintaining an extra map.
512 Id int
513
514 // Inline holds the field index if the field is part of an inlined struct.
515 Inline []int
516}
517
518var structMap = make(map[reflect.Type]*structInfo)
519var fieldMapMutex sync.RWMutex
520var unmarshalerType reflect.Type
521
522func init() {
523 var v Unmarshaler
524 unmarshalerType = reflect.ValueOf(&v).Elem().Type()
525}
526
527func getStructInfo(st reflect.Type) (*structInfo, error) {
528 fieldMapMutex.RLock()
529 sinfo, found := structMap[st]
530 fieldMapMutex.RUnlock()
531 if found {
532 return sinfo, nil
533 }
534
535 n := st.NumField()
536 fieldsMap := make(map[string]fieldInfo)
537 fieldsList := make([]fieldInfo, 0, n)
538 inlineMap := -1
539 inlineUnmarshalers := [][]int(nil)
540 for i := 0; i != n; i++ {
541 field := st.Field(i)
542 if field.PkgPath != "" && !field.Anonymous {
543 continue // Private field
544 }
545
546 info := fieldInfo{Num: i}
547
548 tag := field.Tag.Get("yaml")
549 if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
550 tag = string(field.Tag)
551 }
552 if tag == "-" {
553 continue
554 }
555
556 inline := false
557 fields := strings.Split(tag, ",")
558 if len(fields) > 1 {
559 for _, flag := range fields[1:] {
560 switch flag {
561 case "omitempty":
562 info.OmitEmpty = true
563 case "flow":
564 info.Flow = true
565 case "inline":
566 inline = true
567 default:
568 return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
569 }
570 }
571 tag = fields[0]
572 }
573
574 if inline {
575 switch field.Type.Kind() {
576 case reflect.Map:
577 if inlineMap >= 0 {
578 return nil, errors.New("multiple ,inline maps in struct " + st.String())
579 }
580 if field.Type.Key() != reflect.TypeOf("") {
581 return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
582 }
583 inlineMap = info.Num
584 case reflect.Struct, reflect.Ptr:
585 ftype := field.Type
586 for ftype.Kind() == reflect.Ptr {
587 ftype = ftype.Elem()
588 }
589 if ftype.Kind() != reflect.Struct {
590 return nil, errors.New("option ,inline may only be used on a struct or map field")
591 }
592 if reflect.PtrTo(ftype).Implements(unmarshalerType) {
593 inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
594 } else {
595 sinfo, err := getStructInfo(ftype)
596 if err != nil {
597 return nil, err
598 }
599 for _, index := range sinfo.InlineUnmarshalers {
600 inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
601 }
602 for _, finfo := range sinfo.FieldsList {
603 if _, found := fieldsMap[finfo.Key]; found {
604 msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
605 return nil, errors.New(msg)
606 }
607 if finfo.Inline == nil {
608 finfo.Inline = []int{i, finfo.Num}
609 } else {
610 finfo.Inline = append([]int{i}, finfo.Inline...)
611 }
612 finfo.Id = len(fieldsList)
613 fieldsMap[finfo.Key] = finfo
614 fieldsList = append(fieldsList, finfo)
615 }
616 }
617 default:
618 return nil, errors.New("option ,inline may only be used on a struct or map field")
619 }
620 continue
621 }
622
623 if tag != "" {
624 info.Key = tag
625 } else {
626 info.Key = strings.ToLower(field.Name)
627 }
628
629 if _, found = fieldsMap[info.Key]; found {
630 msg := "duplicated key '" + info.Key + "' in struct " + st.String()
631 return nil, errors.New(msg)
632 }
633
634 info.Id = len(fieldsList)
635 fieldsList = append(fieldsList, info)
636 fieldsMap[info.Key] = info
637 }
638
639 sinfo = &structInfo{
640 FieldsMap: fieldsMap,
641 FieldsList: fieldsList,
642 InlineMap: inlineMap,
643 InlineUnmarshalers: inlineUnmarshalers,
644 }
645
646 fieldMapMutex.Lock()
647 structMap[st] = sinfo
648 fieldMapMutex.Unlock()
649 return sinfo, nil
650}
651
652// IsZeroer is used to check whether an object is zero to
653// determine whether it should be omitted when marshaling
654// with the omitempty flag. One notable implementation
655// is time.Time.
656type IsZeroer interface {
657 IsZero() bool
658}
659
660func isZero(v reflect.Value) bool {
661 kind := v.Kind()
662 if z, ok := v.Interface().(IsZeroer); ok {
663 if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
664 return true
665 }
666 return z.IsZero()
667 }
668 switch kind {
669 case reflect.String:
670 return len(v.String()) == 0
671 case reflect.Interface, reflect.Ptr:
672 return v.IsNil()
673 case reflect.Slice:
674 return v.Len() == 0
675 case reflect.Map:
676 return v.Len() == 0
677 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
678 return v.Int() == 0
679 case reflect.Float32, reflect.Float64:
680 return v.Float() == 0
681 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
682 return v.Uint() == 0
683 case reflect.Bool:
684 return !v.Bool()
685 case reflect.Struct:
686 vt := v.Type()
687 for i := v.NumField() - 1; i >= 0; i-- {
688 if vt.Field(i).PkgPath != "" {
689 continue // Private field
690 }
691 if !isZero(v.Field(i)) {
692 return false
693 }
694 }
695 return true
696 }
697 return false
698}
diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go
new file mode 100644
index 0000000..7c6d007
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlh.go
@@ -0,0 +1,807 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25import (
26 "fmt"
27 "io"
28)
29
30// The version directive data.
31type yaml_version_directive_t struct {
32 major int8 // The major version number.
33 minor int8 // The minor version number.
34}
35
36// The tag directive data.
37type yaml_tag_directive_t struct {
38 handle []byte // The tag handle.
39 prefix []byte // The tag prefix.
40}
41
42type yaml_encoding_t int
43
44// The stream encoding.
45const (
46 // Let the parser choose the encoding.
47 yaml_ANY_ENCODING yaml_encoding_t = iota
48
49 yaml_UTF8_ENCODING // The default UTF-8 encoding.
50 yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
51 yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
52)
53
54type yaml_break_t int
55
56// Line break types.
57const (
58 // Let the parser choose the break type.
59 yaml_ANY_BREAK yaml_break_t = iota
60
61 yaml_CR_BREAK // Use CR for line breaks (Mac style).
62 yaml_LN_BREAK // Use LN for line breaks (Unix style).
63 yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
64)
65
66type yaml_error_type_t int
67
68// Many bad things could happen with the parser and emitter.
69const (
70 // No error is produced.
71 yaml_NO_ERROR yaml_error_type_t = iota
72
73 yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
74 yaml_READER_ERROR // Cannot read or decode the input stream.
75 yaml_SCANNER_ERROR // Cannot scan the input stream.
76 yaml_PARSER_ERROR // Cannot parse the input stream.
77 yaml_COMPOSER_ERROR // Cannot compose a YAML document.
78 yaml_WRITER_ERROR // Cannot write to the output stream.
79 yaml_EMITTER_ERROR // Cannot emit a YAML stream.
80)
81
82// The pointer position.
83type yaml_mark_t struct {
84 index int // The position index.
85 line int // The position line.
86 column int // The position column.
87}
88
89// Node Styles
90
91type yaml_style_t int8
92
93type yaml_scalar_style_t yaml_style_t
94
95// Scalar styles.
96const (
97 // Let the emitter choose the style.
98 yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
99
100 yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
101 yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
102 yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
103 yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
104 yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
105)
106
107type yaml_sequence_style_t yaml_style_t
108
109// Sequence styles.
110const (
111 // Let the emitter choose the style.
112 yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
113
114 yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
115 yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
116)
117
118type yaml_mapping_style_t yaml_style_t
119
120// Mapping styles.
121const (
122 // Let the emitter choose the style.
123 yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
124
125 yaml_BLOCK_MAPPING_STYLE // The block mapping style.
126 yaml_FLOW_MAPPING_STYLE // The flow mapping style.
127)
128
129// Tokens
130
131type yaml_token_type_t int
132
133// Token types.
134const (
135 // An empty token.
136 yaml_NO_TOKEN yaml_token_type_t = iota
137
138 yaml_STREAM_START_TOKEN // A STREAM-START token.
139 yaml_STREAM_END_TOKEN // A STREAM-END token.
140
141 yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
142 yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
143 yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
144 yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
145
146 yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
147 yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
148 yaml_BLOCK_END_TOKEN // A BLOCK-END token.
149
150 yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
151 yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
152 yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
153 yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
154
155 yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
156 yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
157 yaml_KEY_TOKEN // A KEY token.
158 yaml_VALUE_TOKEN // A VALUE token.
159
160 yaml_ALIAS_TOKEN // An ALIAS token.
161 yaml_ANCHOR_TOKEN // An ANCHOR token.
162 yaml_TAG_TOKEN // A TAG token.
163 yaml_SCALAR_TOKEN // A SCALAR token.
164)
165
166func (tt yaml_token_type_t) String() string {
167 switch tt {
168 case yaml_NO_TOKEN:
169 return "yaml_NO_TOKEN"
170 case yaml_STREAM_START_TOKEN:
171 return "yaml_STREAM_START_TOKEN"
172 case yaml_STREAM_END_TOKEN:
173 return "yaml_STREAM_END_TOKEN"
174 case yaml_VERSION_DIRECTIVE_TOKEN:
175 return "yaml_VERSION_DIRECTIVE_TOKEN"
176 case yaml_TAG_DIRECTIVE_TOKEN:
177 return "yaml_TAG_DIRECTIVE_TOKEN"
178 case yaml_DOCUMENT_START_TOKEN:
179 return "yaml_DOCUMENT_START_TOKEN"
180 case yaml_DOCUMENT_END_TOKEN:
181 return "yaml_DOCUMENT_END_TOKEN"
182 case yaml_BLOCK_SEQUENCE_START_TOKEN:
183 return "yaml_BLOCK_SEQUENCE_START_TOKEN"
184 case yaml_BLOCK_MAPPING_START_TOKEN:
185 return "yaml_BLOCK_MAPPING_START_TOKEN"
186 case yaml_BLOCK_END_TOKEN:
187 return "yaml_BLOCK_END_TOKEN"
188 case yaml_FLOW_SEQUENCE_START_TOKEN:
189 return "yaml_FLOW_SEQUENCE_START_TOKEN"
190 case yaml_FLOW_SEQUENCE_END_TOKEN:
191 return "yaml_FLOW_SEQUENCE_END_TOKEN"
192 case yaml_FLOW_MAPPING_START_TOKEN:
193 return "yaml_FLOW_MAPPING_START_TOKEN"
194 case yaml_FLOW_MAPPING_END_TOKEN:
195 return "yaml_FLOW_MAPPING_END_TOKEN"
196 case yaml_BLOCK_ENTRY_TOKEN:
197 return "yaml_BLOCK_ENTRY_TOKEN"
198 case yaml_FLOW_ENTRY_TOKEN:
199 return "yaml_FLOW_ENTRY_TOKEN"
200 case yaml_KEY_TOKEN:
201 return "yaml_KEY_TOKEN"
202 case yaml_VALUE_TOKEN:
203 return "yaml_VALUE_TOKEN"
204 case yaml_ALIAS_TOKEN:
205 return "yaml_ALIAS_TOKEN"
206 case yaml_ANCHOR_TOKEN:
207 return "yaml_ANCHOR_TOKEN"
208 case yaml_TAG_TOKEN:
209 return "yaml_TAG_TOKEN"
210 case yaml_SCALAR_TOKEN:
211 return "yaml_SCALAR_TOKEN"
212 }
213 return "<unknown token>"
214}
215
216// The token structure.
217type yaml_token_t struct {
218 // The token type.
219 typ yaml_token_type_t
220
221 // The start/end of the token.
222 start_mark, end_mark yaml_mark_t
223
224 // The stream encoding (for yaml_STREAM_START_TOKEN).
225 encoding yaml_encoding_t
226
227 // The alias/anchor/scalar value or tag/tag directive handle
228 // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
229 value []byte
230
231 // The tag suffix (for yaml_TAG_TOKEN).
232 suffix []byte
233
234 // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
235 prefix []byte
236
237 // The scalar style (for yaml_SCALAR_TOKEN).
238 style yaml_scalar_style_t
239
240 // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
241 major, minor int8
242}
243
244// Events
245
246type yaml_event_type_t int8
247
248// Event types.
249const (
250 // An empty event.
251 yaml_NO_EVENT yaml_event_type_t = iota
252
253 yaml_STREAM_START_EVENT // A STREAM-START event.
254 yaml_STREAM_END_EVENT // A STREAM-END event.
255 yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
256 yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
257 yaml_ALIAS_EVENT // An ALIAS event.
258 yaml_SCALAR_EVENT // A SCALAR event.
259 yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
260 yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
261 yaml_MAPPING_START_EVENT // A MAPPING-START event.
262 yaml_MAPPING_END_EVENT // A MAPPING-END event.
263 yaml_TAIL_COMMENT_EVENT
264)
265
266var eventStrings = []string{
267 yaml_NO_EVENT: "none",
268 yaml_STREAM_START_EVENT: "stream start",
269 yaml_STREAM_END_EVENT: "stream end",
270 yaml_DOCUMENT_START_EVENT: "document start",
271 yaml_DOCUMENT_END_EVENT: "document end",
272 yaml_ALIAS_EVENT: "alias",
273 yaml_SCALAR_EVENT: "scalar",
274 yaml_SEQUENCE_START_EVENT: "sequence start",
275 yaml_SEQUENCE_END_EVENT: "sequence end",
276 yaml_MAPPING_START_EVENT: "mapping start",
277 yaml_MAPPING_END_EVENT: "mapping end",
278 yaml_TAIL_COMMENT_EVENT: "tail comment",
279}
280
281func (e yaml_event_type_t) String() string {
282 if e < 0 || int(e) >= len(eventStrings) {
283 return fmt.Sprintf("unknown event %d", e)
284 }
285 return eventStrings[e]
286}
287
288// The event structure.
289type yaml_event_t struct {
290
291 // The event type.
292 typ yaml_event_type_t
293
294 // The start and end of the event.
295 start_mark, end_mark yaml_mark_t
296
297 // The document encoding (for yaml_STREAM_START_EVENT).
298 encoding yaml_encoding_t
299
300 // The version directive (for yaml_DOCUMENT_START_EVENT).
301 version_directive *yaml_version_directive_t
302
303 // The list of tag directives (for yaml_DOCUMENT_START_EVENT).
304 tag_directives []yaml_tag_directive_t
305
306 // The comments
307 head_comment []byte
308 line_comment []byte
309 foot_comment []byte
310 tail_comment []byte
311
312 // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
313 anchor []byte
314
315 // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
316 tag []byte
317
318 // The scalar value (for yaml_SCALAR_EVENT).
319 value []byte
320
321 // Is the document start/end indicator implicit, or the tag optional?
322 // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
323 implicit bool
324
325 // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
326 quoted_implicit bool
327
328 // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
329 style yaml_style_t
330}
331
332func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
333func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
334func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
335
336// Nodes
337
338const (
339 yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
340 yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
341 yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
342 yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
343 yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
344 yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
345
346 yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
347 yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
348
349 // Not in original libyaml.
350 yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
351 yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
352
353 yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
354 yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
355 yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
356)
357
358type yaml_node_type_t int
359
360// Node types.
361const (
362 // An empty node.
363 yaml_NO_NODE yaml_node_type_t = iota
364
365 yaml_SCALAR_NODE // A scalar node.
366 yaml_SEQUENCE_NODE // A sequence node.
367 yaml_MAPPING_NODE // A mapping node.
368)
369
370// An element of a sequence node.
371type yaml_node_item_t int
372
373// An element of a mapping node.
374type yaml_node_pair_t struct {
375 key int // The key of the element.
376 value int // The value of the element.
377}
378
379// The node structure.
380type yaml_node_t struct {
381 typ yaml_node_type_t // The node type.
382 tag []byte // The node tag.
383
384 // The node data.
385
386 // The scalar parameters (for yaml_SCALAR_NODE).
387 scalar struct {
388 value []byte // The scalar value.
389 length int // The length of the scalar value.
390 style yaml_scalar_style_t // The scalar style.
391 }
392
393 // The sequence parameters (for YAML_SEQUENCE_NODE).
394 sequence struct {
395 items_data []yaml_node_item_t // The stack of sequence items.
396 style yaml_sequence_style_t // The sequence style.
397 }
398
399 // The mapping parameters (for yaml_MAPPING_NODE).
400 mapping struct {
401 pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
402 pairs_start *yaml_node_pair_t // The beginning of the stack.
403 pairs_end *yaml_node_pair_t // The end of the stack.
404 pairs_top *yaml_node_pair_t // The top of the stack.
405 style yaml_mapping_style_t // The mapping style.
406 }
407
408 start_mark yaml_mark_t // The beginning of the node.
409 end_mark yaml_mark_t // The end of the node.
410
411}
412
413// The document structure.
414type yaml_document_t struct {
415
416 // The document nodes.
417 nodes []yaml_node_t
418
419 // The version directive.
420 version_directive *yaml_version_directive_t
421
422 // The list of tag directives.
423 tag_directives_data []yaml_tag_directive_t
424 tag_directives_start int // The beginning of the tag directives list.
425 tag_directives_end int // The end of the tag directives list.
426
427 start_implicit int // Is the document start indicator implicit?
428 end_implicit int // Is the document end indicator implicit?
429
430 // The start/end of the document.
431 start_mark, end_mark yaml_mark_t
432}
433
434// The prototype of a read handler.
435//
436// The read handler is called when the parser needs to read more bytes from the
437// source. The handler should write not more than size bytes to the buffer.
438// The number of written bytes should be set to the size_read variable.
439//
440// [in,out] data A pointer to an application data specified by
441// yaml_parser_set_input().
442// [out] buffer The buffer to write the data from the source.
443// [in] size The size of the buffer.
444// [out] size_read The actual number of bytes read from the source.
445//
446// On success, the handler should return 1. If the handler failed,
447// the returned value should be 0. On EOF, the handler should set the
448// size_read to 0 and return 1.
449type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
450
451// This structure holds information about a potential simple key.
452type yaml_simple_key_t struct {
453 possible bool // Is a simple key possible?
454 required bool // Is a simple key required?
455 token_number int // The number of the token.
456 mark yaml_mark_t // The position mark.
457}
458
459// The states of the parser.
460type yaml_parser_state_t int
461
462const (
463 yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
464
465 yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
466 yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
467 yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
468 yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
469 yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
470 yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
471 yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
472 yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
473 yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
474 yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
475 yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
476 yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
477 yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
478 yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
479 yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
480 yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
481 yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
482 yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
483 yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
484 yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
485 yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
486 yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
487 yaml_PARSE_END_STATE // Expect nothing.
488)
489
490func (ps yaml_parser_state_t) String() string {
491 switch ps {
492 case yaml_PARSE_STREAM_START_STATE:
493 return "yaml_PARSE_STREAM_START_STATE"
494 case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
495 return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
496 case yaml_PARSE_DOCUMENT_START_STATE:
497 return "yaml_PARSE_DOCUMENT_START_STATE"
498 case yaml_PARSE_DOCUMENT_CONTENT_STATE:
499 return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
500 case yaml_PARSE_DOCUMENT_END_STATE:
501 return "yaml_PARSE_DOCUMENT_END_STATE"
502 case yaml_PARSE_BLOCK_NODE_STATE:
503 return "yaml_PARSE_BLOCK_NODE_STATE"
504 case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
505 return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
506 case yaml_PARSE_FLOW_NODE_STATE:
507 return "yaml_PARSE_FLOW_NODE_STATE"
508 case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
509 return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
510 case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
511 return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
512 case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
513 return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
514 case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
515 return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
516 case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
517 return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
518 case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
519 return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
520 case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
521 return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
522 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
523 return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
524 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
525 return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
526 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
527 return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
528 case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
529 return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
530 case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
531 return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
532 case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
533 return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
534 case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
535 return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
536 case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
537 return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
538 case yaml_PARSE_END_STATE:
539 return "yaml_PARSE_END_STATE"
540 }
541 return "<unknown parser state>"
542}
543
544// This structure holds aliases data.
545type yaml_alias_data_t struct {
546 anchor []byte // The anchor.
547 index int // The node id.
548 mark yaml_mark_t // The anchor mark.
549}
550
551// The parser structure.
552//
553// All members are internal. Manage the structure using the
554// yaml_parser_ family of functions.
555type yaml_parser_t struct {
556
557 // Error handling
558
559 error yaml_error_type_t // Error type.
560
561 problem string // Error description.
562
563 // The byte about which the problem occurred.
564 problem_offset int
565 problem_value int
566 problem_mark yaml_mark_t
567
568 // The error context.
569 context string
570 context_mark yaml_mark_t
571
572 // Reader stuff
573
574 read_handler yaml_read_handler_t // Read handler.
575
576 input_reader io.Reader // File input data.
577 input []byte // String input data.
578 input_pos int
579
580 eof bool // EOF flag
581
582 buffer []byte // The working buffer.
583 buffer_pos int // The current position of the buffer.
584
585 unread int // The number of unread characters in the buffer.
586
587 newlines int // The number of line breaks since last non-break/non-blank character
588
589 raw_buffer []byte // The raw buffer.
590 raw_buffer_pos int // The current position of the buffer.
591
592 encoding yaml_encoding_t // The input encoding.
593
594 offset int // The offset of the current position (in bytes).
595 mark yaml_mark_t // The mark of the current position.
596
597 // Comments
598
599 head_comment []byte // The current head comments
600 line_comment []byte // The current line comments
601 foot_comment []byte // The current foot comments
602 tail_comment []byte // Foot comment that happens at the end of a block.
603 stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
604
605 comments []yaml_comment_t // The folded comments for all parsed tokens
606 comments_head int
607
608 // Scanner stuff
609
610 stream_start_produced bool // Have we started to scan the input stream?
611 stream_end_produced bool // Have we reached the end of the input stream?
612
613 flow_level int // The number of unclosed '[' and '{' indicators.
614
615 tokens []yaml_token_t // The tokens queue.
616 tokens_head int // The head of the tokens queue.
617 tokens_parsed int // The number of tokens fetched from the queue.
618 token_available bool // Does the tokens queue contain a token ready for dequeueing.
619
620 indent int // The current indentation level.
621 indents []int // The indentation levels stack.
622
623 simple_key_allowed bool // May a simple key occur at the current position?
624 simple_keys []yaml_simple_key_t // The stack of simple keys.
625 simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
626
627 // Parser stuff
628
629 state yaml_parser_state_t // The current parser state.
630 states []yaml_parser_state_t // The parser states stack.
631 marks []yaml_mark_t // The stack of marks.
632 tag_directives []yaml_tag_directive_t // The list of TAG directives.
633
634 // Dumper stuff
635
636 aliases []yaml_alias_data_t // The alias data.
637
638 document *yaml_document_t // The currently parsed document.
639}
640
641type yaml_comment_t struct {
642
643 scan_mark yaml_mark_t // Position where scanning for comments started
644 token_mark yaml_mark_t // Position after which tokens will be associated with this comment
645 start_mark yaml_mark_t // Position of '#' comment mark
646 end_mark yaml_mark_t // Position where comment terminated
647
648 head []byte
649 line []byte
650 foot []byte
651}
652
653// Emitter Definitions
654
655// The prototype of a write handler.
656//
657// The write handler is called when the emitter needs to flush the accumulated
658// characters to the output. The handler should write @a size bytes of the
659// @a buffer to the output.
660//
661// @param[in,out] data A pointer to an application data specified by
662// yaml_emitter_set_output().
663// @param[in] buffer The buffer with bytes to be written.
664// @param[in] size The size of the buffer.
665//
666// @returns On success, the handler should return @c 1. If the handler failed,
667// the returned value should be @c 0.
668//
669type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
670
671type yaml_emitter_state_t int
672
673// The emitter states.
674const (
675 // Expect STREAM-START.
676 yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
677
678 yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
679 yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
680 yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
681 yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
682 yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
683 yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
684 yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
685 yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
686 yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
687 yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
688 yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
689 yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
690 yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
691 yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
692 yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
693 yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
694 yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
695 yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
696 yaml_EMIT_END_STATE // Expect nothing.
697)
698
699// The emitter structure.
700//
701// All members are internal. Manage the structure using the @c yaml_emitter_
702// family of functions.
703type yaml_emitter_t struct {
704
705 // Error handling
706
707 error yaml_error_type_t // Error type.
708 problem string // Error description.
709
710 // Writer stuff
711
712 write_handler yaml_write_handler_t // Write handler.
713
714 output_buffer *[]byte // String output data.
715 output_writer io.Writer // File output data.
716
717 buffer []byte // The working buffer.
718 buffer_pos int // The current position of the buffer.
719
720 raw_buffer []byte // The raw buffer.
721 raw_buffer_pos int // The current position of the buffer.
722
723 encoding yaml_encoding_t // The stream encoding.
724
725 // Emitter stuff
726
727 canonical bool // If the output is in the canonical style?
728 best_indent int // The number of indentation spaces.
729 best_width int // The preferred width of the output lines.
730 unicode bool // Allow unescaped non-ASCII characters?
731 line_break yaml_break_t // The preferred line break.
732
733 state yaml_emitter_state_t // The current emitter state.
734 states []yaml_emitter_state_t // The stack of states.
735
736 events []yaml_event_t // The event queue.
737 events_head int // The head of the event queue.
738
739 indents []int // The stack of indentation levels.
740
741 tag_directives []yaml_tag_directive_t // The list of tag directives.
742
743 indent int // The current indentation level.
744
745 flow_level int // The current flow level.
746
747 root_context bool // Is it the document root context?
748 sequence_context bool // Is it a sequence context?
749 mapping_context bool // Is it a mapping context?
750 simple_key_context bool // Is it a simple mapping key context?
751
752 line int // The current line.
753 column int // The current column.
754 whitespace bool // If the last character was a whitespace?
755 indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
756 open_ended bool // If an explicit document end is required?
757
758 space_above bool // Is there's an empty line above?
759 foot_indent int // The indent used to write the foot comment above, or -1 if none.
760
761 // Anchor analysis.
762 anchor_data struct {
763 anchor []byte // The anchor value.
764 alias bool // Is it an alias?
765 }
766
767 // Tag analysis.
768 tag_data struct {
769 handle []byte // The tag handle.
770 suffix []byte // The tag suffix.
771 }
772
773 // Scalar analysis.
774 scalar_data struct {
775 value []byte // The scalar value.
776 multiline bool // Does the scalar contain line breaks?
777 flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
778 block_plain_allowed bool // Can the scalar be expressed in the block plain style?
779 single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
780 block_allowed bool // Can the scalar be expressed in the literal or folded styles?
781 style yaml_scalar_style_t // The output style.
782 }
783
784 // Comments
785 head_comment []byte
786 line_comment []byte
787 foot_comment []byte
788 tail_comment []byte
789
790 key_line_comment []byte
791
792 // Dumper stuff
793
794 opened bool // If the stream was already opened?
795 closed bool // If the stream was already closed?
796
797 // The information associated with the document nodes.
798 anchors *struct {
799 references int // The number of references.
800 anchor int // The anchor id.
801 serialized bool // If the node has been emitted?
802 }
803
804 last_anchor_id int // The last assigned anchor id.
805
806 document *yaml_document_t // The currently emitted document.
807}
diff --git a/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
new file mode 100644
index 0000000..e88f9c5
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
@@ -0,0 +1,198 @@
1//
2// Copyright (c) 2011-2019 Canonical Ltd
3// Copyright (c) 2006-2010 Kirill Simonov
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy of
6// this software and associated documentation files (the "Software"), to deal in
7// the Software without restriction, including without limitation the rights to
8// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9// of the Software, and to permit persons to whom the Software is furnished to do
10// so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23package yaml
24
25const (
26 // The size of the input raw buffer.
27 input_raw_buffer_size = 512
28
29 // The size of the input buffer.
30 // It should be possible to decode the whole raw buffer.
31 input_buffer_size = input_raw_buffer_size * 3
32
33 // The size of the output buffer.
34 output_buffer_size = 128
35
36 // The size of the output raw buffer.
37 // It should be possible to encode the whole output buffer.
38 output_raw_buffer_size = (output_buffer_size*2 + 2)
39
40 // The size of other stacks and queues.
41 initial_stack_size = 16
42 initial_queue_size = 16
43 initial_string_size = 16
44)
45
46// Check if the character at the specified position is an alphabetical
47// character, a digit, '_', or '-'.
48func is_alpha(b []byte, i int) bool {
49 return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
50}
51
52// Check if the character at the specified position is a digit.
53func is_digit(b []byte, i int) bool {
54 return b[i] >= '0' && b[i] <= '9'
55}
56
57// Get the value of a digit.
58func as_digit(b []byte, i int) int {
59 return int(b[i]) - '0'
60}
61
62// Check if the character at the specified position is a hex-digit.
63func is_hex(b []byte, i int) bool {
64 return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
65}
66
67// Get the value of a hex-digit.
68func as_hex(b []byte, i int) int {
69 bi := b[i]
70 if bi >= 'A' && bi <= 'F' {
71 return int(bi) - 'A' + 10
72 }
73 if bi >= 'a' && bi <= 'f' {
74 return int(bi) - 'a' + 10
75 }
76 return int(bi) - '0'
77}
78
79// Check if the character is ASCII.
80func is_ascii(b []byte, i int) bool {
81 return b[i] <= 0x7F
82}
83
84// Check if the character at the start of the buffer can be printed unescaped.
85func is_printable(b []byte, i int) bool {
86 return ((b[i] == 0x0A) || // . == #x0A
87 (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
88 (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
89 (b[i] > 0xC2 && b[i] < 0xED) ||
90 (b[i] == 0xED && b[i+1] < 0xA0) ||
91 (b[i] == 0xEE) ||
92 (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
93 !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
94 !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
95}
96
97// Check if the character at the specified position is NUL.
98func is_z(b []byte, i int) bool {
99 return b[i] == 0x00
100}
101
102// Check if the beginning of the buffer is a BOM.
103func is_bom(b []byte, i int) bool {
104 return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
105}
106
107// Check if the character at the specified position is space.
108func is_space(b []byte, i int) bool {
109 return b[i] == ' '
110}
111
112// Check if the character at the specified position is tab.
113func is_tab(b []byte, i int) bool {
114 return b[i] == '\t'
115}
116
117// Check if the character at the specified position is blank (space or tab).
118func is_blank(b []byte, i int) bool {
119 //return is_space(b, i) || is_tab(b, i)
120 return b[i] == ' ' || b[i] == '\t'
121}
122
123// Check if the character at the specified position is a line break.
124func is_break(b []byte, i int) bool {
125 return (b[i] == '\r' || // CR (#xD)
126 b[i] == '\n' || // LF (#xA)
127 b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
128 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
129 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
130}
131
132func is_crlf(b []byte, i int) bool {
133 return b[i] == '\r' && b[i+1] == '\n'
134}
135
136// Check if the character is a line break or NUL.
137func is_breakz(b []byte, i int) bool {
138 //return is_break(b, i) || is_z(b, i)
139 return (
140 // is_break:
141 b[i] == '\r' || // CR (#xD)
142 b[i] == '\n' || // LF (#xA)
143 b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
144 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
145 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
146 // is_z:
147 b[i] == 0)
148}
149
150// Check if the character is a line break, space, or NUL.
151func is_spacez(b []byte, i int) bool {
152 //return is_space(b, i) || is_breakz(b, i)
153 return (
154 // is_space:
155 b[i] == ' ' ||
156 // is_breakz:
157 b[i] == '\r' || // CR (#xD)
158 b[i] == '\n' || // LF (#xA)
159 b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
160 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
161 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
162 b[i] == 0)
163}
164
165// Check if the character is a line break, space, tab, or NUL.
166func is_blankz(b []byte, i int) bool {
167 //return is_blank(b, i) || is_breakz(b, i)
168 return (
169 // is_blank:
170 b[i] == ' ' || b[i] == '\t' ||
171 // is_breakz:
172 b[i] == '\r' || // CR (#xD)
173 b[i] == '\n' || // LF (#xA)
174 b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
175 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
176 b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
177 b[i] == 0)
178}
179
180// Determine the width of the character.
181func width(b byte) int {
182 // Don't replace these by a switch without first
183 // confirming that it is being inlined.
184 if b&0x80 == 0x00 {
185 return 1
186 }
187 if b&0xE0 == 0xC0 {
188 return 2
189 }
190 if b&0xF0 == 0xE0 {
191 return 3
192 }
193 if b&0xF8 == 0xF0 {
194 return 4
195 }
196 return 0
197
198}