aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/D-YAML
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2021-02-19 17:10:51 -0500
committerRalph Amissah <ralph.amissah@gmail.com>2021-02-24 16:46:47 -0500
commit02ca32ae0a5bc290918d2b2a3288e385b9cc6b11 (patch)
tree06379785e8a0165a7deb981c2eba362894820634 /src/ext_depends/D-YAML
parentbuild from static source-tree pre fetch depends (diff)
external & build dependences in src tree
- external & build dependences boost licensed - ext_depends (external depends) - D-YAML - tinyendian - d2sqlite3 - imageformats - build_depends - dub2nix
Diffstat (limited to 'src/ext_depends/D-YAML')
-rw-r--r--src/ext_depends/D-YAML/.codecov.yml13
-rw-r--r--src/ext_depends/D-YAML/.editorconfig14
-rw-r--r--src/ext_depends/D-YAML/.gitignore66
-rw-r--r--src/ext_depends/D-YAML/.travis.yml41
-rw-r--r--src/ext_depends/D-YAML/LICENSE_1_0.txt23
-rw-r--r--src/ext_depends/D-YAML/README.md97
-rw-r--r--src/ext_depends/D-YAML/appveyor.yml122
-rw-r--r--src/ext_depends/D-YAML/contrib/tinyendian.wrap5
-rw-r--r--src/ext_depends/D-YAML/docs/articles/spec_differences.md64
-rw-r--r--src/ext_depends/D-YAML/docs/index.md11
-rw-r--r--src/ext_depends/D-YAML/docs/logo128.pngbin0 -> 2812 bytes
-rw-r--r--src/ext_depends/D-YAML/docs/logo210.pngbin0 -> 5329 bytes
-rw-r--r--src/ext_depends/D-YAML/docs/tutorials/custom_types.md258
-rw-r--r--src/ext_depends/D-YAML/docs/tutorials/getting_started.md140
-rw-r--r--src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md241
-rw-r--r--src/ext_depends/D-YAML/dub.json25
-rw-r--r--src/ext_depends/D-YAML/examples/constructor/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/constructor/input.yaml8
-rw-r--r--src/ext_depends/D-YAML/examples/constructor/main.d91
-rw-r--r--src/ext_depends/D-YAML/examples/getting_started/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/getting_started/input.yaml2
-rw-r--r--src/ext_depends/D-YAML/examples/getting_started/main.d18
-rw-r--r--src/ext_depends/D-YAML/examples/representer/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/representer/main.d43
-rw-r--r--src/ext_depends/D-YAML/examples/resolver/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/resolver/input.yaml8
-rw-r--r--src/ext_depends/D-YAML/examples/resolver/main.d36
-rw-r--r--src/ext_depends/D-YAML/examples/tojson/dub.json8
-rw-r--r--src/ext_depends/D-YAML/examples/tojson/source/app.d54
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_bench/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_bench/yaml_bench.d179
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_gen/config.yaml46
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_gen/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d316
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_stats/dub.json10
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_stats/small.yaml4
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_stats/yaml_stats.d106
-rw-r--r--src/ext_depends/D-YAML/hmod.cfg123
-rw-r--r--src/ext_depends/D-YAML/meson.build70
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/composer.d375
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/constructor.d611
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/dumper.d287
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/emitter.d1689
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/encoding.d11
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/escapes.d92
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/event.d243
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/exception.d159
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/linebreak.d32
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/loader.d394
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/node.d2488
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/package.d15
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/parser.d958
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/queue.d272
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/reader.d906
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/representer.d517
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/resolver.d261
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/scanner.d1788
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/serializer.d322
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/style.d37
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/tagdirective.d15
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/common.d223
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/compare.d51
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/constructor.d957
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/emitter.d132
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/errors.d64
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d92
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/reader.d37
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/representer.d54
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/resolver.d39
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/test/tokens.d93
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/tinyendian.d213
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/token.d172
-rw-r--r--src/ext_depends/D-YAML/test/data/a-nasty-libyaml-bug.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/aliases-cdumper-bug.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/aliases.events8
-rw-r--r--src/ext_depends/D-YAML/test/data/bmpchars.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/bmpchars.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/bool.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/bool.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/colon-in-flow-context.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-binary.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-binary.data12
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-bool.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-bool.data13
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-custom.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-custom.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-float.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-float.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-int.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-int.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-map.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-map.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-merge.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-merge.data27
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-null.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-null.data18
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-omap.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-omap.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-pairs.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-pairs.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-seq.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-seq.data15
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-set.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-set.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str-ascii.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str-ascii.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str-utf8.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str-utf8.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-str.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-timestamp.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-timestamp.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-value.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/construct-value.data10
-rw-r--r--src/ext_depends/D-YAML/test/data/document-separator-in-quoted-scalar.loader-error11
-rw-r--r--src/ext_depends/D-YAML/test/data/documents.events11
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-anchor-1.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-anchor-2.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-mapping-key.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-merge-key.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-merge-key.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-tag-directive.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/duplicate-yaml-directive.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-anchor.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-document-bug.canonical1
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-document-bug.data0
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-document-bug.empty0
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-documents.single-loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-tag-handle.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-tag-prefix.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/empty-tag.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-document-end.emitter-error6
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-document-start.emitter-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-mapping.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-node-1.emitter-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-node-2.emitter-error7
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-nothing.emitter-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-scalar.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-sequence.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/expected-stream-start.emitter-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/explicit-document.single-loader-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/fetch-complex-value-bug.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/float.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/float.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/forbidden-entry.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/forbidden-key.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/forbidden-value.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/implicit-document.single-loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/int.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/int.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-anchor-1.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-anchor-2.loader-error8
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-anchor.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-base64-data-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-base64-data.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-block-scalar-indicator.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-character.loader-errorbin0 -> 2209 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-character.stream-errorbin0 -> 4193 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-directive-line.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-directive-name-1.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-directive-name-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-escape-character.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-escape-numbers.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-1.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-item-without-trailing-break.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-merge-1.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-merge-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-omap-1.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-omap-2.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-omap-3.loader-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-pairs-1.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-pairs-2.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-pairs-3.loader-error4
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-simple-key.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-starting-character.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-1.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-2.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-directive-handle.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-directive-prefix.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-uri-escapes-1.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-uri-escapes-2.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-uri-escapes-3.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-uri.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-utf8-byte.loader-error66
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-utf8-byte.stream-error66
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-1.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-2.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-3.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-4.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-5.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-6.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/invalid-yaml-version.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/latin.unicode384
-rw-r--r--src/ext_depends/D-YAML/test/data/mappings.events44
-rw-r--r--src/ext_depends/D-YAML/test/data/merge.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/merge.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/more-floats.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/more-floats.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/negative-float-bug.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/negative-float-bug.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-alias-anchor.emitter-error8
-rw-r--r--src/ext_depends/D-YAML/test/data/no-alias-anchor.skip-ext0
-rw-r--r--src/ext_depends/D-YAML/test/data/no-block-collection-end.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/no-block-mapping-end-2.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/no-block-mapping-end.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-document-start.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/no-flow-mapping-end.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-flow-sequence-end.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-node-1.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-node-2.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/no-tag.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/null.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/null.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/odd-utf16.stream-errorbin0 -> 1311 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/recursive.former-dumper-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/remove-possible-simple-key-bug.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/resolver.data30
-rw-r--r--src/ext_depends/D-YAML/test/data/resolver.path30
-rw-r--r--src/ext_depends/D-YAML/test/data/run-parser-crash-bug.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/scalars.events28
-rw-r--r--src/ext_depends/D-YAML/test/data/scan-document-end-bug.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/scan-document-end-bug.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/scan-line-break-bug.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/scan-line-break-bug.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/sequences.events81
-rw-r--r--src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/sloppy-indentation.canonical18
-rw-r--r--src/ext_depends/D-YAML/test/data/sloppy-indentation.data17
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-01.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-01.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-01.tokens1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-02.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-02.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-02.tokens5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-03.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-03.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-03.tokens4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-04.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-04.structure4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-04.tokens4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-05.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-05.structure5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-05.tokens5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-06.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-06.structure4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-06.tokens4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-07.data10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-07.structure4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-07.tokens12
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-08.data10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-08.structure4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-08.tokens15
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-09.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-09.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-09.tokens5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-10.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-10.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-10.tokens5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-11.data9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-11.structure4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-11.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-12.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-12.structure5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-12.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-13.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-13.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-13.tokens1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-14.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-14.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-14.tokens1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-15.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-15.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-15.tokens1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-16.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-16.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-16.tokens5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-17.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-17.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-17.tokens8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-18.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-18.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-18.tokens4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-19.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-19.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-19.tokens7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-20.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-20.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-20.tokens8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-21.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-21.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-21.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-22.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-22.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-22.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-23.data13
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-23.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-23.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-24.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-24.structure5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-24.tokens20
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-25.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-25.structure1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-25.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-26.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-26.structure5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-26.tokens6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-27.data29
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-27.structure17
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-27.tokens20
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-28.data26
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-28.structure10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-02-28.tokens23
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.databin0 -> 34 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.databin0 -> 34 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf8.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-01-utf8.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.databin0 -> 90 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.databin0 -> 90 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf8.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-02-utf8.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-03.canonical14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-03.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-04.canonical13
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-04.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-05.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-05.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-06.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-06.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-06.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-07.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-07.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-08.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-08.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-09.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-09.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-10.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-10.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-11.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-11.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-12.data9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-12.error8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-13.canonical5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-13.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-14.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-14.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-15.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-05-15.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-01.canonical15
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-01.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-02.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-02.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-03.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-03.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-04.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-04.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-05.canonical16
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-05.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-06.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-06.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-07.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-07.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-08.canonical5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-06-08.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-01.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-01.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-01.skip-ext0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-02.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-02.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-02.skip-ext0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-03.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-03.error3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-04.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-04.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-05.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-05.error4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-06.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-06.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-06.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07a.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07a.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07a.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07b.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07b.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-07b.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-08.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-08.data9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-08.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-09.canonical9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-09.data11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-10.canonical15
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-10.data11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-11.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-11.empty2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-12a.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-12a.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-12b.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-12b.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-13.canonical9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-13.data9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-07-13.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-01.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-01.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-02.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-02.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-03.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-03.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-03.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-04.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-04.error6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-05.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-05.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-05.test_loader_skip0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-06.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-06.error4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-07.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-07.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-08.canonical15
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-08.data13
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-09.canonical21
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-09.data11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-10.canonical23
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-10.data15
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-11.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-11.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-12.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-12.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-13.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-13.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-13.skip-ext0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-14.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-14.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-15.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-08-15.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-01.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-01.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-02.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-02.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-03.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-03.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-04.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-04.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-05.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-05.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-06.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-06.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-07.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-07.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-08.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-08.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-09.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-09.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-10.canonical5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-10.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-11.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-11.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-12.canonical12
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-12.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-13.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-13.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-14.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-14.error6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-15.canonical18
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-15.data13
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-16.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-16.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-17.canonical4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-17.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-18.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-18.data9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-19.canonical6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-19.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-20.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-20.data11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-20.skip-ext0
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-21.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-21.error7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-22.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-22.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-23.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-23.data11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-24.canonical10
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-24.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-25.canonical4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-25.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-26.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-26.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-27.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-27.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-28.canonical3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-28.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-29.canonical4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-29.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-30.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-30.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-31.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-31.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-32.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-32.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-33.canonical7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-09-33.data14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-01.canonical12
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-01.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-02.canonical14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-02.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-03.canonical12
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-03.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-04.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-04.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-05.canonical14
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-05.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-06.canonical16
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-06.data2
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-07.canonical16
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-07.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-08.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-08.error5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-09.canonical8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-09.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-10.canonical16
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-10.data8
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-11.canonical24
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-11.data7
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-12.canonical9
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-12.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-13.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-13.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-14.canonical11
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-14.data4
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-15.canonical18
-rw-r--r--src/ext_depends/D-YAML/test/data/spec-10-15.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/str.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/str.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/tags.events12
-rw-r--r--src/ext_depends/D-YAML/test/data/test_mark.marks38
-rw-r--r--src/ext_depends/D-YAML/test/data/timestamp-bugs.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/timestamp-bugs.data6
-rw-r--r--src/ext_depends/D-YAML/test/data/timestamp.data5
-rw-r--r--src/ext_depends/D-YAML/test/data/timestamp.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/unclosed-bracket.loader-error6
-rw-r--r--src/ext_depends/D-YAML/test/data/unclosed-quoted-scalar.loader-error2
-rw-r--r--src/ext_depends/D-YAML/test/data/undefined-anchor.loader-error3
-rw-r--r--src/ext_depends/D-YAML/test/data/undefined-tag-handle.loader-error1
-rw-r--r--src/ext_depends/D-YAML/test/data/unsupported-version.emitter-error5
-rw-r--r--src/ext_depends/D-YAML/test/data/uri.data3
-rw-r--r--src/ext_depends/D-YAML/test/data/uri.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf16be.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf16be.databin0 -> 30 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/utf16le.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf16le.databin0 -> 30 bytes
-rw-r--r--src/ext_depends/D-YAML/test/data/utf8-implicit.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf8-implicit.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf8.code1
-rw-r--r--src/ext_depends/D-YAML/test/data/utf8.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/value.data1
-rw-r--r--src/ext_depends/D-YAML/test/data/value.detect1
-rw-r--r--src/ext_depends/D-YAML/test/data/yaml.data3
-rw-r--r--src/ext_depends/D-YAML/testsuite/dub.json8
-rw-r--r--src/ext_depends/D-YAML/testsuite/source/app.d323
574 files changed, 19508 insertions, 0 deletions
diff --git a/src/ext_depends/D-YAML/.codecov.yml b/src/ext_depends/D-YAML/.codecov.yml
new file mode 100644
index 0000000..7e05d9f
--- /dev/null
+++ b/src/ext_depends/D-YAML/.codecov.yml
@@ -0,0 +1,13 @@
+# Documentation: https://github.com/codecov/support/wiki/codecov.yml
+codecov:
+coverage:
+ precision: 3
+ round: down
+
+ status:
+ # Learn more at https://codecov.io/docs#yaml_default_commit_status
+ project: true
+ patch: true
+ changes: false
+
+comment: false
diff --git a/src/ext_depends/D-YAML/.editorconfig b/src/ext_depends/D-YAML/.editorconfig
new file mode 100644
index 0000000..aa1b122
--- /dev/null
+++ b/src/ext_depends/D-YAML/.editorconfig
@@ -0,0 +1,14 @@
+# EditorConfig file: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+[*.d]
+charset = utf-8
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
diff --git a/src/ext_depends/D-YAML/.gitignore b/src/ext_depends/D-YAML/.gitignore
new file mode 100644
index 0000000..1a1aec4
--- /dev/null
+++ b/src/ext_depends/D-YAML/.gitignore
@@ -0,0 +1,66 @@
+/__test__library__
+/examples/resolver/resolver
+/examples/representer/representer
+/examples/getting_started/getting-started
+/examples/constructor/constructor
+/libdyaml
+/examples/yaml_gen/yaml_gen
+/unittest.obj
+/examples/yaml_stats/yaml_stats
+/examples/yaml_bench/yaml_bench
+/examples/representer/output.yaml
+/examples/getting_started/output.yaml
+/examples/getting_started/main.obj
+/cdc.obj
+/unittest
+
+# Backups #
+###########
+*~
+*.sw*
+
+# dub #
+#######
+*.dub*
+dub.selections.json
+
+# Compiled source #
+###################
+unittest
+cdc
+main
+*.a
+*.lib
+*.o
+*.obj
+*.exe
+docs.json
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.tar
+*.tar.xz
+*.tar.gz
+*.zip
+
+# OS generated files #
+######################
+.DS_Store?
+ehthumbs.db
+Icon?
+Thumbs.db
+.directory
+
+# Profiling outputs #
+#####################
+perf.data
+perf.data.old
+callgrind.out.*
+
+# Test outputs #
+example.yaml
+
+# Unittest Coverage output #
+*.lst
diff --git a/src/ext_depends/D-YAML/.travis.yml b/src/ext_depends/D-YAML/.travis.yml
new file mode 100644
index 0000000..7e284b6
--- /dev/null
+++ b/src/ext_depends/D-YAML/.travis.yml
@@ -0,0 +1,41 @@
+dist: xenial
+sudo: false
+
+language: d
+os:
+ - linux
+d:
+ - dmd
+ - ldc
+
+branches:
+ only:
+ - master
+
+before_install:
+ - sudo apt-get install python3-pip python3-setuptools
+ - pip3 install 'meson==0.48.2'
+
+install:
+ - mkdir .ntmp && curl -L https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip -o .ntmp/ninja-linux.zip
+ - unzip .ntmp/ninja-linux.zip -d .ntmp
+
+before_script:
+ - export PATH=$PATH:$PWD/.ntmp
+
+script:
+ - meson build && ninja -j8 -C build
+ - ninja -j8 -C build test -v
+ - dub build
+ - "dub build dyaml:benchmark"
+ - "dub build dyaml:constructor"
+ - "dub build dyaml:getting-started"
+ - "dub build dyaml:representer"
+ - "dub build dyaml:resolver"
+ - "dub build dyaml:testsuite"
+ - "dub build dyaml:tojson"
+ - "dub build dyaml:yaml_gen"
+ - "dub build dyaml:yaml_stats"
+ - dub test --build=unittest-cov
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
diff --git a/src/ext_depends/D-YAML/LICENSE_1_0.txt b/src/ext_depends/D-YAML/LICENSE_1_0.txt
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/src/ext_depends/D-YAML/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/ext_depends/D-YAML/README.md b/src/ext_depends/D-YAML/README.md
new file mode 100644
index 0000000..4781bdd
--- /dev/null
+++ b/src/ext_depends/D-YAML/README.md
@@ -0,0 +1,97 @@
+# D:YAML
+
+[![travis-ci](https://travis-ci.org/dlang-community/D-YAML.svg?branch=master)](https://travis-ci.org/dlang-community/D-YAML)
+[![codecov](https://codecov.io/gh/dlang-community/D-YAML/branch/master/graph/badge.svg)](https://codecov.io/gh/dlang-community/D-YAML)
+[![code.dlang.org](https://img.shields.io/dub/v/dyaml.svg)](http://code.dlang.org/packages/dyaml)
+
+## Introduction
+
+D:YAML is an open source YAML parser and emitter library for the D programming language.
+It is [almost](https://dlang-community.github.io/D-YAML/articles/spec_differences.html) compliant to the YAML 1.1 specification.
+D:YAML is based on [PyYAML](http://www.pyyaml.org) created by Kirill Simonov.
+
+D:YAML is designed to be easy to use while supporting the full feature set of YAML.
+To start using it in your project, see the [Getting Started](https://dlang-community.github.io/D-YAML/tutorials/getting_started.html) tutorial.
+
+## Features
+
+ - Easy to use, high level API and detailed debugging messages.
+ - Detailed API documentation and tutorials.
+ - Code examples.
+ - Supports all YAML 1.1 constructs. All examples from the YAML 1.1
+ specification are parsed correctly.
+ - Reads from and writes from/to YAML files or in-memory buffers.
+ - UTF-8, UTF-16 and UTF-32 encodings are supported, both big and
+ little endian (plain ASCII also works as it is a subset of UTF-8).
+ - Support for both block (Python-like, based on indentation) and flow
+ (JSON-like, based on bracing) constructs.
+ - Support for YAML anchors and aliases.
+ - Support for default values in mappings.
+ - Support for custom tags (data types), and implicit tag resolution
+ for custom scalar tags.
+ - All tags (data types) described at <http://yaml.org/type/> are
+ supported, with the exception of `tag:yaml.org,2002:yaml`, which is
+ used to represent YAML code in YAML.
+ - Remembers YAML style information between loading and dumping if
+ possible.
+ - Reuses input memory and uses slices to minimize memory allocations.
+ - There is no support for recursive data structures. There are no
+ plans to implement this at the moment.
+
+## Directory structure
+
+| Directory | Contents |
+|---------------|--------------------------------|
+| `./` | This README, utility scripts. |
+| `./docs` | Documentation. |
+| `./source` | Source code. |
+| `./examples/` | Example projects using D:YAML. |
+| `./test` | Unittest data. |
+
+## Installing and tutorial
+
+See the [Getting Started](https://dlang-community.github.io/D-YAML/tutorials/getting_started.html).
+Tutorial and other tutorials that can be found at the [GitHub pages](https://dlang-community.github.io/D-YAML/) or in the `docs` directory of the repository.
+
+API documentation is available [here](https://dyaml.dpldocs.info/dyaml.html).
+
+## License
+
+D:YAML is released under the terms of the [Boost Software
+License 1.0](http://www.boost.org/LICENSE_1_0.txt). This license allows
+you to use the source code in your own projects, open source or
+proprietary, and to modify it to suit your needs. However, in source
+distributions, you have to preserve the license headers in the source
+code and the accompanying license file.
+
+Full text of the license can be found in file `LICENSE_1_0.txt` and is
+also displayed here:
+
+ Boost Software License - Version 1.0 - August 17th, 2003
+
+ Permission is hereby granted, free of charge, to any person or organization
+ obtaining a copy of the software and accompanying documentation covered by
+ this license (the "Software") to use, reproduce, display, distribute,
+ execute, and transmit the Software, and to prepare derivative works of the
+ Software, and to permit third-parties to whom the Software is furnished to
+ do so, all subject to the following:
+
+ The copyright notices in the Software and this entire statement, including
+ the above license grant, this restriction and the following disclaimer,
+ must be included in all copies of the Software, in whole or in part, and
+ all derivative works of the Software, unless such copies or derivative
+ works are solely in the form of machine-executable object code generated by
+ a source language processor.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+## Credits
+
+D:YAML was created by Ferdinand Majerech aka Kiith-Sa and is handled by the [dlang-community](https://github.com/dlang-community) organization since 2017.
+Parts of code based on [PyYAML](http://www.pyyaml.org) created by Kirill Simonov.
diff --git a/src/ext_depends/D-YAML/appveyor.yml b/src/ext_depends/D-YAML/appveyor.yml
new file mode 100644
index 0000000..1efa6be
--- /dev/null
+++ b/src/ext_depends/D-YAML/appveyor.yml
@@ -0,0 +1,122 @@
+platform: x64
+environment:
+ matrix:
+ #- DC: dmd
+ # DVersion: nightly
+ # arch: x64
+ #- DC: dmd
+ # DVersion: nightly
+ # arch: x86
+ #- DC: dmd
+ # DVersion: beta
+ # arch: x64
+ #- DC: dmd
+ # DVersion: beta
+ # arch: x86
+ - DC: dmd
+ DVersion: stable
+ arch: x64
+ - DC: dmd
+ DVersion: stable
+ arch: x86
+ #- DC: ldc
+ # DVersion: beta
+ # arch: x86
+ #- DC: ldc
+ # DVersion: beta
+ # arch: x64
+ - DC: ldc
+ DVersion: stable
+ arch: x86
+ - DC: ldc
+ DVersion: stable
+ arch: x64
+
+skip_tags: false
+branches:
+ only:
+ - master
+
+install:
+ - ps: function ResolveLatestDMD
+ {
+ $version = $env:DVersion;
+ if($version -eq "stable") {
+ $latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString();
+ $url = "http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z";
+ }elseif($version -eq "beta") {
+ $latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString();
+ $latestVersion = $latest.split("-")[0].split("~")[0];
+ $url = "http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z";
+ }elseif($version -eq "nightly") {
+ $url = "http://nightlies.dlang.org/dmd-master-2017-05-20/dmd.master.windows.7z"
+ }else {
+ $url = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z";
+ }
+ $env:PATH += ";C:\dmd2\windows\bin;";
+ return $url;
+ }
+ - ps: function ResolveLatestLDC
+ {
+ $version = $env:DVersion;
+ $arch = $env:arch;
+ if($version -eq "stable") {
+ $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
+ }elseif($version -eq "beta") {
+ $latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-windows-$($arch).7z";
+ } else {
+ $latest = $version;
+ $url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-$($arch).7z";
+ }
+ $env:PATH += ";C:\ldc2-$($latest)-windows-$($arch)\bin";
+ $env:DC = "ldc2";
+ return $url;
+ }
+ - ps: function SetUpDCompiler
+ {
+ $env:toolchain = "msvc";
+ if($env:DC -eq "dmd"){
+ echo "downloading ...";
+ $url = ResolveLatestDMD;
+ echo $url;
+ Invoke-WebRequest $url -OutFile "c:\dmd.7z";
+ echo "finished.";
+ pushd c:\\;
+ 7z x dmd.7z > $null;
+ popd;
+ }
+ elseif($env:DC -eq "ldc"){
+ echo "downloading ...";
+ $url = ResolveLatestLDC;
+ echo $url;
+ Invoke-WebRequest $url -OutFile "c:\ldc.zip";
+ echo "finished.";
+ pushd c:\\;
+ 7z x ldc.zip > $null;
+ popd;
+ }
+ }
+ - ps: SetUpDCompiler
+
+build_script:
+ - ps: if($env:arch -eq "x86"){
+ $env:compilersetupargs = "x86";
+ $env:Darch = "x86";
+ $env:DConf = "m32";
+ }elseif($env:arch -eq "x64"){
+ $env:compilersetupargs = "amd64";
+ $env:Darch = "x86_64";
+ $env:DConf = "m64";
+ }
+ - ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall";
+ - '"%compilersetup%" %compilersetupargs%'
+
+test_script:
+ - echo %PLATFORM%
+ - echo %Darch%
+ - echo %DC%
+ - echo %PATH%
+ - '%DC% --version'
+ - dub test --arch=%Darch% --compiler=%DC%
diff --git a/src/ext_depends/D-YAML/contrib/tinyendian.wrap b/src/ext_depends/D-YAML/contrib/tinyendian.wrap
new file mode 100644
index 0000000..550553b
--- /dev/null
+++ b/src/ext_depends/D-YAML/contrib/tinyendian.wrap
@@ -0,0 +1,5 @@
+[wrap-git]
+directory = tinyendian
+
+url = https://github.com/dlang-community/tinyendian.git
+revision = head
diff --git a/src/ext_depends/D-YAML/docs/articles/spec_differences.md b/src/ext_depends/D-YAML/docs/articles/spec_differences.md
new file mode 100644
index 0000000..93cf038
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/articles/spec_differences.md
@@ -0,0 +1,64 @@
+# Differences between D:YAML and the YAML specification
+
+There are some differences between D:YAML and the YAML 1.1
+specification. Some are caused by difficulty of implementation of some
+features, such as multiple Unicode encodings within single stream, and
+some by unnecessary restrictions or ambiguities in the specification.
+
+Still, D:YAML tries to be as close to the specification as possible. It
+should never load documents with different meaning than according to the
+specification, and documents that fail to load should be very rare (for
+instance, very few files use multiple Unicode encodings).
+
+## List of known differences:
+
+Differences that can cause valid YAML documents not to load:
+
+ - No support for byte order marks and multiple Unicode encodings in a
+ stream.
+
+ - Plain scalars in flow context cannot contain `,`, `:` and `?`. This
+ might change with `:` in the future. See
+ <http://pyyaml.org/wiki/YAMLColonInFlowContext> for details.
+
+ - The specification does not restrict characters for anchors and
+ aliases. This may lead to problems, for instance, the document:
+
+ [ *alias, value ]
+
+ can be interpteted in two ways, as:
+
+ [ "value" ]
+
+ and:
+
+ [ *alias , "value" ]
+
+ Therefore we restrict aliases and anchors to ASCII alphanumeric
+ characters.
+
+ - The specification is confusing about tabs in plain scalars. We don't
+ use tabs in plain scalars at all.
+
+ - There is no support for recursive data structures in DYAML.
+
+Other differences:
+
+ - Indentation is ignored in the flow context, which is less
+ restrictive than the specification. This allows code such as:
+
+ key: {
+ }
+
+ - Indentation rules for quoted scalars are loosed: They don't need to
+ adhere indentation as `"` and `'` clearly mark the beginning and the
+ end of them.
+
+ - We allow `_` in tag handles.
+
+ - Right now, two mappings with the same contents but different
+ orderings are considered unequal, even if they are unordered
+ mappings. This is because all mappings are ordered in the D:YAML
+ implementation. This should change in future, once D associative
+ arrays work with variant types or a map class or struct appears in
+ Phobos.
diff --git a/src/ext_depends/D-YAML/docs/index.md b/src/ext_depends/D-YAML/docs/index.md
new file mode 100644
index 0000000..d0017ea
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/index.md
@@ -0,0 +1,11 @@
+# Welcome to D:YAML documentation!
+
+API Documentation [online](https://dyaml.dpldocs.info/dyaml.html)
+
+Tutorials:
+ - [Getting Started](tutorials/getting_started.md)
+ - [Custom Types](tutorials/custom_types.md)
+ - [YAML Syntax](tutorials/yaml_syntax.md)
+
+Articles:
+ - [Spec Differences](articles/spec_differences.md)
diff --git a/src/ext_depends/D-YAML/docs/logo128.png b/src/ext_depends/D-YAML/docs/logo128.png
new file mode 100644
index 0000000..f00ae05
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/logo128.png
Binary files differ
diff --git a/src/ext_depends/D-YAML/docs/logo210.png b/src/ext_depends/D-YAML/docs/logo210.png
new file mode 100644
index 0000000..66bef66
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/logo210.png
Binary files differ
diff --git a/src/ext_depends/D-YAML/docs/tutorials/custom_types.md b/src/ext_depends/D-YAML/docs/tutorials/custom_types.md
new file mode 100644
index 0000000..7e4e10b
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/tutorials/custom_types.md
@@ -0,0 +1,258 @@
+# Custom YAML data types
+
+Sometimes you need to serialize complex data types such as classes. To
+do this you could use plain nodes such as mappings with classes' fields.
+YAML also supports custom types with identifiers called *tags*. That is
+the topic of this tutorial.
+
+Each YAML node has a tag specifying its type. For instance: strings use
+the tag `tag:yaml.org,2002:str`. Tags of most default types are
+*implicitly resolved* during parsing - you don't need to specify tag for
+each float, integer, etc. D:YAML can also implicitly resolve custom
+tags, as we will show later.
+
+## Constructor
+
+D:YAML supports conversion to user-defined types. Adding a constructor to read
+the data from the node is all that is needed.
+
+We will implement support for an RGB color type. It is implemented as
+the following struct:
+
+```D
+struct Color
+{
+ ubyte red;
+ ubyte green;
+ ubyte blue;
+}
+```
+
+First, we need our type to have an appropriate constructor. The constructor
+will take a const *Node* to construct from. The node is guaranteed to
+contain either a *string*, an array of *Node* or of *Node.Pair*,
+depending on whether we're constructing our value from a scalar,
+sequence, or mapping, respectively.
+
+In this tutorial, we have a constructor to construct a color from a scalar,
+using CSS-like format, RRGGBB, or from a mapping, where we use the
+following format: {r:RRR, g:GGG, b:BBB} . Code of these functions:
+
+```D
+
+this(const Node node, string tag) @safe
+{
+ if (tag == "!color-mapping")
+ {
+ //Will throw if a value is missing, is not an integer, or is out of range.
+ red = node["r"].as!ubyte;
+ green = node["g"].as!ubyte;
+ blue = node["b"].as!ubyte;
+ }
+ else
+ {
+ string value = node.as!string;
+
+ if(value.length != 6)
+ {
+ throw new Exception("Invalid color: " ~ value);
+ }
+ //We don't need to check for uppercase chars this way.
+ value = value.toLower();
+
+ //Get value of a hex digit.
+ uint hex(char c)
+ {
+ import std.ascii;
+ if(!std.ascii.isHexDigit(c))
+ {
+ throw new Exception("Invalid color: " ~ value);
+ }
+
+ if(std.ascii.isDigit(c))
+ {
+ return c - '0';
+ }
+ return c - 'a' + 10;
+ }
+
+ red = cast(ubyte)(16 * hex(value[0]) + hex(value[1]));
+ green = cast(ubyte)(16 * hex(value[2]) + hex(value[3]));
+ blue = cast(ubyte)(16 * hex(value[4]) + hex(value[5]));
+ }
+}
+```
+
+Next, we need some YAML data using our new tag. Create a file called
+`input.yaml` with the following contents:
+
+```YAML
+scalar-red: !color FF0000
+scalar-orange: !color FFFF00
+mapping-red: !color-mapping {r: 255, g: 0, b: 0}
+mapping-orange:
+ !color-mapping
+ r: 255
+ g: 255
+ b: 0
+```
+
+You can see that we're using tag `!color` for scalar colors, and
+`!color-mapping` for colors expressed as mappings.
+
+Finally, the code to put it all together:
+
+```D
+void main()
+{
+ auto red = Color(255, 0, 0);
+ auto orange = Color(255, 255, 0);
+
+ try
+ {
+ auto root = Loader.fromFile("input.yaml").load();
+
+ if(root["scalar-red"].as!Color == red &&
+ root["mapping-red"].as!Color == red &&
+ root["scalar-orange"].as!Color == orange &&
+ root["mapping-orange"].as!Color == orange)
+ {
+ writeln("SUCCESS");
+ return;
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+
+ writeln("FAILURE");
+}
+```
+
+First we load the YAML document, and then have the resulting *Node*s converted
+to Colors via their constructor.
+
+You can find the source code for what we've done so far in the
+`examples/constructor` directory in the D:YAML package.
+
+## Resolver
+
+Specifying tag for every color can be tedious. D:YAML can implicitly
+resolve scalar tags using regular expressions. This is how default types
+are resolved. We will use the [Resolver](../api/dyaml.resolver.html)
+class to add implicit tag resolution for the Color data type (in its
+scalar form).
+
+We use the *addImplicitResolver()* method of *Resolver*, passing the
+tag, regular expression the scalar must match to resolve to this tag,
+and a string of possible starting characters of the scalar. Then we pass
+the *Resolver* to *Loader*.
+
+Note that resolvers added first override ones added later. If no
+resolver matches a scalar, YAML string tag is used. Therefore our custom
+values must not be resolvable as any non-string YAML data type.
+
+Add this to your code to add implicit resolution of `!color`.
+
+```D
+import std.regex;
+auto resolver = new Resolver;
+resolver.addImplicitResolver("!color", regex("[0-9a-fA-F]{6}"),
+ "0123456789abcdefABCDEF");
+
+auto loader = Loader.fromFile("input.yaml");
+
+loader.resolver = resolver;
+```
+
+Now, change contents of `input.yaml` to this:
+
+```YAML
+scalar-red: FF0000
+scalar-orange: FFFF00
+mapping-red: !color-mapping {r: 255, g: 0, b: 0}
+mapping-orange:
+ !color-mapping
+ r: 255
+ g: 255
+ b: 0
+```
+
+We no longer need to specify the tag for scalar color values. Compile
+and test the example. If everything went as expected, it should report
+success.
+
+You can find the complete code in the `examples/resolver` directory in
+the D:YAML package.
+
+## Representer
+
+Now that you can load custom data types, it might be good to know how to
+dump them.
+
+The *Node* struct simply attempts to cast all unrecognized types to *Node*.
+This gives each type a consistent and simple way of being represented in a
+document. All we need to do is specify a `Node opCast(T: Node)()` method for
+any types we wish to support. It is also possible to specify specific styles
+for each representation.
+
+Each type may only have one opCast!Node. Default YAML types are already
+supported.
+
+With the following code, we will add support for dumping the our Color
+type.
+
+```D
+Node opCast(T: Node)() const
+{
+ static immutable hex = "0123456789ABCDEF";
+
+ //Using the color format from the Constructor example.
+ string scalar;
+ foreach(channel; [red, green, blue])
+ {
+ scalar ~= hex[channel / 16];
+ scalar ~= hex[channel % 16];
+ }
+
+ //Representing as a scalar, with custom tag to specify this data type.
+ return Node(scalar, "!color");
+}
+```
+
+First we convert the colour data to a string with the CSS-like format we've
+used before. Then, we create a scalar *Node* with our desired tag.
+
+Since a type can only have one opCast!Node method, we don't dump
+*Color* both in the scalar and mapping formats we've used before.
+However, you can decide to dump the node with different formats/tags in
+the method itself. E.g. you could dump the Color as a
+mapping based on some arbitrary condition, such as the color being
+white.
+
+```D
+void main()
+{
+ try
+ {
+ auto dumper = dumper(File("output.yaml", "w").lockingTextWriter);
+
+ auto document = Node([Color(255, 0, 0),
+ Color(0, 255, 0),
+ Color(0, 0, 255)]);
+
+ dumper.dump(document);
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+}
+```
+
+We construct a *Dumper* to file `output.yaml`. Then, we create a simple node
+containing a sequence of colors and finally, we dump it.
+
+Source code for this section can be found in the `examples/representer`
+directory of the D:YAML package.
diff --git a/src/ext_depends/D-YAML/docs/tutorials/getting_started.md b/src/ext_depends/D-YAML/docs/tutorials/getting_started.md
new file mode 100644
index 0000000..58cf191
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/tutorials/getting_started.md
@@ -0,0 +1,140 @@
+# Getting started
+
+Welcome to D:YAML\! D:YAML is a
+[YAML](http://en.wikipedia.org/wiki/YAML) parser library for the [D
+programming language](http://dlang.org). This tutorial will explain how
+to set D:YAML up and use it in your projects.
+
+This is meant to be the **simplest possible** introduction to D:YAML.
+Some of this information might already be known to you. Only basic usage
+is covered.
+
+## Setting up
+
+### Install the DMD compiler
+
+Digital Mars D compiler, or DMD, is the most commonly used D compiler.
+You can find its newest version [here](http://dlang.org/download.html).
+Download the version of DMD for your operating system and install it.
+
+Note: Other D compilers exist, such as [GDC](http://gdcproject.org/) and
+[LDC](https://github.com/ldc-developers/ldc).
+
+## Your first D:YAML project
+
+First, create a directory for your project and navigate to that directory
+using your preferred command line. Then simply execute these two commands:
+
+ dub init
+ dub add dyaml
+
+In that directory, create a new file named `input.yaml` and paste this data
+into the file:
+
+```YAML
+Hello World : [Hello, World]
+Answer: 42
+```
+
+This will serve as input for our example.
+
+Now we need to parse it. Open the file named `source/app.d` and paste the
+following code into the file:
+
+```D
+import std.stdio;
+import dyaml;
+
+void main()
+{
+ //Read the input.
+ Node root = Loader.fromFile("input.yaml").load();
+
+ //Display the data read.
+ foreach(string word; root["Hello World"])
+ {
+ writeln(word);
+ }
+ writeln("The answer is ", root["Answer"].as!int);
+
+ //Dump the loaded document to output.yaml.
+ dumper(File("output.yaml", "w").lockingTextWriter).dump(root);
+}
+```
+
+### Explanation of the code
+
+First, we import the *dyaml* module. This is the only D:YAML module
+you need to import - it automatically imports all needed modules.
+
+Next we load the file using the *Loader.fromFile().load()* method. *Loader* is a
+struct used for parsing YAML documents. The *fromFile()* method loads the
+document from a file. The *load()* method loads the
+file as **one** YAML document, or throws *YAMLException*, D:YAML
+exception type, if the file could not be parsed or contains more than
+one document. Note that we don't do any error checking here in order to
+keep the example as simple as possible.
+
+*Node* represents a node in a YAML document. It can be a sequence
+(array), mapping (associative array) or a scalar (value). Here the root
+node is a mapping, and we use the index operator to get subnodes with
+keys "Hello World" and "Answer". We iterate over the former, as it is a
+sequence, and use the *Node.as()* method on the latter to read its value
+as an integer.
+
+You can iterate over a mapping or sequence as if it was an associative
+or normal array, respectively. If you try to iterate over a scalar, it
+will throw a *YAMLException*.
+
+You can iterate using *Node* as the iterated type, or specify the type
+iterated nodes are expected to have. D:YAML will automatically convert
+to that type if possible. Here we specify the *string* type, so we
+iterate over the "Hello World" sequence as an array of strings. If it is
+not possible to convert to iterated type, a *YAMLException* is thrown.
+For instance, if we specified *int* here, we would get an error, as
+"Hello" cannot be converted to an integer.
+
+The *Node.as()* method is used to read value of a scalar node as
+specified type. If the scalar does not have the specified type, D:YAML
+will try to convert it, throwing *YAMLException* if not possible.
+
+Finally we dump the document we just read to `output.yaml` with the
+*Dumper.dump()* method. *Dumper* is a struct used to dump YAML
+documents. *dumper()* accepts a range to write the document to.
+The *dump()* method writes one or more documents to the range,
+throwing *YAMLException* if it could not be written to.
+
+D:YAML tries to preserve style information in documents so e.g. `[Hello,
+World]` is not turned into:
+
+```YAML
+- Hello
+- World
+```
+
+However, comments are not preserved and neither are any extra formatting
+whitespace that doesn't affect the meaning of YAML contents.
+
+### Compiling
+
+Run the following command in your project's directory:
+
+ dub build
+
+DUB will automatically download D:YAML and compile it, and then it
+will compile our program. This will generate an executable called
+`getting-started` or `getting-started.exe` in your directory. When you
+run it, it should produce the following output:
+
+ Hello
+ World
+ The answer is 42
+
+You may also run ```dub run``` to combine the compile+run steps.
+
+### Conclusion
+
+You should now have a basic idea about how to use D:YAML. To learn more,
+look at the [API documentation](https://dyaml.dpldocs.info/dyaml.html) and other tutorials.
+You can find code for this example in the `example/getting_started`
+directory in the package.
diff --git a/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md b/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md
new file mode 100644
index 0000000..2df7f8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md
@@ -0,0 +1,241 @@
+# YAML syntax
+
+This is an introduction to the most common YAML constructs. For more detailed
+information, see [PyYAML documentation](http://pyyaml.org/wiki/PyYAMLDocumentation),
+which this article is based on,
+[Chapter 2 of the YAML specification](http://yaml.org/spec/1.1/#id857168)
+or the [Wikipedia page](http://en.wikipedia.org/wiki/YAML).
+
+YAML is a data serialization format designed for human readability. YAML is a
+recursive acronym for "YAML Ain't Markup Language".
+
+YAML is similar to JSON, and in fact, JSON is a subset of YAML 1.2; but YAML has
+some more advanced features and is easier to read. However, it is also more
+difficult to parse (and probably somewhat slower). Data is stored in mappings
+(associative arrays), sequences (lists) and scalars (single values). Data
+structure hierarchy depends either on indentation (block context, similar to
+Python code), or nesting of brackets and braces (flow context, similar to JSON).
+YAML comments begin with `#` and continue until the end of line.
+
+
+## Documents
+
+A YAML stream consists of one or more documents starting with `---` and
+optionally ending with `...` . `---` can be left out for the first document.
+
+Single document with no explicit start or end:
+
+```
+ - Red
+ - Green
+ - Blue
+```
+Same document with explicit start and end:
+```
+ ---
+ - Red
+ - Green
+ - Blue
+ ...
+```
+A stream containing multiple documents:
+```
+ ---
+ - Red
+ - Green
+ - Blue
+ ---
+ - Linux
+ - BSD
+ ---
+ answer : 42
+```
+
+## Sequences
+
+Sequences are arrays of nodes of any type, similar e.g. to Python lists.
+In block context, each item begins with hyphen+space "- ". In flow context,
+sequences have syntax similar to D arrays.
+
+```
+ #Block context
+ - Red
+ - Green
+ - Blue
+```
+```
+ #Flow context
+ [Red, Green, Blue]
+```
+```
+ #Nested
+ -
+ - Red
+ - Green
+ - Blue
+ -
+ - Linux
+ - BSD
+```
+```
+ #Nested flow
+ [[Red, Green, Blue], [Linux, BSD]]
+```
+```
+ #Nested in a mapping
+ Colors:
+ - Red
+ - Green
+ - Blue
+ Operating systems:
+ - Linux
+ - BSD
+```
+
+## Mappings
+
+Mappings are associative arrays where each key and value can be of any type,
+similar e.g. to Python dictionaries. In block context, keys and values are
+separated by colon+space ": ". In flow context, mappings have syntax similar
+to D associative arrays, but with braces instead of brackets:
+
+```
+ #Block context
+ CPU: Athlon
+ GPU: Radeon
+ OS: Linux
+
+```
+```
+ #Flow context
+ {CPU: Athlon, GPU: Radeon, OS: Linux}
+
+```
+```
+ #Nested
+ PC:
+ CPU: Athlon
+ GPU: Radeon
+ OS: Debian
+ Phone:
+ CPU: Cortex
+ GPU: PowerVR
+ OS: Android
+
+```
+```
+ #Nested flow
+ {PC: {CPU: Athlon, GPU: Radeon, OS: Debian},
+ Phone: {CPU: Cortex, GPU: PowerVR, OS: Android}}
+```
+```
+ #Nested in a sequence
+ - CPU: Athlon
+ GPU: Radeon
+ OS: Debian
+ - CPU: Cortex
+ GPU: PowerVR
+ OS: Android
+```
+
+Complex keys start with question mark+space "? ".
+
+```
+ #Nested in a sequence
+ ? [CPU, GPU]: [Athlon, Radeon]
+ OS: Debian
+```
+
+## Scalars
+
+Scalars are simple values such as integers, strings, timestamps and so on.
+There are multiple scalar styles.
+
+Plain scalars use no quotes, start with the first non-space and end with the
+last non-space character:
+
+```
+ scalar: Plain scalar
+```
+
+Single quoted scalars start and end with single quotes. A single quote is
+represented by a pair of single quotes ''.
+
+```
+ scalar: 'Single quoted scalar ending with some spaces '
+```
+
+Double quoted scalars support C-style escape sequences.
+
+```
+ scalar: "Double quoted scalar \n with some \\ escape sequences"
+```
+
+Block scalars are convenient for multi-line values. They start either with
+`|` or with `>`. With `|`, the newlines in the scalar are preserved.
+With `>`, the newlines between two non-empty lines are removed.
+
+```
+ scalar: |
+ Newlines are preserved
+ First line
+ Second line
+```
+```
+ scalar: >
+ Newlines are folded
+ This is still the first paragraph
+
+ This is the second
+ paragraph
+```
+
+## Anchors and aliases
+
+Anchors and aliases can reduce size of YAML code by allowing you to define a
+value once, assign an anchor to it and use alias referring to that anchor
+anywhere else you need that value. It is possible to use this to create
+recursive data structures and some parsers support this; however, D:YAML does
+not (this might change in the future, but it is unlikely).
+
+```
+ Person: &AD
+ gender: male
+ name: Arthur Dent
+ Clone: *AD
+```
+
+## Tags
+
+Tags are identifiers that specify data types of YAML nodes. Most default YAML
+tags are resolved implicitly, so there is no need to specify them. D:YAML also
+supports implicit resolution for custom, user specified tags.
+
+Explicitly specified tags:
+
+```
+ answer: !!int "42"
+ name: !!str "Arthur Dent"
+```
+
+Implicit tags:
+
+```
+ answer: 42 #int
+ name: Arthur Dent #string
+```
+
+This table shows D types stored in *yaml.Node* default YAML tags are converted to.
+Some of these might change in the future (especially !!map and !!set).
+
+|YAML tag |D type |
+|-----------------------|-----------------------|
+|!!null |dyaml.node.YAMLNull |
+|!!bool |bool |
+|!!int |long |
+|!!float |real |
+|!!binary |ubyte[] |
+|!!timestamp |std.datetime.SysTime |
+|!!map, !!omap, !!pairs |dyaml.node.Node.Pair[] |
+|!!seq, !!set |dyaml.node.Node[] |
+|!!str |string |
diff --git a/src/ext_depends/D-YAML/dub.json b/src/ext_depends/D-YAML/dub.json
new file mode 100644
index 0000000..07ee17e
--- /dev/null
+++ b/src/ext_depends/D-YAML/dub.json
@@ -0,0 +1,25 @@
+{
+ "name": "dyaml",
+ "description": "YAML parser and emitter",
+ "authors": [
+ "Ferdinand Majerech",
+ "Cameron \"Herringway\" Ross"
+ ],
+ "license": "BSL-1.0",
+ "dependencies": {
+ "tinyendian" : "~>0.2.0"
+ },
+ "homepage": "https://github.com/dlang-community/D-YAML",
+ "copyright": "Copyright © 2011-2018, Ferdinand Majerech",
+ "subPackages": [
+ "examples/constructor",
+ "examples/getting_started",
+ "examples/representer",
+ "examples/resolver",
+ "examples/tojson",
+ "examples/yaml_bench",
+ "examples/yaml_gen",
+ "examples/yaml_stats",
+ "testsuite"
+ ]
+}
diff --git a/src/ext_depends/D-YAML/examples/constructor/dub.json b/src/ext_depends/D-YAML/examples/constructor/dub.json
new file mode 100644
index 0000000..1aca4ee
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/constructor/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "constructor",
+ "targetType": "executable",
+ "sourceFiles": ["main.d"],
+ "mainSourceFile": "main.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*"}
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/constructor/input.yaml b/src/ext_depends/D-YAML/examples/constructor/input.yaml
new file mode 100644
index 0000000..8d56926
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/constructor/input.yaml
@@ -0,0 +1,8 @@
+scalar-red: !color FF0000
+scalar-orange: !color FFFF00
+mapping-red: !color-mapping {r: 255, g: 0, b: 0}
+mapping-orange:
+ !color-mapping
+ r: 255
+ g: 255
+ b: 0
diff --git a/src/ext_depends/D-YAML/examples/constructor/main.d b/src/ext_depends/D-YAML/examples/constructor/main.d
new file mode 100644
index 0000000..50826f1
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/constructor/main.d
@@ -0,0 +1,91 @@
+import std.stdio;
+import std.string;
+import dyaml;
+
+struct Color
+{
+ ubyte red;
+ ubyte green;
+ ubyte blue;
+
+ this(ubyte r, ubyte g, ubyte b) @safe
+ {
+ red = r;
+ green = g;
+ blue = b;
+ }
+
+ this(const Node node, string tag) @safe
+ {
+ if (tag == "!color-mapping")
+ {
+ //Will throw if a value is missing, is not an integer, or is out of range.
+ red = node["r"].as!ubyte;
+ green = node["g"].as!ubyte;
+ blue = node["b"].as!ubyte;
+ }
+ else
+ {
+ string value = node.as!string;
+
+ if(value.length != 6)
+ {
+ throw new Exception("Invalid color: " ~ value);
+ }
+ //We don't need to check for uppercase chars this way.
+ value = value.toLower();
+
+ //Get value of a hex digit.
+ uint hex(char c)
+ {
+ import std.ascii;
+ if(!std.ascii.isHexDigit(c))
+ {
+ throw new Exception("Invalid color: " ~ value);
+ }
+
+ if(std.ascii.isDigit(c))
+ {
+ return c - '0';
+ }
+ return c - 'a' + 10;
+ }
+
+ red = cast(ubyte)(16 * hex(value[0]) + hex(value[1]));
+ green = cast(ubyte)(16 * hex(value[2]) + hex(value[3]));
+ blue = cast(ubyte)(16 * hex(value[4]) + hex(value[5]));
+ }
+ }
+}
+
+void main(string[] args)
+{
+ auto red = Color(255, 0, 0);
+ auto orange = Color(255, 255, 0);
+
+ string path = "input.yaml";
+ if (args.length > 1)
+ {
+ path = args[1];
+ }
+
+ try
+ {
+ auto root = Loader.fromFile(path).load();
+
+ if(root["scalar-red"].as!Color == red &&
+ root["mapping-red"].as!Color == red &&
+ root["scalar-orange"].as!Color == orange &&
+ root["mapping-orange"].as!Color == orange)
+ {
+ writeln("SUCCESS");
+ return;
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+
+ writeln("FAILURE");
+}
diff --git a/src/ext_depends/D-YAML/examples/getting_started/dub.json b/src/ext_depends/D-YAML/examples/getting_started/dub.json
new file mode 100644
index 0000000..844c006
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/getting_started/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "getting-started",
+ "targetType": "executable",
+ "sourceFiles": ["main.d"],
+ "mainSourceFile": "main.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/getting_started/input.yaml b/src/ext_depends/D-YAML/examples/getting_started/input.yaml
new file mode 100644
index 0000000..8b093ae
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/getting_started/input.yaml
@@ -0,0 +1,2 @@
+Hello World : [Hello, World]
+Answer : 42
diff --git a/src/ext_depends/D-YAML/examples/getting_started/main.d b/src/ext_depends/D-YAML/examples/getting_started/main.d
new file mode 100644
index 0000000..2cc242c
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/getting_started/main.d
@@ -0,0 +1,18 @@
+import std.stdio;
+import dyaml;
+
+void main()
+{
+ //Read the input.
+ Node root = Loader.fromFile("input.yaml").load();
+
+ //Display the data read.
+ foreach(string word; root["Hello World"])
+ {
+ writeln(word);
+ }
+ writeln("The answer is ", root["Answer"].as!int);
+
+ //Dump the loaded document to output.yaml.
+ dumper().dump(File("output.yaml", "w").lockingTextWriter, root);
+}
diff --git a/src/ext_depends/D-YAML/examples/representer/dub.json b/src/ext_depends/D-YAML/examples/representer/dub.json
new file mode 100644
index 0000000..c46c42f
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/representer/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "representer",
+ "targetType": "executable",
+ "sourceFiles": ["main.d"],
+ "mainSourceFile": "main.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/representer/main.d b/src/ext_depends/D-YAML/examples/representer/main.d
new file mode 100644
index 0000000..18ec4c5
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/representer/main.d
@@ -0,0 +1,43 @@
+import std.stdio;
+import dyaml;
+
+struct Color
+{
+ ubyte red;
+ ubyte green;
+ ubyte blue;
+
+ Node opCast(T: Node)() const
+ {
+ static immutable hex = "0123456789ABCDEF";
+
+ //Using the color format from the Constructor example.
+ string scalar;
+ foreach(channel; [red, green, blue])
+ {
+ scalar ~= hex[channel / 16];
+ scalar ~= hex[channel % 16];
+ }
+
+ //Representing as a scalar, with custom tag to specify this data type.
+ return Node(scalar, "!color");
+ }
+}
+
+void main()
+{
+ try
+ {
+ auto dumper = dumper();
+
+ auto document = Node([Color(255, 0, 0),
+ Color(0, 255, 0),
+ Color(0, 0, 255)]);
+
+ dumper.dump(File("output.yaml", "w").lockingTextWriter, document);
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/resolver/dub.json b/src/ext_depends/D-YAML/examples/resolver/dub.json
new file mode 100644
index 0000000..30b55d8
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/resolver/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "resolver",
+ "targetType": "executable",
+ "sourceFiles": ["main.d"],
+ "mainSourceFile": "main.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/resolver/input.yaml b/src/ext_depends/D-YAML/examples/resolver/input.yaml
new file mode 100644
index 0000000..99b9a5a
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/resolver/input.yaml
@@ -0,0 +1,8 @@
+scalar-red: FF0000
+scalar-orange: FFFF00
+mapping-red: !color-mapping {r: 255, g: 0, b: 0}
+mapping-orange:
+ !color-mapping
+ r: 255
+ g: 255
+ b: 0
diff --git a/src/ext_depends/D-YAML/examples/resolver/main.d b/src/ext_depends/D-YAML/examples/resolver/main.d
new file mode 100644
index 0000000..f3c08a1
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/resolver/main.d
@@ -0,0 +1,36 @@
+import std.regex;
+import std.stdio;
+import dyaml;
+
+int main(string[] args)
+{
+ string path = "input.yaml";
+ if (args.length > 1)
+ {
+ path = args[1];
+ }
+
+ try
+ {
+
+ auto loader = Loader.fromFile("input.yaml");
+ loader.resolver.addImplicitResolver("!color", regex("[0-9a-fA-F]{6}"),
+ "0123456789abcdefABCDEF");
+
+ auto root = loader.load();
+
+ if(root["scalar-red"].tag == "!color" &&
+ root["scalar-orange"].tag == "!color")
+ {
+ writeln("SUCCESS");
+ return 0;
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+
+ writeln("FAILURE");
+ return 1;
+}
diff --git a/src/ext_depends/D-YAML/examples/tojson/dub.json b/src/ext_depends/D-YAML/examples/tojson/dub.json
new file mode 100644
index 0000000..ba014b8
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/tojson/dub.json
@@ -0,0 +1,8 @@
+{
+ "name": "tojson",
+ "targetType": "executable",
+ "dependencies":
+ {
+ "dyaml": "*"
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/tojson/source/app.d b/src/ext_depends/D-YAML/examples/tojson/source/app.d
new file mode 100644
index 0000000..654274f
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/tojson/source/app.d
@@ -0,0 +1,54 @@
+module dyaml.tojson;
+import std.datetime;
+import std.json;
+import std.stdio;
+import dyaml;
+
+void main()
+{
+ auto doc = Loader.fromFile(stdin).load();
+ auto json = doc.toJSON;
+ writeln(json.toPrettyString);
+}
+
+JSONValue toJSON(Node node)
+{
+ JSONValue output;
+ final switch (node.type)
+ {
+ case NodeType.sequence:
+ output = JSONValue(string[].init);
+ foreach (Node seqNode; node)
+ {
+ output.array ~= seqNode.toJSON();
+ }
+ break;
+ case NodeType.mapping:
+ output = JSONValue(string[string].init);
+ foreach (Node keyNode, Node valueNode; node)
+ {
+ output[keyNode.as!string] = valueNode.toJSON();
+ }
+ break;
+ case NodeType.string:
+ output = node.as!string;
+ break;
+ case NodeType.integer:
+ output = node.as!long;
+ break;
+ case NodeType.decimal:
+ output = node.as!real;
+ break;
+ case NodeType.boolean:
+ output = node.as!bool;
+ break;
+ case NodeType.timestamp:
+ output = node.as!SysTime.toISOExtString();
+ break;
+ case NodeType.merge:
+ case NodeType.null_:
+ case NodeType.binary:
+ case NodeType.invalid:
+ }
+ return output;
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_bench/dub.json b/src/ext_depends/D-YAML/examples/yaml_bench/dub.json
new file mode 100644
index 0000000..b4e778f
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_bench/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "benchmark",
+ "targetType": "executable",
+ "sourceFiles": ["yaml_bench.d"],
+ "mainSourceFile": "yaml_bench.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_bench/yaml_bench.d b/src/ext_depends/D-YAML/examples/yaml_bench/yaml_bench.d
new file mode 100644
index 0000000..bb8446e
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_bench/yaml_bench.d
@@ -0,0 +1,179 @@
+
+module dyaml.yaml_bench;
+//Benchmark that loads, and optionally extracts data from and/or emits a YAML file.
+
+import std.algorithm;
+import std.conv;
+import std.datetime.systime;
+import std.datetime.stopwatch;
+import std.file;
+import std.getopt;
+import std.range;
+import std.stdio;
+import std.string;
+import dyaml;
+
+///Get data out of every node.
+void extract(ref Node document) @safe
+{
+ void crawl(ref Node root) @safe
+ {
+ final switch (root.nodeID)
+ {
+ case NodeID.scalar:
+ switch(root.tag)
+ {
+ case "tag:yaml.org,2002:null": auto value = root.as!YAMLNull; break;
+ case "tag:yaml.org,2002:bool": auto value = root.as!bool; break;
+ case "tag:yaml.org,2002:int": auto value = root.as!long; break;
+ case "tag:yaml.org,2002:float": auto value = root.as!real; break;
+ case "tag:yaml.org,2002:binary": auto value = root.as!(ubyte[]); break;
+ case "tag:yaml.org,2002:timestamp": auto value = root.as!SysTime; break;
+ case "tag:yaml.org,2002:str": auto value = root.as!string; break;
+ default: writeln("Unrecognozed tag: ", root.tag);
+ }
+ break;
+ case NodeID.sequence:
+ foreach(ref Node node; root)
+ {
+ crawl(node);
+ }
+ break;
+ case NodeID.mapping:
+ foreach(ref Node key, ref Node value; root)
+ {
+ crawl(key);
+ crawl(value);
+ }
+ break;
+ case NodeID.invalid:
+ assert(0);
+ }
+ }
+
+ crawl(document);
+}
+
+void main(string[] args) //@safe
+{
+ import std.array : array;
+ bool get = false;
+ bool dump = false;
+ bool reload = false;
+ bool quiet = false;
+ bool verbose = false;
+ bool scanOnly = false;
+ uint runs = 1;
+
+ auto help = getopt(
+ args,
+ "get|g", "Extract data from the file (using Node.as()).", &get,
+ "dump|d", "Dump the loaded data (to YAML_FILE.dump).", &dump,
+ "runs|r", "Repeat parsing the file NUM times.", &runs,
+ "reload", "Reload the file from the diskl on every repeat By default,"~
+ " the file is loaded to memory once and repeatedly parsed from memory.", &reload,
+ "quiet|q", "Don't print anything.", &quiet,
+ "verbose|v", "Print even more.", &verbose,
+ "scan-only|s", "Do not execute the entire parsing process, only scanning. Overrides '--dump'", &scanOnly
+ );
+
+ if (help.helpWanted || (args.length < 2))
+ {
+ defaultGetoptPrinter(
+ "D:YAML benchmark\n"~
+ "Copyright (C) 2011-2018 Ferdinand Majerech, Cameron \"Herringway\" Ross\n"~
+ "Usage: yaml_bench [OPTION ...] [YAML_FILE]\n\n"~
+ "Loads and optionally extracts data and/or dumps a YAML file.\n",
+ help.options
+ );
+ return;
+ }
+
+ string file = args[1];
+
+ auto stopWatch = StopWatch(AutoStart.yes);
+ void[] fileInMemory;
+ if(!reload) { fileInMemory = std.file.read(file); }
+ void[] fileWorkingCopy = fileInMemory.dup;
+ auto loadTime = stopWatch.peek();
+ stopWatch.reset();
+ try
+ {
+ // Instead of constructing a resolver/constructor with each Loader,
+ // construct them once to remove noise when profiling.
+ auto resolver = Resolver.withDefaultResolvers;
+
+ auto constructTime = stopWatch.peek();
+
+ Node[] nodes;
+
+ void runLoaderBenchmark() //@safe
+ {
+ // Loading the file rewrites the loaded buffer, so if we don't reload from
+ // disk, we need to use a copy of the originally loaded file.
+ if(reload) { fileInMemory = std.file.read(file); }
+ else { fileWorkingCopy[] = fileInMemory[]; }
+ void[] fileToLoad = reload ? fileInMemory : fileWorkingCopy;
+
+ auto loader = Loader.fromBuffer(fileToLoad);
+ if(scanOnly)
+ {
+ loader.scanBench();
+ return;
+ }
+
+ loader.resolver = resolver;
+ nodes = loader.array;
+ }
+ void runDumpBenchmark() @safe
+ {
+ if(dump)
+ {
+ dumper().dump(File(file ~ ".dump", "w").lockingTextWriter, nodes);
+ }
+ }
+ void runGetBenchmark() @safe
+ {
+ if(get) foreach(ref node; nodes)
+ {
+ extract(node);
+ }
+ }
+ auto totalTime = benchmark!(runLoaderBenchmark, runDumpBenchmark, runGetBenchmark)(runs);
+ if (!quiet)
+ {
+ auto enabledOptions =
+ only(
+ get ? "Get" : "",
+ dump ? "Dump" : "",
+ reload ? "Reload" : "",
+ scanOnly ? "Scan Only": ""
+ ).filter!(x => x != "");
+ if (!enabledOptions.empty)
+ {
+ writefln!"Options enabled: %-(%s, %)"(enabledOptions);
+ }
+ if (verbose)
+ {
+ if (!reload)
+ {
+ writeln("Time to load file: ", loadTime);
+ }
+ writeln("Time to set up resolver: ", constructTime);
+ }
+ writeln("Runs: ", runs);
+ foreach(time, func, enabled; lockstep(totalTime[], only("Loader", "Dumper", "Get"), only(true, dump, get)))
+ {
+ if (enabled)
+ {
+ writeln("Average time spent on ", func, ": ", time / runs);
+ writeln("Total time spent on ", func, ": ", time);
+ }
+ }
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln("ERROR: ", e.msg);
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_gen/config.yaml b/src/ext_depends/D-YAML/examples/yaml_gen/config.yaml
new file mode 100644
index 0000000..5484686
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_gen/config.yaml
@@ -0,0 +1,46 @@
+root-type: map
+documents: 2
+complex-keys: false
+collection-keys: false
+min-nodes-per-document: 4096
+encoding: utf-8
+indent: 4
+text-width: 40
+
+#Note: setting collection probabilities too high can lead to stack overflow as
+#we end up with extremely deeply nested structures
+
+string:
+ probability: 20
+ alphabet: " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_0123456789ábćčďéěǵǧȟíǐǰḱǩĺľḿńňóǒôäṕŕřśšť"
+ range: {min: 1, max: 40, dist: cubic}
+int:
+ probability: 10
+ range: {min: -10000000, max: 10000000, dist: linear}
+float:
+ probability: 10
+ range: {min: -10000000.0, max: 10000000.0, dist: linear}
+bool:
+ probability: 10
+timestamp:
+ probability: 10
+ round-chance: 0.9
+ range: {min: 0, max: 1231200000000000000, dist: linear}
+binary:
+ probability: 4
+ range: {min: 1, max: 400, dist: quadratic}
+map:
+ probability: 2
+ range: {min: 1, max: 20, dist: cubic}
+omap:
+ probability: 1
+ range: {min: 1, max: 20, dist: cubic}
+pairs:
+ probability: 1
+ range: {min: 1, max: 20, dist: cubic}
+seq:
+ probability: 2
+ range: {min: 1, max: 20, dist: cubic}
+set:
+ probability: 1
+ range: {min: 1, max: 20, dist: cubic}
diff --git a/src/ext_depends/D-YAML/examples/yaml_gen/dub.json b/src/ext_depends/D-YAML/examples/yaml_gen/dub.json
new file mode 100644
index 0000000..1f5a2d1
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_gen/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "yaml_gen",
+ "targetType": "executable",
+ "sourceFiles": ["yaml_gen.d"],
+ "mainSourceFile": "yaml_gen.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d b/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
new file mode 100644
index 0000000..b970c31
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
@@ -0,0 +1,316 @@
+
+///Random YAML generator. Used to generate benchmarking inputs.
+
+import std.algorithm;
+import std.conv;
+import std.datetime;
+import std.math;
+import std.random;
+import std.stdio;
+import std.string;
+import dyaml;
+
+
+Node config;
+Node function(bool)[string] generators;
+auto typesScalar = ["string", "int", "float", "bool", "timestamp", "binary"];
+auto typesScalarKey = ["string", "int", "float", "timestamp"];
+auto typesCollection = ["map","omap", "pairs", "seq", "set"];
+ulong minNodesDocument;
+ulong totalNodes;
+
+static this()
+{
+ generators["string"] = &genString;
+ generators["int"] = &genInt;
+ generators["float"] = &genFloat;
+ generators["bool"] = &genBool;
+ generators["timestamp"] = &genTimestamp;
+ generators["binary"] = &genBinary;
+ generators["map"] = &genMap;
+ generators["omap"] = &genOmap;
+ generators["pairs"] = &genPairs;
+ generators["seq"] = &genSeq;
+ generators["set"] = &genSet;
+}
+
+real randomNormalized(const string distribution = "linear")
+{
+ auto generator = Random(unpredictableSeed());
+ const r = uniform!"[]"(0.0L, 1.0L, generator);
+ switch(distribution)
+ {
+ case "linear":
+ return r;
+ case "quadratic":
+ return r * r;
+ case "cubic":
+ return r * r * r;
+ default:
+ writeln("Unknown random distribution: ", distribution,
+ ", falling back to linear");
+ return randomNormalized("linear");
+ }
+}
+
+long randomLong(const long min, const long max, const string distribution = "linear")
+{
+ return min + cast(long)round((max - min) * randomNormalized(distribution));
+}
+
+real randomReal(const real min, const real max, const string distribution = "linear")
+{
+ return min + (max - min) * randomNormalized(distribution);
+}
+
+dchar randomChar(const dstring chars)
+{
+ return chars[randomLong(0, chars.length - 1)];
+}
+
+string randomType(string[] types)
+{
+ auto probabilities = new uint[types.length];
+ foreach(index, type; types)
+ {
+ probabilities[index] = config[type]["probability"].as!uint;
+ }
+ return types[dice(probabilities)];
+}
+
+Node genString(bool root = false)
+{
+ auto range = config["string"]["range"];
+
+ auto alphabet = config["string"]["alphabet"].as!dstring;
+
+ const chars = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ dchar[] result = new dchar[chars];
+ result[0] = randomChar(alphabet);
+ foreach(i; 1 .. chars)
+ {
+ result[i] = randomChar(alphabet);
+ }
+
+ return Node(result.to!string);
+}
+
+Node genInt(bool root = false)
+{
+ auto range = config["int"]["range"];
+
+ const result = randomLong(range["min"].as!int, range["max"].as!int,
+ range["dist"].as!string);
+
+ return Node(result);
+}
+
+Node genFloat(bool root = false)
+{
+ auto range = config["float"]["range"];
+
+ const result = randomReal(range["min"].as!real, range["max"].as!real,
+ range["dist"].as!string);
+
+ return Node(result);
+}
+
+Node genBool(bool root = false)
+{
+ return Node([true, false][randomLong(0, 1)]);
+}
+
+Node genTimestamp(bool root = false)
+{
+ auto range = config["timestamp"]["range"];
+
+ auto hnsecs = randomLong(range["min"].as!ulong, range["max"].as!ulong,
+ range["dist"].as!string);
+
+ if(randomNormalized() <= config["timestamp"]["round-chance"].as!real)
+ {
+ hnsecs -= hnsecs % 10000000;
+ }
+
+ return Node(SysTime(hnsecs));
+}
+
+Node genBinary(bool root = false)
+{
+ auto range = config["binary"]["range"];
+
+ const bytes = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ ubyte[] result = new ubyte[bytes];
+ foreach(i; 0 .. bytes)
+ {
+ result[i] = cast(ubyte)randomLong(0, 255);
+ }
+
+ return Node(result);
+}
+
+Node nodes(const bool root, Node range, const string tag, const bool set = false)
+{
+ auto types = config["collection-keys"].as!bool ? typesCollection : [];
+ types ~= (set ? typesScalarKey : typesScalar);
+
+ Node[] nodes;
+ if(root)
+ {
+ while(!(totalNodes >= minNodesDocument))
+ {
+ nodes.assumeSafeAppend;
+ nodes ~= generateNode(randomType(types));
+ }
+ }
+ else
+ {
+ const elems = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ nodes = new Node[elems];
+ foreach(i; 0 .. elems)
+ {
+ nodes[i] = generateNode(randomType(types));
+ }
+ }
+
+ return Node(nodes, tag);
+}
+
+Node genSeq(bool root = false)
+{
+ return nodes(root, config["seq"]["range"], "tag:yaml.org,2002:seq");
+}
+
+Node genSet(bool root = false)
+{
+ return nodes(root, config["seq"]["range"], "tag:yaml.org,2002:set", true);
+}
+
+Node pairs(bool root, bool complex, Node range, string tag)
+{
+ Node[] keys, values;
+
+ if(root)
+ {
+ while(!(totalNodes >= minNodesDocument))
+ {
+ const key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ // Maps can't contain duplicate keys
+ if(tag.endsWith("map") && keys.canFind(key)) { continue; }
+ keys.assumeSafeAppend;
+ values.assumeSafeAppend;
+ keys ~= key;
+ values ~= generateNode(randomType(typesScalar ~ typesCollection));
+ }
+ }
+ else
+ {
+ const pairs = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ keys = new Node[pairs];
+ values = new Node[pairs];
+ outer: foreach(i; 0 .. pairs)
+ {
+ auto key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ // Maps can't contain duplicate keys
+ while(tag.endsWith("map") && keys[0 .. i].canFind(key))
+ {
+ key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ }
+ keys[i] = key;
+ values[i] = generateNode(randomType(typesScalar ~ typesCollection));
+ }
+ }
+
+ return Node(keys, values, tag);
+}
+
+Node genMap(bool root = false)
+{
+ Node range = config["map"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:map");
+}
+
+Node genOmap(bool root = false)
+{
+ Node range = config["omap"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:omap");
+}
+
+Node genPairs(bool root = false)
+{
+ Node range = config["pairs"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:pairs");
+}
+
+Node generateNode(const string type, bool root = false)
+{
+ ++totalNodes;
+ return generators[type](root);
+}
+
+Node[] generate(const string configFileName)
+{
+ config = Loader.fromFile(configFileName).load();
+
+ minNodesDocument = config["min-nodes-per-document"].as!long;
+
+ Node[] result;
+ foreach(i; 0 .. config["documents"].as!uint)
+ {
+ result ~= generateNode(config["root-type"].as!string, true);
+ totalNodes = 0;
+ }
+
+ return result;
+}
+
+
+void main(string[] args)
+{
+ //Help message.
+ if(args.length == 1)
+ {
+ writeln("Usage: yaml_gen FILE [CONFIG_FILE]\n");
+ writeln("Generates a random YAML file and writes it to FILE.");
+ writeln("If provided, CONFIG_FILE overrides the default config file.");
+ return;
+ }
+
+ string configFile = args.length >= 3 ? args[2] : "config.yaml";
+
+ try
+ {
+ //Generate and dump the nodes.
+ Node[] generated = generate(configFile);
+
+ auto dumper = dumper();
+ auto encoding = config["encoding"];
+
+ dumper.indent = config["indent"].as!uint;
+ dumper.textWidth = config["text-width"].as!uint;
+ switch(encoding.as!string)
+ {
+ case "utf-16": dumper.dump!wchar(File(args[1], "w").lockingTextWriter, generated); break;
+ case "utf-32": dumper.dump!dchar(File(args[1], "w").lockingTextWriter, generated); break;
+ default: dumper.dump!char(File(args[1], "w").lockingTextWriter, generated); break;
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln("ERROR: ", e.msg);
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_stats/dub.json b/src/ext_depends/D-YAML/examples/yaml_stats/dub.json
new file mode 100644
index 0000000..c86f091
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_stats/dub.json
@@ -0,0 +1,10 @@
+{
+ "name": "yaml_stats",
+ "targetType": "executable",
+ "sourceFiles": ["yaml_stats.d"],
+ "mainSourceFile": "yaml_stats.d",
+ "dependencies":
+ {
+ "dyaml": { "version" : "*" }
+ }
+}
diff --git a/src/ext_depends/D-YAML/examples/yaml_stats/small.yaml b/src/ext_depends/D-YAML/examples/yaml_stats/small.yaml
new file mode 100644
index 0000000..4f5c0ea
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_stats/small.yaml
@@ -0,0 +1,4 @@
+- 1
+- 2 : 'a'
+ 3 : 'b'
+- 4 : [1.0, 2.1, 3.2]
diff --git a/src/ext_depends/D-YAML/examples/yaml_stats/yaml_stats.d b/src/ext_depends/D-YAML/examples/yaml_stats/yaml_stats.d
new file mode 100644
index 0000000..b3f6c17
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_stats/yaml_stats.d
@@ -0,0 +1,106 @@
+
+///Example D:YAML application that displays statistics about YAML documents.
+
+import std.stdio;
+import std.string;
+import dyaml;
+
+
+///Collects statistics about a YAML document and returns them as string.
+string statistics(ref Node document)
+{
+ size_t nodes;
+ size_t scalars, sequences, mappings;
+ size_t seqItems, mapPairs;
+
+ size_t[string] tags;
+
+ void crawl(ref Node root)
+ {
+ ++nodes;
+ if((root.tag in tags) is null)
+ {
+ tags[root.tag] = 0;
+ }
+ ++tags[root.tag];
+ final switch (root.nodeID)
+ {
+ case NodeID.scalar:
+ ++scalars;
+ return;
+ case NodeID.sequence:
+ ++sequences;
+ seqItems += root.length;
+ foreach(ref Node node; root)
+ {
+ crawl(node);
+ }
+ return;
+ case NodeID.mapping:
+ ++mappings;
+ mapPairs += root.length;
+ foreach(ref Node key, ref Node value; root)
+ {
+ crawl(key);
+ crawl(value);
+ }
+ return;
+ case NodeID.invalid:
+ assert(0);
+ }
+ }
+
+ crawl(document);
+
+ string tagStats = "\nTag statistics:\n";
+ foreach(tag, count; tags)
+ {
+ tagStats ~= format("\n%s : %s", tag, count);
+ }
+
+ return format( "\nNodes: %s" ~
+ "\n\nScalars: %s" ~
+ "\nSequences: %s" ~
+ "\nMappings: %s" ~
+ "\n\nAverage sequence length: %s" ~
+ "\nAverage mapping length: %s" ~
+ "\n\n%s",
+ nodes, scalars, sequences, mappings,
+ sequences == 0.0 ? 0.0 : cast(real)seqItems / sequences,
+ mappings == 0.0 ? 0.0 : cast(real)mapPairs / mappings,
+ tagStats);
+}
+
+void main(string[] args)
+{
+ //Help message
+ if(args.length == 1)
+ {
+ writeln("Usage: yaml_stats [YAML_FILE ...]\n");
+ writeln("Analyzes YAML files with provided filenames and displays statistics.");
+ return;
+ }
+
+ //Print stats about every document in every file.
+ foreach(file; args[1 .. $])
+ {
+ writeln("\nFile ", file);
+ writeln("------------------------------------------------------------");
+ try
+ {
+ auto loader = Loader.fromFile(file);
+
+ size_t idx = 0;
+ foreach(ref document; loader)
+ {
+ writeln("\nDocument ", idx++);
+ writeln("----------------------------------------");
+ writeln(statistics(document));
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln("ERROR: ", e.msg);
+ }
+ }
+}
diff --git a/src/ext_depends/D-YAML/hmod.cfg b/src/ext_depends/D-YAML/hmod.cfg
new file mode 100644
index 0000000..41badb2
--- /dev/null
+++ b/src/ext_depends/D-YAML/hmod.cfg
@@ -0,0 +1,123 @@
+
+# This file contains configuration options for harbored-mod (hmod).
+#
+# By default, hmod loads configuration from file 'hmod.cfg' in the directory from where
+# hmod is running, if such file exists. These configuration options can also be passed
+# as command-line options for hmod, overriding contents of the config file, if any,
+# with the exception of options that allow multiple values (such as 'exclude' or
+# 'macros') where the values specified as command-line options are *added* to the values
+# in config file.
+
+
+
+# Source code files or directories to document. Specify more than once to document more
+# files/directories, e.g:
+#
+# sources = ./sources
+# sources = ./thirdparty
+#
+# This will document both the source code in the ./source/ and ./thirdparty/ directories.
+#
+# For DUB (http://code.dlang.org) projects, './sources' is usually a good setting here.
+source = ./source/dyaml
+
+
+# Directory where the generated documentation will be written.
+output-directory = ./doc/html/api
+
+
+# Modules or packages to exclude from generated documentation. Specify more than once to
+# exclude more modules/packages, e.g:
+#
+# exclude = tharsis.util
+# exclude = tharsis.entity.gamestate
+#
+# This will exclude both the package (or module) tharsis.util and module (or package)
+# tharsis.entity.gamestate .
+
+exclude = dyaml.all
+exclude = dyaml.anchor
+exclude = dyaml.composer
+exclude = dyaml.emitter
+exclude = dyaml.encoding
+exclude = dyaml.escapes
+exclude = dyaml.event
+exclude = dyaml.fastcharsearch
+exclude = dyaml.flags
+exclude = dyaml.nogcutil
+exclude = dyaml.parser
+exclude = dyaml.queue
+exclude = dyaml.reader
+exclude = dyaml.scanner
+exclude = dyaml.serializer
+exclude = dyaml.streamcompat
+exclude = dyaml.tag
+exclude = dyaml.tagdirective
+exclude = dyaml.testcommon
+exclude = dyaml.testcompare
+exclude = dyaml.testconstructor
+exclude = dyaml.testemitter
+exclude = dyaml.testerrors
+exclude = dyaml.testinputoutput
+exclude = dyaml.testreader
+exclude = dyaml.testrepresenter
+exclude = dyaml.testresolver
+exclude = dyaml.testtokens
+exclude = dyaml.token
+exclude = dyaml.unused
+exclude = dyaml.zerostring
+
+# DDoc+markdown source of the main page of your documentation. Currently the main page is
+# blank by default; this can be used to fill it with something useful.
+
+index =
+
+
+# DDoc+markdown source of additional content to add to the table of contents sidebar.
+# Useful e.g. to add links to tutorials.
+
+toc-additional =
+
+
+# CSS file to use for styling. Can be used to replace the default style.
+# To create a new style, you can start by generating the default style file with
+# 'hmod --generate-css CSS_OUT_FILE' (CSS_OUT_FILE is name the generated file will have)
+# and then modifying the CSS to get the desired style.
+
+css =
+
+
+# File to load DDoc macros from. Can be used to override builtin macros or add new ones.
+# Can be specified more than once to use multiple macro files, e.g.:
+#
+# macros = macros.ddoc
+# macros = moremacros.ddoc
+
+
+macros =
+
+# Additional config file to load, if needed. Configuration options in specified file will
+# override or add to any options specified before this line, and will be overridden by
+# any options after this line. Think of it as including the config file in this file.
+
+config =
+
+
+
+#---------------------------------------------------------------------------
+# Configuration options **only** useful for harbored-mod testing
+#---------------------------------------------------------------------------
+# Uncommenting these will result in printing help information; only useful for testing.
+#
+# # Print help message.
+#
+# help
+#
+#
+# # Generate default CSS file and write it to specified file.
+# generate-css = hmod-style.css
+#
+#
+# # Generate default config file and write it to 'hmod.cfg'.
+#
+# generate-cfg
diff --git a/src/ext_depends/D-YAML/meson.build b/src/ext_depends/D-YAML/meson.build
new file mode 100644
index 0000000..68d17c7
--- /dev/null
+++ b/src/ext_depends/D-YAML/meson.build
@@ -0,0 +1,70 @@
+project('D-YAML', 'd',
+ meson_version: '>=0.40.0',
+ subproject_dir: 'contrib',
+ version: '0.8.0'
+)
+
+project_soversion = '0'
+
+src_dir = include_directories('source/')
+pkgc = import('pkgconfig')
+
+dyaml_src = [
+ 'source/dyaml/composer.d',
+ 'source/dyaml/constructor.d',
+ 'source/dyaml/dumper.d',
+ 'source/dyaml/emitter.d',
+ 'source/dyaml/encoding.d',
+ 'source/dyaml/escapes.d',
+ 'source/dyaml/event.d',
+ 'source/dyaml/exception.d',
+ 'source/dyaml/linebreak.d',
+ 'source/dyaml/loader.d',
+ 'source/dyaml/node.d',
+ 'source/dyaml/package.d',
+ 'source/dyaml/parser.d',
+ 'source/dyaml/queue.d',
+ 'source/dyaml/reader.d',
+ 'source/dyaml/representer.d',
+ 'source/dyaml/resolver.d',
+ 'source/dyaml/scanner.d',
+ 'source/dyaml/serializer.d',
+ 'source/dyaml/style.d',
+ 'source/dyaml/tagdirective.d',
+ 'source/dyaml/test/common.d',
+ 'source/dyaml/test/compare.d',
+ 'source/dyaml/test/constructor.d',
+ 'source/dyaml/test/emitter.d',
+ 'source/dyaml/test/errors.d',
+ 'source/dyaml/test/inputoutput.d',
+ 'source/dyaml/test/reader.d',
+ 'source/dyaml/test/representer.d',
+ 'source/dyaml/test/resolver.d',
+ 'source/dyaml/test/tokens.d',
+ 'source/dyaml/token.d'
+]
+install_subdir('source/dyaml', install_dir: 'include/d/yaml/')
+
+tinyendian_dep = dependency('tinyendian', version: '>=0.2.0', fallback: ['tinyendian', 'tinyendian_dep'])
+
+dyaml_lib = library('dyaml',
+ [dyaml_src],
+ include_directories: [src_dir],
+ dependencies: [tinyendian_dep],
+ install: true,
+ version: meson.project_version(),
+ soversion: project_soversion
+)
+pkgc.generate(name: 'dyaml',
+ libraries: dyaml_lib,
+ subdirs: 'd/yaml/',
+ version: meson.project_version(),
+ description: 'YAML parser and emitter for the D programming language.'
+)
+
+# Make D-YAML easy to use as subproject
+dyaml_dep = declare_dependency(
+ link_with: dyaml_lib,
+ include_directories: [src_dir],
+ dependencies: [tinyendian_dep]
+)
diff --git a/src/ext_depends/D-YAML/source/dyaml/composer.d b/src/ext_depends/D-YAML/source/dyaml/composer.d
new file mode 100644
index 0000000..c000b02
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/composer.d
@@ -0,0 +1,375 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * Composes nodes from YAML events provided by parser.
+ * Code based on PyYAML: http://www.pyyaml.org
+ */
+module dyaml.composer;
+
+import core.memory;
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.exception;
+import std.range;
+import std.typecons;
+
+import dyaml.constructor;
+import dyaml.event;
+import dyaml.exception;
+import dyaml.node;
+import dyaml.parser;
+import dyaml.resolver;
+
+
+package:
+/**
+ * Exception thrown at composer errors.
+ *
+ * See_Also: MarkedYAMLException
+ */
+class ComposerException : MarkedYAMLException
+{
+ mixin MarkedExceptionCtors;
+}
+
+///Composes YAML documents from events provided by a Parser.
+struct Composer
+{
+ private:
+ ///Parser providing YAML events.
+ Parser parser_;
+ ///Resolver resolving tags (data types).
+ Resolver resolver_;
+ ///Nodes associated with anchors. Used by YAML aliases.
+ Node[string] anchors_;
+
+ ///Used to reduce allocations when creating pair arrays.
+ ///
+ ///We need one appender for each nesting level that involves
+ ///a pair array, as the inner levels are processed as a
+ ///part of the outer levels. Used as a stack.
+ Appender!(Node.Pair[])[] pairAppenders_;
+ ///Used to reduce allocations when creating node arrays.
+ ///
+ ///We need one appender for each nesting level that involves
+ ///a node array, as the inner levels are processed as a
+ ///part of the outer levels. Used as a stack.
+ Appender!(Node[])[] nodeAppenders_;
+
+ public:
+ /**
+ * Construct a composer.
+ *
+ * Params: parser = Parser to provide YAML events.
+ * resolver = Resolver to resolve tags (data types).
+ */
+ this(Parser parser, Resolver resolver) @safe
+ {
+ parser_ = parser;
+ resolver_ = resolver;
+ }
+
+ /**
+ * Determine if there are any nodes left.
+ *
+ * Must be called before loading as it handles the stream start event.
+ */
+ bool checkNode() @safe
+ {
+ // If next event is stream start, skip it
+ parser_.skipOver!"a.id == b"(EventID.streamStart);
+
+ //True if there are more documents available.
+ return parser_.front.id != EventID.streamEnd;
+ }
+
+ ///Get a YAML document as a node (the root of the document).
+ Node getNode() @safe
+ {
+ //Get the root node of the next document.
+ assert(parser_.front.id != EventID.streamEnd,
+ "Trying to get a node from Composer when there is no node to " ~
+ "get. use checkNode() to determine if there is a node.");
+
+ return composeDocument();
+ }
+
+ private:
+
+ void skipExpected(const EventID id) @safe
+ {
+ const foundExpected = parser_.skipOver!"a.id == b"(id);
+ assert(foundExpected, text("Expected ", id, " not found."));
+ }
+ ///Ensure that appenders for specified nesting levels exist.
+ ///
+ ///Params: pairAppenderLevel = Current level in the pair appender stack.
+ /// nodeAppenderLevel = Current level the node appender stack.
+ void ensureAppendersExist(const uint pairAppenderLevel, const uint nodeAppenderLevel)
+ @safe
+ {
+ while(pairAppenders_.length <= pairAppenderLevel)
+ {
+ pairAppenders_ ~= appender!(Node.Pair[])();
+ }
+ while(nodeAppenders_.length <= nodeAppenderLevel)
+ {
+ nodeAppenders_ ~= appender!(Node[])();
+ }
+ }
+
+ ///Compose a YAML document and return its root node.
+ Node composeDocument() @safe
+ {
+ skipExpected(EventID.documentStart);
+
+ //Compose the root node.
+ Node node = composeNode(0, 0);
+
+ skipExpected(EventID.documentEnd);
+
+ anchors_.destroy();
+ return node;
+ }
+
+ /// Compose a node.
+ ///
+ /// Params: pairAppenderLevel = Current level of the pair appender stack.
+ /// nodeAppenderLevel = Current level of the node appender stack.
+ Node composeNode(const uint pairAppenderLevel, const uint nodeAppenderLevel) @safe
+ {
+ if(parser_.front.id == EventID.alias_)
+ {
+ const event = parser_.front;
+ parser_.popFront();
+ const anchor = event.anchor;
+ enforce((anchor in anchors_) !is null,
+ new ComposerException("Found undefined alias: " ~ anchor,
+ event.startMark));
+
+ //If the node referenced by the anchor is uninitialized,
+ //it's not finished, i.e. we're currently composing it
+ //and trying to use it recursively here.
+ enforce(anchors_[anchor] != Node(),
+ new ComposerException("Found recursive alias: " ~ anchor,
+ event.startMark));
+
+ return anchors_[anchor];
+ }
+
+ const event = parser_.front;
+ const anchor = event.anchor;
+ if((anchor !is null) && (anchor in anchors_) !is null)
+ {
+ throw new ComposerException("Found duplicate anchor: " ~ anchor,
+ event.startMark);
+ }
+
+ Node result;
+ //Associate the anchor, if any, with an uninitialized node.
+ //used to detect duplicate and recursive anchors.
+ if(anchor !is null)
+ {
+ anchors_[anchor] = Node();
+ }
+
+ switch (parser_.front.id)
+ {
+ case EventID.scalar:
+ result = composeScalarNode();
+ break;
+ case EventID.sequenceStart:
+ result = composeSequenceNode(pairAppenderLevel, nodeAppenderLevel);
+ break;
+ case EventID.mappingStart:
+ result = composeMappingNode(pairAppenderLevel, nodeAppenderLevel);
+ break;
+ default: assert(false, "This code should never be reached");
+ }
+
+ if(anchor !is null)
+ {
+ anchors_[anchor] = result;
+ }
+ return result;
+ }
+
+ ///Compose a scalar node.
+ Node composeScalarNode() @safe
+ {
+ const event = parser_.front;
+ parser_.popFront();
+ const tag = resolver_.resolve(NodeID.scalar, event.tag, event.value,
+ event.implicit);
+
+ Node node = constructNode(event.startMark, event.endMark, tag,
+ event.value);
+ node.scalarStyle = event.scalarStyle;
+
+ return node;
+ }
+
+ /// Compose a sequence node.
+ ///
+ /// Params: pairAppenderLevel = Current level of the pair appender stack.
+ /// nodeAppenderLevel = Current level of the node appender stack.
+ Node composeSequenceNode(const uint pairAppenderLevel, const uint nodeAppenderLevel)
+ @safe
+ {
+ ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel);
+ auto nodeAppender = &(nodeAppenders_[nodeAppenderLevel]);
+
+ const startEvent = parser_.front;
+ parser_.popFront();
+ const tag = resolver_.resolve(NodeID.sequence, startEvent.tag, null,
+ startEvent.implicit);
+
+ while(parser_.front.id != EventID.sequenceEnd)
+ {
+ nodeAppender.put(composeNode(pairAppenderLevel, nodeAppenderLevel + 1));
+ }
+
+ Node node = constructNode(startEvent.startMark, parser_.front.endMark,
+ tag, nodeAppender.data.dup);
+ node.collectionStyle = startEvent.collectionStyle;
+ parser_.popFront();
+ nodeAppender.clear();
+
+ return node;
+ }
+
+ /**
+ * Flatten a node, merging it with nodes referenced through YAMLMerge data type.
+ *
+ * Node must be a mapping or a sequence of mappings.
+ *
+ * Params: root = Node to flatten.
+ * startMark = Start position of the node.
+ * endMark = End position of the node.
+ * pairAppenderLevel = Current level of the pair appender stack.
+ * nodeAppenderLevel = Current level of the node appender stack.
+ *
+ * Returns: Flattened mapping as pairs.
+ */
+ Node.Pair[] flatten(ref Node root, const Mark startMark, const Mark endMark,
+ const uint pairAppenderLevel, const uint nodeAppenderLevel) @safe
+ {
+ void error(Node node)
+ {
+ //this is Composer, but the code is related to Constructor.
+ throw new ConstructorException("While constructing a mapping, " ~
+ "expected a mapping or a list of " ~
+ "mappings for merging, but found: " ~
+ text(node.type) ~
+ " NOTE: line/column shows topmost parent " ~
+ "to which the content is being merged",
+ startMark, endMark);
+ }
+
+ ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel);
+ auto pairAppender = &(pairAppenders_[pairAppenderLevel]);
+
+ final switch (root.nodeID)
+ {
+ case NodeID.mapping:
+ Node[] toMerge;
+ toMerge.reserve(root.length);
+ foreach (ref Node key, ref Node value; root)
+ {
+ if(key.type == NodeType.merge)
+ {
+ toMerge ~= value;
+ }
+ else
+ {
+ auto temp = Node.Pair(key, value);
+ pairAppender.put(temp);
+ }
+ }
+ foreach (node; toMerge)
+ {
+ pairAppender.put(flatten(node, startMark, endMark,
+ pairAppenderLevel + 1, nodeAppenderLevel));
+ }
+ break;
+ case NodeID.sequence:
+ foreach (ref Node node; root)
+ {
+ if (node.nodeID != NodeID.mapping)
+ {
+ error(node);
+ }
+ pairAppender.put(flatten(node, startMark, endMark,
+ pairAppenderLevel + 1, nodeAppenderLevel));
+ }
+ break;
+ case NodeID.scalar:
+ case NodeID.invalid:
+ error(root);
+ break;
+ }
+
+ auto flattened = pairAppender.data.dup;
+ pairAppender.clear();
+
+ return flattened;
+ }
+
+ /// Compose a mapping node.
+ ///
+ /// Params: pairAppenderLevel = Current level of the pair appender stack.
+ /// nodeAppenderLevel = Current level of the node appender stack.
+ Node composeMappingNode(const uint pairAppenderLevel, const uint nodeAppenderLevel)
+ @safe
+ {
+ ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel);
+ const startEvent = parser_.front;
+ parser_.popFront();
+ const tag = resolver_.resolve(NodeID.mapping, startEvent.tag, null,
+ startEvent.implicit);
+ auto pairAppender = &(pairAppenders_[pairAppenderLevel]);
+
+ Tuple!(Node, Mark)[] toMerge;
+ while(parser_.front.id != EventID.mappingEnd)
+ {
+ auto pair = Node.Pair(composeNode(pairAppenderLevel + 1, nodeAppenderLevel),
+ composeNode(pairAppenderLevel + 1, nodeAppenderLevel));
+
+ //Need to flatten and merge the node referred by YAMLMerge.
+ if(pair.key.type == NodeType.merge)
+ {
+ toMerge ~= tuple(pair.value, cast(Mark)parser_.front.endMark);
+ }
+ //Not YAMLMerge, just add the pair.
+ else
+ {
+ pairAppender.put(pair);
+ }
+ }
+ foreach(node; toMerge)
+ {
+ merge(*pairAppender, flatten(node[0], startEvent.startMark, node[1],
+ pairAppenderLevel + 1, nodeAppenderLevel));
+ }
+ auto numUnique = pairAppender.data.dup
+ .sort!((x,y) => x.key > y.key)
+ .uniq!((x,y) => x.key == y.key)
+ .walkLength;
+ enforce(numUnique == pairAppender.data.length,
+ new ComposerException("Duplicate key found in mapping", parser_.front.startMark));
+
+ Node node = constructNode(startEvent.startMark, parser_.front.endMark,
+ tag, pairAppender.data.dup);
+ node.collectionStyle = startEvent.collectionStyle;
+ parser_.popFront();
+
+ pairAppender.clear();
+ return node;
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/constructor.d b/src/ext_depends/D-YAML/source/dyaml/constructor.d
new file mode 100644
index 0000000..bc1d75c
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/constructor.d
@@ -0,0 +1,611 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * Class that processes YAML mappings, sequences and scalars into nodes.
+ * This can be used to add custom data types. A tutorial can be found
+ * $(LINK2 https://dlang-community.github.io/D-YAML/, here).
+ */
+module dyaml.constructor;
+
+
+import std.array;
+import std.algorithm;
+import std.base64;
+import std.container;
+import std.conv;
+import std.datetime;
+import std.exception;
+import std.regex;
+import std.string;
+import std.typecons;
+import std.utf;
+
+import dyaml.node;
+import dyaml.exception;
+import dyaml.style;
+
+package:
+
+// Exception thrown at constructor errors.
+class ConstructorException : YAMLException
+{
+ /// Construct a ConstructorException.
+ ///
+ /// Params: msg = Error message.
+ /// start = Start position of the error context.
+ /// end = End position of the error context.
+ this(string msg, Mark start, Mark end, string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(msg ~ "\nstart: " ~ start.toString() ~ "\nend: " ~ end.toString(),
+ file, line);
+ }
+}
+
+/** Constructs YAML values.
+ *
+ * Each YAML scalar, sequence or mapping has a tag specifying its data type.
+ * Constructor uses user-specifyable functions to create a node of desired
+ * data type from a scalar, sequence or mapping.
+ *
+ *
+ * Each of these functions is associated with a tag, and can process either
+ * a scalar, a sequence, or a mapping. The constructor passes each value to
+ * the function with corresponding tag, which then returns the resulting value
+ * that can be stored in a node.
+ *
+ * If a tag is detected with no known constructor function, it is considered an error.
+ */
+/*
+ * Construct a node.
+ *
+ * Params: start = Start position of the node.
+ * end = End position of the node.
+ * tag = Tag (data type) of the node.
+ * value = Value to construct node from (string, nodes or pairs).
+ * style = Style of the node (scalar or collection style).
+ *
+ * Returns: Constructed node.
+ */
+Node constructNode(T)(const Mark start, const Mark end, const string tag,
+ T value) @safe
+ if((is(T : string) || is(T == Node[]) || is(T == Node.Pair[])))
+{
+ Node newNode;
+ try
+ {
+ switch(tag)
+ {
+ case "tag:yaml.org,2002:null":
+ newNode = Node(YAMLNull(), tag);
+ break;
+ case "tag:yaml.org,2002:bool":
+ static if(is(T == string))
+ {
+ newNode = Node(constructBool(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be bools");
+ case "tag:yaml.org,2002:int":
+ static if(is(T == string))
+ {
+ newNode = Node(constructLong(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be ints");
+ case "tag:yaml.org,2002:float":
+ static if(is(T == string))
+ {
+ newNode = Node(constructReal(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be floats");
+ case "tag:yaml.org,2002:binary":
+ static if(is(T == string))
+ {
+ newNode = Node(constructBinary(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be binary data");
+ case "tag:yaml.org,2002:timestamp":
+ static if(is(T == string))
+ {
+ newNode = Node(constructTimestamp(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be timestamps");
+ case "tag:yaml.org,2002:str":
+ static if(is(T == string))
+ {
+ newNode = Node(constructString(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be strings");
+ case "tag:yaml.org,2002:value":
+ static if(is(T == string))
+ {
+ newNode = Node(constructString(value), tag);
+ break;
+ }
+ else throw new Exception("Only scalars can be values");
+ case "tag:yaml.org,2002:omap":
+ static if(is(T == Node[]))
+ {
+ newNode = Node(constructOrderedMap(value), tag);
+ break;
+ }
+ else throw new Exception("Only sequences can be ordered maps");
+ case "tag:yaml.org,2002:pairs":
+ static if(is(T == Node[]))
+ {
+ newNode = Node(constructPairs(value), tag);
+ break;
+ }
+ else throw new Exception("Only sequences can be pairs");
+ case "tag:yaml.org,2002:set":
+ static if(is(T == Node.Pair[]))
+ {
+ newNode = Node(constructSet(value), tag);
+ break;
+ }
+ else throw new Exception("Only mappings can be sets");
+ case "tag:yaml.org,2002:seq":
+ static if(is(T == Node[]))
+ {
+ newNode = Node(constructSequence(value), tag);
+ break;
+ }
+ else throw new Exception("Only sequences can be sequences");
+ case "tag:yaml.org,2002:map":
+ static if(is(T == Node.Pair[]))
+ {
+ newNode = Node(constructMap(value), tag);
+ break;
+ }
+ else throw new Exception("Only mappings can be maps");
+ case "tag:yaml.org,2002:merge":
+ newNode = Node(YAMLMerge(), tag);
+ break;
+ default:
+ newNode = Node(value, tag);
+ break;
+ }
+ }
+ catch(Exception e)
+ {
+ throw new ConstructorException("Error constructing " ~ typeid(T).toString()
+ ~ ":\n" ~ e.msg, start, end);
+ }
+
+ newNode.startMark_ = start;
+
+ return newNode;
+}
+
+private:
+// Construct a boolean _node.
+bool constructBool(const string str) @safe
+{
+ string value = str.toLower();
+ if(value.among!("yes", "true", "on")){return true;}
+ if(value.among!("no", "false", "off")){return false;}
+ throw new Exception("Unable to parse boolean value: " ~ value);
+}
+
+// Construct an integer (long) _node.
+long constructLong(const string str) @safe
+{
+ string value = str.replace("_", "");
+ const char c = value[0];
+ const long sign = c != '-' ? 1 : -1;
+ if(c == '-' || c == '+')
+ {
+ value = value[1 .. $];
+ }
+
+ enforce(value != "", new Exception("Unable to parse float value: " ~ value));
+
+ long result;
+ try
+ {
+ //Zero.
+ if(value == "0") {result = cast(long)0;}
+ //Binary.
+ else if(value.startsWith("0b")){result = sign * to!int(value[2 .. $], 2);}
+ //Hexadecimal.
+ else if(value.startsWith("0x")){result = sign * to!int(value[2 .. $], 16);}
+ //Octal.
+ else if(value[0] == '0') {result = sign * to!int(value, 8);}
+ //Sexagesimal.
+ else if(value.canFind(":"))
+ {
+ long val;
+ long base = 1;
+ foreach_reverse(digit; value.split(":"))
+ {
+ val += to!long(digit) * base;
+ base *= 60;
+ }
+ result = sign * val;
+ }
+ //Decimal.
+ else{result = sign * to!long(value);}
+ }
+ catch(ConvException e)
+ {
+ throw new Exception("Unable to parse integer value: " ~ value);
+ }
+
+ return result;
+}
+@safe unittest
+{
+ string canonical = "685230";
+ string decimal = "+685_230";
+ string octal = "02472256";
+ string hexadecimal = "0x_0A_74_AE";
+ string binary = "0b1010_0111_0100_1010_1110";
+ string sexagesimal = "190:20:30";
+
+ assert(685230 == constructLong(canonical));
+ assert(685230 == constructLong(decimal));
+ assert(685230 == constructLong(octal));
+ assert(685230 == constructLong(hexadecimal));
+ assert(685230 == constructLong(binary));
+ assert(685230 == constructLong(sexagesimal));
+}
+
+// Construct a floating point (real) _node.
+real constructReal(const string str) @safe
+{
+ string value = str.replace("_", "").toLower();
+ const char c = value[0];
+ const real sign = c != '-' ? 1.0 : -1.0;
+ if(c == '-' || c == '+')
+ {
+ value = value[1 .. $];
+ }
+
+ enforce(value != "" && value != "nan" && value != "inf" && value != "-inf",
+ new Exception("Unable to parse float value: " ~ value));
+
+ real result;
+ try
+ {
+ //Infinity.
+ if (value == ".inf"){result = sign * real.infinity;}
+ //Not a Number.
+ else if(value == ".nan"){result = real.nan;}
+ //Sexagesimal.
+ else if(value.canFind(":"))
+ {
+ real val = 0.0;
+ real base = 1.0;
+ foreach_reverse(digit; value.split(":"))
+ {
+ val += to!real(digit) * base;
+ base *= 60.0;
+ }
+ result = sign * val;
+ }
+ //Plain floating point.
+ else{result = sign * to!real(value);}
+ }
+ catch(ConvException e)
+ {
+ throw new Exception("Unable to parse float value: \"" ~ value ~ "\"");
+ }
+
+ return result;
+}
+@safe unittest
+{
+ bool eq(real a, real b, real epsilon = 0.2) @safe
+ {
+ return a >= (b - epsilon) && a <= (b + epsilon);
+ }
+
+ string canonical = "6.8523015e+5";
+ string exponential = "685.230_15e+03";
+ string fixed = "685_230.15";
+ string sexagesimal = "190:20:30.15";
+ string negativeInf = "-.inf";
+ string NaN = ".NaN";
+
+ assert(eq(685230.15, constructReal(canonical)));
+ assert(eq(685230.15, constructReal(exponential)));
+ assert(eq(685230.15, constructReal(fixed)));
+ assert(eq(685230.15, constructReal(sexagesimal)));
+ assert(eq(-real.infinity, constructReal(negativeInf)));
+ assert(to!string(constructReal(NaN)) == "nan");
+}
+
+// Construct a binary (base64) _node.
+ubyte[] constructBinary(const string value) @safe
+{
+ import std.ascii : newline;
+ import std.array : array;
+
+ // For an unknown reason, this must be nested to work (compiler bug?).
+ try
+ {
+ return Base64.decode(value.representation.filter!(c => !newline.canFind(c)).array);
+ }
+ catch(Base64Exception e)
+ {
+ throw new Exception("Unable to decode base64 value: " ~ e.msg);
+ }
+}
+
+@safe unittest
+{
+ auto test = "The Answer: 42".representation;
+ char[] buffer;
+ buffer.length = 256;
+ string input = Base64.encode(test, buffer).idup;
+ const value = constructBinary(input);
+ assert(value == test);
+ assert(value == [84, 104, 101, 32, 65, 110, 115, 119, 101, 114, 58, 32, 52, 50]);
+}
+
+// Construct a timestamp (SysTime) _node.
+SysTime constructTimestamp(const string str) @safe
+{
+ string value = str;
+
+ auto YMDRegexp = regex("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)");
+ auto HMSRegexp = regex("^[Tt \t]+([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(\\.[0-9]*)?");
+ auto TZRegexp = regex("^[ \t]*Z|([-+][0-9][0-9]?)(:[0-9][0-9])?");
+
+ try
+ {
+ // First, get year, month and day.
+ auto matches = match(value, YMDRegexp);
+
+ enforce(!matches.empty,
+ new Exception("Unable to parse timestamp value: " ~ value));
+
+ auto captures = matches.front.captures;
+ const year = to!int(captures[1]);
+ const month = to!int(captures[2]);
+ const day = to!int(captures[3]);
+
+ // If available, get hour, minute, second and fraction, if present.
+ value = matches.front.post;
+ matches = match(value, HMSRegexp);
+ if(matches.empty)
+ {
+ return SysTime(DateTime(year, month, day), UTC());
+ }
+
+ captures = matches.front.captures;
+ const hour = to!int(captures[1]);
+ const minute = to!int(captures[2]);
+ const second = to!int(captures[3]);
+ const hectonanosecond = cast(int)(to!real("0" ~ captures[4]) * 10_000_000);
+
+ // If available, get timezone.
+ value = matches.front.post;
+ matches = match(value, TZRegexp);
+ if(matches.empty || matches.front.captures[0] == "Z")
+ {
+ // No timezone.
+ return SysTime(DateTime(year, month, day, hour, minute, second),
+ hectonanosecond.dur!"hnsecs", UTC());
+ }
+
+ // We have a timezone, so parse it.
+ captures = matches.front.captures;
+ int sign = 1;
+ int tzHours;
+ if(!captures[1].empty)
+ {
+ if(captures[1][0] == '-') {sign = -1;}
+ tzHours = to!int(captures[1][1 .. $]);
+ }
+ const tzMinutes = (!captures[2].empty) ? to!int(captures[2][1 .. $]) : 0;
+ const tzOffset = dur!"minutes"(sign * (60 * tzHours + tzMinutes));
+
+ return SysTime(DateTime(year, month, day, hour, minute, second),
+ hectonanosecond.dur!"hnsecs",
+ new immutable SimpleTimeZone(tzOffset));
+ }
+ catch(ConvException e)
+ {
+ throw new Exception("Unable to parse timestamp value " ~ value ~ " : " ~ e.msg);
+ }
+ catch(DateTimeException e)
+ {
+ throw new Exception("Invalid timestamp value " ~ value ~ " : " ~ e.msg);
+ }
+
+ assert(false, "This code should never be reached");
+}
+@safe unittest
+{
+ string timestamp(string value)
+ {
+ return constructTimestamp(value).toISOString();
+ }
+
+ string canonical = "2001-12-15T02:59:43.1Z";
+ string iso8601 = "2001-12-14t21:59:43.10-05:00";
+ string spaceSeparated = "2001-12-14 21:59:43.10 -5";
+ string noTZ = "2001-12-15 2:59:43.10";
+ string noFraction = "2001-12-15 2:59:43";
+ string ymd = "2002-12-14";
+
+ assert(timestamp(canonical) == "20011215T025943.1Z");
+ //avoiding float conversion errors
+ assert(timestamp(iso8601) == "20011214T215943.0999999-05:00" ||
+ timestamp(iso8601) == "20011214T215943.1-05:00");
+ assert(timestamp(spaceSeparated) == "20011214T215943.0999999-05:00" ||
+ timestamp(spaceSeparated) == "20011214T215943.1-05:00");
+ assert(timestamp(noTZ) == "20011215T025943.0999999Z" ||
+ timestamp(noTZ) == "20011215T025943.1Z");
+ assert(timestamp(noFraction) == "20011215T025943Z");
+ assert(timestamp(ymd) == "20021214T000000Z");
+}
+
+// Construct a string _node.
+string constructString(const string str) @safe
+{
+ return str;
+}
+
+// Convert a sequence of single-element mappings into a sequence of pairs.
+Node.Pair[] getPairs(string type, const Node[] nodes) @safe
+{
+ Node.Pair[] pairs;
+ pairs.reserve(nodes.length);
+ foreach(node; nodes)
+ {
+ enforce(node.nodeID == NodeID.mapping && node.length == 1,
+ new Exception("While constructing " ~ type ~
+ ", expected a mapping with single element"));
+
+ pairs ~= node.as!(Node.Pair[]);
+ }
+
+ return pairs;
+}
+
+// Construct an ordered map (ordered sequence of key:value pairs without duplicates) _node.
+Node.Pair[] constructOrderedMap(const Node[] nodes) @safe
+{
+ auto pairs = getPairs("ordered map", nodes);
+
+ //Detect duplicates.
+ //TODO this should be replaced by something with deterministic memory allocation.
+ auto keys = redBlackTree!Node();
+ foreach(ref pair; pairs)
+ {
+ enforce(!(pair.key in keys),
+ new Exception("Duplicate entry in an ordered map: "
+ ~ pair.key.debugString()));
+ keys.insert(pair.key);
+ }
+ return pairs;
+}
+@safe unittest
+{
+ Node[] alternateTypes(uint length) @safe
+ {
+ Node[] pairs;
+ foreach(long i; 0 .. length)
+ {
+ auto pair = (i % 2) ? Node.Pair(i.to!string, i) : Node.Pair(i, i.to!string);
+ pairs ~= Node([pair]);
+ }
+ return pairs;
+ }
+
+ Node[] sameType(uint length) @safe
+ {
+ Node[] pairs;
+ foreach(long i; 0 .. length)
+ {
+ auto pair = Node.Pair(i.to!string, i);
+ pairs ~= Node([pair]);
+ }
+ return pairs;
+ }
+
+ assertThrown(constructOrderedMap(alternateTypes(8) ~ alternateTypes(2)));
+ assertNotThrown(constructOrderedMap(alternateTypes(8)));
+ assertThrown(constructOrderedMap(sameType(64) ~ sameType(16)));
+ assertThrown(constructOrderedMap(alternateTypes(64) ~ alternateTypes(16)));
+ assertNotThrown(constructOrderedMap(sameType(64)));
+ assertNotThrown(constructOrderedMap(alternateTypes(64)));
+}
+
+// Construct a pairs (ordered sequence of key: value pairs allowing duplicates) _node.
+Node.Pair[] constructPairs(const Node[] nodes) @safe
+{
+ return getPairs("pairs", nodes);
+}
+
+// Construct a set _node.
+Node[] constructSet(const Node.Pair[] pairs) @safe
+{
+ // In future, the map here should be replaced with something with deterministic
+ // memory allocation if possible.
+ // Detect duplicates.
+ ubyte[Node] map;
+ Node[] nodes;
+ nodes.reserve(pairs.length);
+ foreach(pair; pairs)
+ {
+ enforce((pair.key in map) is null, new Exception("Duplicate entry in a set"));
+ map[pair.key] = 0;
+ nodes ~= pair.key;
+ }
+
+ return nodes;
+}
+@safe unittest
+{
+ Node.Pair[] set(uint length) @safe
+ {
+ Node.Pair[] pairs;
+ foreach(long i; 0 .. length)
+ {
+ pairs ~= Node.Pair(i.to!string, YAMLNull());
+ }
+
+ return pairs;
+ }
+
+ auto DuplicatesShort = set(8) ~ set(2);
+ auto noDuplicatesShort = set(8);
+ auto DuplicatesLong = set(64) ~ set(4);
+ auto noDuplicatesLong = set(64);
+
+ bool eq(Node.Pair[] a, Node[] b)
+ {
+ if(a.length != b.length){return false;}
+ foreach(i; 0 .. a.length)
+ {
+ if(a[i].key != b[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ auto nodeDuplicatesShort = DuplicatesShort.dup;
+ auto nodeNoDuplicatesShort = noDuplicatesShort.dup;
+ auto nodeDuplicatesLong = DuplicatesLong.dup;
+ auto nodeNoDuplicatesLong = noDuplicatesLong.dup;
+
+ assertThrown(constructSet(nodeDuplicatesShort));
+ assertNotThrown(constructSet(nodeNoDuplicatesShort));
+ assertThrown(constructSet(nodeDuplicatesLong));
+ assertNotThrown(constructSet(nodeNoDuplicatesLong));
+}
+
+// Construct a sequence (array) _node.
+Node[] constructSequence(Node[] nodes) @safe
+{
+ return nodes;
+}
+
+// Construct an unordered map (unordered set of key:value _pairs without duplicates) _node.
+Node.Pair[] constructMap(Node.Pair[] pairs) @safe
+{
+ //Detect duplicates.
+ //TODO this should be replaced by something with deterministic memory allocation.
+ auto keys = redBlackTree!Node();
+ foreach(ref pair; pairs)
+ {
+ enforce(!(pair.key in keys),
+ new Exception("Duplicate entry in a map: " ~ pair.key.debugString()));
+ keys.insert(pair.key);
+ }
+ return pairs;
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/dumper.d b/src/ext_depends/D-YAML/source/dyaml/dumper.d
new file mode 100644
index 0000000..51f232f
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/dumper.d
@@ -0,0 +1,287 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML dumper.
+ *
+ * Code based on $(LINK2 http://www.pyyaml.org, PyYAML).
+ */
+module dyaml.dumper;
+
+import std.array;
+import std.range.primitives;
+import std.typecons;
+
+import dyaml.emitter;
+import dyaml.event;
+import dyaml.exception;
+import dyaml.linebreak;
+import dyaml.node;
+import dyaml.representer;
+import dyaml.resolver;
+import dyaml.serializer;
+import dyaml.style;
+import dyaml.tagdirective;
+
+
+/**
+ * Dumps YAML documents to files or streams.
+ *
+ * User specified Representer and/or Resolver can be used to support new
+ * tags / data types.
+ *
+ * Setters are provided to affect output details (style, etc.).
+ */
+auto dumper()
+{
+ auto dumper = Dumper();
+ dumper.resolver = Resolver.withDefaultResolvers;
+ return dumper;
+}
+
+struct Dumper
+{
+ private:
+ //Indentation width.
+ int indent_ = 2;
+ //Tag directives to use.
+ TagDirective[] tags_;
+ public:
+ //Resolver to resolve tags.
+ Resolver resolver;
+ //Write scalars in canonical form?
+ bool canonical;
+ //Preferred text width.
+ uint textWidth = 80;
+ //Line break to use. Unix by default.
+ LineBreak lineBreak = LineBreak.unix;
+ //YAML version string. Default is 1.1.
+ string YAMLVersion = "1.1";
+ //Always explicitly write document start? Default is no explicit start.
+ bool explicitStart = false;
+ //Always explicitly write document end? Default is no explicit end.
+ bool explicitEnd = false;
+
+ //Name of the output file or stream, used in error messages.
+ string name = "<unknown>";
+
+ // Default style for scalar nodes. If style is $(D ScalarStyle.invalid), the _style is chosen automatically.
+ ScalarStyle defaultScalarStyle = ScalarStyle.invalid;
+ // Default style for collection nodes. If style is $(D CollectionStyle.invalid), the _style is chosen automatically.
+ CollectionStyle defaultCollectionStyle = CollectionStyle.invalid;
+
+ @disable bool opEquals(ref Dumper);
+ @disable int opCmp(ref Dumper);
+
+ ///Set indentation width. 2 by default. Must not be zero.
+ @property void indent(uint indent) pure @safe nothrow
+ in
+ {
+ assert(indent != 0, "Can't use zero YAML indent width");
+ }
+ do
+ {
+ indent_ = indent;
+ }
+
+ /**
+ * Specify tag directives.
+ *
+ * A tag directive specifies a shorthand notation for specifying _tags.
+ * Each tag directive associates a handle with a prefix. This allows for
+ * compact tag notation.
+ *
+ * Each handle specified MUST start and end with a '!' character
+ * (a single character "!" handle is allowed as well).
+ *
+ * Only alphanumeric characters, '-', and '__' may be used in handles.
+ *
+ * Each prefix MUST not be empty.
+ *
+ * The "!!" handle is used for default YAML _tags with prefix
+ * "tag:yaml.org,2002:". This can be overridden.
+ *
+ * Params: tags = Tag directives (keys are handles, values are prefixes).
+ */
+ @property void tagDirectives(string[string] tags) pure @safe
+ {
+ TagDirective[] t;
+ foreach(handle, prefix; tags)
+ {
+ assert(handle.length >= 1 && handle[0] == '!' && handle[$ - 1] == '!',
+ "A tag handle is empty or does not start and end with a " ~
+ "'!' character : " ~ handle);
+ assert(prefix.length >= 1, "A tag prefix is empty");
+ t ~= TagDirective(handle, prefix);
+ }
+ tags_ = t;
+ }
+ ///
+ @safe unittest
+ {
+ auto dumper = dumper();
+ string[string] directives;
+ directives["!short!"] = "tag:long.org,2011:";
+ //This will emit tags starting with "tag:long.org,2011"
+ //with a "!short!" prefix instead.
+ dumper.tagDirectives(directives);
+ dumper.dump(new Appender!string(), Node("foo"));
+ }
+
+ /**
+ * Dump one or more YAML _documents to the file/stream.
+ *
+ * Note that while you can call dump() multiple times on the same
+ * dumper, you will end up writing multiple YAML "files" to the same
+ * file/stream.
+ *
+ * Params: documents = Documents to _dump (root nodes of the _documents).
+ *
+ * Throws: YAMLException on error (e.g. invalid nodes,
+ * unable to write to file/stream).
+ */
+ void dump(CharacterType = char, Range)(Range range, Node[] documents ...)
+ if (isOutputRange!(Range, CharacterType) &&
+ isOutputRange!(Range, char) || isOutputRange!(Range, wchar) || isOutputRange!(Range, dchar))
+ {
+ try
+ {
+ auto emitter = new Emitter!(Range, CharacterType)(range, canonical, indent_, textWidth, lineBreak);
+ auto serializer = Serializer(resolver, explicitStart ? Yes.explicitStart : No.explicitStart,
+ explicitEnd ? Yes.explicitEnd : No.explicitEnd, YAMLVersion, tags_);
+ serializer.startStream(emitter);
+ foreach(ref document; documents)
+ {
+ auto data = representData(document, defaultScalarStyle, defaultCollectionStyle);
+ serializer.serialize(emitter, data);
+ }
+ serializer.endStream(emitter);
+ }
+ catch(YAMLException e)
+ {
+ throw new YAMLException("Unable to dump YAML to stream "
+ ~ name ~ " : " ~ e.msg, e.file, e.line);
+ }
+ }
+}
+///Write to a file
+@safe unittest
+{
+ auto node = Node([1, 2, 3, 4, 5]);
+ dumper().dump(new Appender!string(), node);
+}
+///Write multiple YAML documents to a file
+@safe unittest
+{
+ auto node1 = Node([1, 2, 3, 4, 5]);
+ auto node2 = Node("This document contains only one string");
+ dumper().dump(new Appender!string(), node1, node2);
+ //Or with an array:
+ dumper().dump(new Appender!string(), [node1, node2]);
+}
+///Write to memory
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ dumper().dump(stream, node);
+}
+///Use a custom resolver to support custom data types and/or implicit tags
+@safe unittest
+{
+ import std.regex : regex;
+ auto node = Node([1, 2, 3, 4, 5]);
+ auto dumper = dumper();
+ dumper.resolver.addImplicitResolver("!tag", regex("A.*"), "A");
+ dumper.dump(new Appender!string(), node);
+}
+/// Set default scalar style
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node("Hello world!");
+ auto dumper = dumper();
+ dumper.defaultScalarStyle = ScalarStyle.singleQuoted;
+ dumper.dump(stream, node);
+}
+/// Set default collection style
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node(["Hello", "world!"]);
+ auto dumper = dumper();
+ dumper.defaultCollectionStyle = CollectionStyle.flow;
+ dumper.dump(stream, node);
+}
+// Make sure the styles are actually used
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node([Node("Hello world!"), Node(["Hello", "world!"])]);
+ auto dumper = dumper();
+ dumper.defaultScalarStyle = ScalarStyle.singleQuoted;
+ dumper.defaultCollectionStyle = CollectionStyle.flow;
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+ assert(stream.data == "[!!str 'Hello world!', [!!str 'Hello', !!str 'world!']]\n");
+}
+// Explicit document start/end markers
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ auto dumper = dumper();
+ dumper.explicitEnd = true;
+ dumper.explicitStart = true;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+ //Skip version string
+ assert(stream.data[0..3] == "---");
+ //account for newline at end
+ assert(stream.data[$-4..$-1] == "...");
+}
+// No explicit document start/end markers
+@safe unittest
+{
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ auto dumper = dumper();
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+ //Skip version string
+ assert(stream.data[0..3] != "---");
+ //account for newline at end
+ assert(stream.data[$-4..$-1] != "...");
+}
+// Windows, macOS line breaks
+@safe unittest
+{
+ auto node = Node(0);
+ {
+ auto stream = new Appender!string();
+ auto dumper = dumper();
+ dumper.explicitEnd = true;
+ dumper.explicitStart = true;
+ dumper.YAMLVersion = null;
+ dumper.lineBreak = LineBreak.windows;
+ dumper.dump(stream, node);
+ assert(stream.data == "--- 0\r\n...\r\n");
+ }
+ {
+ auto stream = new Appender!string();
+ auto dumper = dumper();
+ dumper.explicitEnd = true;
+ dumper.explicitStart = true;
+ dumper.YAMLVersion = null;
+ dumper.lineBreak = LineBreak.macintosh;
+ dumper.dump(stream, node);
+ assert(stream.data == "--- 0\r...\r");
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/emitter.d b/src/ext_depends/D-YAML/source/dyaml/emitter.d
new file mode 100644
index 0000000..c797eb9
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/emitter.d
@@ -0,0 +1,1689 @@
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML emitter.
+ * Code based on PyYAML: http://www.pyyaml.org
+ */
+module dyaml.emitter;
+
+
+import std.algorithm;
+import std.array;
+import std.ascii;
+import std.conv;
+import std.encoding;
+import std.exception;
+import std.format;
+import std.range;
+import std.string;
+import std.system;
+import std.typecons;
+import std.utf;
+
+import dyaml.encoding;
+import dyaml.escapes;
+import dyaml.event;
+import dyaml.exception;
+import dyaml.linebreak;
+import dyaml.queue;
+import dyaml.style;
+import dyaml.tagdirective;
+
+
+package:
+
+//Stores results of analysis of a scalar, determining e.g. what scalar style to use.
+struct ScalarAnalysis
+{
+ //Scalar itself.
+ string scalar;
+
+ enum AnalysisFlags
+ {
+ empty = 1<<0,
+ multiline = 1<<1,
+ allowFlowPlain = 1<<2,
+ allowBlockPlain = 1<<3,
+ allowSingleQuoted = 1<<4,
+ allowDoubleQuoted = 1<<5,
+ allowBlock = 1<<6,
+ isNull = 1<<7
+ }
+
+ ///Analysis results.
+ BitFlags!AnalysisFlags flags;
+}
+
+private alias isNewLine = among!('\n', '\u0085', '\u2028', '\u2029');
+
+private alias isSpecialChar = among!('#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\\', '\'', '"', '%', '@', '`');
+
+private alias isFlowIndicator = among!(',', '?', '[', ']', '{', '}');
+
+private alias isSpace = among!('\0', '\n', '\r', '\u0085', '\u2028', '\u2029', ' ', '\t');
+
+//Emits YAML events into a file/stream.
+struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
+{
+ private:
+ ///Default tag handle shortcuts and replacements.
+ static TagDirective[] defaultTagDirectives_ =
+ [TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
+
+ ///Stream to write to.
+ Range stream_;
+
+ /// Type used for upcoming emitter steps
+ alias EmitterFunction = void function(typeof(this)*) @safe;
+
+ ///Stack of states.
+ Appender!(EmitterFunction[]) states_;
+
+ ///Current state.
+ EmitterFunction state_;
+
+ ///Event queue.
+ Queue!Event events_;
+ ///Event we're currently emitting.
+ Event event_;
+
+ ///Stack of previous indentation levels.
+ Appender!(int[]) indents_;
+ ///Current indentation level.
+ int indent_ = -1;
+
+ ///Level of nesting in flow context. If 0, we're in block context.
+ uint flowLevel_ = 0;
+
+ /// Describes context (where we are in the document).
+ enum Context
+ {
+ /// Root node of a document.
+ root,
+ /// Sequence.
+ sequence,
+ /// Mapping.
+ mappingNoSimpleKey,
+ /// Mapping, in a simple key.
+ mappingSimpleKey,
+ }
+ /// Current context.
+ Context context_;
+
+ ///Characteristics of the last emitted character:
+
+ ///Line.
+ uint line_ = 0;
+ ///Column.
+ uint column_ = 0;
+ ///Whitespace character?
+ bool whitespace_ = true;
+ ///indentation space, '-', '?', or ':'?
+ bool indentation_ = true;
+
+ ///Does the document require an explicit document indicator?
+ bool openEnded_;
+
+ ///Formatting details.
+
+ ///Canonical scalar format?
+ bool canonical_;
+ ///Best indentation width.
+ uint bestIndent_ = 2;
+ ///Best text width.
+ uint bestWidth_ = 80;
+ ///Best line break character/s.
+ LineBreak bestLineBreak_;
+
+ ///Tag directive handle - prefix pairs.
+ TagDirective[] tagDirectives_;
+
+ ///Anchor/alias to process.
+ string preparedAnchor_ = null;
+ ///Tag to process.
+ string preparedTag_ = null;
+
+ ///Analysis result of the current scalar.
+ ScalarAnalysis analysis_;
+ ///Style of the current scalar.
+ ScalarStyle style_ = ScalarStyle.invalid;
+
+ public:
+ @disable int opCmp(ref Emitter);
+ @disable bool opEquals(ref Emitter);
+
+ /**
+ * Construct an emitter.
+ *
+ * Params: stream = Output range to write to.
+ * canonical = Write scalars in canonical form?
+ * indent = Indentation width.
+ * lineBreak = Line break character/s.
+ */
+ this(Range stream, const bool canonical, const int indent, const int width,
+ const LineBreak lineBreak) @safe
+ {
+ states_.reserve(32);
+ indents_.reserve(32);
+ stream_ = stream;
+ canonical_ = canonical;
+ nextExpected!"expectStreamStart"();
+
+ if(indent > 1 && indent < 10){bestIndent_ = indent;}
+ if(width > bestIndent_ * 2) {bestWidth_ = width;}
+ bestLineBreak_ = lineBreak;
+
+ analysis_.flags.isNull = true;
+ }
+
+ ///Emit an event.
+ void emit(Event event) @safe
+ {
+ events_.push(event);
+ while(!needMoreEvents())
+ {
+ event_ = events_.pop();
+ callNext();
+ event_.destroy();
+ }
+ }
+
+ private:
+ ///Pop and return the newest state in states_.
+ EmitterFunction popState() @safe
+ in(states_.data.length > 0,
+ "Emitter: Need to pop a state but there are no states left")
+ {
+ const result = states_.data[$-1];
+ states_.shrinkTo(states_.data.length - 1);
+ return result;
+ }
+
+ void pushState(string D)() @safe
+ {
+ states_ ~= mixin("function(typeof(this)* self) { self."~D~"(); }");
+ }
+
+ ///Pop and return the newest indent in indents_.
+ int popIndent() @safe
+ in(indents_.data.length > 0,
+ "Emitter: Need to pop an indent level but there" ~
+ " are no indent levels left")
+ {
+ const result = indents_.data[$-1];
+ indents_.shrinkTo(indents_.data.length - 1);
+ return result;
+ }
+
+ ///Write a string to the file/stream.
+ void writeString(const scope char[] str) @safe
+ {
+ static if(is(CharType == char))
+ {
+ copy(str, stream_);
+ }
+ static if(is(CharType == wchar))
+ {
+ const buffer = to!wstring(str);
+ copy(buffer, stream_);
+ }
+ static if(is(CharType == dchar))
+ {
+ const buffer = to!dstring(str);
+ copy(buffer, stream_);
+ }
+ }
+
+ ///In some cases, we wait for a few next events before emitting.
+ bool needMoreEvents() @safe nothrow
+ {
+ if(events_.length == 0){return true;}
+
+ const event = events_.peek();
+ if(event.id == EventID.documentStart){return needEvents(1);}
+ if(event.id == EventID.sequenceStart){return needEvents(2);}
+ if(event.id == EventID.mappingStart) {return needEvents(3);}
+
+ return false;
+ }
+
+ ///Determines if we need specified number of more events.
+ bool needEvents(in uint count) @safe nothrow
+ {
+ int level;
+
+ foreach(const event; events_.range)
+ {
+ if(event.id.among!(EventID.documentStart, EventID.sequenceStart, EventID.mappingStart)) {++level;}
+ else if(event.id.among!(EventID.documentEnd, EventID.sequenceEnd, EventID.mappingEnd)) {--level;}
+ else if(event.id == EventID.streamStart){level = -1;}
+
+ if(level < 0)
+ {
+ return false;
+ }
+ }
+
+ return events_.length < (count + 1);
+ }
+
+ ///Increase indentation level.
+ void increaseIndent(const Flag!"flow" flow = No.flow, const bool indentless = false) @safe
+ {
+ indents_ ~= indent_;
+ if(indent_ == -1)
+ {
+ indent_ = flow ? bestIndent_ : 0;
+ }
+ else if(!indentless)
+ {
+ indent_ += bestIndent_;
+ }
+ }
+
+ ///Determines if the type of current event is as specified. Throws if no event.
+ bool eventTypeIs(in EventID id) const pure @safe
+ in(!event_.isNull, "Expected an event, but no event is available.")
+ {
+ return event_.id == id;
+ }
+
+
+ //States.
+
+
+ //Stream handlers.
+
+ ///Handle start of a file/stream.
+ void expectStreamStart() @safe
+ in(eventTypeIs(EventID.streamStart),
+ "Expected streamStart, but got " ~ event_.idString)
+ {
+
+ writeStreamStart();
+ nextExpected!"expectDocumentStart!(Yes.first)"();
+ }
+
+ ///Expect nothing, throwing if we still have something.
+ void expectNothing() @safe
+ {
+ assert(0, "Expected nothing, but got " ~ event_.idString);
+ }
+
+ //Document handlers.
+
+ ///Handle start of a document.
+ void expectDocumentStart(Flag!"first" first)() @safe
+ in(eventTypeIs(EventID.documentStart) || eventTypeIs(EventID.streamEnd),
+ "Expected documentStart or streamEnd, but got " ~ event_.idString)
+ {
+
+ if(event_.id == EventID.documentStart)
+ {
+ const YAMLVersion = event_.value;
+ auto tagDirectives = event_.tagDirectives;
+ if(openEnded_ && (YAMLVersion !is null || tagDirectives !is null))
+ {
+ writeIndicator("...", Yes.needWhitespace);
+ writeIndent();
+ }
+
+ if(YAMLVersion !is null)
+ {
+ writeVersionDirective(prepareVersion(YAMLVersion));
+ }
+
+ if(tagDirectives !is null)
+ {
+ tagDirectives_ = tagDirectives;
+ sort!"icmp(a.handle, b.handle) < 0"(tagDirectives_);
+
+ foreach(ref pair; tagDirectives_)
+ {
+ writeTagDirective(prepareTagHandle(pair.handle),
+ prepareTagPrefix(pair.prefix));
+ }
+ }
+
+ bool eq(ref TagDirective a, ref TagDirective b){return a.handle == b.handle;}
+ //Add any default tag directives that have not been overriden.
+ foreach(ref def; defaultTagDirectives_)
+ {
+ if(!std.algorithm.canFind!eq(tagDirectives_, def))
+ {
+ tagDirectives_ ~= def;
+ }
+ }
+
+ const implicit = first && !event_.explicitDocument && !canonical_ &&
+ YAMLVersion is null && tagDirectives is null &&
+ !checkEmptyDocument();
+ if(!implicit)
+ {
+ writeIndent();
+ writeIndicator("---", Yes.needWhitespace);
+ if(canonical_){writeIndent();}
+ }
+ nextExpected!"expectRootNode"();
+ }
+ else if(event_.id == EventID.streamEnd)
+ {
+ if(openEnded_)
+ {
+ writeIndicator("...", Yes.needWhitespace);
+ writeIndent();
+ }
+ writeStreamEnd();
+ nextExpected!"expectNothing"();
+ }
+ }
+
+ ///Handle end of a document.
+ void expectDocumentEnd() @safe
+ in(eventTypeIs(EventID.documentEnd),
+ "Expected DocumentEnd, but got " ~ event_.idString)
+ {
+
+ writeIndent();
+ if(event_.explicitDocument)
+ {
+ writeIndicator("...", Yes.needWhitespace);
+ writeIndent();
+ }
+ nextExpected!"expectDocumentStart!(No.first)"();
+ }
+
+ ///Handle the root node of a document.
+ void expectRootNode() @safe
+ {
+ pushState!"expectDocumentEnd"();
+ expectNode(Context.root);
+ }
+
+ ///Handle a mapping node.
+ //
+ //Params: simpleKey = Are we in a simple key?
+ void expectMappingNode(const bool simpleKey = false) @safe
+ {
+ expectNode(simpleKey ? Context.mappingSimpleKey : Context.mappingNoSimpleKey);
+ }
+
+ ///Handle a sequence node.
+ void expectSequenceNode() @safe
+ {
+ expectNode(Context.sequence);
+ }
+
+ ///Handle a new node. Context specifies where in the document we are.
+ void expectNode(const Context context) @safe
+ {
+ context_ = context;
+
+ const flowCollection = event_.collectionStyle == CollectionStyle.flow;
+
+ switch(event_.id)
+ {
+ case EventID.alias_: expectAlias(); break;
+ case EventID.scalar:
+ processAnchor("&");
+ processTag();
+ expectScalar();
+ break;
+ case EventID.sequenceStart:
+ processAnchor("&");
+ processTag();
+ if(flowLevel_ > 0 || canonical_ || flowCollection || checkEmptySequence())
+ {
+ expectFlowSequence();
+ }
+ else
+ {
+ expectBlockSequence();
+ }
+ break;
+ case EventID.mappingStart:
+ processAnchor("&");
+ processTag();
+ if(flowLevel_ > 0 || canonical_ || flowCollection || checkEmptyMapping())
+ {
+ expectFlowMapping();
+ }
+ else
+ {
+ expectBlockMapping();
+ }
+ break;
+ default:
+ assert(0, "Expected alias_, scalar, sequenceStart or " ~
+ "mappingStart, but got: " ~ event_.idString);
+ }
+ }
+ ///Handle an alias.
+ void expectAlias() @safe
+ in(event_.anchor != "", "Anchor is not specified for alias")
+ {
+ processAnchor("*");
+ nextExpected(popState());
+ }
+
+ ///Handle a scalar.
+ void expectScalar() @safe
+ {
+ increaseIndent(Yes.flow);
+ processScalar();
+ indent_ = popIndent();
+ nextExpected(popState());
+ }
+
+ //Flow sequence handlers.
+
+ ///Handle a flow sequence.
+ void expectFlowSequence() @safe
+ {
+ writeIndicator("[", Yes.needWhitespace, Yes.whitespace);
+ ++flowLevel_;
+ increaseIndent(Yes.flow);
+ nextExpected!"expectFlowSequenceItem!(Yes.first)"();
+ }
+
+ ///Handle a flow sequence item.
+ void expectFlowSequenceItem(Flag!"first" first)() @safe
+ {
+ if(event_.id == EventID.sequenceEnd)
+ {
+ indent_ = popIndent();
+ --flowLevel_;
+ static if(!first) if(canonical_)
+ {
+ writeIndicator(",", No.needWhitespace);
+ writeIndent();
+ }
+ writeIndicator("]", No.needWhitespace);
+ nextExpected(popState());
+ return;
+ }
+ static if(!first){writeIndicator(",", No.needWhitespace);}
+ if(canonical_ || column_ > bestWidth_){writeIndent();}
+ pushState!"expectFlowSequenceItem!(No.first)"();
+ expectSequenceNode();
+ }
+
+ //Flow mapping handlers.
+
+ ///Handle a flow mapping.
+ void expectFlowMapping() @safe
+ {
+ writeIndicator("{", Yes.needWhitespace, Yes.whitespace);
+ ++flowLevel_;
+ increaseIndent(Yes.flow);
+ nextExpected!"expectFlowMappingKey!(Yes.first)"();
+ }
+
+ ///Handle a key in a flow mapping.
+ void expectFlowMappingKey(Flag!"first" first)() @safe
+ {
+ if(event_.id == EventID.mappingEnd)
+ {
+ indent_ = popIndent();
+ --flowLevel_;
+ static if (!first) if(canonical_)
+ {
+ writeIndicator(",", No.needWhitespace);
+ writeIndent();
+ }
+ writeIndicator("}", No.needWhitespace);
+ nextExpected(popState());
+ return;
+ }
+
+ static if(!first){writeIndicator(",", No.needWhitespace);}
+ if(canonical_ || column_ > bestWidth_){writeIndent();}
+ if(!canonical_ && checkSimpleKey())
+ {
+ pushState!"expectFlowMappingSimpleValue"();
+ expectMappingNode(true);
+ return;
+ }
+
+ writeIndicator("?", Yes.needWhitespace);
+ pushState!"expectFlowMappingValue"();
+ expectMappingNode();
+ }
+
+ ///Handle a simple value in a flow mapping.
+ void expectFlowMappingSimpleValue() @safe
+ {
+ writeIndicator(":", No.needWhitespace);
+ pushState!"expectFlowMappingKey!(No.first)"();
+ expectMappingNode();
+ }
+
+ ///Handle a complex value in a flow mapping.
+ void expectFlowMappingValue() @safe
+ {
+ if(canonical_ || column_ > bestWidth_){writeIndent();}
+ writeIndicator(":", Yes.needWhitespace);
+ pushState!"expectFlowMappingKey!(No.first)"();
+ expectMappingNode();
+ }
+
+ //Block sequence handlers.
+
+ ///Handle a block sequence.
+ void expectBlockSequence() @safe
+ {
+ const indentless = (context_ == Context.mappingNoSimpleKey ||
+ context_ == Context.mappingSimpleKey) && !indentation_;
+ increaseIndent(No.flow, indentless);
+ nextExpected!"expectBlockSequenceItem!(Yes.first)"();
+ }
+
+ ///Handle a block sequence item.
+ void expectBlockSequenceItem(Flag!"first" first)() @safe
+ {
+ static if(!first) if(event_.id == EventID.sequenceEnd)
+ {
+ indent_ = popIndent();
+ nextExpected(popState());
+ return;
+ }
+
+ writeIndent();
+ writeIndicator("-", Yes.needWhitespace, No.whitespace, Yes.indentation);
+ pushState!"expectBlockSequenceItem!(No.first)"();
+ expectSequenceNode();
+ }
+
+ //Block mapping handlers.
+
+ ///Handle a block mapping.
+ void expectBlockMapping() @safe
+ {
+ increaseIndent(No.flow);
+ nextExpected!"expectBlockMappingKey!(Yes.first)"();
+ }
+
+ ///Handle a key in a block mapping.
+ void expectBlockMappingKey(Flag!"first" first)() @safe
+ {
+ static if(!first) if(event_.id == EventID.mappingEnd)
+ {
+ indent_ = popIndent();
+ nextExpected(popState());
+ return;
+ }
+
+ writeIndent();
+ if(checkSimpleKey())
+ {
+ pushState!"expectBlockMappingSimpleValue"();
+ expectMappingNode(true);
+ return;
+ }
+
+ writeIndicator("?", Yes.needWhitespace, No.whitespace, Yes.indentation);
+ pushState!"expectBlockMappingValue"();
+ expectMappingNode();
+ }
+
+ ///Handle a simple value in a block mapping.
+ void expectBlockMappingSimpleValue() @safe
+ {
+ writeIndicator(":", No.needWhitespace);
+ pushState!"expectBlockMappingKey!(No.first)"();
+ expectMappingNode();
+ }
+
+ ///Handle a complex value in a block mapping.
+ void expectBlockMappingValue() @safe
+ {
+ writeIndent();
+ writeIndicator(":", Yes.needWhitespace, No.whitespace, Yes.indentation);
+ pushState!"expectBlockMappingKey!(No.first)"();
+ expectMappingNode();
+ }
+
+ //Checkers.
+
+ ///Check if an empty sequence is next.
+ bool checkEmptySequence() const @safe pure nothrow
+ {
+ return event_.id == EventID.sequenceStart && events_.length > 0
+ && events_.peek().id == EventID.sequenceEnd;
+ }
+
+ ///Check if an empty mapping is next.
+ bool checkEmptyMapping() const @safe pure nothrow
+ {
+ return event_.id == EventID.mappingStart && events_.length > 0
+ && events_.peek().id == EventID.mappingEnd;
+ }
+
+ ///Check if an empty document is next.
+ bool checkEmptyDocument() const @safe pure nothrow
+ {
+ if(event_.id != EventID.documentStart || events_.length == 0)
+ {
+ return false;
+ }
+
+ const event = events_.peek();
+ const emptyScalar = event.id == EventID.scalar && (event.anchor is null) &&
+ (event.tag is null) && event.implicit && event.value == "";
+ return emptyScalar;
+ }
+
+ ///Check if a simple key is next.
+ bool checkSimpleKey() @safe
+ {
+ uint length;
+ const id = event_.id;
+ const scalar = id == EventID.scalar;
+ const collectionStart = id == EventID.mappingStart ||
+ id == EventID.sequenceStart;
+
+ if((id == EventID.alias_ || scalar || collectionStart)
+ && (event_.anchor !is null))
+ {
+ if(preparedAnchor_ is null)
+ {
+ preparedAnchor_ = prepareAnchor(event_.anchor);
+ }
+ length += preparedAnchor_.length;
+ }
+
+ if((scalar || collectionStart) && (event_.tag !is null))
+ {
+ if(preparedTag_ is null){preparedTag_ = prepareTag(event_.tag);}
+ length += preparedTag_.length;
+ }
+
+ if(scalar)
+ {
+ if(analysis_.flags.isNull){analysis_ = analyzeScalar(event_.value);}
+ length += analysis_.scalar.length;
+ }
+
+ if(length >= 128){return false;}
+
+ return id == EventID.alias_ ||
+ (scalar && !analysis_.flags.empty && !analysis_.flags.multiline) ||
+ checkEmptySequence() ||
+ checkEmptyMapping();
+ }
+
+ ///Process and write a scalar.
+ void processScalar() @safe
+ {
+ if(analysis_.flags.isNull){analysis_ = analyzeScalar(event_.value);}
+ if(style_ == ScalarStyle.invalid)
+ {
+ style_ = chooseScalarStyle();
+ }
+
+ //if(analysis_.flags.multiline && (context_ != Context.mappingSimpleKey) &&
+ // ([ScalarStyle.invalid, ScalarStyle.plain, ScalarStyle.singleQuoted, ScalarStyle.doubleQuoted)
+ // .canFind(style_))
+ //{
+ // writeIndent();
+ //}
+ auto writer = ScalarWriter!(Range, CharType)(&this, analysis_.scalar,
+ context_ != Context.mappingSimpleKey);
+ with(writer) final switch(style_)
+ {
+ case ScalarStyle.invalid: assert(false);
+ case ScalarStyle.doubleQuoted: writeDoubleQuoted(); break;
+ case ScalarStyle.singleQuoted: writeSingleQuoted(); break;
+ case ScalarStyle.folded: writeFolded(); break;
+ case ScalarStyle.literal: writeLiteral(); break;
+ case ScalarStyle.plain: writePlain(); break;
+ }
+ analysis_.flags.isNull = true;
+ style_ = ScalarStyle.invalid;
+ }
+
+ ///Process and write an anchor/alias.
+ void processAnchor(const string indicator) @safe
+ {
+ if(event_.anchor is null)
+ {
+ preparedAnchor_ = null;
+ return;
+ }
+ if(preparedAnchor_ is null)
+ {
+ preparedAnchor_ = prepareAnchor(event_.anchor);
+ }
+ if(preparedAnchor_ !is null && preparedAnchor_ != "")
+ {
+ writeIndicator(indicator, Yes.needWhitespace);
+ writeString(preparedAnchor_);
+ }
+ preparedAnchor_ = null;
+ }
+
+ ///Process and write a tag.
+ void processTag() @safe
+ {
+ string tag = event_.tag;
+
+ if(event_.id == EventID.scalar)
+ {
+ if(style_ == ScalarStyle.invalid){style_ = chooseScalarStyle();}
+ if((!canonical_ || (tag is null)) &&
+ (style_ == ScalarStyle.plain ? event_.implicit : !event_.implicit && (tag is null)))
+ {
+ preparedTag_ = null;
+ return;
+ }
+ if(event_.implicit && (tag is null))
+ {
+ tag = "!";
+ preparedTag_ = null;
+ }
+ }
+ else if((!canonical_ || (tag is null)) && event_.implicit)
+ {
+ preparedTag_ = null;
+ return;
+ }
+
+ assert(tag != "", "Tag is not specified");
+ if(preparedTag_ is null){preparedTag_ = prepareTag(tag);}
+ if(preparedTag_ !is null && preparedTag_ != "")
+ {
+ writeIndicator(preparedTag_, Yes.needWhitespace);
+ }
+ preparedTag_ = null;
+ }
+
+ ///Determine style to write the current scalar in.
+ ScalarStyle chooseScalarStyle() @safe
+ {
+ if(analysis_.flags.isNull){analysis_ = analyzeScalar(event_.value);}
+
+ const style = event_.scalarStyle;
+ const invalidOrPlain = style == ScalarStyle.invalid || style == ScalarStyle.plain;
+ const block = style == ScalarStyle.literal || style == ScalarStyle.folded;
+ const singleQuoted = style == ScalarStyle.singleQuoted;
+ const doubleQuoted = style == ScalarStyle.doubleQuoted;
+
+ const allowPlain = flowLevel_ > 0 ? analysis_.flags.allowFlowPlain
+ : analysis_.flags.allowBlockPlain;
+ //simple empty or multiline scalars can't be written in plain style
+ const simpleNonPlain = (context_ == Context.mappingSimpleKey) &&
+ (analysis_.flags.empty || analysis_.flags.multiline);
+
+ if(doubleQuoted || canonical_)
+ {
+ return ScalarStyle.doubleQuoted;
+ }
+
+ if(invalidOrPlain && event_.implicit && !simpleNonPlain && allowPlain)
+ {
+ return ScalarStyle.plain;
+ }
+
+ if(block && flowLevel_ == 0 && context_ != Context.mappingSimpleKey &&
+ analysis_.flags.allowBlock)
+ {
+ return style;
+ }
+
+ if((invalidOrPlain || singleQuoted) &&
+ analysis_.flags.allowSingleQuoted &&
+ !(context_ == Context.mappingSimpleKey && analysis_.flags.multiline))
+ {
+ return ScalarStyle.singleQuoted;
+ }
+
+ return ScalarStyle.doubleQuoted;
+ }
+
+ ///Prepare YAML version string for output.
+ static string prepareVersion(const string YAMLVersion) @safe
+ in(YAMLVersion.split(".")[0] == "1",
+ "Unsupported YAML version: " ~ YAMLVersion)
+ {
+ return YAMLVersion;
+ }
+
+ ///Encode an Unicode character for tag directive and write it to writer.
+ static void encodeChar(Writer)(ref Writer writer, in dchar c) @safe
+ {
+ char[4] data;
+ const bytes = encode(data, c);
+ //For each byte add string in format %AB , where AB are hex digits of the byte.
+ foreach(const char b; data[0 .. bytes])
+ {
+ formattedWrite(writer, "%%%02X", cast(ubyte)b);
+ }
+ }
+
+ ///Prepare tag directive handle for output.
+ static string prepareTagHandle(const string handle) @safe
+ in(handle != "", "Tag handle must not be empty")
+ in(handle.drop(1).dropBack(1).all!(c => isAlphaNum(c) || c.among!('-', '_')),
+ "Tag handle contains invalid characters")
+ {
+ return handle;
+ }
+
+ ///Prepare tag directive prefix for output.
+ static string prepareTagPrefix(const string prefix) @safe
+ in(prefix != "", "Tag prefix must not be empty")
+ {
+ auto appender = appender!string();
+ const int offset = prefix[0] == '!';
+ size_t start, end;
+
+ foreach(const size_t i, const dchar c; prefix)
+ {
+ const size_t idx = i + offset;
+ if(isAlphaNum(c) || c.among!('-', ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '!', '~', '*', '\\', '\'', '(', ')', '[', ']', '%'))
+ {
+ end = idx + 1;
+ continue;
+ }
+
+ if(start < idx){appender.put(prefix[start .. idx]);}
+ start = end = idx + 1;
+
+ encodeChar(appender, c);
+ }
+
+ end = min(end, prefix.length);
+ if(start < end){appender.put(prefix[start .. end]);}
+ return appender.data;
+ }
+
+ ///Prepare tag for output.
+ string prepareTag(in string tag) @safe
+ in(tag != "", "Tag must not be empty")
+ {
+
+ string tagString = tag;
+ if(tagString == "!"){return tagString;}
+ string handle;
+ string suffix = tagString;
+
+ //Sort lexicographically by prefix.
+ sort!"icmp(a.prefix, b.prefix) < 0"(tagDirectives_);
+ foreach(ref pair; tagDirectives_)
+ {
+ auto prefix = pair.prefix;
+ if(tagString.startsWith(prefix) &&
+ (prefix != "!" || prefix.length < tagString.length))
+ {
+ handle = pair.handle;
+ suffix = tagString[prefix.length .. $];
+ }
+ }
+
+ auto appender = appender!string();
+ appender.put(handle !is null && handle != "" ? handle : "!<");
+ size_t start, end;
+ foreach(const dchar c; suffix)
+ {
+ if(isAlphaNum(c) || c.among!('-', ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\\', '\'', '(', ')', '[', ']') ||
+ (c == '!' && handle != "!"))
+ {
+ ++end;
+ continue;
+ }
+ if(start < end){appender.put(suffix[start .. end]);}
+ start = end = end + 1;
+
+ encodeChar(appender, c);
+ }
+
+ if(start < end){appender.put(suffix[start .. end]);}
+ if(handle is null || handle == ""){appender.put(">");}
+
+ return appender.data;
+ }
+
+ ///Prepare anchor for output.
+ static string prepareAnchor(const string anchor) @safe
+ in(anchor != "", "Anchor must not be empty")
+ in(anchor.all!(c => isAlphaNum(c) || c.among!('-', '_')), "Anchor contains invalid characters")
+ {
+ return anchor;
+ }
+
+ ///Analyze specifed scalar and return the analysis result.
+ static ScalarAnalysis analyzeScalar(string scalar) @safe
+ {
+ ScalarAnalysis analysis;
+ analysis.flags.isNull = false;
+ analysis.scalar = scalar;
+
+ //Empty scalar is a special case.
+ if(scalar is null || scalar == "")
+ {
+ with(ScalarAnalysis.AnalysisFlags)
+ analysis.flags =
+ empty |
+ allowBlockPlain |
+ allowSingleQuoted |
+ allowDoubleQuoted;
+ return analysis;
+ }
+
+ //Indicators and special characters (All false by default).
+ bool blockIndicators, flowIndicators, lineBreaks, specialCharacters;
+
+ //Important whitespace combinations (All false by default).
+ bool leadingSpace, leadingBreak, trailingSpace, trailingBreak,
+ breakSpace, spaceBreak;
+
+ //Check document indicators.
+ if(scalar.startsWith("---", "..."))
+ {
+ blockIndicators = flowIndicators = true;
+ }
+
+ //First character or preceded by a whitespace.
+ bool preceededByWhitespace = true;
+
+ //Last character or followed by a whitespace.
+ bool followedByWhitespace = scalar.length == 1 ||
+ scalar[1].among!(' ', '\t', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029');
+
+ //The previous character is a space/break (false by default).
+ bool previousSpace, previousBreak;
+
+ foreach(const size_t index, const dchar c; scalar)
+ {
+ //Check for indicators.
+ if(index == 0)
+ {
+ //Leading indicators are special characters.
+ if(c.isSpecialChar)
+ {
+ flowIndicators = blockIndicators = true;
+ }
+ if(':' == c || '?' == c)
+ {
+ flowIndicators = true;
+ if(followedByWhitespace){blockIndicators = true;}
+ }
+ if(c == '-' && followedByWhitespace)
+ {
+ flowIndicators = blockIndicators = true;
+ }
+ }
+ else
+ {
+ //Some indicators cannot appear within a scalar as well.
+ if(c.isFlowIndicator){flowIndicators = true;}
+ if(c == ':')
+ {
+ flowIndicators = true;
+ if(followedByWhitespace){blockIndicators = true;}
+ }
+ if(c == '#' && preceededByWhitespace)
+ {
+ flowIndicators = blockIndicators = true;
+ }
+ }
+
+ //Check for line breaks, special, and unicode characters.
+ if(c.isNewLine){lineBreaks = true;}
+ if(!(c == '\n' || (c >= '\x20' && c <= '\x7E')) &&
+ !((c == '\u0085' || (c >= '\xA0' && c <= '\uD7FF') ||
+ (c >= '\uE000' && c <= '\uFFFD')) && c != '\uFEFF'))
+ {
+ specialCharacters = true;
+ }
+
+ //Detect important whitespace combinations.
+ if(c == ' ')
+ {
+ if(index == 0){leadingSpace = true;}
+ if(index == scalar.length - 1){trailingSpace = true;}
+ if(previousBreak){breakSpace = true;}
+ previousSpace = true;
+ previousBreak = false;
+ }
+ else if(c.isNewLine)
+ {
+ if(index == 0){leadingBreak = true;}
+ if(index == scalar.length - 1){trailingBreak = true;}
+ if(previousSpace){spaceBreak = true;}
+ previousSpace = false;
+ previousBreak = true;
+ }
+ else
+ {
+ previousSpace = previousBreak = false;
+ }
+
+ //Prepare for the next character.
+ preceededByWhitespace = c.isSpace != 0;
+ followedByWhitespace = index + 2 >= scalar.length ||
+ scalar[index + 2].isSpace;
+ }
+
+ with(ScalarAnalysis.AnalysisFlags)
+ {
+ //Let's decide what styles are allowed.
+ analysis.flags |= allowFlowPlain | allowBlockPlain | allowSingleQuoted |
+ allowDoubleQuoted | allowBlock;
+
+ //Leading and trailing whitespaces are bad for plain scalars.
+ if(leadingSpace || leadingBreak || trailingSpace || trailingBreak)
+ {
+ analysis.flags &= ~(allowFlowPlain | allowBlockPlain);
+ }
+
+ //We do not permit trailing spaces for block scalars.
+ if(trailingSpace)
+ {
+ analysis.flags &= ~allowBlock;
+ }
+
+ //Spaces at the beginning of a new line are only acceptable for block
+ //scalars.
+ if(breakSpace)
+ {
+ analysis.flags &= ~(allowFlowPlain | allowBlockPlain | allowSingleQuoted);
+ }
+
+ //Spaces followed by breaks, as well as special character are only
+ //allowed for double quoted scalars.
+ if(spaceBreak || specialCharacters)
+ {
+ analysis.flags &= ~(allowFlowPlain | allowBlockPlain | allowSingleQuoted | allowBlock);
+ }
+
+ //Although the plain scalar writer supports breaks, we never emit
+ //multiline plain scalars.
+ if(lineBreaks)
+ {
+ analysis.flags &= ~(allowFlowPlain | allowBlockPlain);
+ analysis.flags |= multiline;
+ }
+
+ //Flow indicators are forbidden for flow plain scalars.
+ if(flowIndicators)
+ {
+ analysis.flags &= ~allowFlowPlain;
+ }
+
+ //Block indicators are forbidden for block plain scalars.
+ if(blockIndicators)
+ {
+ analysis.flags &= ~allowBlockPlain;
+ }
+ }
+ return analysis;
+ }
+
+ @safe unittest
+ {
+ with(analyzeScalar("").flags)
+ {
+ // workaround for empty being std.range.primitives.empty here
+ alias empty = ScalarAnalysis.AnalysisFlags.empty;
+ assert(empty && allowBlockPlain && allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar("a").flags)
+ {
+ assert(allowFlowPlain && allowBlockPlain && allowSingleQuoted && allowDoubleQuoted && allowBlock);
+ }
+ with(analyzeScalar(" ").flags)
+ {
+ assert(allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar(" a").flags)
+ {
+ assert(allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar("a ").flags)
+ {
+ assert(allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar("\na").flags)
+ {
+ assert(allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar("a\n").flags)
+ {
+ assert(allowSingleQuoted && allowDoubleQuoted);
+ }
+ with(analyzeScalar("\n").flags)
+ {
+ assert(multiline && allowSingleQuoted && allowDoubleQuoted && allowBlock);
+ }
+ with(analyzeScalar(" \n").flags)
+ {
+ assert(multiline && allowDoubleQuoted);
+ }
+ with(analyzeScalar("\n a").flags)
+ {
+ assert(multiline && allowDoubleQuoted && allowBlock);
+ }
+ }
+
+ //Writers.
+
+ ///Start the YAML stream (write the unicode byte order mark).
+ void writeStreamStart() @safe
+ {
+ //Write BOM (except for UTF-8)
+ static if(is(CharType == wchar) || is(CharType == dchar))
+ {
+ stream_.put(cast(CharType)'\uFEFF');
+ }
+ }
+
+ ///End the YAML stream.
+ void writeStreamEnd() @safe {}
+
+ ///Write an indicator (e.g. ":", "[", ">", etc.).
+ void writeIndicator(const scope char[] indicator,
+ const Flag!"needWhitespace" needWhitespace,
+ const Flag!"whitespace" whitespace = No.whitespace,
+ const Flag!"indentation" indentation = No.indentation) @safe
+ {
+ const bool prefixSpace = !whitespace_ && needWhitespace;
+ whitespace_ = whitespace;
+ indentation_ = indentation_ && indentation;
+ openEnded_ = false;
+ column_ += indicator.length;
+ if(prefixSpace)
+ {
+ ++column_;
+ writeString(" ");
+ }
+ writeString(indicator);
+ }
+
+ ///Write indentation.
+ void writeIndent() @safe
+ {
+ const indent = indent_ == -1 ? 0 : indent_;
+
+ if(!indentation_ || column_ > indent || (column_ == indent && !whitespace_))
+ {
+ writeLineBreak();
+ }
+ if(column_ < indent)
+ {
+ whitespace_ = true;
+
+ //Used to avoid allocation of arbitrary length strings.
+ static immutable spaces = " ";
+ size_t numSpaces = indent - column_;
+ column_ = indent;
+ while(numSpaces >= spaces.length)
+ {
+ writeString(spaces);
+ numSpaces -= spaces.length;
+ }
+ writeString(spaces[0 .. numSpaces]);
+ }
+ }
+
+ ///Start new line.
+ void writeLineBreak(const scope char[] data = null) @safe
+ {
+ whitespace_ = indentation_ = true;
+ ++line_;
+ column_ = 0;
+ writeString(data is null ? lineBreak(bestLineBreak_) : data);
+ }
+
+ ///Write a YAML version directive.
+ void writeVersionDirective(const string versionText) @safe
+ {
+ writeString("%YAML ");
+ writeString(versionText);
+ writeLineBreak();
+ }
+
+ ///Write a tag directive.
+ void writeTagDirective(const string handle, const string prefix) @safe
+ {
+ writeString("%TAG ");
+ writeString(handle);
+ writeString(" ");
+ writeString(prefix);
+ writeLineBreak();
+ }
+ void nextExpected(string D)() @safe
+ {
+ state_ = mixin("function(typeof(this)* self) { self."~D~"(); }");
+ }
+ void nextExpected(EmitterFunction f) @safe
+ {
+ state_ = f;
+ }
+ void callNext() @safe
+ {
+ state_(&this);
+ }
+}
+
+
+private:
+
+///RAII struct used to write out scalar values.
+struct ScalarWriter(Range, CharType)
+{
+ invariant()
+ {
+ assert(emitter_.bestIndent_ > 0 && emitter_.bestIndent_ < 10,
+ "Emitter bestIndent must be 1 to 9 for one-character indent hint");
+ }
+
+ private:
+ @disable int opCmp(ref Emitter!(Range, CharType));
+ @disable bool opEquals(ref Emitter!(Range, CharType));
+
+ ///Used as "null" UTF-32 character.
+ static immutable dcharNone = dchar.max;
+
+ ///Emitter used to emit the scalar.
+ Emitter!(Range, CharType)* emitter_;
+
+ ///UTF-8 encoded text of the scalar to write.
+ string text_;
+
+ ///Can we split the scalar into multiple lines?
+ bool split_;
+ ///Are we currently going over spaces in the text?
+ bool spaces_;
+ ///Are we currently going over line breaks in the text?
+ bool breaks_;
+
+ ///Start and end byte of the text range we're currently working with.
+ size_t startByte_, endByte_;
+ ///End byte of the text range including the currently processed character.
+ size_t nextEndByte_;
+ ///Start and end character of the text range we're currently working with.
+ long startChar_, endChar_;
+
+ public:
+ ///Construct a ScalarWriter using emitter to output text.
+ this(Emitter!(Range, CharType)* emitter, string text, const bool split = true) @safe nothrow
+ {
+ emitter_ = emitter;
+ text_ = text;
+ split_ = split;
+ }
+
+ ///Write text as single quoted scalar.
+ void writeSingleQuoted() @safe
+ {
+ emitter_.writeIndicator("\'", Yes.needWhitespace);
+ spaces_ = breaks_ = false;
+ resetTextPosition();
+
+ do
+ {
+ const dchar c = nextChar();
+ if(spaces_)
+ {
+ if(c != ' ' && tooWide() && split_ &&
+ startByte_ != 0 && endByte_ != text_.length)
+ {
+ writeIndent(Flag!"ResetSpace".no);
+ updateRangeStart();
+ }
+ else if(c != ' ')
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ }
+ else if(breaks_)
+ {
+ if(!c.isNewLine)
+ {
+ writeStartLineBreak();
+ writeLineBreaks();
+ emitter_.writeIndent();
+ }
+ }
+ else if((c == dcharNone || c == '\'' || c == ' ' || c.isNewLine)
+ && startChar_ < endChar_)
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ if(c == '\'')
+ {
+ emitter_.column_ += 2;
+ emitter_.writeString("\'\'");
+ startByte_ = endByte_ + 1;
+ startChar_ = endChar_ + 1;
+ }
+ updateBreaks(c, Flag!"UpdateSpaces".yes);
+ }while(endByte_ < text_.length);
+
+ emitter_.writeIndicator("\'", No.needWhitespace);
+ }
+
+ ///Write text as double quoted scalar.
+ void writeDoubleQuoted() @safe
+ {
+ resetTextPosition();
+ emitter_.writeIndicator("\"", Yes.needWhitespace);
+ do
+ {
+ const dchar c = nextChar();
+ //handle special characters
+ if(c == dcharNone || c.among!('\"', '\\', '\u0085', '\u2028', '\u2029', '\uFEFF') ||
+ !((c >= '\x20' && c <= '\x7E') ||
+ ((c >= '\xA0' && c <= '\uD7FF') || (c >= '\uE000' && c <= '\uFFFD'))))
+ {
+ if(startChar_ < endChar_)
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ if(c != dcharNone)
+ {
+ auto appender = appender!string();
+ if(const dchar es = toEscape(c))
+ {
+ appender.put('\\');
+ appender.put(es);
+ }
+ else
+ {
+ //Write an escaped Unicode character.
+ const format = c <= 255 ? "\\x%02X":
+ c <= 65535 ? "\\u%04X": "\\U%08X";
+ formattedWrite(appender, format, cast(uint)c);
+ }
+
+ emitter_.column_ += appender.data.length;
+ emitter_.writeString(appender.data);
+ startChar_ = endChar_ + 1;
+ startByte_ = nextEndByte_;
+ }
+ }
+ if((endByte_ > 0 && endByte_ < text_.length - strideBack(text_, text_.length))
+ && (c == ' ' || startChar_ >= endChar_)
+ && (emitter_.column_ + endChar_ - startChar_ > emitter_.bestWidth_)
+ && split_)
+ {
+ //text_[2:1] is ok in Python but not in D, so we have to use min()
+ emitter_.writeString(text_[min(startByte_, endByte_) .. endByte_]);
+ emitter_.writeString("\\");
+ emitter_.column_ += startChar_ - endChar_ + 1;
+ startChar_ = max(startChar_, endChar_);
+ startByte_ = max(startByte_, endByte_);
+
+ writeIndent(Flag!"ResetSpace".yes);
+ if(charAtStart() == ' ')
+ {
+ emitter_.writeString("\\");
+ ++emitter_.column_;
+ }
+ }
+ }while(endByte_ < text_.length);
+ emitter_.writeIndicator("\"", No.needWhitespace);
+ }
+
+ ///Write text as folded block scalar.
+ void writeFolded() @safe
+ {
+ initBlock('>');
+ bool leadingSpace = true;
+ spaces_ = false;
+ breaks_ = true;
+ resetTextPosition();
+
+ do
+ {
+ const dchar c = nextChar();
+ if(breaks_)
+ {
+ if(!c.isNewLine)
+ {
+ if(!leadingSpace && c != dcharNone && c != ' ')
+ {
+ writeStartLineBreak();
+ }
+ leadingSpace = (c == ' ');
+ writeLineBreaks();
+ if(c != dcharNone){emitter_.writeIndent();}
+ }
+ }
+ else if(spaces_)
+ {
+ if(c != ' ' && tooWide())
+ {
+ writeIndent(Flag!"ResetSpace".no);
+ updateRangeStart();
+ }
+ else if(c != ' ')
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ }
+ else if(c == dcharNone || c.isNewLine || c == ' ')
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ if(c == dcharNone){emitter_.writeLineBreak();}
+ }
+ updateBreaks(c, Flag!"UpdateSpaces".yes);
+ }while(endByte_ < text_.length);
+ }
+
+ ///Write text as literal block scalar.
+ void writeLiteral() @safe
+ {
+ initBlock('|');
+ breaks_ = true;
+ resetTextPosition();
+
+ do
+ {
+ const dchar c = nextChar();
+ if(breaks_)
+ {
+ if(!c.isNewLine)
+ {
+ writeLineBreaks();
+ if(c != dcharNone){emitter_.writeIndent();}
+ }
+ }
+ else if(c == dcharNone || c.isNewLine)
+ {
+ writeCurrentRange(Flag!"UpdateColumn".no);
+ if(c == dcharNone){emitter_.writeLineBreak();}
+ }
+ updateBreaks(c, Flag!"UpdateSpaces".no);
+ }while(endByte_ < text_.length);
+ }
+
+ ///Write text as plain scalar.
+ void writePlain() @safe
+ {
+ if(emitter_.context_ == Emitter!(Range, CharType).Context.root){emitter_.openEnded_ = true;}
+ if(text_ == ""){return;}
+ if(!emitter_.whitespace_)
+ {
+ ++emitter_.column_;
+ emitter_.writeString(" ");
+ }
+ emitter_.whitespace_ = emitter_.indentation_ = false;
+ spaces_ = breaks_ = false;
+ resetTextPosition();
+
+ do
+ {
+ const dchar c = nextChar();
+ if(spaces_)
+ {
+ if(c != ' ' && tooWide() && split_)
+ {
+ writeIndent(Flag!"ResetSpace".yes);
+ updateRangeStart();
+ }
+ else if(c != ' ')
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ }
+ else if(breaks_)
+ {
+ if(!c.isNewLine)
+ {
+ writeStartLineBreak();
+ writeLineBreaks();
+ writeIndent(Flag!"ResetSpace".yes);
+ }
+ }
+ else if(c == dcharNone || c.isNewLine || c == ' ')
+ {
+ writeCurrentRange(Flag!"UpdateColumn".yes);
+ }
+ updateBreaks(c, Flag!"UpdateSpaces".yes);
+ }while(endByte_ < text_.length);
+ }
+
+ private:
+ ///Get next character and move end of the text range to it.
+ @property dchar nextChar() pure @safe
+ {
+ ++endChar_;
+ endByte_ = nextEndByte_;
+ if(endByte_ >= text_.length){return dcharNone;}
+ const c = text_[nextEndByte_];
+ //c is ascii, no need to decode.
+ if(c < 0x80)
+ {
+ ++nextEndByte_;
+ return c;
+ }
+ return decode(text_, nextEndByte_);
+ }
+
+ ///Get character at start of the text range.
+ @property dchar charAtStart() const pure @safe
+ {
+ size_t idx = startByte_;
+ return decode(text_, idx);
+ }
+
+ ///Is the current line too wide?
+ @property bool tooWide() const pure @safe nothrow
+ {
+ return startChar_ + 1 == endChar_ &&
+ emitter_.column_ > emitter_.bestWidth_;
+ }
+
+ ///Determine hints (indicators) for block scalar.
+ size_t determineBlockHints(char[] hints, uint bestIndent) const pure @safe
+ {
+ size_t hintsIdx;
+ if(text_.length == 0)
+ return hintsIdx;
+
+ dchar lastChar(const string str, ref size_t end)
+ {
+ size_t idx = end = end - strideBack(str, end);
+ return decode(text_, idx);
+ }
+
+ size_t end = text_.length;
+ const last = lastChar(text_, end);
+ const secondLast = end > 0 ? lastChar(text_, end) : 0;
+
+ if(text_[0].isNewLine || text_[0] == ' ')
+ {
+ hints[hintsIdx++] = cast(char)('0' + bestIndent);
+ }
+ if(!last.isNewLine)
+ {
+ hints[hintsIdx++] = '-';
+ }
+ else if(std.utf.count(text_) == 1 || secondLast.isNewLine)
+ {
+ hints[hintsIdx++] = '+';
+ }
+ return hintsIdx;
+ }
+
+ ///Initialize for block scalar writing with specified indicator.
+ void initBlock(const char indicator) @safe
+ {
+ char[4] hints;
+ hints[0] = indicator;
+ const hintsLength = 1 + determineBlockHints(hints[1 .. $], emitter_.bestIndent_);
+ emitter_.writeIndicator(hints[0 .. hintsLength], Yes.needWhitespace);
+ if(hints.length > 0 && hints[$ - 1] == '+')
+ {
+ emitter_.openEnded_ = true;
+ }
+ emitter_.writeLineBreak();
+ }
+
+ ///Write out the current text range.
+ void writeCurrentRange(const Flag!"UpdateColumn" updateColumn) @safe
+ {
+ emitter_.writeString(text_[startByte_ .. endByte_]);
+ if(updateColumn){emitter_.column_ += endChar_ - startChar_;}
+ updateRangeStart();
+ }
+
+ ///Write line breaks in the text range.
+ void writeLineBreaks() @safe
+ {
+ foreach(const dchar br; text_[startByte_ .. endByte_])
+ {
+ if(br == '\n'){emitter_.writeLineBreak();}
+ else
+ {
+ char[4] brString;
+ const bytes = encode(brString, br);
+ emitter_.writeLineBreak(brString[0 .. bytes]);
+ }
+ }
+ updateRangeStart();
+ }
+
+ ///Write line break if start of the text range is a newline.
+ void writeStartLineBreak() @safe
+ {
+ if(charAtStart == '\n'){emitter_.writeLineBreak();}
+ }
+
+ ///Write indentation, optionally resetting whitespace/indentation flags.
+ void writeIndent(const Flag!"ResetSpace" resetSpace) @safe
+ {
+ emitter_.writeIndent();
+ if(resetSpace)
+ {
+ emitter_.whitespace_ = emitter_.indentation_ = false;
+ }
+ }
+
+ ///Move start of text range to its end.
+ void updateRangeStart() pure @safe nothrow
+ {
+ startByte_ = endByte_;
+ startChar_ = endChar_;
+ }
+
+ ///Update the line breaks_ flag, optionally updating the spaces_ flag.
+ void updateBreaks(in dchar c, const Flag!"UpdateSpaces" updateSpaces) pure @safe
+ {
+ if(c == dcharNone){return;}
+ breaks_ = (c.isNewLine != 0);
+ if(updateSpaces){spaces_ = c == ' ';}
+ }
+
+ ///Move to the beginning of text.
+ void resetTextPosition() pure @safe nothrow
+ {
+ startByte_ = endByte_ = nextEndByte_ = 0;
+ startChar_ = endChar_ = -1;
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/encoding.d b/src/ext_depends/D-YAML/source/dyaml/encoding.d
new file mode 100644
index 0000000..50c10b9
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/encoding.d
@@ -0,0 +1,11 @@
+// Copyright Ferdinand Majerech 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.encoding;
+
+
+import tinyendian;
+
+alias Encoding = tinyendian.UTFEncoding;
diff --git a/src/ext_depends/D-YAML/source/dyaml/escapes.d b/src/ext_depends/D-YAML/source/dyaml/escapes.d
new file mode 100644
index 0000000..32080a2
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/escapes.d
@@ -0,0 +1,92 @@
+
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.escapes;
+
+package:
+
+import std.meta : AliasSeq;
+alias escapes = AliasSeq!('0', 'a', 'b', 't', '\t', 'n', 'v', 'f', 'r', 'e', ' ',
+ '\"', '\\', 'N', '_', 'L', 'P');
+
+/// YAML hex codes specifying the length of the hex number.
+alias escapeHexCodeList = AliasSeq!('x', 'u', 'U');
+
+/// Convert a YAML escape to a dchar.
+dchar fromEscape(dchar escape) @safe pure nothrow @nogc
+{
+ switch(escape)
+ {
+ case '0': return '\0';
+ case 'a': return '\x07';
+ case 'b': return '\x08';
+ case 't': return '\x09';
+ case '\t': return '\x09';
+ case 'n': return '\x0A';
+ case 'v': return '\x0B';
+ case 'f': return '\x0C';
+ case 'r': return '\x0D';
+ case 'e': return '\x1B';
+ case ' ': return '\x20';
+ case '\"': return '\"';
+ case '\\': return '\\';
+ case 'N': return '\x85'; //'\u0085';
+ case '_': return '\xA0';
+ case 'L': return '\u2028';
+ case 'P': return '\u2029';
+ default: assert(false, "No such YAML escape");
+ }
+}
+
+/**
+ * Convert a dchar to a YAML escape.
+ *
+ * Params:
+ * value = The possibly escapable character.
+ *
+ * Returns:
+ * If the character passed as parameter can be escaped, returns the matching
+ * escape, otherwise returns a null character.
+ */
+dchar toEscape(dchar value) @safe pure nothrow @nogc
+{
+ switch(value)
+ {
+ case '\0': return '0';
+ case '\x07': return 'a';
+ case '\x08': return 'b';
+ case '\x09': return 't';
+ case '\x0A': return 'n';
+ case '\x0B': return 'v';
+ case '\x0C': return 'f';
+ case '\x0D': return 'r';
+ case '\x1B': return 'e';
+ case '\"': return '\"';
+ case '\\': return '\\';
+ case '\xA0': return '_';
+ case '\x85': return 'N';
+ case '\u2028': return 'L';
+ case '\u2029': return 'P';
+ default: return 0;
+ }
+}
+
+/// Get the length of a hexadecimal number determined by its hex code.
+///
+/// Need a function as associative arrays don't work with @nogc.
+/// (And this may be even faster with a function.)
+uint escapeHexLength(dchar hexCode) @safe pure nothrow @nogc
+{
+ switch(hexCode)
+ {
+ case 'x': return 2;
+ case 'u': return 4;
+ case 'U': return 8;
+ default: assert(false, "No such YAML hex code");
+ }
+}
+
diff --git a/src/ext_depends/D-YAML/source/dyaml/event.d b/src/ext_depends/D-YAML/source/dyaml/event.d
new file mode 100644
index 0000000..f4a747f
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/event.d
@@ -0,0 +1,243 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML events.
+ * Code based on PyYAML: http://www.pyyaml.org
+ */
+module dyaml.event;
+
+import std.array;
+import std.conv;
+
+import dyaml.exception;
+import dyaml.reader;
+import dyaml.tagdirective;
+import dyaml.style;
+
+
+package:
+///Event types.
+enum EventID : ubyte
+{
+ invalid = 0, /// Invalid (uninitialized) event.
+ streamStart, /// Stream start
+ streamEnd, /// Stream end
+ documentStart, /// Document start
+ documentEnd, /// Document end
+ alias_, /// Alias
+ scalar, /// Scalar
+ sequenceStart, /// Sequence start
+ sequenceEnd, /// Sequence end
+ mappingStart, /// Mapping start
+ mappingEnd /// Mapping end
+}
+
+/**
+ * YAML event produced by parser.
+ *
+ * 48 bytes on 64bit.
+ */
+struct Event
+{
+ @disable int opCmp(ref Event);
+
+ ///Value of the event, if any.
+ string value;
+ ///Start position of the event in file/stream.
+ Mark startMark;
+ ///End position of the event in file/stream.
+ Mark endMark;
+ union
+ {
+ struct
+ {
+ ///Anchor of the event, if any.
+ string _anchor;
+ ///Tag of the event, if any.
+ string _tag;
+ }
+ ///Tag directives, if this is a DocumentStart.
+ //TagDirectives tagDirectives;
+ TagDirective[] _tagDirectives;
+ }
+ ///Event type.
+ EventID id = EventID.invalid;
+ ///Style of scalar event, if this is a scalar event.
+ ScalarStyle scalarStyle = ScalarStyle.invalid;
+ union
+ {
+ ///Should the tag be implicitly resolved?
+ bool implicit;
+ /**
+ * Is this document event explicit?
+ *
+ * Used if this is a DocumentStart or DocumentEnd.
+ */
+ bool explicitDocument;
+ }
+ ///Collection style, if this is a SequenceStart or MappingStart.
+ CollectionStyle collectionStyle = CollectionStyle.invalid;
+
+ ///Is this a null (uninitialized) event?
+ @property bool isNull() const pure @safe nothrow {return id == EventID.invalid;}
+
+ ///Get string representation of the token ID.
+ @property string idString() const @safe {return to!string(id);}
+
+ auto ref anchor() inout @trusted pure {
+ assert(id != EventID.documentStart, "DocumentStart events cannot have anchors.");
+ return _anchor;
+ }
+
+ auto ref tag() inout @trusted pure {
+ assert(id != EventID.documentStart, "DocumentStart events cannot have tags.");
+ return _tag;
+ }
+
+ auto ref tagDirectives() inout @trusted pure {
+ assert(id == EventID.documentStart, "Only DocumentStart events have tag directives.");
+ return _tagDirectives;
+ }
+}
+
+/**
+ * Construct a simple event.
+ *
+ * Params: start = Start position of the event in the file/stream.
+ * end = End position of the event in the file/stream.
+ * anchor = Anchor, if this is an alias event.
+ */
+Event event(EventID id)(const Mark start, const Mark end, const string anchor = null)
+ @safe
+ in(!(id == EventID.alias_ && anchor == ""), "Missing anchor for alias event")
+{
+ Event result;
+ result.startMark = start;
+ result.endMark = end;
+ result.anchor = anchor;
+ result.id = id;
+ return result;
+}
+
+/**
+ * Construct a collection (mapping or sequence) start event.
+ *
+ * Params: start = Start position of the event in the file/stream.
+ * end = End position of the event in the file/stream.
+ * anchor = Anchor of the sequence, if any.
+ * tag = Tag of the sequence, if specified.
+ * implicit = Should the tag be implicitly resolved?
+ * style = Style to use when outputting document.
+ */
+Event collectionStartEvent(EventID id)
+ (const Mark start, const Mark end, const string anchor, const string tag,
+ const bool implicit, const CollectionStyle style) pure @safe nothrow
+{
+ static assert(id == EventID.sequenceStart || id == EventID.sequenceEnd ||
+ id == EventID.mappingStart || id == EventID.mappingEnd);
+ Event result;
+ result.startMark = start;
+ result.endMark = end;
+ result.anchor = anchor;
+ result.tag = tag;
+ result.id = id;
+ result.implicit = implicit;
+ result.collectionStyle = style;
+ return result;
+}
+
+/**
+ * Construct a stream start event.
+ *
+ * Params: start = Start position of the event in the file/stream.
+ * end = End position of the event in the file/stream.
+ */
+Event streamStartEvent(const Mark start, const Mark end)
+ pure @safe nothrow
+{
+ Event result;
+ result.startMark = start;
+ result.endMark = end;
+ result.id = EventID.streamStart;
+ return result;
+}
+
+///Aliases for simple events.
+alias streamEndEvent = event!(EventID.streamEnd);
+alias aliasEvent = event!(EventID.alias_);
+alias sequenceEndEvent = event!(EventID.sequenceEnd);
+alias mappingEndEvent = event!(EventID.mappingEnd);
+
+///Aliases for collection start events.
+alias sequenceStartEvent = collectionStartEvent!(EventID.sequenceStart);
+alias mappingStartEvent = collectionStartEvent!(EventID.mappingStart);
+
+/**
+ * Construct a document start event.
+ *
+ * Params: start = Start position of the event in the file/stream.
+ * end = End position of the event in the file/stream.
+ * explicit = Is this an explicit document start?
+ * YAMLVersion = YAML version string of the document.
+ * tagDirectives = Tag directives of the document.
+ */
+Event documentStartEvent(const Mark start, const Mark end, const bool explicit, string YAMLVersion,
+ TagDirective[] tagDirectives) pure @safe nothrow
+{
+ Event result;
+ result.value = YAMLVersion;
+ result.startMark = start;
+ result.endMark = end;
+ result.id = EventID.documentStart;
+ result.explicitDocument = explicit;
+ result.tagDirectives = tagDirectives;
+ return result;
+}
+
+/**
+ * Construct a document end event.
+ *
+ * Params: start = Start position of the event in the file/stream.
+ * end = End position of the event in the file/stream.
+ * explicit = Is this an explicit document end?
+ */
+Event documentEndEvent(const Mark start, const Mark end, const bool explicit) pure @safe nothrow
+{
+ Event result;
+ result.startMark = start;
+ result.endMark = end;
+ result.id = EventID.documentEnd;
+ result.explicitDocument = explicit;
+ return result;
+}
+
+/// Construct a scalar event.
+///
+/// Params: start = Start position of the event in the file/stream.
+/// end = End position of the event in the file/stream.
+/// anchor = Anchor of the scalar, if any.
+/// tag = Tag of the scalar, if specified.
+/// implicit = Should the tag be implicitly resolved?
+/// value = String value of the scalar.
+/// style = Scalar style.
+Event scalarEvent(const Mark start, const Mark end, const string anchor, const string tag,
+ const bool implicit, const string value,
+ const ScalarStyle style = ScalarStyle.invalid) @safe pure nothrow @nogc
+{
+ Event result;
+ result.value = value;
+ result.startMark = start;
+ result.endMark = end;
+
+ result.anchor = anchor;
+ result.tag = tag;
+
+ result.id = EventID.scalar;
+ result.scalarStyle = style;
+ result.implicit = implicit;
+ return result;
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/exception.d b/src/ext_depends/D-YAML/source/dyaml/exception.d
new file mode 100644
index 0000000..2f13a44
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/exception.d
@@ -0,0 +1,159 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+///Exceptions thrown by D:YAML and _exception related code.
+module dyaml.exception;
+
+
+import std.algorithm;
+import std.array;
+import std.string;
+import std.conv;
+
+
+/// Base class for all exceptions thrown by D:YAML.
+class YAMLException : Exception
+{
+ /// Construct a YAMLException with specified message and position where it was thrown.
+ public this(string msg, string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(msg, file, line);
+ }
+}
+
+/// Position in a YAML stream, used for error messages.
+struct Mark
+{
+ package:
+ /// File name.
+ string name_;
+ /// Line number.
+ ushort line_;
+ /// Column number.
+ ushort column_;
+
+ public:
+ /// Construct a Mark with specified line and column in the file.
+ this(string name, const uint line, const uint column) @safe pure nothrow @nogc
+ {
+ name_ = name;
+ line_ = cast(ushort)min(ushort.max, line);
+ // This *will* overflow on extremely wide files but saves CPU time
+ // (mark ctor takes ~5% of time)
+ column_ = cast(ushort)column;
+ }
+
+ /// Get a file name.
+ @property string name() @safe pure nothrow @nogc const
+ {
+ return name_;
+ }
+
+ /// Get a line number.
+ @property ushort line() @safe pure nothrow @nogc const
+ {
+ return line_;
+ }
+
+ /// Get a column number.
+ @property ushort column() @safe pure nothrow @nogc const
+ {
+ return column_;
+ }
+
+ /// Get a string representation of the mark.
+ string toString() @safe pure nothrow const
+ {
+ // Line/column numbers start at zero internally, make them start at 1.
+ static string clamped(ushort v) @safe pure nothrow
+ {
+ return text(v + 1, v == ushort.max ? " or higher" : "");
+ }
+ return "file " ~ name_ ~ ",line " ~ clamped(line_) ~ ",column " ~ clamped(column_);
+ }
+}
+
+package:
+// A struct storing parameters to the MarkedYAMLException constructor.
+struct MarkedYAMLExceptionData
+{
+ // Context of the error.
+ string context;
+ // Position of the context in a YAML buffer.
+ Mark contextMark;
+ // The error itself.
+ string problem;
+ // Position if the error.
+ Mark problemMark;
+}
+
+// Base class of YAML exceptions with marked positions of the problem.
+abstract class MarkedYAMLException : YAMLException
+{
+ // Construct a MarkedYAMLException with specified context and problem.
+ this(string context, const Mark contextMark, string problem, const Mark problemMark,
+ string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
+ {
+ const msg = context ~ '\n' ~
+ (contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~
+ problem ~ '\n' ~ problemMark.toString() ~ '\n';
+ super(msg, file, line);
+ }
+
+ // Construct a MarkedYAMLException with specified problem.
+ this(string problem, const Mark problemMark,
+ string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(problem ~ '\n' ~ problemMark.toString(), file, line);
+ }
+
+ /// Construct a MarkedYAMLException from a struct storing constructor parameters.
+ this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
+ {
+ with(data) this(context, contextMark, problem, problemMark);
+ }
+}
+
+// Constructors of YAML exceptions are mostly the same, so we use a mixin.
+//
+// See_Also: YAMLException
+template ExceptionCtors()
+{
+ public this(string msg, string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(msg, file, line);
+ }
+}
+
+// Constructors of marked YAML exceptions are mostly the same, so we use a mixin.
+//
+// See_Also: MarkedYAMLException
+template MarkedExceptionCtors()
+{
+ public:
+ this(string context, const Mark contextMark, string problem,
+ const Mark problemMark, string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(context, contextMark, problem, problemMark,
+ file, line);
+ }
+
+ this(string problem, const Mark problemMark,
+ string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super(problem, problemMark, file, line);
+ }
+
+ this(ref const(MarkedYAMLExceptionData) data) @safe pure nothrow
+ {
+ super(data);
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/linebreak.d b/src/ext_depends/D-YAML/source/dyaml/linebreak.d
new file mode 100644
index 0000000..1f0f661
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/linebreak.d
@@ -0,0 +1,32 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.linebreak;
+
+
+///Enumerates platform specific line breaks.
+enum LineBreak
+{
+ ///Unix line break ("\n").
+ unix,
+ ///Windows line break ("\r\n").
+ windows,
+ ///Macintosh line break ("\r").
+ macintosh
+}
+
+package:
+
+//Get line break string for specified line break.
+string lineBreak(in LineBreak b) pure @safe nothrow
+{
+ final switch(b)
+ {
+ case LineBreak.unix: return "\n";
+ case LineBreak.windows: return "\r\n";
+ case LineBreak.macintosh: return "\r";
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/loader.d b/src/ext_depends/D-YAML/source/dyaml/loader.d
new file mode 100644
index 0000000..7e7096c
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/loader.d
@@ -0,0 +1,394 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/// Class used to load YAML documents.
+module dyaml.loader;
+
+
+import std.exception;
+import std.file;
+import std.stdio : File;
+import std.string;
+
+import dyaml.composer;
+import dyaml.constructor;
+import dyaml.event;
+import dyaml.exception;
+import dyaml.node;
+import dyaml.parser;
+import dyaml.reader;
+import dyaml.resolver;
+import dyaml.scanner;
+import dyaml.token;
+
+
+/** Loads YAML documents from files or char[].
+ *
+ * User specified Constructor and/or Resolver can be used to support new
+ * tags / data types.
+ */
+struct Loader
+{
+ private:
+ // Processes character data to YAML tokens.
+ Scanner scanner_;
+ // Processes tokens to YAML events.
+ Parser parser_;
+ // Resolves tags (data types).
+ Resolver resolver_;
+ // Name of the input file or stream, used in error messages.
+ string name_ = "<unknown>";
+ // Are we done loading?
+ bool done_;
+ // Last node read from stream
+ Node currentNode;
+ // Has the range interface been initialized yet?
+ bool rangeInitialized;
+
+ public:
+ @disable this();
+ @disable int opCmp(ref Loader);
+ @disable bool opEquals(ref Loader);
+
+ /** Construct a Loader to load YAML from a file.
+ *
+ * Params: filename = Name of the file to load from.
+ * file = Already-opened file to load from.
+ *
+ * Throws: YAMLException if the file could not be opened or read.
+ */
+ static Loader fromFile(string filename) @trusted
+ {
+ try
+ {
+ auto loader = Loader(std.file.read(filename), filename);
+ return loader;
+ }
+ catch(FileException e)
+ {
+ throw new YAMLException("Unable to open file %s for YAML loading: %s"
+ .format(filename, e.msg), e.file, e.line);
+ }
+ }
+ /// ditto
+ static Loader fromFile(File file) @system
+ {
+ auto loader = Loader(file.byChunk(4096).join, file.name);
+ return loader;
+ }
+
+ /** Construct a Loader to load YAML from a string.
+ *
+ * Params: data = String to load YAML from. The char[] version $(B will)
+ * overwrite its input during parsing as D:YAML reuses memory.
+ *
+ * Returns: Loader loading YAML from given string.
+ *
+ * Throws:
+ *
+ * YAMLException if data could not be read (e.g. a decoding error)
+ */
+ static Loader fromString(char[] data) @safe
+ {
+ return Loader(cast(ubyte[])data);
+ }
+ /// Ditto
+ static Loader fromString(string data) @safe
+ {
+ return fromString(data.dup);
+ }
+ /// Load a char[].
+ @safe unittest
+ {
+ assert(Loader.fromString("42".dup).load().as!int == 42);
+ }
+ /// Load a string.
+ @safe unittest
+ {
+ assert(Loader.fromString("42").load().as!int == 42);
+ }
+
+ /** Construct a Loader to load YAML from a buffer.
+ *
+ * Params: yamlData = Buffer with YAML data to load. This may be e.g. a file
+ * loaded to memory or a string with YAML data. Note that
+ * buffer $(B will) be overwritten, as D:YAML minimizes
+ * memory allocations by reusing the input _buffer.
+ * $(B Must not be deleted or modified by the user as long
+ * as nodes loaded by this Loader are in use!) - Nodes may
+ * refer to data in this buffer.
+ *
+ * Note that D:YAML looks for byte-order-marks YAML files encoded in
+ * UTF-16/UTF-32 (and sometimes UTF-8) use to specify the encoding and
+ * endianness, so it should be enough to load an entire file to a buffer and
+ * pass it to D:YAML, regardless of Unicode encoding.
+ *
+ * Throws: YAMLException if yamlData contains data illegal in YAML.
+ */
+ static Loader fromBuffer(ubyte[] yamlData) @safe
+ {
+ return Loader(yamlData);
+ }
+ /// Ditto
+ static Loader fromBuffer(void[] yamlData) @system
+ {
+ return Loader(yamlData);
+ }
+ /// Ditto
+ private this(void[] yamlData, string name = "<unknown>") @system
+ {
+ this(cast(ubyte[])yamlData, name);
+ }
+ /// Ditto
+ private this(ubyte[] yamlData, string name = "<unknown>") @safe
+ {
+ resolver_ = Resolver.withDefaultResolvers;
+ name_ = name;
+ try
+ {
+ auto reader_ = new Reader(yamlData, name);
+ scanner_ = Scanner(reader_);
+ parser_ = new Parser(scanner_);
+ }
+ catch(YAMLException e)
+ {
+ throw new YAMLException("Unable to open %s for YAML loading: %s"
+ .format(name_, e.msg), e.file, e.line);
+ }
+ }
+
+
+ /// Set stream _name. Used in debugging messages.
+ void name(string name) pure @safe nothrow @nogc
+ {
+ name_ = name;
+ }
+
+ /// Specify custom Resolver to use.
+ auto ref resolver() pure @safe nothrow @nogc
+ {
+ return resolver_;
+ }
+
+ /** Load single YAML document.
+ *
+ * If none or more than one YAML document is found, this throws a YAMLException.
+ *
+ * This can only be called once; this is enforced by contract.
+ *
+ * Returns: Root node of the document.
+ *
+ * Throws: YAMLException if there wasn't exactly one document
+ * or on a YAML parsing error.
+ */
+ Node load() @safe
+ {
+ enforce!YAMLException(!empty, "Zero documents in stream");
+ auto output = front;
+ popFront();
+ enforce!YAMLException(empty, "More than one document in stream");
+ return output;
+ }
+
+ /** Implements the empty range primitive.
+ *
+ * If there's no more documents left in the stream, this will be true.
+ *
+ * Returns: `true` if no more documents left, `false` otherwise.
+ */
+ bool empty() @safe
+ {
+ // currentNode and done_ are both invalid until popFront is called once
+ if (!rangeInitialized)
+ {
+ popFront();
+ }
+ return done_;
+ }
+ /** Implements the popFront range primitive.
+ *
+ * Reads the next document from the stream, if possible.
+ */
+ void popFront() @safe
+ {
+ // Composer initialization is done here in case the constructor is
+ // modified, which is a pretty common case.
+ static Composer composer;
+ if (!rangeInitialized)
+ {
+ composer = Composer(parser_, resolver_);
+ rangeInitialized = true;
+ }
+ assert(!done_, "Loader.popFront called on empty range");
+ if (composer.checkNode())
+ {
+ currentNode = composer.getNode();
+ }
+ else
+ {
+ done_ = true;
+ }
+ }
+ /** Implements the front range primitive.
+ *
+ * Returns: the current document as a Node.
+ */
+ Node front() @safe
+ {
+ // currentNode and done_ are both invalid until popFront is called once
+ if (!rangeInitialized)
+ {
+ popFront();
+ }
+ return currentNode;
+ }
+
+ // Scan all tokens, throwing them away. Used for benchmarking.
+ void scanBench() @safe
+ {
+ try
+ {
+ while(!scanner_.empty)
+ {
+ scanner_.popFront();
+ }
+ }
+ catch(YAMLException e)
+ {
+ throw new YAMLException("Unable to scan YAML from stream " ~
+ name_ ~ " : " ~ e.msg, e.file, e.line);
+ }
+ }
+
+
+ // Parse and return all events. Used for debugging.
+ auto parse() @safe
+ {
+ return parser_;
+ }
+}
+/// Load single YAML document from a file:
+@safe unittest
+{
+ write("example.yaml", "Hello world!");
+ auto rootNode = Loader.fromFile("example.yaml").load();
+ assert(rootNode == "Hello world!");
+}
+/// Load single YAML document from an already-opened file:
+@system unittest
+{
+ // Open a temporary file
+ auto file = File.tmpfile;
+ // Write valid YAML
+ file.write("Hello world!");
+ // Return to the beginning
+ file.seek(0);
+ // Load document
+ auto rootNode = Loader.fromFile(file).load();
+ assert(rootNode == "Hello world!");
+}
+/// Load all YAML documents from a file:
+@safe unittest
+{
+ import std.array : array;
+ import std.file : write;
+ write("example.yaml",
+ "---\n"~
+ "Hello world!\n"~
+ "...\n"~
+ "---\n"~
+ "Hello world 2!\n"~
+ "...\n"
+ );
+ auto nodes = Loader.fromFile("example.yaml").array;
+ assert(nodes.length == 2);
+}
+/// Iterate over YAML documents in a file, lazily loading them:
+@safe unittest
+{
+ import std.file : write;
+ write("example.yaml",
+ "---\n"~
+ "Hello world!\n"~
+ "...\n"~
+ "---\n"~
+ "Hello world 2!\n"~
+ "...\n"
+ );
+ auto loader = Loader.fromFile("example.yaml");
+
+ foreach(ref node; loader)
+ {
+ //Do something
+ }
+}
+/// Load YAML from a string:
+@safe unittest
+{
+ string yaml_input = ("red: '#ff0000'\n" ~
+ "green: '#00ff00'\n" ~
+ "blue: '#0000ff'");
+
+ auto colors = Loader.fromString(yaml_input).load();
+
+ foreach(string color, string value; colors)
+ {
+ // Do something with the color and its value...
+ }
+}
+
+/// Load a file into a buffer in memory and then load YAML from that buffer:
+@safe unittest
+{
+ import std.file : read, write;
+ import std.stdio : writeln;
+ // Create a yaml document
+ write("example.yaml",
+ "---\n"~
+ "Hello world!\n"~
+ "...\n"~
+ "---\n"~
+ "Hello world 2!\n"~
+ "...\n"
+ );
+ try
+ {
+ string buffer = readText("example.yaml");
+ auto yamlNode = Loader.fromString(buffer);
+
+ // Read data from yamlNode here...
+ }
+ catch(FileException e)
+ {
+ writeln("Failed to read file 'example.yaml'");
+ }
+}
+/// Use a custom resolver to support custom data types and/or implicit tags:
+@safe unittest
+{
+ import std.file : write;
+ // Create a yaml document
+ write("example.yaml",
+ "---\n"~
+ "Hello world!\n"~
+ "...\n"
+ );
+
+ auto loader = Loader.fromFile("example.yaml");
+
+ // Add resolver expressions here...
+ // loader.resolver.addImplicitResolver(...);
+
+ auto rootNode = loader.load();
+}
+
+//Issue #258 - https://github.com/dlang-community/D-YAML/issues/258
+@safe unittest
+{
+ auto yaml = "{\n\"root\": {\n\t\"key\": \"value\"\n }\n}";
+ auto doc = Loader.fromString(yaml).load();
+ assert(doc.isValid);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/node.d b/src/ext_depends/D-YAML/source/dyaml/node.d
new file mode 100644
index 0000000..24a62a4
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/node.d
@@ -0,0 +1,2488 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/// Node of a YAML document. Used to read YAML data once it's loaded,
+/// and to prepare data to emit.
+module dyaml.node;
+
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.datetime;
+import std.exception;
+import std.math;
+import std.meta : AliasSeq;
+import std.range;
+import std.string;
+import std.traits;
+import std.typecons;
+import std.variant;
+
+import dyaml.event;
+import dyaml.exception;
+import dyaml.style;
+
+/// Exception thrown at node related errors.
+class NodeException : YAMLException
+{
+ package:
+ // Construct a NodeException.
+ //
+ // Params: msg = Error message.
+ // start = Start position of the node.
+ this(string msg, Mark start, string file = __FILE__, size_t line = __LINE__)
+ @safe
+ {
+ super(msg ~ "\nNode at: " ~ start.toString(), file, line);
+ }
+}
+
+// Node kinds.
+enum NodeID : ubyte
+{
+ scalar,
+ sequence,
+ mapping,
+ invalid
+}
+
+/// Null YAML type. Used in nodes with _null values.
+struct YAMLNull
+{
+ /// Used for string conversion.
+ string toString() const pure @safe nothrow {return "null";}
+}
+
+// Merge YAML type, used to support "tag:yaml.org,2002:merge".
+package struct YAMLMerge{}
+
+// Key-value pair of YAML nodes, used in mappings.
+private struct Pair
+{
+ public:
+ /// Key node.
+ Node key;
+ /// Value node.
+ Node value;
+
+ /// Construct a Pair from two values. Will be converted to Nodes if needed.
+ this(K, V)(K key, V value)
+ {
+ static if(is(Unqual!K == Node)){this.key = key;}
+ else {this.key = Node(key);}
+ static if(is(Unqual!V == Node)){this.value = value;}
+ else {this.value = Node(value);}
+ }
+
+ /// Equality test with another Pair.
+ bool opEquals(const ref Pair rhs) const @safe
+ {
+ return key == rhs.key && value == rhs.value;
+ }
+
+ // Comparison with another Pair.
+ int opCmp(ref const(Pair) rhs) const @safe
+ {
+ const keyCmp = key.opCmp(rhs.key);
+ return keyCmp != 0 ? keyCmp
+ : value.opCmp(rhs.value);
+ }
+}
+
+enum NodeType
+{
+ null_,
+ merge,
+ boolean,
+ integer,
+ decimal,
+ binary,
+ timestamp,
+ string,
+ mapping,
+ sequence,
+ invalid
+}
+
+/** YAML node.
+ *
+ * This is a pseudo-dynamic type that can store any YAML value, including a
+ * sequence or mapping of nodes. You can get data from a Node directly or
+ * iterate over it if it's a collection.
+ */
+struct Node
+{
+ public:
+ alias Pair = .Pair;
+
+ package:
+ // YAML value type.
+ alias Value = Algebraic!(YAMLNull, YAMLMerge, bool, long, real, ubyte[], SysTime, string,
+ Node.Pair[], Node[]);
+
+ // Can Value hold this type naturally?
+ enum allowed(T) = isIntegral!T ||
+ isFloatingPoint!T ||
+ isSomeString!T ||
+ is(Unqual!T == bool) ||
+ Value.allowed!T;
+
+ // Stored value.
+ Value value_;
+ // Start position of the node.
+ Mark startMark_;
+
+ // Tag of the node.
+ string tag_;
+ // Node scalar style. Used to remember style this node was loaded with.
+ ScalarStyle scalarStyle = ScalarStyle.invalid;
+ // Node collection style. Used to remember style this node was loaded with.
+ CollectionStyle collectionStyle = CollectionStyle.invalid;
+
+ public:
+ /** Construct a Node from a value.
+ *
+ * Any type except for Node can be stored in a Node, but default YAML
+ * types (integers, floats, strings, timestamps, etc.) will be stored
+ * more efficiently. To create a node representing a null value,
+ * construct it from YAMLNull.
+ *
+ * If value is a node, its value will be copied directly. The tag and
+ * other information attached to the original node will be discarded.
+ *
+ * If value is an array of nodes or pairs, it is stored directly.
+ * Otherwise, every value in the array is converted to a node, and
+ * those nodes are stored.
+ *
+ * Note that to emit any non-default types you store
+ * in a node, you need a Representer to represent them in YAML -
+ * otherwise emitting will fail.
+ *
+ * Params: value = Value to store in the node.
+ * tag = Overrides tag of the node when emitted, regardless
+ * of tag determined by Representer. Representer uses
+ * this to determine YAML data type when a D data type
+ * maps to multiple different YAML data types. Tag must
+ * be in full form, e.g. "tag:yaml.org,2002:int", not
+ * a shortcut, like "!!int".
+ */
+ this(T)(T value, const string tag = null) @safe
+ if (allowed!T || isArray!T || isAssociativeArray!T || is(Unqual!T == Node) || castableToNode!T)
+ {
+ tag_ = tag;
+
+ //Unlike with assignment, we're just copying the value.
+ static if (is(Unqual!T == Node))
+ {
+ setValue(value.value_);
+ }
+ else static if(isSomeString!T)
+ {
+ setValue(value.to!string);
+ }
+ else static if(is(Unqual!T == bool))
+ {
+ setValue(cast(bool)value);
+ }
+ else static if(isIntegral!T)
+ {
+ setValue(cast(long)value);
+ }
+ else static if(isFloatingPoint!T)
+ {
+ setValue(cast(real)value);
+ }
+ else static if (isArray!T)
+ {
+ alias ElementT = Unqual!(ElementType!T);
+ // Construction from raw node or pair array.
+ static if(is(ElementT == Node) || is(ElementT == Node.Pair))
+ {
+ setValue(value);
+ }
+ // Need to handle byte buffers separately.
+ else static if(is(ElementT == byte) || is(ElementT == ubyte))
+ {
+ setValue(cast(ubyte[]) value);
+ }
+ else
+ {
+ Node[] nodes;
+ foreach(ref v; value)
+ {
+ nodes ~= Node(v);
+ }
+ setValue(nodes);
+ }
+ }
+ else static if (isAssociativeArray!T)
+ {
+ Node.Pair[] pairs;
+ foreach(k, ref v; value)
+ {
+ pairs ~= Pair(k, v);
+ }
+ setValue(pairs);
+ }
+ // User defined type.
+ else
+ {
+ setValue(value);
+ }
+ }
+ /// Construct a scalar node
+ @safe unittest
+ {
+ // Integer
+ {
+ auto node = Node(5);
+ }
+ // String
+ {
+ auto node = Node("Hello world!");
+ }
+ // Floating point
+ {
+ auto node = Node(5.0f);
+ }
+ // Boolean
+ {
+ auto node = Node(true);
+ }
+ // Time
+ {
+ auto node = Node(SysTime(DateTime(2005, 6, 15, 20, 0, 0), UTC()));
+ }
+ // Integer, dumped as a string
+ {
+ auto node = Node(5, "tag:yaml.org,2002:str");
+ }
+ }
+ /// Construct a sequence node
+ @safe unittest
+ {
+ // Will be emitted as a sequence (default for arrays)
+ {
+ auto seq = Node([1, 2, 3, 4, 5]);
+ }
+ // Will be emitted as a set (overridden tag)
+ {
+ auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
+ }
+ // Can also store arrays of arrays
+ {
+ auto node = Node([[1,2], [3,4]]);
+ }
+ }
+ /// Construct a mapping node
+ @safe unittest
+ {
+ // Will be emitted as an unordered mapping (default for mappings)
+ auto map = Node([1 : "a", 2 : "b"]);
+ // Will be emitted as an ordered map (overridden tag)
+ auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
+ // Will be emitted as pairs (overridden tag)
+ auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
+ }
+ @safe unittest
+ {
+ {
+ auto node = Node(42);
+ assert(node.nodeID == NodeID.scalar);
+ assert(node.as!int == 42 && node.as!float == 42.0f && node.as!string == "42");
+ }
+
+ {
+ auto node = Node("string");
+ assert(node.as!string == "string");
+ }
+ }
+ @safe unittest
+ {
+ with(Node([1, 2, 3]))
+ {
+ assert(nodeID == NodeID.sequence);
+ assert(length == 3);
+ assert(opIndex(2).as!int == 3);
+ }
+
+ }
+ @safe unittest
+ {
+ int[string] aa;
+ aa["1"] = 1;
+ aa["2"] = 2;
+ with(Node(aa))
+ {
+ assert(nodeID == NodeID.mapping);
+ assert(length == 2);
+ assert(opIndex("2").as!int == 2);
+ }
+ }
+ @safe unittest
+ {
+ auto node = Node(Node(4, "tag:yaml.org,2002:str"));
+ assert(node == 4);
+ assert(node.tag_ == "");
+ }
+
+ /** Construct a node from arrays of _keys and _values.
+ *
+ * Constructs a mapping node with key-value pairs from
+ * _keys and _values, keeping their order. Useful when order
+ * is important (ordered maps, pairs).
+ *
+ *
+ * keys and values must have equal length.
+ *
+ *
+ * If _keys and/or _values are nodes, they are stored directly/
+ * Otherwise they are converted to nodes and then stored.
+ *
+ * Params: keys = Keys of the mapping, from first to last pair.
+ * values = Values of the mapping, from first to last pair.
+ * tag = Overrides tag of the node when emitted, regardless
+ * of tag determined by Representer. Representer uses
+ * this to determine YAML data type when a D data type
+ * maps to multiple different YAML data types.
+ * This is used to differentiate between YAML unordered
+ * mappings ("!!map"), ordered mappings ("!!omap"), and
+ * pairs ("!!pairs") which are all internally
+ * represented as an array of node pairs. Tag must be
+ * in full form, e.g. "tag:yaml.org,2002:omap", not a
+ * shortcut, like "!!omap".
+ *
+ */
+ this(K, V)(K[] keys, V[] values, const string tag = null)
+ if(!(isSomeString!(K[]) || isSomeString!(V[])))
+ in(keys.length == values.length,
+ "Lengths of keys and values arrays to construct " ~
+ "a YAML node from don't match")
+ {
+ tag_ = tag;
+
+ Node.Pair[] pairs;
+ foreach(i; 0 .. keys.length){pairs ~= Pair(keys[i], values[i]);}
+ setValue(pairs);
+ }
+ ///
+ @safe unittest
+ {
+ // Will be emitted as an unordered mapping (default for mappings)
+ auto map = Node([1, 2], ["a", "b"]);
+ // Will be emitted as an ordered map (overridden tag)
+ auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap");
+ // Will be emitted as pairs (overriden tag)
+ auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs");
+ }
+ @safe unittest
+ {
+ with(Node(["1", "2"], [1, 2]))
+ {
+ assert(nodeID == NodeID.mapping);
+ assert(length == 2);
+ assert(opIndex("2").as!int == 2);
+ }
+
+ }
+
+ /// Is this node valid (initialized)?
+ @property bool isValid() const @safe pure nothrow
+ {
+ return value_.hasValue;
+ }
+
+ /// Return tag of the node.
+ @property string tag() const @safe nothrow
+ {
+ return tag_;
+ }
+
+ /// Return the start position of the node.
+ @property Mark startMark() const @safe pure nothrow
+ {
+ return startMark_;
+ }
+
+ /** Equality test.
+ *
+ * If T is Node, recursively compares all subnodes.
+ * This might be quite expensive if testing entire documents.
+ *
+ * If T is not Node, gets a value of type T from the node and tests
+ * equality with that.
+ *
+ * To test equality with a null YAML value, use YAMLNull.
+ *
+ * Params: rhs = Variable to test equality with.
+ *
+ * Returns: true if equal, false otherwise.
+ */
+ bool opEquals(const Node rhs) const @safe
+ {
+ return opCmp(rhs) == 0;
+ }
+ bool opEquals(T)(const auto ref T rhs) const
+ {
+ try
+ {
+ auto stored = get!(T, No.stringConversion);
+ // NaNs aren't normally equal to each other, but we'll pretend they are.
+ static if(isFloatingPoint!T)
+ {
+ return rhs == stored || (isNaN(rhs) && isNaN(stored));
+ }
+ else
+ {
+ return rhs == stored;
+ }
+ }
+ catch(NodeException e)
+ {
+ return false;
+ }
+ }
+ ///
+ @safe unittest
+ {
+ auto node = Node(42);
+
+ assert(node == 42);
+ assert(node != "42");
+ assert(node != "43");
+
+ auto node2 = Node(YAMLNull());
+ assert(node2 == YAMLNull());
+
+ const node3 = Node(42);
+ assert(node3 == 42);
+ }
+
+ /// Shortcut for get().
+ alias as = get;
+
+ /** Get the value of the node as specified type.
+ *
+ * If the specifed type does not match type in the node,
+ * conversion is attempted. The stringConversion template
+ * parameter can be used to disable conversion from non-string
+ * types to strings.
+ *
+ * Numeric values are range checked, throwing if out of range of
+ * requested type.
+ *
+ * Timestamps are stored as std.datetime.SysTime.
+ * Binary values are decoded and stored as ubyte[].
+ *
+ * To get a null value, use get!YAMLNull . This is to
+ * prevent getting null values for types such as strings or classes.
+ *
+ * $(BR)$(B Mapping default values:)
+ *
+ * $(PBR
+ * The '=' key can be used to denote the default value of a mapping.
+ * This can be used when a node is scalar in early versions of a program,
+ * but is replaced by a mapping later. Even if the node is a mapping, the
+ * get method can be used as if it was a scalar if it has a default value.
+ * This way, new YAML files where the node is a mapping can still be read
+ * by old versions of the program, which expect the node to be a scalar.
+ * )
+ *
+ * Returns: Value of the node as specified type.
+ *
+ * Throws: NodeException if unable to convert to specified type, or if
+ * the value is out of range of requested type.
+ */
+ inout(T) get(T, Flag!"stringConversion" stringConversion = Yes.stringConversion)() inout
+ if (allowed!(Unqual!T) || hasNodeConstructor!(Unqual!T))
+ {
+ if(isType!(Unqual!T)){return getValue!T;}
+
+ static if(!allowed!(Unqual!T))
+ {
+ static if (hasSimpleNodeConstructor!T)
+ {
+ alias params = AliasSeq!(this);
+ }
+ else static if (hasExpandedNodeConstructor!T)
+ {
+ alias params = AliasSeq!(this, tag_);
+ }
+ else
+ {
+ static assert(0, "Unknown Node constructor?");
+ }
+
+ static if (is(T == class))
+ {
+ return new inout T(params);
+ }
+ else static if (is(T == struct))
+ {
+ return T(params);
+ }
+ else
+ {
+ static assert(0, "Unhandled user type");
+ }
+ } else {
+
+ // If we're getting from a mapping and we're not getting Node.Pair[],
+ // we're getting the default value.
+ if(nodeID == NodeID.mapping){return this["="].get!( T, stringConversion);}
+
+ static if(isSomeString!T)
+ {
+ static if(!stringConversion)
+ {
+ enforce(type == NodeType.string, new NodeException(
+ "Node stores unexpected type: " ~ text(type) ~
+ ". Expected: " ~ typeid(T).toString(), startMark_));
+ return to!T(getValue!string);
+ }
+ else
+ {
+ // Try to convert to string.
+ try
+ {
+ return coerceValue!T();
+ }
+ catch(VariantException e)
+ {
+ throw new NodeException("Unable to convert node value to string", startMark_);
+ }
+ }
+ }
+ else static if(isFloatingPoint!T)
+ {
+ final switch (type)
+ {
+ case NodeType.integer:
+ return to!T(getValue!long);
+ case NodeType.decimal:
+ return to!T(getValue!real);
+ case NodeType.binary:
+ case NodeType.string:
+ case NodeType.boolean:
+ case NodeType.null_:
+ case NodeType.merge:
+ case NodeType.invalid:
+ case NodeType.timestamp:
+ case NodeType.mapping:
+ case NodeType.sequence:
+ throw new NodeException("Node stores unexpected type: " ~ text(type) ~
+ ". Expected: " ~ typeid(T).toString, startMark_);
+ }
+ }
+ else static if(isIntegral!T)
+ {
+ enforce(type == NodeType.integer, new NodeException("Node stores unexpected type: " ~ text(type) ~
+ ". Expected: " ~ typeid(T).toString, startMark_));
+ immutable temp = getValue!long;
+ enforce(temp >= T.min && temp <= T.max,
+ new NodeException("Integer value of type " ~ typeid(T).toString() ~
+ " out of range. Value: " ~ to!string(temp), startMark_));
+ return temp.to!T;
+ }
+ else throw new NodeException("Node stores unexpected type: " ~ text(type) ~
+ ". Expected: " ~ typeid(T).toString, startMark_);
+ }
+ }
+ /// Automatic type conversion
+ @safe unittest
+ {
+ auto node = Node(42);
+
+ assert(node.get!int == 42);
+ assert(node.get!string == "42");
+ assert(node.get!double == 42.0);
+ }
+ /// Scalar node to struct and vice versa
+ @safe unittest
+ {
+ import dyaml.dumper : dumper;
+ import dyaml.loader : Loader;
+ static struct MyStruct
+ {
+ int x, y, z;
+
+ this(int x, int y, int z) @safe
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ this(Node node) @safe
+ {
+ auto parts = node.as!string().split(":");
+ x = parts[0].to!int;
+ y = parts[1].to!int;
+ z = parts[2].to!int;
+ }
+
+ Node opCast(T: Node)() @safe
+ {
+ //Using custom scalar format, x:y:z.
+ auto scalar = format("%s:%s:%s", x, y, z);
+ //Representing as a scalar, with custom tag to specify this data type.
+ return Node(scalar, "!mystruct.tag");
+ }
+ }
+
+ auto appender = new Appender!string;
+
+ // Dump struct to yaml document
+ dumper().dump(appender, Node(MyStruct(1,2,3)));
+
+ // Read yaml document back as a MyStruct
+ auto loader = Loader.fromString(appender.data);
+ Node node = loader.load();
+ assert(node.as!MyStruct == MyStruct(1,2,3));
+ }
+ /// Sequence node to struct and vice versa
+ @safe unittest
+ {
+ import dyaml.dumper : dumper;
+ import dyaml.loader : Loader;
+ static struct MyStruct
+ {
+ int x, y, z;
+
+ this(int x, int y, int z) @safe
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ this(Node node) @safe
+ {
+ x = node[0].as!int;
+ y = node[1].as!int;
+ z = node[2].as!int;
+ }
+
+ Node opCast(T: Node)()
+ {
+ return Node([x, y, z], "!mystruct.tag");
+ }
+ }
+
+ auto appender = new Appender!string;
+
+ // Dump struct to yaml document
+ dumper().dump(appender, Node(MyStruct(1,2,3)));
+
+ // Read yaml document back as a MyStruct
+ auto loader = Loader.fromString(appender.data);
+ Node node = loader.load();
+ assert(node.as!MyStruct == MyStruct(1,2,3));
+ }
+ /// Mapping node to struct and vice versa
+ @safe unittest
+ {
+ import dyaml.dumper : dumper;
+ import dyaml.loader : Loader;
+ static struct MyStruct
+ {
+ int x, y, z;
+
+ Node opCast(T: Node)()
+ {
+ auto pairs = [Node.Pair("x", x),
+ Node.Pair("y", y),
+ Node.Pair("z", z)];
+ return Node(pairs, "!mystruct.tag");
+ }
+
+ this(int x, int y, int z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ this(Node node) @safe
+ {
+ x = node["x"].as!int;
+ y = node["y"].as!int;
+ z = node["z"].as!int;
+ }
+ }
+
+ auto appender = new Appender!string;
+
+ // Dump struct to yaml document
+ dumper().dump(appender, Node(MyStruct(1,2,3)));
+
+ // Read yaml document back as a MyStruct
+ auto loader = Loader.fromString(appender.data);
+ Node node = loader.load();
+ assert(node.as!MyStruct == MyStruct(1,2,3));
+ }
+ /// Classes can be used too
+ @system unittest {
+ import dyaml.dumper : dumper;
+ import dyaml.loader : Loader;
+
+ static class MyClass
+ {
+ int x, y, z;
+
+ this(int x, int y, int z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ this(Node node) @safe inout
+ {
+ auto parts = node.as!string().split(":");
+ x = parts[0].to!int;
+ y = parts[1].to!int;
+ z = parts[2].to!int;
+ }
+
+ ///Useful for Node.as!string.
+ override string toString()
+ {
+ return format("MyClass(%s, %s, %s)", x, y, z);
+ }
+
+ Node opCast(T: Node)() @safe
+ {
+ //Using custom scalar format, x:y:z.
+ auto scalar = format("%s:%s:%s", x, y, z);
+ //Representing as a scalar, with custom tag to specify this data type.
+ return Node(scalar, "!myclass.tag");
+ }
+ override bool opEquals(Object o)
+ {
+ if (auto other = cast(MyClass)o)
+ {
+ return (other.x == x) && (other.y == y) && (other.z == z);
+ }
+ return false;
+ }
+ }
+ auto appender = new Appender!string;
+
+ // Dump class to yaml document
+ dumper().dump(appender, Node(new MyClass(1,2,3)));
+
+ // Read yaml document back as a MyClass
+ auto loader = Loader.fromString(appender.data);
+ Node node = loader.load();
+ assert(node.as!MyClass == new MyClass(1,2,3));
+ }
+ // Make sure custom tags and styles are kept.
+ @safe unittest
+ {
+ static struct MyStruct
+ {
+ Node opCast(T: Node)()
+ {
+ auto node = Node("hi", "!mystruct.tag");
+ node.setStyle(ScalarStyle.doubleQuoted);
+ return node;
+ }
+ }
+
+ auto node = Node(MyStruct.init);
+ assert(node.tag == "!mystruct.tag");
+ assert(node.scalarStyle == ScalarStyle.doubleQuoted);
+ }
+ // ditto, but for collection style
+ @safe unittest
+ {
+ static struct MyStruct
+ {
+ Node opCast(T: Node)()
+ {
+ auto node = Node(["hi"], "!mystruct.tag");
+ node.setStyle(CollectionStyle.flow);
+ return node;
+ }
+ }
+
+ auto node = Node(MyStruct.init);
+ assert(node.tag == "!mystruct.tag");
+ assert(node.collectionStyle == CollectionStyle.flow);
+ }
+ @safe unittest
+ {
+ assertThrown!NodeException(Node("42").get!int);
+ assertThrown!NodeException(Node("42").get!double);
+ assertThrown!NodeException(Node(long.max).get!ushort);
+ Node(YAMLNull()).get!YAMLNull;
+ }
+ @safe unittest
+ {
+ const node = Node(42);
+ assert(node.get!int == 42);
+ assert(node.get!string == "42");
+ assert(node.get!double == 42.0);
+
+ immutable node2 = Node(42);
+ assert(node2.get!int == 42);
+ assert(node2.get!(const int) == 42);
+ assert(node2.get!(immutable int) == 42);
+ assert(node2.get!string == "42");
+ assert(node2.get!(const string) == "42");
+ assert(node2.get!(immutable string) == "42");
+ assert(node2.get!double == 42.0);
+ assert(node2.get!(const double) == 42.0);
+ assert(node2.get!(immutable double) == 42.0);
+ }
+
+ /** If this is a collection, return its _length.
+ *
+ * Otherwise, throw NodeException.
+ *
+ * Returns: Number of elements in a sequence or key-value pairs in a mapping.
+ *
+ * Throws: NodeException if this is not a sequence nor a mapping.
+ */
+ @property size_t length() const @safe
+ {
+ final switch(nodeID)
+ {
+ case NodeID.sequence:
+ return getValue!(Node[]).length;
+ case NodeID.mapping:
+ return getValue!(Pair[]).length;
+ case NodeID.scalar:
+ case NodeID.invalid:
+ throw new NodeException("Trying to get length of a " ~ nodeTypeString ~ " node",
+ startMark_);
+ }
+ }
+ @safe unittest
+ {
+ auto node = Node([1,2,3]);
+ assert(node.length == 3);
+ const cNode = Node([1,2,3]);
+ assert(cNode.length == 3);
+ immutable iNode = Node([1,2,3]);
+ assert(iNode.length == 3);
+ }
+
+ /** Get the element at specified index.
+ *
+ * If the node is a sequence, index must be integral.
+ *
+ *
+ * If the node is a mapping, return the value corresponding to the first
+ * key equal to index. containsKey() can be used to determine if a mapping
+ * has a specific key.
+ *
+ * To get element at a null index, use YAMLNull for index.
+ *
+ * Params: index = Index to use.
+ *
+ * Returns: Value corresponding to the index.
+ *
+ * Throws: NodeException if the index could not be found,
+ * non-integral index is used with a sequence or the node is
+ * not a collection.
+ */
+ ref inout(Node) opIndex(T)(T index) inout @safe
+ {
+ final switch (nodeID)
+ {
+ case NodeID.sequence:
+ checkSequenceIndex(index);
+ static if(isIntegral!T)
+ {
+ return getValue!(Node[])[index];
+ }
+ else
+ {
+ assert(false, "Only integers may index sequence nodes");
+ }
+ case NodeID.mapping:
+ auto idx = findPair(index);
+ if(idx >= 0)
+ {
+ return getValue!(Pair[])[idx].value;
+ }
+
+ string msg = "Mapping index not found" ~ (isSomeString!T ? ": " ~ to!string(index) : "");
+ throw new NodeException(msg, startMark_);
+ case NodeID.scalar:
+ case NodeID.invalid:
+ throw new NodeException("Trying to index a " ~ nodeTypeString ~ " node", startMark_);
+ }
+ }
+ ///
+ @safe unittest
+ {
+ Node narray = Node([11, 12, 13, 14]);
+ Node nmap = Node(["11", "12", "13", "14"], [11, 12, 13, 14]);
+
+ assert(narray[0].as!int == 11);
+ assert(null !is collectException(narray[42]));
+ assert(nmap["11"].as!int == 11);
+ assert(nmap["14"].as!int == 14);
+ }
+ @safe unittest
+ {
+ Node narray = Node([11, 12, 13, 14]);
+ Node nmap = Node(["11", "12", "13", "14"], [11, 12, 13, 14]);
+
+ assert(narray[0].as!int == 11);
+ assert(null !is collectException(narray[42]));
+ assert(nmap["11"].as!int == 11);
+ assert(nmap["14"].as!int == 14);
+ assert(null !is collectException(nmap["42"]));
+
+ narray.add(YAMLNull());
+ nmap.add(YAMLNull(), "Nothing");
+ assert(narray[4].as!YAMLNull == YAMLNull());
+ assert(nmap[YAMLNull()].as!string == "Nothing");
+
+ assertThrown!NodeException(nmap[11]);
+ assertThrown!NodeException(nmap[14]);
+ }
+
+ /** Determine if a collection contains specified value.
+ *
+ * If the node is a sequence, check if it contains the specified value.
+ * If it's a mapping, check if it has a value that matches specified value.
+ *
+ * Params: rhs = Item to look for. Use YAMLNull to check for a null value.
+ *
+ * Returns: true if rhs was found, false otherwise.
+ *
+ * Throws: NodeException if the node is not a collection.
+ */
+ bool contains(T)(T rhs) const
+ {
+ return contains_!(T, No.key, "contains")(rhs);
+ }
+ @safe unittest
+ {
+ auto mNode = Node(["1", "2", "3"]);
+ assert(mNode.contains("2"));
+ const cNode = Node(["1", "2", "3"]);
+ assert(cNode.contains("2"));
+ immutable iNode = Node(["1", "2", "3"]);
+ assert(iNode.contains("2"));
+ }
+
+
+ /** Determine if a mapping contains specified key.
+ *
+ * Params: rhs = Key to look for. Use YAMLNull to check for a null key.
+ *
+ * Returns: true if rhs was found, false otherwise.
+ *
+ * Throws: NodeException if the node is not a mapping.
+ */
+ bool containsKey(T)(T rhs) const
+ {
+ return contains_!(T, Yes.key, "containsKey")(rhs);
+ }
+
+ // Unittest for contains() and containsKey().
+ @safe unittest
+ {
+ auto seq = Node([1, 2, 3, 4, 5]);
+ assert(seq.contains(3));
+ assert(seq.contains(5));
+ assert(!seq.contains("5"));
+ assert(!seq.contains(6));
+ assert(!seq.contains(float.nan));
+ assertThrown!NodeException(seq.containsKey(5));
+
+ auto seq2 = Node(["1", "2"]);
+ assert(seq2.contains("1"));
+ assert(!seq2.contains(1));
+
+ auto map = Node(["1", "2", "3", "4"], [1, 2, 3, 4]);
+ assert(map.contains(1));
+ assert(!map.contains("1"));
+ assert(!map.contains(5));
+ assert(!map.contains(float.nan));
+ assert(map.containsKey("1"));
+ assert(map.containsKey("4"));
+ assert(!map.containsKey(1));
+ assert(!map.containsKey("5"));
+
+ assert(!seq.contains(YAMLNull()));
+ assert(!map.contains(YAMLNull()));
+ assert(!map.containsKey(YAMLNull()));
+ seq.add(YAMLNull());
+ map.add("Nothing", YAMLNull());
+ assert(seq.contains(YAMLNull()));
+ assert(map.contains(YAMLNull()));
+ assert(!map.containsKey(YAMLNull()));
+ map.add(YAMLNull(), "Nothing");
+ assert(map.containsKey(YAMLNull()));
+
+ auto map2 = Node([1, 2, 3, 4], [1, 2, 3, 4]);
+ assert(!map2.contains("1"));
+ assert(map2.contains(1));
+ assert(!map2.containsKey("1"));
+ assert(map2.containsKey(1));
+
+ // scalar
+ assertThrown!NodeException(Node(1).contains(4));
+ assertThrown!NodeException(Node(1).containsKey(4));
+
+ auto mapNan = Node([1.0, 2, double.nan], [1, double.nan, 5]);
+
+ assert(mapNan.contains(double.nan));
+ assert(mapNan.containsKey(double.nan));
+ }
+
+ /// Assignment (shallow copy) by value.
+ void opAssign()(auto ref Node rhs)
+ {
+ assumeWontThrow(setValue(rhs.value_));
+ startMark_ = rhs.startMark_;
+ tag_ = rhs.tag_;
+ scalarStyle = rhs.scalarStyle;
+ collectionStyle = rhs.collectionStyle;
+ }
+ // Unittest for opAssign().
+ @safe unittest
+ {
+ auto seq = Node([1, 2, 3, 4, 5]);
+ auto assigned = seq;
+ assert(seq == assigned,
+ "Node.opAssign() doesn't produce an equivalent copy");
+ }
+
+ /** Set element at specified index in a collection.
+ *
+ * This method can only be called on collection nodes.
+ *
+ * If the node is a sequence, index must be integral.
+ *
+ * If the node is a mapping, sets the _value corresponding to the first
+ * key matching index (including conversion, so e.g. "42" matches 42).
+ *
+ * If the node is a mapping and no key matches index, a new key-value
+ * pair is added to the mapping. In sequences the index must be in
+ * range. This ensures behavior siilar to D arrays and associative
+ * arrays.
+ *
+ * To set element at a null index, use YAMLNull for index.
+ *
+ * Params:
+ * value = Value to assign.
+ * index = Index of the value to set.
+ *
+ * Throws: NodeException if the node is not a collection, index is out
+ * of range or if a non-integral index is used on a sequence node.
+ */
+ void opIndexAssign(K, V)(V value, K index)
+ {
+ final switch (nodeID)
+ {
+ case NodeID.sequence:
+ checkSequenceIndex(index);
+ static if(isIntegral!K || is(Unqual!K == bool))
+ {
+ auto nodes = getValue!(Node[]);
+ static if(is(Unqual!V == Node)){nodes[index] = value;}
+ else {nodes[index] = Node(value);}
+ setValue(nodes);
+ return;
+ }
+ assert(false, "Only integers may index sequence nodes");
+ case NodeID.mapping:
+ const idx = findPair(index);
+ if(idx < 0){add(index, value);}
+ else
+ {
+ auto pairs = as!(Node.Pair[])();
+ static if(is(Unqual!V == Node)){pairs[idx].value = value;}
+ else {pairs[idx].value = Node(value);}
+ setValue(pairs);
+ }
+ return;
+ case NodeID.scalar:
+ case NodeID.invalid:
+ throw new NodeException("Trying to index a " ~ nodeTypeString ~ " node", startMark_);
+ }
+ }
+ @safe unittest
+ {
+ with(Node([1, 2, 3, 4, 3]))
+ {
+ opIndexAssign(42, 3);
+ assert(length == 5);
+ assert(opIndex(3).as!int == 42);
+
+ opIndexAssign(YAMLNull(), 0);
+ assert(opIndex(0) == YAMLNull());
+ }
+ with(Node(["1", "2", "3"], [4, 5, 6]))
+ {
+ opIndexAssign(42, "3");
+ opIndexAssign(123, 456);
+ assert(length == 4);
+ assert(opIndex("3").as!int == 42);
+ assert(opIndex(456).as!int == 123);
+
+ opIndexAssign(43, 3);
+ //3 and "3" should be different
+ assert(length == 5);
+ assert(opIndex("3").as!int == 42);
+ assert(opIndex(3).as!int == 43);
+
+ opIndexAssign(YAMLNull(), "2");
+ assert(opIndex("2") == YAMLNull());
+ }
+ }
+
+ /** Return a range object iterating over a sequence, getting each
+ * element as T.
+ *
+ * If T is Node, simply iterate over the nodes in the sequence.
+ * Otherwise, convert each node to T during iteration.
+ *
+ * Throws: NodeException if the node is not a sequence or an element
+ * could not be converted to specified type.
+ */
+ template sequence(T = Node)
+ {
+ struct Range(N)
+ {
+ N subnodes;
+ size_t position;
+
+ this(N nodes)
+ {
+ subnodes = nodes;
+ position = 0;
+ }
+
+ /* Input range functionality. */
+ bool empty() const @property { return position >= subnodes.length; }
+
+ void popFront()
+ {
+ enforce(!empty, "Attempted to popFront an empty sequence");
+ position++;
+ }
+
+ T front() const @property
+ {
+ enforce(!empty, "Attempted to take the front of an empty sequence");
+ static if (is(Unqual!T == Node))
+ return subnodes[position];
+ else
+ return subnodes[position].as!T;
+ }
+
+ /* Forward range functionality. */
+ Range save() { return this; }
+
+ /* Bidirectional range functionality. */
+ void popBack()
+ {
+ enforce(!empty, "Attempted to popBack an empty sequence");
+ subnodes = subnodes[0 .. $ - 1];
+ }
+
+ T back()
+ {
+ enforce(!empty, "Attempted to take the back of an empty sequence");
+ static if (is(Unqual!T == Node))
+ return subnodes[$ - 1];
+ else
+ return subnodes[$ - 1].as!T;
+ }
+
+ /* Random-access range functionality. */
+ size_t length() const @property { return subnodes.length; }
+ T opIndex(size_t index)
+ {
+ static if (is(Unqual!T == Node))
+ return subnodes[index];
+ else
+ return subnodes[index].as!T;
+ }
+
+ static assert(isInputRange!Range);
+ static assert(isForwardRange!Range);
+ static assert(isBidirectionalRange!Range);
+ static assert(isRandomAccessRange!Range);
+ }
+ auto sequence()
+ {
+ enforce(nodeID == NodeID.sequence,
+ new NodeException("Trying to 'sequence'-iterate over a " ~ nodeTypeString ~ " node",
+ startMark_));
+ return Range!(Node[])(get!(Node[]));
+ }
+ auto sequence() const
+ {
+ enforce(nodeID == NodeID.sequence,
+ new NodeException("Trying to 'sequence'-iterate over a " ~ nodeTypeString ~ " node",
+ startMark_));
+ return Range!(const(Node)[])(get!(Node[]));
+ }
+ }
+ @safe unittest
+ {
+ Node n1 = Node([1, 2, 3, 4]);
+ int[int] array;
+ Node n2 = Node(array);
+ const n3 = Node([1, 2, 3, 4]);
+
+ auto r = n1.sequence!int.map!(x => x * 10);
+ assert(r.equal([10, 20, 30, 40]));
+
+ assertThrown(n2.sequence);
+
+ auto r2 = n3.sequence!int.map!(x => x * 10);
+ assert(r2.equal([10, 20, 30, 40]));
+ }
+
+ /** Return a range object iterating over mapping's pairs.
+ *
+ * Throws: NodeException if the node is not a mapping.
+ *
+ */
+ template mapping()
+ {
+ struct Range(T)
+ {
+ T pairs;
+ size_t position;
+
+ this(T pairs) @safe
+ {
+ this.pairs = pairs;
+ position = 0;
+ }
+
+ /* Input range functionality. */
+ bool empty() @safe { return position >= pairs.length; }
+
+ void popFront() @safe
+ {
+ enforce(!empty, "Attempted to popFront an empty mapping");
+ position++;
+ }
+
+ auto front() @safe
+ {
+ enforce(!empty, "Attempted to take the front of an empty mapping");
+ return pairs[position];
+ }
+
+ /* Forward range functionality. */
+ Range save() @safe { return this; }
+
+ /* Bidirectional range functionality. */
+ void popBack() @safe
+ {
+ enforce(!empty, "Attempted to popBack an empty mapping");
+ pairs = pairs[0 .. $ - 1];
+ }
+
+ auto back() @safe
+ {
+ enforce(!empty, "Attempted to take the back of an empty mapping");
+ return pairs[$ - 1];
+ }
+
+ /* Random-access range functionality. */
+ size_t length() const @property @safe { return pairs.length; }
+ auto opIndex(size_t index) @safe { return pairs[index]; }
+
+ static assert(isInputRange!Range);
+ static assert(isForwardRange!Range);
+ static assert(isBidirectionalRange!Range);
+ static assert(isRandomAccessRange!Range);
+ }
+
+ auto mapping()
+ {
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to 'mapping'-iterate over a "
+ ~ nodeTypeString ~ " node", startMark_));
+ return Range!(Node.Pair[])(get!(Node.Pair[]));
+ }
+ auto mapping() const
+ {
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to 'mapping'-iterate over a "
+ ~ nodeTypeString ~ " node", startMark_));
+ return Range!(const(Node.Pair)[])(get!(Node.Pair[]));
+ }
+ }
+ @safe unittest
+ {
+ int[int] array;
+ Node n = Node(array);
+ n[1] = "foo";
+ n[2] = "bar";
+ n[3] = "baz";
+
+ string[int] test;
+ foreach (pair; n.mapping)
+ test[pair.key.as!int] = pair.value.as!string;
+
+ assert(test[1] == "foo");
+ assert(test[2] == "bar");
+ assert(test[3] == "baz");
+
+ int[int] constArray = [1: 2, 3: 4];
+ const x = Node(constArray);
+ foreach (pair; x.mapping)
+ assert(pair.value == constArray[pair.key.as!int]);
+ }
+
+ /** Return a range object iterating over mapping's keys.
+ *
+ * If K is Node, simply iterate over the keys in the mapping.
+ * Otherwise, convert each key to T during iteration.
+ *
+ * Throws: NodeException if the nodes is not a mapping or an element
+ * could not be converted to specified type.
+ */
+ auto mappingKeys(K = Node)() const
+ {
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to 'mappingKeys'-iterate over a "
+ ~ nodeTypeString ~ " node", startMark_));
+ static if (is(Unqual!K == Node))
+ return mapping.map!(pair => pair.key);
+ else
+ return mapping.map!(pair => pair.key.as!K);
+ }
+ @safe unittest
+ {
+ int[int] array;
+ Node m1 = Node(array);
+ m1["foo"] = 2;
+ m1["bar"] = 3;
+
+ assert(m1.mappingKeys.equal(["foo", "bar"]) || m1.mappingKeys.equal(["bar", "foo"]));
+
+ const cm1 = Node(["foo": 2, "bar": 3]);
+
+ assert(cm1.mappingKeys.equal(["foo", "bar"]) || cm1.mappingKeys.equal(["bar", "foo"]));
+ }
+
+ /** Return a range object iterating over mapping's values.
+ *
+ * If V is Node, simply iterate over the values in the mapping.
+ * Otherwise, convert each key to V during iteration.
+ *
+ * Throws: NodeException if the nodes is not a mapping or an element
+ * could not be converted to specified type.
+ */
+ auto mappingValues(V = Node)() const
+ {
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to 'mappingValues'-iterate over a "
+ ~ nodeTypeString ~ " node", startMark_));
+ static if (is(Unqual!V == Node))
+ return mapping.map!(pair => pair.value);
+ else
+ return mapping.map!(pair => pair.value.as!V);
+ }
+ @safe unittest
+ {
+ int[int] array;
+ Node m1 = Node(array);
+ m1["foo"] = 2;
+ m1["bar"] = 3;
+
+ assert(m1.mappingValues.equal([2, 3]) || m1.mappingValues.equal([3, 2]));
+
+ const cm1 = Node(["foo": 2, "bar": 3]);
+
+ assert(cm1.mappingValues.equal([2, 3]) || cm1.mappingValues.equal([3, 2]));
+ }
+
+
+ /** Foreach over a sequence, getting each element as T.
+ *
+ * If T is Node, simply iterate over the nodes in the sequence.
+ * Otherwise, convert each node to T during iteration.
+ *
+ * Throws: NodeException if the node is not a sequence or an
+ * element could not be converted to specified type.
+ */
+ int opApply(D)(D dg) if (isDelegate!D && (Parameters!D.length == 1))
+ {
+ enforce(nodeID == NodeID.sequence,
+ new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node",
+ startMark_));
+
+ int result;
+ foreach(ref node; get!(Node[]))
+ {
+ static if(is(Unqual!(Parameters!D[0]) == Node))
+ {
+ result = dg(node);
+ }
+ else
+ {
+ Parameters!D[0] temp = node.as!(Parameters!D[0]);
+ result = dg(temp);
+ }
+ if(result){break;}
+ }
+ return result;
+ }
+ /// ditto
+ int opApply(D)(D dg) const if (isDelegate!D && (Parameters!D.length == 1))
+ {
+ enforce(nodeID == NodeID.sequence,
+ new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node",
+ startMark_));
+
+ int result;
+ foreach(ref node; get!(Node[]))
+ {
+ static if(is(Unqual!(Parameters!D[0]) == Node))
+ {
+ result = dg(node);
+ }
+ else
+ {
+ Parameters!D[0] temp = node.as!(Parameters!D[0]);
+ result = dg(temp);
+ }
+ if(result){break;}
+ }
+ return result;
+ }
+ @safe unittest
+ {
+ Node n1 = Node(11);
+ Node n2 = Node(12);
+ Node n3 = Node(13);
+ Node n4 = Node(14);
+ Node narray = Node([n1, n2, n3, n4]);
+ const cNArray = narray;
+
+ int[] array, array2, array3;
+ foreach(int value; narray)
+ {
+ array ~= value;
+ }
+ foreach(Node node; narray)
+ {
+ array2 ~= node.as!int;
+ }
+ foreach (const Node node; cNArray)
+ {
+ array3 ~= node.as!int;
+ }
+ assert(array == [11, 12, 13, 14]);
+ assert(array2 == [11, 12, 13, 14]);
+ assert(array3 == [11, 12, 13, 14]);
+ }
+ @safe unittest
+ {
+ string[] testStrs = ["1", "2", "3"];
+ auto node1 = Node(testStrs);
+ int i = 0;
+ foreach (string elem; node1)
+ {
+ assert(elem == testStrs[i]);
+ i++;
+ }
+ const node2 = Node(testStrs);
+ i = 0;
+ foreach (string elem; node2)
+ {
+ assert(elem == testStrs[i]);
+ i++;
+ }
+ immutable node3 = Node(testStrs);
+ i = 0;
+ foreach (string elem; node3)
+ {
+ assert(elem == testStrs[i]);
+ i++;
+ }
+ }
+ @safe unittest
+ {
+ auto node = Node(["a":1, "b":2, "c":3]);
+ const cNode = node;
+ assertThrown({foreach (Node n; node) {}}());
+ assertThrown({foreach (const Node n; cNode) {}}());
+ }
+
+ /** Foreach over a mapping, getting each key/value as K/V.
+ *
+ * If the K and/or V is Node, simply iterate over the nodes in the mapping.
+ * Otherwise, convert each key/value to T during iteration.
+ *
+ * Throws: NodeException if the node is not a mapping or an
+ * element could not be converted to specified type.
+ */
+ int opApply(DG)(DG dg) if (isDelegate!DG && (Parameters!DG.length == 2))
+ {
+ alias K = Parameters!DG[0];
+ alias V = Parameters!DG[1];
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node",
+ startMark_));
+
+ int result;
+ foreach(ref pair; get!(Node.Pair[]))
+ {
+ static if(is(Unqual!K == Node) && is(Unqual!V == Node))
+ {
+ result = dg(pair.key, pair.value);
+ }
+ else static if(is(Unqual!K == Node))
+ {
+ V tempValue = pair.value.as!V;
+ result = dg(pair.key, tempValue);
+ }
+ else static if(is(Unqual!V == Node))
+ {
+ K tempKey = pair.key.as!K;
+ result = dg(tempKey, pair.value);
+ }
+ else
+ {
+ K tempKey = pair.key.as!K;
+ V tempValue = pair.value.as!V;
+ result = dg(tempKey, tempValue);
+ }
+
+ if(result){break;}
+ }
+ return result;
+ }
+ /// ditto
+ int opApply(DG)(DG dg) const if (isDelegate!DG && (Parameters!DG.length == 2))
+ {
+ alias K = Parameters!DG[0];
+ alias V = Parameters!DG[1];
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node",
+ startMark_));
+
+ int result;
+ foreach(ref pair; get!(Node.Pair[]))
+ {
+ static if(is(Unqual!K == Node) && is(Unqual!V == Node))
+ {
+ result = dg(pair.key, pair.value);
+ }
+ else static if(is(Unqual!K == Node))
+ {
+ V tempValue = pair.value.as!V;
+ result = dg(pair.key, tempValue);
+ }
+ else static if(is(Unqual!V == Node))
+ {
+ K tempKey = pair.key.as!K;
+ result = dg(tempKey, pair.value);
+ }
+ else
+ {
+ K tempKey = pair.key.as!K;
+ V tempValue = pair.value.as!V;
+ result = dg(tempKey, tempValue);
+ }
+
+ if(result){break;}
+ }
+ return result;
+ }
+ @safe unittest
+ {
+ Node n1 = Node(cast(long)11);
+ Node n2 = Node(cast(long)12);
+ Node n3 = Node(cast(long)13);
+ Node n4 = Node(cast(long)14);
+
+ Node k1 = Node("11");
+ Node k2 = Node("12");
+ Node k3 = Node("13");
+ Node k4 = Node("14");
+
+ Node nmap1 = Node([Pair(k1, n1),
+ Pair(k2, n2),
+ Pair(k3, n3),
+ Pair(k4, n4)]);
+
+ int[string] expected = ["11" : 11,
+ "12" : 12,
+ "13" : 13,
+ "14" : 14];
+ int[string] array;
+ foreach(string key, int value; nmap1)
+ {
+ array[key] = value;
+ }
+ assert(array == expected);
+
+ Node nmap2 = Node([Pair(k1, Node(cast(long)5)),
+ Pair(k2, Node(true)),
+ Pair(k3, Node(cast(real)1.0)),
+ Pair(k4, Node("yarly"))]);
+
+ foreach(string key, Node value; nmap2)
+ {
+ switch(key)
+ {
+ case "11": assert(value.as!int == 5 ); break;
+ case "12": assert(value.as!bool == true ); break;
+ case "13": assert(value.as!float == 1.0 ); break;
+ case "14": assert(value.as!string == "yarly"); break;
+ default: assert(false);
+ }
+ }
+ const nmap3 = nmap2;
+
+ foreach(const Node key, const Node value; nmap3)
+ {
+ switch(key.as!string)
+ {
+ case "11": assert(value.as!int == 5 ); break;
+ case "12": assert(value.as!bool == true ); break;
+ case "13": assert(value.as!float == 1.0 ); break;
+ case "14": assert(value.as!string == "yarly"); break;
+ default: assert(false);
+ }
+ }
+ }
+ @safe unittest
+ {
+ string[int] testStrs = [0: "1", 1: "2", 2: "3"];
+ auto node1 = Node(testStrs);
+ foreach (const int i, string elem; node1)
+ {
+ assert(elem == testStrs[i]);
+ }
+ const node2 = Node(testStrs);
+ foreach (const int i, string elem; node2)
+ {
+ assert(elem == testStrs[i]);
+ }
+ immutable node3 = Node(testStrs);
+ foreach (const int i, string elem; node3)
+ {
+ assert(elem == testStrs[i]);
+ }
+ }
+ @safe unittest
+ {
+ auto node = Node(["a", "b", "c"]);
+ const cNode = node;
+ assertThrown({foreach (Node a, Node b; node) {}}());
+ assertThrown({foreach (const Node a, const Node b; cNode) {}}());
+ }
+
+ /** Add an element to a sequence.
+ *
+ * This method can only be called on sequence nodes.
+ *
+ * If value is a node, it is copied to the sequence directly. Otherwise
+ * value is converted to a node and then stored in the sequence.
+ *
+ * $(P When emitting, all values in the sequence will be emitted. When
+ * using the !!set tag, the user needs to ensure that all elements in
+ * the sequence are unique, otherwise $(B invalid) YAML code will be
+ * emitted.)
+ *
+ * Params: value = Value to _add to the sequence.
+ */
+ void add(T)(T value)
+ {
+ if (!isValid)
+ {
+ setValue(Node[].init);
+ }
+ enforce(nodeID == NodeID.sequence,
+ new NodeException("Trying to add an element to a " ~ nodeTypeString ~ " node", startMark_));
+
+ auto nodes = get!(Node[])();
+ static if(is(Unqual!T == Node)){nodes ~= value;}
+ else {nodes ~= Node(value);}
+ setValue(nodes);
+ }
+ @safe unittest
+ {
+ with(Node([1, 2, 3, 4]))
+ {
+ add(5.0f);
+ assert(opIndex(4).as!float == 5.0f);
+ }
+ with(Node())
+ {
+ add(5.0f);
+ assert(opIndex(0).as!float == 5.0f);
+ }
+ with(Node(5.0f))
+ {
+ assertThrown!NodeException(add(5.0f));
+ }
+ with(Node([5.0f : true]))
+ {
+ assertThrown!NodeException(add(5.0f));
+ }
+ }
+
+ /** Add a key-value pair to a mapping.
+ *
+ * This method can only be called on mapping nodes.
+ *
+ * If key and/or value is a node, it is copied to the mapping directly.
+ * Otherwise it is converted to a node and then stored in the mapping.
+ *
+ * $(P It is possible for the same key to be present more than once in a
+ * mapping. When emitting, all key-value pairs will be emitted.
+ * This is useful with the "!!pairs" tag, but will result in
+ * $(B invalid) YAML with "!!map" and "!!omap" tags.)
+ *
+ * Params: key = Key to _add.
+ * value = Value to _add.
+ */
+ void add(K, V)(K key, V value)
+ {
+ if (!isValid)
+ {
+ setValue(Node.Pair[].init);
+ }
+ enforce(nodeID == NodeID.mapping,
+ new NodeException("Trying to add a key-value pair to a " ~
+ nodeTypeString ~ " node",
+ startMark_));
+
+ auto pairs = get!(Node.Pair[])();
+ pairs ~= Pair(key, value);
+ setValue(pairs);
+ }
+ @safe unittest
+ {
+ with(Node([1, 2], [3, 4]))
+ {
+ add(5, "6");
+ assert(opIndex(5).as!string == "6");
+ }
+ with(Node())
+ {
+ add(5, "6");
+ assert(opIndex(5).as!string == "6");
+ }
+ with(Node(5.0f))
+ {
+ assertThrown!NodeException(add(5, "6"));
+ }
+ with(Node([5.0f]))
+ {
+ assertThrown!NodeException(add(5, "6"));
+ }
+ }
+
+ /** Determine whether a key is in a mapping, and access its value.
+ *
+ * This method can only be called on mapping nodes.
+ *
+ * Params: key = Key to search for.
+ *
+ * Returns: A pointer to the value (as a Node) corresponding to key,
+ * or null if not found.
+ *
+ * Note: Any modification to the node can invalidate the returned
+ * pointer.
+ *
+ * See_Also: contains
+ */
+ inout(Node*) opBinaryRight(string op, K)(K key) inout
+ if (op == "in")
+ {
+ enforce(nodeID == NodeID.mapping, new NodeException("Trying to use 'in' on a " ~
+ nodeTypeString ~ " node", startMark_));
+
+ auto idx = findPair(key);
+ if(idx < 0)
+ {
+ return null;
+ }
+ else
+ {
+ return &(get!(Node.Pair[])[idx].value);
+ }
+ }
+ @safe unittest
+ {
+ auto mapping = Node(["foo", "baz"], ["bar", "qux"]);
+ assert("bad" !in mapping && ("bad" in mapping) is null);
+ Node* foo = "foo" in mapping;
+ assert(foo !is null);
+ assert(*foo == Node("bar"));
+ assert(foo.get!string == "bar");
+ *foo = Node("newfoo");
+ assert(mapping["foo"] == Node("newfoo"));
+ }
+ @safe unittest
+ {
+ auto mNode = Node(["a": 2]);
+ assert("a" in mNode);
+ const cNode = Node(["a": 2]);
+ assert("a" in cNode);
+ immutable iNode = Node(["a": 2]);
+ assert("a" in iNode);
+ }
+
+ /** Remove first (if any) occurence of a value in a collection.
+ *
+ * This method can only be called on collection nodes.
+ *
+ * If the node is a sequence, the first node matching value is removed.
+ * If the node is a mapping, the first key-value pair where _value
+ * matches specified value is removed.
+ *
+ * Params: rhs = Value to _remove.
+ *
+ * Throws: NodeException if the node is not a collection.
+ */
+ void remove(T)(T rhs)
+ {
+ remove_!(T, No.key, "remove")(rhs);
+ }
+ @safe unittest
+ {
+ with(Node([1, 2, 3, 4, 3]))
+ {
+ remove(3);
+ assert(length == 4);
+ assert(opIndex(2).as!int == 4);
+ assert(opIndex(3).as!int == 3);
+
+ add(YAMLNull());
+ assert(length == 5);
+ remove(YAMLNull());
+ assert(length == 4);
+ }
+ with(Node(["1", "2", "3"], [4, 5, 6]))
+ {
+ remove(4);
+ assert(length == 2);
+ add("nullkey", YAMLNull());
+ assert(length == 3);
+ remove(YAMLNull());
+ assert(length == 2);
+ }
+ }
+
+ /** Remove element at the specified index of a collection.
+ *
+ * This method can only be called on collection nodes.
+ *
+ * If the node is a sequence, index must be integral.
+ *
+ * If the node is a mapping, remove the first key-value pair where
+ * key matches index.
+ *
+ * If the node is a mapping and no key matches index, nothing is removed
+ * and no exception is thrown. This ensures behavior siilar to D arrays
+ * and associative arrays.
+ *
+ * Params: index = Index to remove at.
+ *
+ * Throws: NodeException if the node is not a collection, index is out
+ * of range or if a non-integral index is used on a sequence node.
+ */
+ void removeAt(T)(T index)
+ {
+ remove_!(T, Yes.key, "removeAt")(index);
+ }
+ @safe unittest
+ {
+ with(Node([1, 2, 3, 4, 3]))
+ {
+ removeAt(3);
+ assertThrown!NodeException(removeAt("3"));
+ assert(length == 4);
+ assert(opIndex(3).as!int == 3);
+ }
+ with(Node(["1", "2", "3"], [4, 5, 6]))
+ {
+ // no integer 2 key, so don't remove anything
+ removeAt(2);
+ assert(length == 3);
+ removeAt("2");
+ assert(length == 2);
+ add(YAMLNull(), "nullval");
+ assert(length == 3);
+ removeAt(YAMLNull());
+ assert(length == 2);
+ }
+ }
+
+ /// Compare with another _node.
+ int opCmp(const ref Node rhs) const @safe
+ {
+ // Compare tags - if equal or both null, we need to compare further.
+ const tagCmp = (tag_ is null) ? (rhs.tag_ is null) ? 0 : -1
+ : (rhs.tag_ is null) ? 1 : std.algorithm.comparison.cmp(tag_, rhs.tag_);
+ if(tagCmp != 0){return tagCmp;}
+
+ static int cmp(T1, T2)(T1 a, T2 b)
+ {
+ return a > b ? 1 :
+ a < b ? -1 :
+ 0;
+ }
+
+ // Compare validity: if both valid, we have to compare further.
+ const v1 = isValid;
+ const v2 = rhs.isValid;
+ if(!v1){return v2 ? -1 : 0;}
+ if(!v2){return 1;}
+
+ const typeCmp = cmp(type, rhs.type);
+ if(typeCmp != 0){return typeCmp;}
+
+ static int compareCollections(T)(const ref Node lhs, const ref Node rhs)
+ {
+ const c1 = lhs.getValue!T;
+ const c2 = rhs.getValue!T;
+ if(c1 is c2){return 0;}
+ if(c1.length != c2.length)
+ {
+ return cmp(c1.length, c2.length);
+ }
+ // Equal lengths, compare items.
+ foreach(i; 0 .. c1.length)
+ {
+ const itemCmp = c1[i].opCmp(c2[i]);
+ if(itemCmp != 0){return itemCmp;}
+ }
+ return 0;
+ }
+
+ final switch(type)
+ {
+ case NodeType.string:
+ return std.algorithm.cmp(getValue!string,
+ rhs.getValue!string);
+ case NodeType.integer:
+ return cmp(getValue!long, rhs.getValue!long);
+ case NodeType.boolean:
+ const b1 = getValue!bool;
+ const b2 = rhs.getValue!bool;
+ return b1 ? b2 ? 0 : 1
+ : b2 ? -1 : 0;
+ case NodeType.binary:
+ const b1 = getValue!(ubyte[]);
+ const b2 = rhs.getValue!(ubyte[]);
+ return std.algorithm.cmp(b1, b2);
+ case NodeType.null_:
+ return 0;
+ case NodeType.decimal:
+ const r1 = getValue!real;
+ const r2 = rhs.getValue!real;
+ if(isNaN(r1))
+ {
+ return isNaN(r2) ? 0 : -1;
+ }
+ if(isNaN(r2))
+ {
+ return 1;
+ }
+ // Fuzzy equality.
+ if(r1 <= r2 + real.epsilon && r1 >= r2 - real.epsilon)
+ {
+ return 0;
+ }
+ return cmp(r1, r2);
+ case NodeType.timestamp:
+ const t1 = getValue!SysTime;
+ const t2 = rhs.getValue!SysTime;
+ return cmp(t1, t2);
+ case NodeType.mapping:
+ return compareCollections!(Pair[])(this, rhs);
+ case NodeType.sequence:
+ return compareCollections!(Node[])(this, rhs);
+ case NodeType.merge:
+ assert(false, "Cannot compare merge nodes");
+ case NodeType.invalid:
+ assert(false, "Cannot compare invalid nodes");
+ }
+ }
+
+ // Ensure opCmp is symmetric for collections
+ @safe unittest
+ {
+ auto node1 = Node(
+ [
+ Node("New York Yankees", "tag:yaml.org,2002:str"),
+ Node("Atlanta Braves", "tag:yaml.org,2002:str")
+ ], "tag:yaml.org,2002:seq"
+ );
+ auto node2 = Node(
+ [
+ Node("Detroit Tigers", "tag:yaml.org,2002:str"),
+ Node("Chicago cubs", "tag:yaml.org,2002:str")
+ ], "tag:yaml.org,2002:seq"
+ );
+ assert(node1 > node2);
+ assert(node2 < node1);
+ }
+
+ // Compute hash of the node.
+ hash_t toHash() nothrow const @trusted
+ {
+ const valueHash = value_.toHash();
+
+ return tag_ is null ? valueHash : tag_.hashOf(valueHash);
+ }
+ @safe unittest
+ {
+ assert(Node(42).toHash() != Node(41).toHash());
+ assert(Node(42).toHash() != Node(42, "some-tag").toHash());
+ }
+
+ /// Get type of the node value.
+ @property NodeType type() const @safe nothrow
+ {
+ if (value_.type is typeid(bool))
+ {
+ return NodeType.boolean;
+ }
+ else if (value_.type is typeid(long))
+ {
+ return NodeType.integer;
+ }
+ else if (value_.type is typeid(Node[]))
+ {
+ return NodeType.sequence;
+ }
+ else if (value_.type is typeid(ubyte[]))
+ {
+ return NodeType.binary;
+ }
+ else if (value_.type is typeid(string))
+ {
+ return NodeType.string;
+ }
+ else if (value_.type is typeid(Node.Pair[]))
+ {
+ return NodeType.mapping;
+ }
+ else if (value_.type is typeid(SysTime))
+ {
+ return NodeType.timestamp;
+ }
+ else if (value_.type is typeid(YAMLNull))
+ {
+ return NodeType.null_;
+ }
+ else if (value_.type is typeid(YAMLMerge))
+ {
+ return NodeType.merge;
+ }
+ else if (value_.type is typeid(real))
+ {
+ return NodeType.decimal;
+ }
+ else if (!value_.hasValue)
+ {
+ return NodeType.invalid;
+ }
+ else assert(0, text(value_.type));
+ }
+
+ /// Get the kind of node this is.
+ @property NodeID nodeID() const @safe nothrow
+ {
+ final switch (type)
+ {
+ case NodeType.sequence:
+ return NodeID.sequence;
+ case NodeType.mapping:
+ return NodeID.mapping;
+ case NodeType.boolean:
+ case NodeType.integer:
+ case NodeType.binary:
+ case NodeType.string:
+ case NodeType.timestamp:
+ case NodeType.null_:
+ case NodeType.merge:
+ case NodeType.decimal:
+ return NodeID.scalar;
+ case NodeType.invalid:
+ return NodeID.invalid;
+ }
+ }
+ package:
+
+ // Get a string representation of the node tree. Used for debugging.
+ //
+ // Params: level = Level of the node in the tree.
+ //
+ // Returns: String representing the node tree.
+ @property string debugString(uint level = 0) const @safe
+ {
+ string indent;
+ foreach(i; 0 .. level){indent ~= " ";}
+
+ final switch (nodeID)
+ {
+ case NodeID.invalid:
+ return indent ~ "invalid";
+ case NodeID.sequence:
+ string result = indent ~ "sequence:\n";
+ foreach(ref node; get!(Node[]))
+ {
+ result ~= node.debugString(level + 1);
+ }
+ return result;
+ case NodeID.mapping:
+ string result = indent ~ "mapping:\n";
+ foreach(ref pair; get!(Node.Pair[]))
+ {
+ result ~= indent ~ " pair\n";
+ result ~= pair.key.debugString(level + 2);
+ result ~= pair.value.debugString(level + 2);
+ }
+ return result;
+ case NodeID.scalar:
+ return indent ~ "scalar(" ~
+ (convertsTo!string ? get!string : text(type)) ~ ")\n";
+ }
+ }
+
+
+ public:
+ @property string nodeTypeString() const @safe nothrow
+ {
+ final switch (nodeID)
+ {
+ case NodeID.mapping:
+ return "mapping";
+ case NodeID.sequence:
+ return "sequence";
+ case NodeID.scalar:
+ return "scalar";
+ case NodeID.invalid:
+ return "invalid";
+ }
+ }
+
+ // Determine if the value can be converted to specified type.
+ @property bool convertsTo(T)() const
+ {
+ if(isType!T){return true;}
+
+ // Every type allowed in Value should be convertible to string.
+ static if(isSomeString!T) {return true;}
+ else static if(isFloatingPoint!T){return type.among!(NodeType.integer, NodeType.decimal);}
+ else static if(isIntegral!T) {return type == NodeType.integer;}
+ else static if(is(Unqual!T==bool)){return type == NodeType.boolean;}
+ else {return false;}
+ }
+ /**
+ * Sets the style of this node when dumped.
+ *
+ * Params: style = Any valid style.
+ */
+ void setStyle(CollectionStyle style) @safe
+ {
+ enforce(!isValid || (nodeID.among(NodeID.mapping, NodeID.sequence)), new NodeException(
+ "Cannot set collection style for non-collection nodes", startMark_));
+ collectionStyle = style;
+ }
+ /// Ditto
+ void setStyle(ScalarStyle style) @safe
+ {
+ enforce(!isValid || (nodeID == NodeID.scalar), new NodeException(
+ "Cannot set scalar style for non-scalar nodes", startMark_));
+ scalarStyle = style;
+ }
+ ///
+ @safe unittest
+ {
+ import dyaml.dumper;
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ node.setStyle(CollectionStyle.block);
+
+ auto dumper = dumper();
+ dumper.dump(stream, node);
+ }
+ ///
+ @safe unittest
+ {
+ import dyaml.dumper;
+ auto stream = new Appender!string();
+ auto node = Node(4);
+ node.setStyle(ScalarStyle.literal);
+
+ auto dumper = dumper();
+ dumper.dump(stream, node);
+ }
+ @safe unittest
+ {
+ assertThrown!NodeException(Node(4).setStyle(CollectionStyle.block));
+ assertThrown!NodeException(Node([4]).setStyle(ScalarStyle.literal));
+ }
+ @safe unittest
+ {
+ import dyaml.dumper;
+ {
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ node.setStyle(CollectionStyle.block);
+ auto dumper = dumper();
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+
+ //Block style should start with a hyphen.
+ assert(stream.data[0] == '-');
+ }
+ {
+ auto stream = new Appender!string();
+ auto node = Node([1, 2, 3, 4, 5]);
+ node.setStyle(CollectionStyle.flow);
+ auto dumper = dumper();
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+
+ //Flow style should start with a bracket.
+ assert(stream.data[0] == '[');
+ }
+ {
+ auto stream = new Appender!string();
+ auto node = Node(1);
+ node.setStyle(ScalarStyle.singleQuoted);
+ auto dumper = dumper();
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+
+ assert(stream.data == "!!int '1'\n");
+ }
+ {
+ auto stream = new Appender!string();
+ auto node = Node(1);
+ node.setStyle(ScalarStyle.doubleQuoted);
+ auto dumper = dumper();
+ dumper.explicitEnd = false;
+ dumper.explicitStart = false;
+ dumper.YAMLVersion = null;
+ dumper.dump(stream, node);
+
+ assert(stream.data == "!!int \"1\"\n");
+ }
+ }
+
+ private:
+ // Determine if the value stored by the node is of specified type.
+ //
+ // This only works for default YAML types, not for user defined types.
+ @property bool isType(T)() const
+ {
+ return value_.type is typeid(Unqual!T);
+ }
+
+ // Implementation of contains() and containsKey().
+ bool contains_(T, Flag!"key" key, string func)(T rhs) const
+ {
+ final switch (nodeID)
+ {
+ case NodeID.mapping:
+ return findPair!(T, key)(rhs) >= 0;
+ case NodeID.sequence:
+ static if(!key)
+ {
+ foreach(ref node; getValue!(Node[]))
+ {
+ if(node == rhs){return true;}
+ }
+ return false;
+ }
+ else
+ {
+ throw new NodeException("Trying to use " ~ func ~ "() on a " ~ nodeTypeString ~ " node",
+ startMark_);
+ }
+ case NodeID.scalar:
+ case NodeID.invalid:
+ throw new NodeException("Trying to use " ~ func ~ "() on a " ~ nodeTypeString ~ " node",
+ startMark_);
+ }
+
+ }
+
+ // Implementation of remove() and removeAt()
+ void remove_(T, Flag!"key" key, string func)(T rhs)
+ {
+ static void removeElem(E, I)(ref Node node, I index)
+ {
+ auto elems = node.getValue!(E[]);
+ moveAll(elems[cast(size_t)index + 1 .. $], elems[cast(size_t)index .. $ - 1]);
+ elems.length = elems.length - 1;
+ node.setValue(elems);
+ }
+
+ final switch (nodeID)
+ {
+ case NodeID.mapping:
+ const index = findPair!(T, key)(rhs);
+ if(index >= 0){removeElem!Pair(this, index);}
+ break;
+ case NodeID.sequence:
+ static long getIndex(ref Node node, ref T rhs)
+ {
+ foreach(idx, ref elem; node.get!(Node[]))
+ {
+ if(elem.convertsTo!T && elem.as!(T, No.stringConversion) == rhs)
+ {
+ return idx;
+ }
+ }
+ return -1;
+ }
+
+ const index = select!key(rhs, getIndex(this, rhs));
+
+ // This throws if the index is not integral.
+ checkSequenceIndex(index);
+
+ static if(isIntegral!(typeof(index))){removeElem!Node(this, index); break; }
+ else {assert(false, "Non-integral sequence index");}
+ case NodeID.scalar:
+ case NodeID.invalid:
+ throw new NodeException("Trying to " ~ func ~ "() from a " ~ nodeTypeString ~ " node",
+ startMark_);
+ }
+ }
+
+ // Get index of pair with key (or value, if key is false) matching index.
+ // Cannot be inferred @safe due to https://issues.dlang.org/show_bug.cgi?id=16528
+ sizediff_t findPair(T, Flag!"key" key = Yes.key)(const ref T index) const @safe
+ {
+ const pairs = getValue!(Pair[])();
+ const(Node)* node;
+ foreach(idx, ref const(Pair) pair; pairs)
+ {
+ static if(key){node = &pair.key;}
+ else {node = &pair.value;}
+
+
+ const bool typeMatch = (isFloatingPoint!T && (node.type.among!(NodeType.integer, NodeType.decimal))) ||
+ (isIntegral!T && node.type == NodeType.integer) ||
+ (is(Unqual!T==bool) && node.type == NodeType.boolean) ||
+ (isSomeString!T && node.type == NodeType.string) ||
+ (node.isType!T);
+ if(typeMatch && *node == index)
+ {
+ return idx;
+ }
+ }
+ return -1;
+ }
+
+ // Check if index is integral and in range.
+ void checkSequenceIndex(T)(T index) const
+ {
+ assert(nodeID == NodeID.sequence,
+ "checkSequenceIndex() called on a " ~ nodeTypeString ~ " node");
+
+ static if(!isIntegral!T)
+ {
+ throw new NodeException("Indexing a sequence with a non-integral type.", startMark_);
+ }
+ else
+ {
+ enforce(index >= 0 && index < getValue!(Node[]).length,
+ new NodeException("Sequence index out of range: " ~ to!string(index),
+ startMark_));
+ }
+ }
+ // Safe wrapper for getting a value out of the variant.
+ inout(T) getValue(T)() @trusted inout
+ {
+ return value_.get!T;
+ }
+ // Safe wrapper for coercing a value out of the variant.
+ inout(T) coerceValue(T)() @trusted inout
+ {
+ return (cast(Value)value_).coerce!T;
+ }
+ // Safe wrapper for setting a value for the variant.
+ void setValue(T)(T value) @trusted
+ {
+ static if (allowed!T)
+ {
+ value_ = value;
+ }
+ else
+ {
+ auto tmpNode = cast(Node)value;
+ tag_ = tmpNode.tag;
+ scalarStyle = tmpNode.scalarStyle;
+ collectionStyle = tmpNode.collectionStyle;
+ value_ = tmpNode.value_;
+ }
+ }
+}
+
+package:
+// Merge pairs into an array of pairs based on merge rules in the YAML spec.
+//
+// Any new pair will only be added if there is not already a pair
+// with the same key.
+//
+// Params: pairs = Appender managing the array of pairs to merge into.
+// toMerge = Pairs to merge.
+void merge(ref Appender!(Node.Pair[]) pairs, Node.Pair[] toMerge) @safe
+{
+ bool eq(ref Node.Pair a, ref Node.Pair b){return a.key == b.key;}
+
+ foreach(ref pair; toMerge) if(!canFind!eq(pairs.data, pair))
+ {
+ pairs.put(pair);
+ }
+}
+
+enum hasNodeConstructor(T) = hasSimpleNodeConstructor!T || hasExpandedNodeConstructor!T;
+template hasSimpleNodeConstructor(T)
+{
+ static if (is(T == struct))
+ {
+ enum hasSimpleNodeConstructor = is(typeof(T(Node.init)));
+ }
+ else static if (is(T == class))
+ {
+ enum hasSimpleNodeConstructor = is(typeof(new inout T(Node.init)));
+ }
+ else enum hasSimpleNodeConstructor = false;
+}
+template hasExpandedNodeConstructor(T)
+{
+ static if (is(T == struct))
+ {
+ enum hasExpandedNodeConstructor = is(typeof(T(Node.init, "")));
+ }
+ else static if (is(T == class))
+ {
+ enum hasExpandedNodeConstructor = is(typeof(new inout T(Node.init, "")));
+ }
+ else enum hasExpandedNodeConstructor = false;
+}
+enum castableToNode(T) = (is(T == struct) || is(T == class)) && is(typeof(T.opCast!Node()) : Node);
diff --git a/src/ext_depends/D-YAML/source/dyaml/package.d b/src/ext_depends/D-YAML/source/dyaml/package.d
new file mode 100644
index 0000000..e61b716
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/package.d
@@ -0,0 +1,15 @@
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml;
+
+public import dyaml.dumper;
+public import dyaml.encoding;
+public import dyaml.exception;
+public import dyaml.linebreak;
+public import dyaml.loader;
+public import dyaml.resolver;
+public import dyaml.style;
+public import dyaml.node;
diff --git a/src/ext_depends/D-YAML/source/dyaml/parser.d b/src/ext_depends/D-YAML/source/dyaml/parser.d
new file mode 100644
index 0000000..7e0b78a
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/parser.d
@@ -0,0 +1,958 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML parser.
+ * Code based on PyYAML: http://www.pyyaml.org
+ */
+module dyaml.parser;
+
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.exception;
+import std.typecons;
+
+import dyaml.event;
+import dyaml.exception;
+import dyaml.scanner;
+import dyaml.style;
+import dyaml.token;
+import dyaml.tagdirective;
+
+
+package:
+/**
+ * The following YAML grammar is LL(1) and is parsed by a recursive descent
+ * parser.
+ *
+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+ * implicit_document ::= block_node DOCUMENT-END*
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ * block_node_or_indentless_sequence ::=
+ * ALIAS
+ * | properties (block_content | indentless_block_sequence)?
+ * | block_content
+ * | indentless_block_sequence
+ * block_node ::= ALIAS
+ * | properties block_content?
+ * | block_content
+ * flow_node ::= ALIAS
+ * | properties flow_content?
+ * | flow_content
+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
+ * block_content ::= block_collection | flow_collection | SCALAR
+ * flow_content ::= flow_collection | SCALAR
+ * block_collection ::= block_sequence | block_mapping
+ * flow_collection ::= flow_sequence | flow_mapping
+ * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+ * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+ * block_mapping ::= BLOCK-MAPPING_START
+ * ((KEY block_node_or_indentless_sequence?)?
+ * (VALUE block_node_or_indentless_sequence?)?)*
+ * BLOCK-END
+ * flow_sequence ::= FLOW-SEQUENCE-START
+ * (flow_sequence_entry FLOW-ENTRY)*
+ * flow_sequence_entry?
+ * FLOW-SEQUENCE-END
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ * flow_mapping ::= FLOW-MAPPING-START
+ * (flow_mapping_entry FLOW-ENTRY)*
+ * flow_mapping_entry?
+ * FLOW-MAPPING-END
+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ *
+ * FIRST sets:
+ *
+ * stream: { STREAM-START }
+ * explicit_document: { DIRECTIVE DOCUMENT-START }
+ * implicit_document: FIRST(block_node)
+ * block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START }
+ * flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START }
+ * block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
+ * flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
+ * block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START }
+ * flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
+ * block_sequence: { BLOCK-SEQUENCE-START }
+ * block_mapping: { BLOCK-MAPPING-START }
+ * block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY }
+ * indentless_sequence: { ENTRY }
+ * flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
+ * flow_sequence: { FLOW-SEQUENCE-START }
+ * flow_mapping: { FLOW-MAPPING-START }
+ * flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
+ * flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
+ */
+
+
+/**
+ * Marked exception thrown at parser errors.
+ *
+ * See_Also: MarkedYAMLException
+ */
+class ParserException : MarkedYAMLException
+{
+ mixin MarkedExceptionCtors;
+}
+
+/// Generates events from tokens provided by a Scanner.
+///
+/// While Parser receives tokens with non-const character slices, the events it
+/// produces are immutable strings, which are usually the same slices, cast to string.
+/// Parser is the last layer of D:YAML that may possibly do any modifications to these
+/// slices.
+final class Parser
+{
+ private:
+ ///Default tag handle shortcuts and replacements.
+ static TagDirective[] defaultTagDirectives_ =
+ [TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
+
+ ///Scanner providing YAML tokens.
+ Scanner scanner_;
+
+ ///Event produced by the most recent state.
+ Event currentEvent_;
+
+ ///YAML version string.
+ string YAMLVersion_ = null;
+ ///Tag handle shortcuts and replacements.
+ TagDirective[] tagDirectives_;
+
+ ///Stack of states.
+ Appender!(Event delegate() @safe[]) states_;
+ ///Stack of marks used to keep track of extents of e.g. YAML collections.
+ Appender!(Mark[]) marks_;
+
+ ///Current state.
+ Event delegate() @safe state_;
+
+ public:
+ ///Construct a Parser using specified Scanner.
+ this(Scanner scanner) @safe
+ {
+ state_ = &parseStreamStart;
+ scanner_ = scanner;
+ states_.reserve(32);
+ marks_.reserve(32);
+ }
+
+ /**
+ * Check if any events are left. May have side effects in some cases.
+ */
+ bool empty() @safe
+ {
+ ensureState();
+ return currentEvent_.isNull;
+ }
+
+ /**
+ * Return the current event.
+ *
+ * Must not be called if there are no events left.
+ */
+ Event front() @safe
+ {
+ ensureState();
+ assert(!currentEvent_.isNull, "No event left to peek");
+ return currentEvent_;
+ }
+
+ /**
+ * Skip to the next event.
+ *
+ * Must not be called if there are no events left.
+ */
+ void popFront() @safe
+ {
+ currentEvent_.id = EventID.invalid;
+ ensureState();
+ }
+
+ private:
+ /// If current event is invalid, load the next valid one if possible.
+ void ensureState() @safe
+ {
+ if(currentEvent_.isNull && state_ !is null)
+ {
+ currentEvent_ = state_();
+ }
+ }
+ ///Pop and return the newest state in states_.
+ Event delegate() @safe popState() @safe
+ {
+ enforce(states_.data.length > 0,
+ new YAMLException("Parser: Need to pop state but no states left to pop"));
+ const result = states_.data.back;
+ states_.shrinkTo(states_.data.length - 1);
+ return result;
+ }
+
+ ///Pop and return the newest mark in marks_.
+ Mark popMark() @safe
+ {
+ enforce(marks_.data.length > 0,
+ new YAMLException("Parser: Need to pop mark but no marks left to pop"));
+ const result = marks_.data.back;
+ marks_.shrinkTo(marks_.data.length - 1);
+ return result;
+ }
+
+ /// Push a state on the stack
+ void pushState(Event delegate() @safe state) @safe
+ {
+ states_ ~= state;
+ }
+ /// Push a mark on the stack
+ void pushMark(Mark mark) @safe
+ {
+ marks_ ~= mark;
+ }
+
+ /**
+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+ * implicit_document ::= block_node DOCUMENT-END*
+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+ */
+
+ ///Parse stream start.
+ Event parseStreamStart() @safe
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+ state_ = &parseImplicitDocumentStart;
+ return streamStartEvent(token.startMark, token.endMark);
+ }
+
+ /// Parse implicit document start, unless explicit detected: if so, parse explicit.
+ Event parseImplicitDocumentStart() @safe
+ {
+ // Parse an implicit document.
+ if(!scanner_.front.id.among!(TokenID.directive, TokenID.documentStart,
+ TokenID.streamEnd))
+ {
+ tagDirectives_ = defaultTagDirectives_;
+ const token = scanner_.front;
+
+ pushState(&parseDocumentEnd);
+ state_ = &parseBlockNode;
+
+ return documentStartEvent(token.startMark, token.endMark, false, null, null);
+ }
+ return parseDocumentStart();
+ }
+
+ ///Parse explicit document start.
+ Event parseDocumentStart() @safe
+ {
+ //Parse any extra document end indicators.
+ while(scanner_.front.id == TokenID.documentEnd)
+ {
+ scanner_.popFront();
+ }
+
+ //Parse an explicit document.
+ if(scanner_.front.id != TokenID.streamEnd)
+ {
+ const startMark = scanner_.front.startMark;
+
+ auto tagDirectives = processDirectives();
+ enforce(scanner_.front.id == TokenID.documentStart,
+ new ParserException("Expected document start but found " ~
+ scanner_.front.idString,
+ scanner_.front.startMark));
+
+ const endMark = scanner_.front.endMark;
+ scanner_.popFront();
+ pushState(&parseDocumentEnd);
+ state_ = &parseDocumentContent;
+ return documentStartEvent(startMark, endMark, true, YAMLVersion_, tagDirectives);
+ }
+ else
+ {
+ //Parse the end of the stream.
+ const token = scanner_.front;
+ scanner_.popFront();
+ assert(states_.data.length == 0);
+ assert(marks_.data.length == 0);
+ state_ = null;
+ return streamEndEvent(token.startMark, token.endMark);
+ }
+ }
+
+ ///Parse document end (explicit or implicit).
+ Event parseDocumentEnd() @safe
+ {
+ Mark startMark = scanner_.front.startMark;
+ const bool explicit = scanner_.front.id == TokenID.documentEnd;
+ Mark endMark = startMark;
+ if (explicit)
+ {
+ endMark = scanner_.front.endMark;
+ scanner_.popFront();
+ }
+
+ state_ = &parseDocumentStart;
+
+ return documentEndEvent(startMark, endMark, explicit);
+ }
+
+ ///Parse document content.
+ Event parseDocumentContent() @safe
+ {
+ if(scanner_.front.id.among!(TokenID.directive, TokenID.documentStart,
+ TokenID.documentEnd, TokenID.streamEnd))
+ {
+ state_ = popState();
+ return processEmptyScalar(scanner_.front.startMark);
+ }
+ return parseBlockNode();
+ }
+
+ /// Process directives at the beginning of a document.
+ TagDirective[] processDirectives() @safe
+ {
+ // Destroy version and tag handles from previous document.
+ YAMLVersion_ = null;
+ tagDirectives_.length = 0;
+
+ // Process directives.
+ while(scanner_.front.id == TokenID.directive)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+ string value = token.value.idup;
+ if(token.directive == DirectiveType.yaml)
+ {
+ enforce(YAMLVersion_ is null,
+ new ParserException("Duplicate YAML directive", token.startMark));
+ const minor = value.split(".")[0];
+ enforce(minor == "1",
+ new ParserException("Incompatible document (version 1.x is required)",
+ token.startMark));
+ YAMLVersion_ = value;
+ }
+ else if(token.directive == DirectiveType.tag)
+ {
+ auto handle = value[0 .. token.valueDivider];
+
+ foreach(ref pair; tagDirectives_)
+ {
+ // handle
+ const h = pair.handle;
+ enforce(h != handle, new ParserException("Duplicate tag handle: " ~ handle,
+ token.startMark));
+ }
+ tagDirectives_ ~=
+ TagDirective(handle, value[token.valueDivider .. $]);
+ }
+ // Any other directive type is ignored (only YAML and TAG are in YAML
+ // 1.1/1.2, any other directives are "reserved")
+ }
+
+ TagDirective[] value = tagDirectives_;
+
+ //Add any default tag handles that haven't been overridden.
+ foreach(ref defaultPair; defaultTagDirectives_)
+ {
+ bool found;
+ foreach(ref pair; tagDirectives_) if(defaultPair.handle == pair.handle)
+ {
+ found = true;
+ break;
+ }
+ if(!found) {tagDirectives_ ~= defaultPair; }
+ }
+
+ return value;
+ }
+
+ /**
+ * block_node_or_indentless_sequence ::= ALIAS
+ * | properties (block_content | indentless_block_sequence)?
+ * | block_content
+ * | indentless_block_sequence
+ * block_node ::= ALIAS
+ * | properties block_content?
+ * | block_content
+ * flow_node ::= ALIAS
+ * | properties flow_content?
+ * | flow_content
+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
+ * block_content ::= block_collection | flow_collection | SCALAR
+ * flow_content ::= flow_collection | SCALAR
+ * block_collection ::= block_sequence | block_mapping
+ * flow_collection ::= flow_sequence | flow_mapping
+ */
+
+ ///Parse a node.
+ Event parseNode(const Flag!"block" block,
+ const Flag!"indentlessSequence" indentlessSequence = No.indentlessSequence)
+ @trusted
+ {
+ if(scanner_.front.id == TokenID.alias_)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+ state_ = popState();
+ return aliasEvent(token.startMark, token.endMark,
+ cast(string)token.value);
+ }
+
+ string anchor;
+ string tag;
+ Mark startMark, endMark, tagMark;
+ bool invalidMarks = true;
+ // The index in the tag string where tag handle ends and tag suffix starts.
+ uint tagHandleEnd;
+
+ //Get anchor/tag if detected. Return false otherwise.
+ bool get(const TokenID id, const Flag!"first" first, ref string target) @safe
+ {
+ if(scanner_.front.id != id){return false;}
+ invalidMarks = false;
+ const token = scanner_.front;
+ scanner_.popFront();
+ if(first){startMark = token.startMark;}
+ if(id == TokenID.tag)
+ {
+ tagMark = token.startMark;
+ tagHandleEnd = token.valueDivider;
+ }
+ endMark = token.endMark;
+ target = token.value.idup;
+ return true;
+ }
+
+ //Anchor and/or tag can be in any order.
+ if(get(TokenID.anchor, Yes.first, anchor)){get(TokenID.tag, No.first, tag);}
+ else if(get(TokenID.tag, Yes.first, tag)) {get(TokenID.anchor, No.first, anchor);}
+
+ if(tag !is null){tag = processTag(tag, tagHandleEnd, startMark, tagMark);}
+
+ if(invalidMarks)
+ {
+ startMark = endMark = scanner_.front.startMark;
+ }
+
+ bool implicit = (tag is null || tag == "!");
+
+ if(indentlessSequence && scanner_.front.id == TokenID.blockEntry)
+ {
+ state_ = &parseIndentlessSequenceEntry;
+ return sequenceStartEvent
+ (startMark, scanner_.front.endMark, anchor,
+ tag, implicit, CollectionStyle.block);
+ }
+
+ if(scanner_.front.id == TokenID.scalar)
+ {
+ auto token = scanner_.front;
+ scanner_.popFront();
+ auto value = token.style == ScalarStyle.doubleQuoted
+ ? handleDoubleQuotedScalarEscapes(token.value)
+ : cast(string)token.value;
+
+ implicit = (token.style == ScalarStyle.plain && tag is null) || tag == "!";
+ state_ = popState();
+ return scalarEvent(startMark, token.endMark, anchor, tag,
+ implicit, value, token.style);
+ }
+
+ if(scanner_.front.id == TokenID.flowSequenceStart)
+ {
+ endMark = scanner_.front.endMark;
+ state_ = &parseFlowSequenceEntry!(Yes.first);
+ return sequenceStartEvent(startMark, endMark, anchor, tag,
+ implicit, CollectionStyle.flow);
+ }
+
+ if(scanner_.front.id == TokenID.flowMappingStart)
+ {
+ endMark = scanner_.front.endMark;
+ state_ = &parseFlowMappingKey!(Yes.first);
+ return mappingStartEvent(startMark, endMark, anchor, tag,
+ implicit, CollectionStyle.flow);
+ }
+
+ if(block && scanner_.front.id == TokenID.blockSequenceStart)
+ {
+ endMark = scanner_.front.endMark;
+ state_ = &parseBlockSequenceEntry!(Yes.first);
+ return sequenceStartEvent(startMark, endMark, anchor, tag,
+ implicit, CollectionStyle.block);
+ }
+
+ if(block && scanner_.front.id == TokenID.blockMappingStart)
+ {
+ endMark = scanner_.front.endMark;
+ state_ = &parseBlockMappingKey!(Yes.first);
+ return mappingStartEvent(startMark, endMark, anchor, tag,
+ implicit, CollectionStyle.block);
+ }
+
+ if(anchor !is null || tag !is null)
+ {
+ state_ = popState();
+
+ //PyYAML uses a tuple(implicit, false) for the second last arg here,
+ //but the second bool is never used after that - so we don't use it.
+
+ //Empty scalars are allowed even if a tag or an anchor is specified.
+ return scalarEvent(startMark, endMark, anchor, tag,
+ implicit , "");
+ }
+
+ const token = scanner_.front;
+ throw new ParserException("While parsing a " ~ (block ? "block" : "flow") ~ " node",
+ startMark, "expected node content, but found: "
+ ~ token.idString, token.startMark);
+ }
+
+ /// Handle escape sequences in a double quoted scalar.
+ ///
+ /// Moved here from scanner as it can't always be done in-place with slices.
+ string handleDoubleQuotedScalarEscapes(const(char)[] tokenValue) const @safe
+ {
+ string notInPlace;
+ bool inEscape;
+ auto appender = appender!(string)();
+ for(const(char)[] oldValue = tokenValue; !oldValue.empty();)
+ {
+ const dchar c = oldValue.front();
+ oldValue.popFront();
+
+ if(!inEscape)
+ {
+ if(c != '\\')
+ {
+ if(notInPlace is null) { appender.put(c); }
+ else { notInPlace ~= c; }
+ continue;
+ }
+ // Escape sequence starts with a '\'
+ inEscape = true;
+ continue;
+ }
+
+ import dyaml.escapes;
+ scope(exit) { inEscape = false; }
+
+ // 'Normal' escape sequence.
+ if(c.among!(escapes))
+ {
+ if(notInPlace is null)
+ {
+ // \L and \C can't be handled in place as the expand into
+ // many-byte unicode chars
+ if(c != 'L' && c != 'P')
+ {
+ appender.put(dyaml.escapes.fromEscape(c));
+ continue;
+ }
+ // Need to duplicate as we won't fit into
+ // token.value - which is what appender uses
+ notInPlace = appender.data.dup;
+ notInPlace ~= dyaml.escapes.fromEscape(c);
+ continue;
+ }
+ notInPlace ~= dyaml.escapes.fromEscape(c);
+ continue;
+ }
+
+ // Unicode char written in hexadecimal in an escape sequence.
+ if(c.among!(escapeHexCodeList))
+ {
+ // Scanner has already checked that the hex string is valid.
+
+ const hexLength = dyaml.escapes.escapeHexLength(c);
+ // Any hex digits are 1-byte so this works.
+ const(char)[] hex = oldValue[0 .. hexLength];
+ oldValue = oldValue[hexLength .. $];
+ import std.ascii : isHexDigit;
+ assert(!hex.canFind!(d => !d.isHexDigit),
+ "Scanner must ensure the hex string is valid");
+
+ const decoded = cast(dchar)parse!int(hex, 16u);
+ if(notInPlace is null) { appender.put(decoded); }
+ else { notInPlace ~= decoded; }
+ continue;
+ }
+
+ assert(false, "Scanner must handle unsupported escapes");
+ }
+
+ return notInPlace is null ? appender.data : notInPlace;
+ }
+
+ /**
+ * Process a tag string retrieved from a tag token.
+ *
+ * Params: tag = Tag before processing.
+ * handleEnd = Index in tag where tag handle ends and tag suffix
+ * starts.
+ * startMark = Position of the node the tag belongs to.
+ * tagMark = Position of the tag.
+ */
+ string processTag(const string tag, const uint handleEnd,
+ const Mark startMark, const Mark tagMark)
+ const @safe
+ {
+ const handle = tag[0 .. handleEnd];
+ const suffix = tag[handleEnd .. $];
+
+ if(handle.length > 0)
+ {
+ string replacement;
+ foreach(ref pair; tagDirectives_)
+ {
+ if(pair.handle == handle)
+ {
+ replacement = pair.prefix;
+ break;
+ }
+ }
+ //handle must be in tagDirectives_
+ enforce(replacement !is null,
+ new ParserException("While parsing a node", startMark,
+ "found undefined tag handle: " ~ handle, tagMark));
+ return replacement ~ suffix;
+ }
+ return suffix;
+ }
+
+ ///Wrappers to parse nodes.
+ Event parseBlockNode() @safe {return parseNode(Yes.block);}
+ Event parseFlowNode() @safe {return parseNode(No.block);}
+ Event parseBlockNodeOrIndentlessSequence() @safe {return parseNode(Yes.block, Yes.indentlessSequence);}
+
+ ///block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+
+ ///Parse an entry of a block sequence. If first is true, this is the first entry.
+ Event parseBlockSequenceEntry(Flag!"first" first)() @safe
+ {
+ static if(first)
+ {
+ pushMark(scanner_.front.startMark);
+ scanner_.popFront();
+ }
+
+ if(scanner_.front.id == TokenID.blockEntry)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+ if(!scanner_.front.id.among!(TokenID.blockEntry, TokenID.blockEnd))
+ {
+ pushState(&parseBlockSequenceEntry!(No.first));
+ return parseBlockNode();
+ }
+
+ state_ = &parseBlockSequenceEntry!(No.first);
+ return processEmptyScalar(token.endMark);
+ }
+
+ if(scanner_.front.id != TokenID.blockEnd)
+ {
+ const token = scanner_.front;
+ throw new ParserException("While parsing a block collection", marks_.data.back,
+ "expected block end, but found " ~ token.idString,
+ token.startMark);
+ }
+
+ state_ = popState();
+ popMark();
+ const token = scanner_.front;
+ scanner_.popFront();
+ return sequenceEndEvent(token.startMark, token.endMark);
+ }
+
+ ///indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+
+ ///Parse an entry of an indentless sequence.
+ Event parseIndentlessSequenceEntry() @safe
+ {
+ if(scanner_.front.id == TokenID.blockEntry)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+
+ if(!scanner_.front.id.among!(TokenID.blockEntry, TokenID.key,
+ TokenID.value, TokenID.blockEnd))
+ {
+ pushState(&parseIndentlessSequenceEntry);
+ return parseBlockNode();
+ }
+
+ state_ = &parseIndentlessSequenceEntry;
+ return processEmptyScalar(token.endMark);
+ }
+
+ state_ = popState();
+ const token = scanner_.front;
+ return sequenceEndEvent(token.startMark, token.endMark);
+ }
+
+ /**
+ * block_mapping ::= BLOCK-MAPPING_START
+ * ((KEY block_node_or_indentless_sequence?)?
+ * (VALUE block_node_or_indentless_sequence?)?)*
+ * BLOCK-END
+ */
+
+ ///Parse a key in a block mapping. If first is true, this is the first key.
+ Event parseBlockMappingKey(Flag!"first" first)() @safe
+ {
+ static if(first)
+ {
+ pushMark(scanner_.front.startMark);
+ scanner_.popFront();
+ }
+
+ if(scanner_.front.id == TokenID.key)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+
+ if(!scanner_.front.id.among!(TokenID.key, TokenID.value, TokenID.blockEnd))
+ {
+ pushState(&parseBlockMappingValue);
+ return parseBlockNodeOrIndentlessSequence();
+ }
+
+ state_ = &parseBlockMappingValue;
+ return processEmptyScalar(token.endMark);
+ }
+
+ if(scanner_.front.id != TokenID.blockEnd)
+ {
+ const token = scanner_.front;
+ throw new ParserException("While parsing a block mapping", marks_.data.back,
+ "expected block end, but found: " ~ token.idString,
+ token.startMark);
+ }
+
+ state_ = popState();
+ popMark();
+ const token = scanner_.front;
+ scanner_.popFront();
+ return mappingEndEvent(token.startMark, token.endMark);
+ }
+
+ ///Parse a value in a block mapping.
+ Event parseBlockMappingValue() @safe
+ {
+ if(scanner_.front.id == TokenID.value)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+
+ if(!scanner_.front.id.among!(TokenID.key, TokenID.value, TokenID.blockEnd))
+ {
+ pushState(&parseBlockMappingKey!(No.first));
+ return parseBlockNodeOrIndentlessSequence();
+ }
+
+ state_ = &parseBlockMappingKey!(No.first);
+ return processEmptyScalar(token.endMark);
+ }
+
+ state_= &parseBlockMappingKey!(No.first);
+ return processEmptyScalar(scanner_.front.startMark);
+ }
+
+ /**
+ * flow_sequence ::= FLOW-SEQUENCE-START
+ * (flow_sequence_entry FLOW-ENTRY)*
+ * flow_sequence_entry?
+ * FLOW-SEQUENCE-END
+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ *
+ * Note that while production rules for both flow_sequence_entry and
+ * flow_mapping_entry are equal, their interpretations are different.
+ * For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?`
+ * generate an inline mapping (set syntax).
+ */
+
+ ///Parse an entry in a flow sequence. If first is true, this is the first entry.
+ Event parseFlowSequenceEntry(Flag!"first" first)() @safe
+ {
+ static if(first)
+ {
+ pushMark(scanner_.front.startMark);
+ scanner_.popFront();
+ }
+
+ if(scanner_.front.id != TokenID.flowSequenceEnd)
+ {
+ static if(!first)
+ {
+ if(scanner_.front.id == TokenID.flowEntry)
+ {
+ scanner_.popFront();
+ }
+ else
+ {
+ const token = scanner_.front;
+ throw new ParserException("While parsing a flow sequence", marks_.data.back,
+ "expected ',' or ']', but got: " ~
+ token.idString, token.startMark);
+ }
+ }
+
+ if(scanner_.front.id == TokenID.key)
+ {
+ const token = scanner_.front;
+ state_ = &parseFlowSequenceEntryMappingKey;
+ return mappingStartEvent(token.startMark, token.endMark,
+ null, null, true, CollectionStyle.flow);
+ }
+ else if(scanner_.front.id != TokenID.flowSequenceEnd)
+ {
+ pushState(&parseFlowSequenceEntry!(No.first));
+ return parseFlowNode();
+ }
+ }
+
+ const token = scanner_.front;
+ scanner_.popFront();
+ state_ = popState();
+ popMark();
+ return sequenceEndEvent(token.startMark, token.endMark);
+ }
+
+ ///Parse a key in flow context.
+ Event parseFlowKey(Event delegate() @safe nextState) @safe
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+
+ if(!scanner_.front.id.among!(TokenID.value, TokenID.flowEntry,
+ TokenID.flowSequenceEnd))
+ {
+ pushState(nextState);
+ return parseFlowNode();
+ }
+
+ state_ = nextState;
+ return processEmptyScalar(token.endMark);
+ }
+
+ ///Parse a mapping key in an entry in a flow sequence.
+ Event parseFlowSequenceEntryMappingKey() @safe
+ {
+ return parseFlowKey(&parseFlowSequenceEntryMappingValue);
+ }
+
+ ///Parse a mapping value in a flow context.
+ Event parseFlowValue(TokenID checkId, Event delegate() @safe nextState)
+ @safe
+ {
+ if(scanner_.front.id == TokenID.value)
+ {
+ const token = scanner_.front;
+ scanner_.popFront();
+ if(!scanner_.front.id.among(TokenID.flowEntry, checkId))
+ {
+ pushState(nextState);
+ return parseFlowNode();
+ }
+
+ state_ = nextState;
+ return processEmptyScalar(token.endMark);
+ }
+
+ state_ = nextState;
+ return processEmptyScalar(scanner_.front.startMark);
+ }
+
+ ///Parse a mapping value in an entry in a flow sequence.
+ Event parseFlowSequenceEntryMappingValue() @safe
+ {
+ return parseFlowValue(TokenID.flowSequenceEnd,
+ &parseFlowSequenceEntryMappingEnd);
+ }
+
+ ///Parse end of a mapping in a flow sequence entry.
+ Event parseFlowSequenceEntryMappingEnd() @safe
+ {
+ state_ = &parseFlowSequenceEntry!(No.first);
+ const token = scanner_.front;
+ return mappingEndEvent(token.startMark, token.startMark);
+ }
+
+ /**
+ * flow_mapping ::= FLOW-MAPPING-START
+ * (flow_mapping_entry FLOW-ENTRY)*
+ * flow_mapping_entry?
+ * FLOW-MAPPING-END
+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+ */
+
+ ///Parse a key in a flow mapping.
+ Event parseFlowMappingKey(Flag!"first" first)() @safe
+ {
+ static if(first)
+ {
+ pushMark(scanner_.front.startMark);
+ scanner_.popFront();
+ }
+
+ if(scanner_.front.id != TokenID.flowMappingEnd)
+ {
+ static if(!first)
+ {
+ if(scanner_.front.id == TokenID.flowEntry)
+ {
+ scanner_.popFront();
+ }
+ else
+ {
+ const token = scanner_.front;
+ throw new ParserException("While parsing a flow mapping", marks_.data.back,
+ "expected ',' or '}', but got: " ~
+ token.idString, token.startMark);
+ }
+ }
+
+ if(scanner_.front.id == TokenID.key)
+ {
+ return parseFlowKey(&parseFlowMappingValue);
+ }
+
+ if(scanner_.front.id != TokenID.flowMappingEnd)
+ {
+ pushState(&parseFlowMappingEmptyValue);
+ return parseFlowNode();
+ }
+ }
+
+ const token = scanner_.front;
+ scanner_.popFront();
+ state_ = popState();
+ popMark();
+ return mappingEndEvent(token.startMark, token.endMark);
+ }
+
+ ///Parse a value in a flow mapping.
+ Event parseFlowMappingValue() @safe
+ {
+ return parseFlowValue(TokenID.flowMappingEnd, &parseFlowMappingKey!(No.first));
+ }
+
+ ///Parse an empty value in a flow mapping.
+ Event parseFlowMappingEmptyValue() @safe
+ {
+ state_ = &parseFlowMappingKey!(No.first);
+ return processEmptyScalar(scanner_.front.startMark);
+ }
+
+ ///Return an empty scalar.
+ Event processEmptyScalar(const Mark mark) @safe pure nothrow const @nogc
+ {
+ return scalarEvent(mark, mark, null, null, true, "");
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/queue.d b/src/ext_depends/D-YAML/source/dyaml/queue.d
new file mode 100644
index 0000000..57b0d34
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/queue.d
@@ -0,0 +1,272 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.queue;
+
+
+import std.traits : hasMember, hasIndirections;
+
+package:
+
+/// Simple queue implemented as a singly linked list with a tail pointer.
+///
+/// Needed in some D:YAML code that needs a queue-like structure without too much
+/// reallocation that goes with an array.
+///
+/// Allocations are non-GC and are damped by a free-list based on the nodes
+/// that are removed. Note that elements lifetime must be managed
+/// outside.
+struct Queue(T)
+if (!hasMember!(T, "__xdtor"))
+{
+
+private:
+
+ // Linked list node containing one element and pointer to the next node.
+ struct Node
+ {
+ T payload_;
+ Node* next_;
+ }
+
+ // Start of the linked list - first element added in time (end of the queue).
+ Node* first_;
+ // Last element of the linked list - last element added in time (start of the queue).
+ Node* last_;
+ // free-list
+ Node* stock;
+
+ // Length of the queue.
+ size_t length_;
+
+ // allocate a new node or recycle one from the stock.
+ Node* makeNewNode(T thePayload, Node* theNext = null) @trusted nothrow @nogc
+ {
+ import std.experimental.allocator : make;
+ import std.experimental.allocator.mallocator : Mallocator;
+
+ Node* result;
+ if (stock !is null)
+ {
+ result = stock;
+ stock = result.next_;
+ result.payload_ = thePayload;
+ result.next_ = theNext;
+ }
+ else
+ {
+ result = Mallocator.instance.make!(Node)(thePayload, theNext);
+ // GC can dispose T managed member if it thinks they are no used...
+ static if (hasIndirections!T)
+ {
+ import core.memory : GC;
+ GC.addRange(result, Node.sizeof);
+ }
+ }
+ return result;
+ }
+
+ // free the stock of available free nodes.
+ void freeStock() @trusted @nogc nothrow
+ {
+ import std.experimental.allocator.mallocator : Mallocator;
+
+ while (stock !is null)
+ {
+ Node* toFree = stock;
+ stock = stock.next_;
+ static if (hasIndirections!T)
+ {
+ import core.memory : GC;
+ GC.removeRange(toFree);
+ }
+ Mallocator.instance.deallocate((cast(ubyte*) toFree)[0 .. Node.sizeof]);
+ }
+ }
+
+public:
+
+ @disable void opAssign(ref Queue);
+ @disable bool opEquals(ref Queue);
+ @disable int opCmp(ref Queue);
+
+ this(this) @safe nothrow @nogc
+ {
+ auto node = first_;
+ first_ = null;
+ last_ = null;
+ while (node !is null)
+ {
+ Node* newLast = makeNewNode(node.payload_);
+ if (last_ !is null)
+ last_.next_ = newLast;
+ if (first_ is null)
+ first_ = newLast;
+ last_ = newLast;
+ node = node.next_;
+ }
+ }
+
+ ~this() @safe nothrow @nogc
+ {
+ freeStock();
+ stock = first_;
+ freeStock();
+ }
+
+ /// Returns a forward range iterating over this queue.
+ auto range() @safe pure nothrow @nogc
+ {
+ static struct Result
+ {
+ private Node* cursor;
+
+ void popFront() @safe pure nothrow @nogc
+ {
+ cursor = cursor.next_;
+ }
+ ref T front() @safe pure nothrow @nogc
+ in(cursor !is null)
+ {
+ return cursor.payload_;
+ }
+ bool empty() @safe pure nothrow @nogc const
+ {
+ return cursor is null;
+ }
+ }
+ return Result(first_);
+ }
+
+ /// Push a new item to the queue.
+ void push(T item) @nogc @safe nothrow
+ {
+ Node* newLast = makeNewNode(item);
+ if (last_ !is null)
+ last_.next_ = newLast;
+ if (first_ is null)
+ first_ = newLast;
+ last_ = newLast;
+ ++length_;
+ }
+
+ /// Insert a new item putting it to specified index in the linked list.
+ void insert(T item, const size_t idx) @safe nothrow
+ in
+ {
+ assert(idx <= length_);
+ }
+ do
+ {
+ if (idx == 0)
+ {
+ first_ = makeNewNode(item, first_);
+ ++length_;
+ }
+ // Adding before last added element, so we can just push.
+ else if (idx == length_)
+ {
+ push(item);
+ }
+ else
+ {
+ // Get the element before one we're inserting.
+ Node* current = first_;
+ foreach (i; 1 .. idx)
+ current = current.next_;
+
+ assert(current);
+ // Insert a new node after current, and put current.next_ behind it.
+ current.next_ = makeNewNode(item, current.next_);
+ ++length_;
+ }
+ }
+
+ /// Returns: The next element in the queue and remove it.
+ T pop() @safe nothrow
+ in
+ {
+ assert(!empty, "Trying to pop an element from an empty queue");
+ }
+ do
+ {
+ T result = peek();
+
+ Node* oldStock = stock;
+ Node* old = first_;
+ first_ = first_.next_;
+
+ // start the stock from the popped element
+ stock = old;
+ old.next_ = null;
+ // add the existing "old" stock to the new first stock element
+ if (oldStock !is null)
+ stock.next_ = oldStock;
+
+ if (--length_ == 0)
+ {
+ assert(first_ is null);
+ last_ = null;
+ }
+
+ return result;
+ }
+
+ /// Returns: The next element in the queue.
+ ref inout(T) peek() @safe pure nothrow inout @nogc
+ in
+ {
+ assert(!empty, "Trying to peek at an element in an empty queue");
+ }
+ do
+ {
+ return first_.payload_;
+ }
+
+ /// Returns: true of the queue empty, false otherwise.
+ bool empty() @safe pure nothrow const @nogc
+ {
+ return first_ is null;
+ }
+
+ /// Returns: The number of elements in the queue.
+ size_t length() @safe pure nothrow const @nogc
+ {
+ return length_;
+ }
+}
+
+@safe nothrow unittest
+{
+ auto queue = Queue!int();
+ assert(queue.empty);
+ foreach (i; 0 .. 65)
+ {
+ queue.push(5);
+ assert(queue.pop() == 5);
+ assert(queue.empty);
+ assert(queue.length_ == 0);
+ }
+
+ int[] array = [1, -1, 2, -2, 3, -3, 4, -4, 5, -5];
+ foreach (i; array)
+ {
+ queue.push(i);
+ }
+
+ array = 42 ~ array[0 .. 3] ~ 42 ~ array[3 .. $] ~ 42;
+ queue.insert(42, 3);
+ queue.insert(42, 0);
+ queue.insert(42, queue.length);
+
+ int[] array2;
+ while (!queue.empty)
+ {
+ array2 ~= queue.pop();
+ }
+
+ assert(array == array2);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/reader.d b/src/ext_depends/D-YAML/source/dyaml/reader.d
new file mode 100644
index 0000000..9fe42fc
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/reader.d
@@ -0,0 +1,906 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.reader;
+
+
+import core.stdc.stdlib;
+import core.stdc.string;
+import core.thread;
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.exception;
+import std.range;
+import std.string;
+import std.system;
+import std.typecons;
+import std.utf;
+
+import tinyendian;
+
+import dyaml.encoding;
+import dyaml.exception;
+
+alias isBreak = among!('\n', '\u0085', '\u2028', '\u2029');
+
+package:
+
+
+///Exception thrown at Reader errors.
+class ReaderException : YAMLException
+{
+ this(string msg, string file = __FILE__, size_t line = __LINE__)
+ @safe pure nothrow
+ {
+ super("Reader error: " ~ msg, file, line);
+ }
+}
+
+/// Provides an API to read characters from a UTF-8 buffer and build slices into that
+/// buffer to avoid allocations (see SliceBuilder).
+final class Reader
+{
+ private:
+ // Buffer of currently loaded characters.
+ char[] buffer_;
+
+ // Current position within buffer. Only data after this position can be read.
+ size_t bufferOffset_;
+
+ // Index of the current character in the buffer.
+ size_t charIndex_;
+ // Number of characters (code points) in buffer_.
+ size_t characterCount_;
+
+ // File name
+ string name_;
+ // Current line in file.
+ uint line_;
+ // Current column in file.
+ uint column_;
+
+ // Original Unicode encoding of the data.
+ Encoding encoding_;
+
+ version(unittest)
+ {
+ // Endianness of the input before it was converted (for testing)
+ Endian endian_;
+ }
+
+ // The number of consecutive ASCII characters starting at bufferOffset_.
+ //
+ // Used to minimize UTF-8 decoding.
+ size_t upcomingASCII_;
+
+ // Index to buffer_ where the last decoded character starts.
+ size_t lastDecodedBufferOffset_;
+ // Offset, relative to charIndex_, of the last decoded character,
+ // in code points, not chars.
+ size_t lastDecodedCharOffset_;
+
+ public:
+ /// Construct a Reader.
+ ///
+ /// Params: buffer = Buffer with YAML data. This may be e.g. the entire
+ /// contents of a file or a string. $(B will) be modified by
+ /// the Reader and other parts of D:YAML (D:YAML tries to
+ /// reuse the buffer to minimize memory allocations)
+ /// name = File name if the buffer is the contents of a file or
+ /// `"<unknown>"` if the buffer is the contents of a string.
+ ///
+ /// Throws: ReaderException on a UTF decoding error or if there are
+ /// nonprintable Unicode characters illegal in YAML.
+ this(ubyte[] buffer, string name = "<unknown>") @safe pure
+ {
+ name_ = name;
+ auto endianResult = fixUTFByteOrder(buffer);
+ if(endianResult.bytesStripped > 0)
+ {
+ throw new ReaderException("Size of UTF-16 or UTF-32 input not aligned " ~
+ "to 2 or 4 bytes, respectively");
+ }
+
+ version(unittest) { endian_ = endianResult.endian; }
+ encoding_ = endianResult.encoding;
+
+ auto utf8Result = toUTF8(endianResult.array, endianResult.encoding);
+ const msg = utf8Result.errorMessage;
+ if(msg !is null)
+ {
+ throw new ReaderException("Error when converting to UTF-8: " ~ msg);
+ }
+
+ buffer_ = utf8Result.utf8;
+
+ characterCount_ = utf8Result.characterCount;
+ // Check that all characters in buffer are printable.
+ enforce(isPrintableValidUTF8(buffer_),
+ new ReaderException("Special unicode characters are not allowed"));
+
+ this.sliceBuilder = SliceBuilder(this);
+ checkASCII();
+ }
+
+ /// Get character at specified index relative to current position.
+ ///
+ /// Params: index = Index of the character to get relative to current position
+ /// in the buffer. Can point outside of the buffer; In that
+ /// case, '\0' will be returned.
+ ///
+ /// Returns: Character at specified position or '\0' if outside of the buffer.
+ ///
+ // XXX removed; search for 'risky' to find why.
+ // Throws: ReaderException if trying to read past the end of the buffer.
+ dchar peek(const size_t index) @safe pure
+ {
+ if(index < upcomingASCII_) { return buffer_[bufferOffset_ + index]; }
+ if(characterCount_ <= charIndex_ + index)
+ {
+ // XXX This is risky; revert this if bugs are introduced. We rely on
+ // the assumption that Reader only uses peek() to detect end of buffer.
+ // The test suite passes.
+ // Revert this case here and in other peek() versions if this causes
+ // errors.
+ // throw new ReaderException("Trying to read past the end of the buffer");
+ return '\0';
+ }
+
+ // Optimized path for Scanner code that peeks chars in linear order to
+ // determine the length of some sequence.
+ if(index == lastDecodedCharOffset_)
+ {
+ ++lastDecodedCharOffset_;
+ const char b = buffer_[lastDecodedBufferOffset_];
+ // ASCII
+ if(b < 0x80)
+ {
+ ++lastDecodedBufferOffset_;
+ return b;
+ }
+ return decode(buffer_, lastDecodedBufferOffset_);
+ }
+
+ // 'Slow' path where we decode everything up to the requested character.
+ const asciiToTake = min(upcomingASCII_, index);
+ lastDecodedCharOffset_ = asciiToTake;
+ lastDecodedBufferOffset_ = bufferOffset_ + asciiToTake;
+ dchar d;
+ while(lastDecodedCharOffset_ <= index)
+ {
+ d = decodeNext();
+ }
+
+ return d;
+ }
+
+ /// Optimized version of peek() for the case where peek index is 0.
+ dchar peek() @safe pure
+ {
+ if(upcomingASCII_ > 0) { return buffer_[bufferOffset_]; }
+ if(characterCount_ <= charIndex_) { return '\0'; }
+
+ lastDecodedCharOffset_ = 0;
+ lastDecodedBufferOffset_ = bufferOffset_;
+ return decodeNext();
+ }
+
+ /// Get byte at specified index relative to current position.
+ ///
+ /// Params: index = Index of the byte to get relative to current position
+ /// in the buffer. Can point outside of the buffer; In that
+ /// case, '\0' will be returned.
+ ///
+ /// Returns: Byte at specified position or '\0' if outside of the buffer.
+ char peekByte(const size_t index) @safe pure nothrow @nogc
+ {
+ return characterCount_ > (charIndex_ + index) ? buffer_[bufferOffset_ + index] : '\0';
+ }
+
+ /// Optimized version of peekByte() for the case where peek byte index is 0.
+ char peekByte() @safe pure nothrow @nogc
+ {
+ return characterCount_ > charIndex_ ? buffer_[bufferOffset_] : '\0';
+ }
+
+
+ /// Get specified number of characters starting at current position.
+ ///
+ /// Note: This gets only a "view" into the internal buffer, which will be
+ /// invalidated after other Reader calls. Use SliceBuilder to build slices
+ /// for permanent use.
+ ///
+ /// Params: length = Number of characters (code points, not bytes) to get. May
+ /// reach past the end of the buffer; in that case the returned
+ /// slice will be shorter.
+ ///
+ /// Returns: Characters starting at current position or an empty slice if out of bounds.
+ char[] prefix(const size_t length) @safe pure
+ {
+ return slice(length);
+ }
+
+ /// Get specified number of bytes, not code points, starting at current position.
+ ///
+ /// Note: This gets only a "view" into the internal buffer, which will be
+ /// invalidated after other Reader calls. Use SliceBuilder to build slices
+ /// for permanent use.
+ ///
+ /// Params: length = Number bytes (not code points) to get. May NOT reach past
+ /// the end of the buffer; should be used with peek() to avoid
+ /// this.
+ ///
+ /// Returns: Bytes starting at current position.
+ char[] prefixBytes(const size_t length) @safe pure nothrow @nogc
+ in(length == 0 || bufferOffset_ + length <= buffer_.length, "prefixBytes out of bounds")
+ {
+ return buffer_[bufferOffset_ .. bufferOffset_ + length];
+ }
+
+ /// Get a slice view of the internal buffer, starting at the current position.
+ ///
+ /// Note: This gets only a "view" into the internal buffer,
+ /// which get invalidated after other Reader calls.
+ ///
+ /// Params: end = End of the slice relative to current position. May reach past
+ /// the end of the buffer; in that case the returned slice will
+ /// be shorter.
+ ///
+ /// Returns: Slice into the internal buffer or an empty slice if out of bounds.
+ char[] slice(const size_t end) @safe pure
+ {
+ // Fast path in case the caller has already peek()ed all the way to end.
+ if(end == lastDecodedCharOffset_)
+ {
+ return buffer_[bufferOffset_ .. lastDecodedBufferOffset_];
+ }
+
+ const asciiToTake = min(upcomingASCII_, end, buffer_.length);
+ lastDecodedCharOffset_ = asciiToTake;
+ lastDecodedBufferOffset_ = bufferOffset_ + asciiToTake;
+
+ // 'Slow' path - decode everything up to end.
+ while(lastDecodedCharOffset_ < end &&
+ lastDecodedBufferOffset_ < buffer_.length)
+ {
+ decodeNext();
+ }
+
+ return buffer_[bufferOffset_ .. lastDecodedBufferOffset_];
+ }
+
+ /// Get the next character, moving buffer position beyond it.
+ ///
+ /// Returns: Next character.
+ ///
+ /// Throws: ReaderException if trying to read past the end of the buffer
+ /// or if invalid data is read.
+ dchar get() @safe pure
+ {
+ const result = peek();
+ forward();
+ return result;
+ }
+
+ /// Get specified number of characters, moving buffer position beyond them.
+ ///
+ /// Params: length = Number or characters (code points, not bytes) to get.
+ ///
+ /// Returns: Characters starting at current position.
+ char[] get(const size_t length) @safe pure
+ {
+ auto result = slice(length);
+ forward(length);
+ return result;
+ }
+
+ /// Move current position forward.
+ ///
+ /// Params: length = Number of characters to move position forward.
+ void forward(size_t length) @safe pure
+ {
+ while(length > 0)
+ {
+ auto asciiToTake = min(upcomingASCII_, length);
+ charIndex_ += asciiToTake;
+ length -= asciiToTake;
+ upcomingASCII_ -= asciiToTake;
+
+ for(; asciiToTake > 0; --asciiToTake)
+ {
+ const c = buffer_[bufferOffset_++];
+ // c is ASCII, do we only need to check for ASCII line breaks.
+ if(c == '\n' || (c == '\r' && buffer_[bufferOffset_] != '\n'))
+ {
+ ++line_;
+ column_ = 0;
+ continue;
+ }
+ ++column_;
+ }
+
+ // If we have used up all upcoming ASCII chars, the next char is
+ // non-ASCII even after this returns, so upcomingASCII_ doesn't need to
+ // be updated - it's zero.
+ if(length == 0) { break; }
+
+ assert(upcomingASCII_ == 0,
+ "Running unicode handling code but we haven't run out of ASCII chars");
+ assert(bufferOffset_ < buffer_.length,
+ "Attempted to decode past the end of YAML buffer");
+ assert(buffer_[bufferOffset_] >= 0x80,
+ "ASCII must be handled by preceding code");
+
+ ++charIndex_;
+ const c = decode(buffer_, bufferOffset_);
+
+ // New line. (can compare with '\n' without decoding since it's ASCII)
+ if(c.isBreak || (c == '\r' && buffer_[bufferOffset_] != '\n'))
+ {
+ ++line_;
+ column_ = 0;
+ }
+ else if(c != '\uFEFF') { ++column_; }
+ --length;
+ checkASCII();
+ }
+
+ lastDecodedBufferOffset_ = bufferOffset_;
+ lastDecodedCharOffset_ = 0;
+ }
+
+ /// Move current position forward by one character.
+ void forward() @safe pure
+ {
+ ++charIndex_;
+ lastDecodedBufferOffset_ = bufferOffset_;
+ lastDecodedCharOffset_ = 0;
+
+ // ASCII
+ if(upcomingASCII_ > 0)
+ {
+ --upcomingASCII_;
+ const c = buffer_[bufferOffset_++];
+
+ if(c == '\n' || (c == '\r' && buffer_[bufferOffset_] != '\n'))
+ {
+ ++line_;
+ column_ = 0;
+ return;
+ }
+ ++column_;
+ return;
+ }
+
+ // UTF-8
+ assert(bufferOffset_ < buffer_.length,
+ "Attempted to decode past the end of YAML buffer");
+ assert(buffer_[bufferOffset_] >= 0x80,
+ "ASCII must be handled by preceding code");
+
+ const c = decode(buffer_, bufferOffset_);
+
+ // New line. (can compare with '\n' without decoding since it's ASCII)
+ if(c.isBreak || (c == '\r' && buffer_[bufferOffset_] != '\n'))
+ {
+ ++line_;
+ column_ = 0;
+ }
+ else if(c != '\uFEFF') { ++column_; }
+
+ checkASCII();
+ }
+
+ /// Used to build slices of read data in Reader; to avoid allocations.
+ SliceBuilder sliceBuilder;
+
+ /// Get a string describing current buffer position, used for error messages.
+ Mark mark() const pure nothrow @nogc @safe { return Mark(name_, line_, column_); }
+
+ /// Get file name.
+ string name() const @safe pure nothrow @nogc { return name_; }
+
+ /// Get current line number.
+ uint line() const @safe pure nothrow @nogc { return line_; }
+
+ /// Get current column number.
+ uint column() const @safe pure nothrow @nogc { return column_; }
+
+ /// Get index of the current character in the buffer.
+ size_t charIndex() const @safe pure nothrow @nogc { return charIndex_; }
+
+ /// Get encoding of the input buffer.
+ Encoding encoding() const @safe pure nothrow @nogc { return encoding_; }
+
+private:
+ // Update upcomingASCII_ (should be called forward()ing over a UTF-8 sequence)
+ void checkASCII() @safe pure nothrow @nogc
+ {
+ upcomingASCII_ = countASCII(buffer_[bufferOffset_ .. $]);
+ }
+
+ // Decode the next character relative to
+ // lastDecodedCharOffset_/lastDecodedBufferOffset_ and update them.
+ //
+ // Does not advance the buffer position. Used in peek() and slice().
+ dchar decodeNext() @safe pure
+ {
+ assert(lastDecodedBufferOffset_ < buffer_.length,
+ "Attempted to decode past the end of YAML buffer");
+ const char b = buffer_[lastDecodedBufferOffset_];
+ ++lastDecodedCharOffset_;
+ // ASCII
+ if(b < 0x80)
+ {
+ ++lastDecodedBufferOffset_;
+ return b;
+ }
+
+ return decode(buffer_, lastDecodedBufferOffset_);
+ }
+}
+
+/// Used to build slices of already read data in Reader buffer, avoiding allocations.
+///
+/// Usually these slices point to unchanged Reader data, but sometimes the data is
+/// changed due to how YAML interprets certain characters/strings.
+///
+/// See begin() documentation.
+struct SliceBuilder
+{
+private:
+ // No copying by the user.
+ @disable this(this);
+ @disable void opAssign(ref SliceBuilder);
+
+ // Reader this builder works in.
+ Reader reader_;
+
+ // Start of the slice om reader_.buffer_ (size_t.max while no slice being build)
+ size_t start_ = size_t.max;
+ // End of the slice om reader_.buffer_ (size_t.max while no slice being build)
+ size_t end_ = size_t.max;
+
+ // Stack of slice ends to revert to (see Transaction)
+ //
+ // Very few levels as we don't want arbitrarily nested transactions.
+ size_t[4] endStack_;
+ // The number of elements currently in endStack_.
+ size_t endStackUsed_;
+
+ @safe const pure nothrow @nogc invariant()
+ {
+ if(!inProgress) { return; }
+ assert(end_ <= reader_.bufferOffset_, "Slice ends after buffer position");
+ assert(start_ <= end_, "Slice start after slice end");
+ }
+
+ // Is a slice currently being built?
+ bool inProgress() @safe const pure nothrow @nogc
+ in(start_ == size_t.max ? end_ == size_t.max : end_ != size_t.max, "start_/end_ are not consistent")
+ {
+ return start_ != size_t.max;
+ }
+
+public:
+ /// Begin building a slice.
+ ///
+ /// Only one slice can be built at any given time; before beginning a new slice,
+ /// finish the previous one (if any).
+ ///
+ /// The slice starts at the current position in the Reader buffer. It can only be
+ /// extended up to the current position in the buffer; Reader methods get() and
+ /// forward() move the position. E.g. it is valid to extend a slice by write()-ing
+ /// a string just returned by get() - but not one returned by prefix() unless the
+ /// position has changed since the prefix() call.
+ void begin() @safe pure nothrow @nogc
+ in(!inProgress, "Beginning a slice while another slice is being built")
+ in(endStackUsed_ == 0, "Slice stack not empty at slice begin")
+ {
+
+ start_ = reader_.bufferOffset_;
+ end_ = reader_.bufferOffset_;
+ }
+
+ /// Finish building a slice and return it.
+ ///
+ /// Any Transactions on the slice must be committed or destroyed before the slice
+ /// is finished.
+ ///
+ /// Returns a string; once a slice is finished it is definitive that its contents
+ /// will not be changed.
+ char[] finish() @safe pure nothrow @nogc
+ in(inProgress, "finish called without begin")
+ in(endStackUsed_ == 0, "Finishing a slice with running transactions.")
+ {
+
+ auto result = reader_.buffer_[start_ .. end_];
+ start_ = end_ = size_t.max;
+ return result;
+ }
+
+ /// Write a string to the slice being built.
+ ///
+ /// Data can only be written up to the current position in the Reader buffer.
+ ///
+ /// If str is a string returned by a Reader method, and str starts right after the
+ /// end of the slice being built, the slice is extended (trivial operation).
+ ///
+ /// See_Also: begin
+ void write(scope char[] str) @safe pure nothrow @nogc
+ {
+ assert(inProgress, "write called without begin");
+ assert(end_ <= reader_.bufferOffset_,
+ "AT START: Slice ends after buffer position");
+
+ // Nothing? Already done.
+ if (str.length == 0) { return; }
+ // If str starts at the end of the slice (is a string returned by a Reader
+ // method), just extend the slice to contain str.
+ if(&str[0] == &reader_.buffer_[end_])
+ {
+ end_ += str.length;
+ }
+ // Even if str does not start at the end of the slice, it still may be returned
+ // by a Reader method and point to buffer. So we need to memmove.
+ else
+ {
+ copy(str, reader_.buffer_[end_..end_ + str.length * char.sizeof]);
+ end_ += str.length;
+ }
+ }
+
+ /// Write a character to the slice being built.
+ ///
+ /// Data can only be written up to the current position in the Reader buffer.
+ ///
+ /// See_Also: begin
+ void write(dchar c) @safe pure
+ in(inProgress, "write called without begin")
+ {
+ if(c < 0x80)
+ {
+ reader_.buffer_[end_++] = cast(char)c;
+ return;
+ }
+
+ // We need to encode a non-ASCII dchar into UTF-8
+ char[4] encodeBuf;
+ const bytes = encode(encodeBuf, c);
+ reader_.buffer_[end_ .. end_ + bytes] = encodeBuf[0 .. bytes];
+ end_ += bytes;
+ }
+
+ /// Insert a character to a specified position in the slice.
+ ///
+ /// Enlarges the slice by 1 char. Note that the slice can only extend up to the
+ /// current position in the Reader buffer.
+ ///
+ /// Params:
+ ///
+ /// c = The character to insert.
+ /// position = Position to insert the character at in code units, not code points.
+ /// Must be less than slice length(); a previously returned length()
+ /// can be used.
+ void insert(const dchar c, const size_t position) @safe pure
+ in(inProgress, "insert called without begin")
+ in(start_ + position <= end_, "Trying to insert after the end of the slice")
+ {
+
+ const point = start_ + position;
+ const movedLength = end_ - point;
+
+ // Encode c into UTF-8
+ char[4] encodeBuf;
+ if(c < 0x80) { encodeBuf[0] = cast(char)c; }
+ const size_t bytes = c < 0x80 ? 1 : encode(encodeBuf, c);
+
+ if(movedLength > 0)
+ {
+ copy(reader_.buffer_[point..point + movedLength * char.sizeof],
+ reader_.buffer_[point + bytes..point + bytes + movedLength * char.sizeof]);
+ }
+ reader_.buffer_[point .. point + bytes] = encodeBuf[0 .. bytes];
+ end_ += bytes;
+ }
+
+ /// Get the current length of the slice.
+ size_t length() @safe const pure nothrow @nogc
+ {
+ return end_ - start_;
+ }
+
+ /// A slice building transaction.
+ ///
+ /// Can be used to save and revert back to slice state.
+ struct Transaction
+ {
+ private:
+ // The slice builder affected by the transaction.
+ SliceBuilder* builder_;
+ // Index of the return point of the transaction in StringBuilder.endStack_.
+ size_t stackLevel_;
+ // True after commit() has been called.
+ bool committed_;
+
+ public:
+ /// Begins a transaction on a SliceBuilder object.
+ ///
+ /// The transaction must end $(B after) any transactions created within the
+ /// transaction but $(B before) the slice is finish()-ed. A transaction can be
+ /// ended either by commit()-ing or reverting through the destructor.
+ ///
+ /// Saves the current state of a slice.
+ this(SliceBuilder* builder) @safe pure nothrow @nogc
+ {
+ builder_ = builder;
+ stackLevel_ = builder_.endStackUsed_;
+ builder_.push();
+ }
+
+ /// Commit changes to the slice.
+ ///
+ /// Ends the transaction - can only be called once, and removes the possibility
+ /// to revert slice state.
+ ///
+ /// Does nothing for a default-initialized transaction (the transaction has not
+ /// been started yet).
+ void commit() @safe pure nothrow @nogc
+ in(!committed_, "Can't commit a transaction more than once")
+ {
+
+ if(builder_ is null) { return; }
+ assert(builder_.endStackUsed_ == stackLevel_ + 1,
+ "Parent transactions don't fully contain child transactions");
+ builder_.apply();
+ committed_ = true;
+ }
+
+ /// Destroy the transaction and revert it if it hasn't been committed yet.
+ void end() @safe pure nothrow @nogc
+ in(builder_ && builder_.endStackUsed_ == stackLevel_ + 1, "Parent transactions don't fully contain child transactions")
+ {
+ builder_.pop();
+ builder_ = null;
+ }
+
+ }
+
+private:
+ // Push the current end of the slice so we can revert to it if needed.
+ //
+ // Used by Transaction.
+ void push() @safe pure nothrow @nogc
+ in(inProgress, "push called without begin")
+ in(endStackUsed_ < endStack_.length, "Slice stack overflow")
+ {
+ endStack_[endStackUsed_++] = end_;
+ }
+
+ // Pop the current end of endStack_ and set the end of the slice to the popped
+ // value, reverting changes since the old end was pushed.
+ //
+ // Used by Transaction.
+ void pop() @safe pure nothrow @nogc
+ in(inProgress, "pop called without begin")
+ in(endStackUsed_ > 0, "Trying to pop an empty slice stack")
+ {
+ end_ = endStack_[--endStackUsed_];
+ }
+
+ // Pop the current end of endStack_, but keep the current end of the slice, applying
+ // changes made since pushing the old end.
+ //
+ // Used by Transaction.
+ void apply() @safe pure nothrow @nogc
+ in(inProgress, "apply called without begin")
+ in(endStackUsed_ > 0, "Trying to apply an empty slice stack")
+ {
+ --endStackUsed_;
+ }
+}
+
+
+private:
+
+// Convert a UTF-8/16/32 buffer to UTF-8, in-place if possible.
+//
+// Params:
+//
+// input = Buffer with UTF-8/16/32 data to decode. May be overwritten by the
+// conversion, in which case the result will be a slice of this buffer.
+// encoding = Encoding of input.
+//
+// Returns:
+//
+// A struct with the following members:
+//
+// $(D string errorMessage) In case of an error, the error message is stored here. If
+// there was no error, errorMessage is NULL. Always check
+// this first.
+// $(D char[] utf8) input converted to UTF-8. May be a slice of input.
+// $(D size_t characterCount) Number of characters (code points) in input.
+auto toUTF8(ubyte[] input, const UTFEncoding encoding) @safe pure nothrow
+{
+ // Documented in function ddoc.
+ struct Result
+ {
+ string errorMessage;
+ char[] utf8;
+ size_t characterCount;
+ }
+
+ Result result;
+
+ // Encode input_ into UTF-8 if it's encoded as UTF-16 or UTF-32.
+ //
+ // Params:
+ //
+ // buffer = The input buffer to encode.
+ // result = A Result struct to put encoded result and any error messages to.
+ //
+ // On error, result.errorMessage will be set.
+ static void encode(C)(C[] input, ref Result result) @safe pure
+ {
+ // We can do UTF-32->UTF-8 in place because all UTF-8 sequences are 4 or
+ // less bytes.
+ static if(is(C == dchar))
+ {
+ char[4] encodeBuf;
+ auto utf8 = cast(char[])input;
+ auto length = 0;
+ foreach(dchar c; input)
+ {
+ ++result.characterCount;
+ // ASCII
+ if(c < 0x80)
+ {
+ utf8[length++] = cast(char)c;
+ continue;
+ }
+
+ std.utf.encode(encodeBuf, c);
+ const bytes = codeLength!char(c);
+ utf8[length .. length + bytes] = encodeBuf[0 .. bytes];
+ length += bytes;
+ }
+ result.utf8 = utf8[0 .. length];
+ }
+ // Unfortunately we can't do UTF-16 in place so we just use std.conv.to
+ else
+ {
+ result.characterCount = std.utf.count(input);
+ result.utf8 = input.to!(char[]);
+ }
+ }
+
+ try final switch(encoding)
+ {
+ case UTFEncoding.UTF_8:
+ result.utf8 = cast(char[])input;
+ result.utf8.validate();
+ result.characterCount = std.utf.count(result.utf8);
+ break;
+ case UTFEncoding.UTF_16:
+ assert(input.length % 2 == 0, "UTF-16 buffer size must be even");
+ encode(cast(wchar[])input, result);
+ break;
+ case UTFEncoding.UTF_32:
+ assert(input.length % 4 == 0, "UTF-32 buffer size must be a multiple of 4");
+ encode(cast(dchar[])input, result);
+ break;
+ }
+ catch(ConvException e) { result.errorMessage = e.msg; }
+ catch(UTFException e) { result.errorMessage = e.msg; }
+ catch(Exception e)
+ {
+ assert(false, "Unexpected exception in encode(): " ~ e.msg);
+ }
+
+ return result;
+}
+
+/// Determine if all characters (code points, not bytes) in a string are printable.
+bool isPrintableValidUTF8(const char[] chars) @safe pure
+{
+ import std.uni : isControl, isWhite;
+ foreach (dchar chr; chars)
+ {
+ if (!chr.isValidDchar || (chr.isControl && !chr.isWhite))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+/// Counts the number of ASCII characters in buffer until the first UTF-8 sequence.
+///
+/// Used to determine how many characters we can process without decoding.
+size_t countASCII(const(char)[] buffer) @safe pure nothrow @nogc
+{
+ return buffer.byCodeUnit.until!(x => x > 0x7F).walkLength;
+}
+// Unittests.
+
+void testEndian(R)()
+{
+ void endian_test(ubyte[] data, Encoding encoding_expected, Endian endian_expected)
+ {
+ auto reader = new R(data);
+ assert(reader.encoding == encoding_expected);
+ assert(reader.endian_ == endian_expected);
+ }
+ ubyte[] little_endian_utf_16 = [0xFF, 0xFE, 0x7A, 0x00];
+ ubyte[] big_endian_utf_16 = [0xFE, 0xFF, 0x00, 0x7A];
+ endian_test(little_endian_utf_16, Encoding.UTF_16, Endian.littleEndian);
+ endian_test(big_endian_utf_16, Encoding.UTF_16, Endian.bigEndian);
+}
+
+void testPeekPrefixForward(R)()
+{
+ import std.encoding;
+ ubyte[] data = bomTable[BOM.utf8].sequence ~ cast(ubyte[])"data";
+ auto reader = new R(data);
+ assert(reader.peek() == 'd');
+ assert(reader.peek(1) == 'a');
+ assert(reader.peek(2) == 't');
+ assert(reader.peek(3) == 'a');
+ assert(reader.peek(4) == '\0');
+ assert(reader.prefix(4) == "data");
+ // assert(reader.prefix(6) == "data\0");
+ reader.forward(2);
+ assert(reader.peek(1) == 'a');
+ // assert(collectException(reader.peek(3)));
+}
+
+void testUTF(R)()
+{
+ import std.encoding;
+ dchar[] data = cast(dchar[])"data";
+ void utf_test(T)(T[] data, BOM bom)
+ {
+ ubyte[] bytes = bomTable[bom].sequence ~
+ (cast(ubyte[])data)[0 .. data.length * T.sizeof];
+ auto reader = new R(bytes);
+ assert(reader.peek() == 'd');
+ assert(reader.peek(1) == 'a');
+ assert(reader.peek(2) == 't');
+ assert(reader.peek(3) == 'a');
+ }
+ utf_test!char(to!(char[])(data), BOM.utf8);
+ utf_test!wchar(to!(wchar[])(data), endian == Endian.bigEndian ? BOM.utf16be : BOM.utf16le);
+ utf_test(data, endian == Endian.bigEndian ? BOM.utf32be : BOM.utf32le);
+}
+
+void test1Byte(R)()
+{
+ ubyte[] data = [97];
+
+ auto reader = new R(data);
+ assert(reader.peek() == 'a');
+ assert(reader.peek(1) == '\0');
+ // assert(collectException(reader.peek(2)));
+}
+
+@system unittest
+{
+ testEndian!Reader();
+ testPeekPrefixForward!Reader();
+ testUTF!Reader();
+ test1Byte!Reader();
+}
+//Issue 257 - https://github.com/dlang-community/D-YAML/issues/257
+@safe unittest
+{
+ import dyaml.loader : Loader;
+ auto yaml = "hello ";
+ auto root = Loader.fromString(yaml).load();
+
+ assert(root.isValid);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/representer.d b/src/ext_depends/D-YAML/source/dyaml/representer.d
new file mode 100644
index 0000000..a7ca802
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/representer.d
@@ -0,0 +1,517 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML node _representer. Prepares YAML nodes for output. A tutorial can be
+ * found $(LINK2 ../tutorials/custom_types.html, here).
+ *
+ * Code based on $(LINK2 http://www.pyyaml.org, PyYAML).
+ */
+module dyaml.representer;
+
+
+import std.algorithm;
+import std.array;
+import std.base64;
+import std.container;
+import std.conv;
+import std.datetime;
+import std.exception;
+import std.format;
+import std.math;
+import std.typecons;
+import std.string;
+
+import dyaml.exception;
+import dyaml.node;
+import dyaml.serializer;
+import dyaml.style;
+
+package:
+///Exception thrown on Representer errors.
+class RepresenterException : YAMLException
+{
+ mixin ExceptionCtors;
+}
+
+/**
+ * Represents YAML nodes as scalar, sequence and mapping nodes ready for output.
+ */
+Node representData(const Node data, ScalarStyle defaultScalarStyle, CollectionStyle defaultCollectionStyle) @safe
+{
+ Node result;
+ final switch(data.type)
+ {
+ case NodeType.null_:
+ result = representNull();
+ break;
+ case NodeType.merge:
+ break;
+ case NodeType.boolean:
+ result = representBool(data);
+ break;
+ case NodeType.integer:
+ result = representLong(data);
+ break;
+ case NodeType.decimal:
+ result = representReal(data);
+ break;
+ case NodeType.binary:
+ result = representBytes(data);
+ break;
+ case NodeType.timestamp:
+ result = representSysTime(data);
+ break;
+ case NodeType.string:
+ result = representString(data);
+ break;
+ case NodeType.mapping:
+ result = representPairs(data, defaultScalarStyle, defaultCollectionStyle);
+ break;
+ case NodeType.sequence:
+ result = representNodes(data, defaultScalarStyle, defaultCollectionStyle);
+ break;
+ case NodeType.invalid:
+ assert(0);
+ }
+
+ final switch (result.nodeID)
+ {
+ case NodeID.scalar:
+ if (result.scalarStyle == ScalarStyle.invalid)
+ {
+ result.scalarStyle = defaultScalarStyle;
+ }
+ break;
+ case NodeID.sequence, NodeID.mapping:
+ if (defaultCollectionStyle != CollectionStyle.invalid)
+ {
+ result.collectionStyle = defaultCollectionStyle;
+ }
+ case NodeID.invalid:
+ }
+
+
+ //Override tag if specified.
+ if(data.tag_ !is null){result.tag_ = data.tag_;}
+
+ //Remember style if this was loaded before.
+ if(data.scalarStyle != ScalarStyle.invalid)
+ {
+ result.scalarStyle = data.scalarStyle;
+ }
+ if(data.collectionStyle != CollectionStyle.invalid)
+ {
+ result.collectionStyle = data.collectionStyle;
+ }
+ return result;
+}
+
+@safe unittest
+{
+ // We don't emit yaml merge nodes.
+ assert(representData(Node(YAMLMerge()), ScalarStyle.invalid, CollectionStyle.invalid) == Node.init);
+}
+
+@safe unittest
+{
+ assert(representData(Node(YAMLNull()), ScalarStyle.invalid, CollectionStyle.invalid) == Node("null", "tag:yaml.org,2002:null"));
+}
+
+@safe unittest
+{
+ assert(representData(Node(cast(string)null), ScalarStyle.invalid, CollectionStyle.invalid) == Node("null", "tag:yaml.org,2002:null"));
+ assert(representData(Node("Hello world!"), ScalarStyle.invalid, CollectionStyle.invalid) == Node("Hello world!", "tag:yaml.org,2002:str"));
+}
+
+@safe unittest
+{
+ assert(representData(Node(64), ScalarStyle.invalid, CollectionStyle.invalid) == Node("64", "tag:yaml.org,2002:int"));
+}
+
+@safe unittest
+{
+ assert(representData(Node(true), ScalarStyle.invalid, CollectionStyle.invalid) == Node("true", "tag:yaml.org,2002:bool"));
+ assert(representData(Node(false), ScalarStyle.invalid, CollectionStyle.invalid) == Node("false", "tag:yaml.org,2002:bool"));
+}
+
+@safe unittest
+{
+ // Float comparison is pretty unreliable...
+ auto result = representData(Node(1.0), ScalarStyle.invalid, CollectionStyle.invalid);
+ assert(approxEqual(result.as!string.to!real, 1.0));
+ assert(result.tag == "tag:yaml.org,2002:float");
+
+ assert(representData(Node(real.nan), ScalarStyle.invalid, CollectionStyle.invalid) == Node(".nan", "tag:yaml.org,2002:float"));
+ assert(representData(Node(real.infinity), ScalarStyle.invalid, CollectionStyle.invalid) == Node(".inf", "tag:yaml.org,2002:float"));
+ assert(representData(Node(-real.infinity), ScalarStyle.invalid, CollectionStyle.invalid) == Node("-.inf", "tag:yaml.org,2002:float"));
+}
+
+@safe unittest
+{
+ assert(representData(Node(SysTime(DateTime(2000, 3, 14, 12, 34, 56), UTC())), ScalarStyle.invalid, CollectionStyle.invalid) == Node("2000-03-14T12:34:56Z", "tag:yaml.org,2002:timestamp"));
+}
+
+@safe unittest
+{
+ assert(representData(Node(Node[].init, "tag:yaml.org,2002:set"), ScalarStyle.invalid, CollectionStyle.invalid) == Node(Node.Pair[].init, "tag:yaml.org,2002:set"));
+ assert(representData(Node(Node[].init, "tag:yaml.org,2002:seq"), ScalarStyle.invalid, CollectionStyle.invalid) == Node(Node[].init, "tag:yaml.org,2002:seq"));
+ {
+ auto nodes = [
+ Node("a"),
+ Node("b"),
+ Node("c"),
+ ];
+ assert(representData(Node(nodes, "tag:yaml.org,2002:set"), ScalarStyle.invalid, CollectionStyle.invalid) ==
+ Node([
+ Node.Pair(
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("null", "tag:yaml.org,2002:null")
+ ),
+ Node.Pair(
+ Node("b", "tag:yaml.org,2002:str"),
+ Node("null", "tag:yaml.org,2002:null")
+ ),
+ Node.Pair(
+ Node("c", "tag:yaml.org,2002:str"),
+ Node("null", "tag:yaml.org,2002:null")
+ )
+ ], "tag:yaml.org,2002:set"));
+ }
+ {
+ auto nodes = [
+ Node("a"),
+ Node("b"),
+ Node("c"),
+ ];
+ assert(representData(Node(nodes, "tag:yaml.org,2002:seq"), ScalarStyle.invalid, CollectionStyle.invalid) ==
+ Node([
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("b", "tag:yaml.org,2002:str"),
+ Node("c", "tag:yaml.org,2002:str")
+ ], "tag:yaml.org,2002:seq"));
+ }
+}
+
+@safe unittest
+{
+ assert(representData(Node(Node.Pair[].init, "tag:yaml.org,2002:omap"), ScalarStyle.invalid, CollectionStyle.invalid) == Node(Node[].init, "tag:yaml.org,2002:omap"));
+ assert(representData(Node(Node.Pair[].init, "tag:yaml.org,2002:pairs"), ScalarStyle.invalid, CollectionStyle.invalid) == Node(Node[].init, "tag:yaml.org,2002:pairs"));
+ assert(representData(Node(Node.Pair[].init, "tag:yaml.org,2002:map"), ScalarStyle.invalid, CollectionStyle.invalid) == Node(Node.Pair[].init, "tag:yaml.org,2002:map"));
+ {
+ auto nodes = [
+ Node.Pair("a", "b"),
+ Node.Pair("a", "c")
+ ];
+ assertThrown(representData(Node(nodes, "tag:yaml.org,2002:omap"), ScalarStyle.invalid, CollectionStyle.invalid));
+ }
+ // Yeah, this gets ugly really fast.
+ {
+ auto nodes = [
+ Node.Pair("a", "b"),
+ Node.Pair("a", "c")
+ ];
+ assert(representData(Node(nodes, "tag:yaml.org,2002:pairs"), ScalarStyle.invalid, CollectionStyle.invalid) ==
+ Node([
+ Node(
+ [Node.Pair(
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("b", "tag:yaml.org,2002:str")
+ )],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [Node.Pair(
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("c", "tag:yaml.org,2002:str")
+ )],
+ "tag:yaml.org,2002:map"),
+ ], "tag:yaml.org,2002:pairs"));
+ }
+ {
+ auto nodes = [
+ Node.Pair("a", "b"),
+ Node.Pair("a", "c")
+ ];
+ assertThrown(representData(Node(nodes, "tag:yaml.org,2002:map"), ScalarStyle.invalid, CollectionStyle.invalid));
+ }
+ {
+ auto nodes = [
+ Node.Pair("a", "b"),
+ Node.Pair("c", "d")
+ ];
+ assert(representData(Node(nodes, "tag:yaml.org,2002:omap"), ScalarStyle.invalid, CollectionStyle.invalid) ==
+ Node([
+ Node([
+ Node.Pair(
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("b", "tag:yaml.org,2002:str")
+ )
+ ], "tag:yaml.org,2002:map"),
+ Node([
+ Node.Pair(
+ Node("c", "tag:yaml.org,2002:str"),
+ Node("d", "tag:yaml.org,2002:str")
+ )
+ ], "tag:yaml.org,2002:map"
+ )], "tag:yaml.org,2002:omap"));
+ }
+ {
+ auto nodes = [
+ Node.Pair("a", "b"),
+ Node.Pair("c", "d")
+ ];
+ assert(representData(Node(nodes, "tag:yaml.org,2002:map"), ScalarStyle.invalid, CollectionStyle.invalid) ==
+ Node([
+ Node.Pair(
+ Node("a", "tag:yaml.org,2002:str"),
+ Node("b", "tag:yaml.org,2002:str")
+ ),
+ Node.Pair(
+ Node("c", "tag:yaml.org,2002:str"),
+ Node("d", "tag:yaml.org,2002:str")
+ ),
+ ], "tag:yaml.org,2002:map"));
+ }
+}
+
+private:
+
+//Represent a _null _node as a _null YAML value.
+Node representNull() @safe
+{
+ return Node("null", "tag:yaml.org,2002:null");
+}
+
+//Represent a string _node as a string scalar.
+Node representString(const Node node) @safe
+{
+ string value = node.as!string;
+ return value is null
+ ? Node("null", "tag:yaml.org,2002:null")
+ : Node(value, "tag:yaml.org,2002:str");
+}
+
+//Represent a bytes _node as a binary scalar.
+Node representBytes(const Node node) @safe
+{
+ const ubyte[] value = node.as!(ubyte[]);
+ if(value is null){return Node("null", "tag:yaml.org,2002:null");}
+
+ auto newNode = Node(Base64.encode(value).idup, "tag:yaml.org,2002:binary");
+ newNode.scalarStyle = ScalarStyle.literal;
+ return newNode;
+}
+
+//Represent a bool _node as a bool scalar.
+Node representBool(const Node node) @safe
+{
+ return Node(node.as!bool ? "true" : "false", "tag:yaml.org,2002:bool");
+}
+
+//Represent a long _node as an integer scalar.
+Node representLong(const Node node) @safe
+{
+ return Node(node.as!long.to!string, "tag:yaml.org,2002:int");
+}
+
+//Represent a real _node as a floating point scalar.
+Node representReal(const Node node) @safe
+{
+ real f = node.as!real;
+ string value = isNaN(f) ? ".nan":
+ f == real.infinity ? ".inf":
+ f == -1.0 * real.infinity ? "-.inf":
+ {auto a = appender!string();
+ formattedWrite(a, "%12f", f);
+ return a.data.strip();}();
+
+ return Node(value, "tag:yaml.org,2002:float");
+}
+
+//Represent a SysTime _node as a timestamp.
+Node representSysTime(const Node node) @safe
+{
+ return Node(node.as!SysTime.toISOExtString(), "tag:yaml.org,2002:timestamp");
+}
+
+//Represent a sequence _node as sequence/set.
+Node representNodes(const Node node, ScalarStyle defaultScalarStyle, CollectionStyle defaultCollectionStyle) @safe
+{
+ auto nodes = node.as!(Node[]);
+ if(node.tag_ == "tag:yaml.org,2002:set")
+ {
+ //YAML sets are mapping with null values.
+ Node.Pair[] pairs;
+ pairs.length = nodes.length;
+
+ foreach(idx, key; nodes)
+ {
+ pairs[idx] = Node.Pair(key, Node("null", "tag:yaml.org,2002:null"));
+ }
+ Node.Pair[] value;
+ value.length = pairs.length;
+
+ auto bestStyle = CollectionStyle.flow;
+ foreach(idx, pair; pairs)
+ {
+ value[idx] = Node.Pair(representData(pair.key, defaultScalarStyle, defaultCollectionStyle), representData(pair.value, defaultScalarStyle, defaultCollectionStyle));
+ if(value[idx].shouldUseBlockStyle)
+ {
+ bestStyle = CollectionStyle.block;
+ }
+ }
+
+ auto newNode = Node(value, node.tag_);
+ newNode.collectionStyle = bestStyle;
+ return newNode;
+ }
+ else
+ {
+ Node[] value;
+ value.length = nodes.length;
+
+ auto bestStyle = CollectionStyle.flow;
+ foreach(idx, item; nodes)
+ {
+ value[idx] = representData(item, defaultScalarStyle, defaultCollectionStyle);
+ const isScalar = value[idx].nodeID == NodeID.scalar;
+ const s = value[idx].scalarStyle;
+ if(!isScalar || (s != ScalarStyle.invalid && s != ScalarStyle.plain))
+ {
+ bestStyle = CollectionStyle.block;
+ }
+ }
+
+ auto newNode = Node(value, "tag:yaml.org,2002:seq");
+ newNode.collectionStyle = bestStyle;
+ return newNode;
+ }
+}
+
+bool shouldUseBlockStyle(const Node value) @safe
+{
+ const isScalar = value.nodeID == NodeID.scalar;
+ const s = value.scalarStyle;
+ return (!isScalar || (s != ScalarStyle.invalid && s != ScalarStyle.plain));
+}
+bool shouldUseBlockStyle(const Node.Pair value) @safe
+{
+ const keyScalar = value.key.nodeID == NodeID.scalar;
+ const valScalar = value.value.nodeID == NodeID.scalar;
+ const keyStyle = value.key.scalarStyle;
+ const valStyle = value.value.scalarStyle;
+ if(!keyScalar ||
+ (keyStyle != ScalarStyle.invalid && keyStyle != ScalarStyle.plain))
+ {
+ return true;
+ }
+ if(!valScalar ||
+ (valStyle != ScalarStyle.invalid && valStyle != ScalarStyle.plain))
+ {
+ return true;
+ }
+ return false;
+}
+
+//Represent a mapping _node as map/ordered map/pairs.
+Node representPairs(const Node node, ScalarStyle defaultScalarStyle, CollectionStyle defaultCollectionStyle) @safe
+{
+ auto pairs = node.as!(Node.Pair[]);
+
+ bool hasDuplicates(const Node.Pair[] pairs) @safe
+ {
+ //TODO this should be replaced by something with deterministic memory allocation.
+ auto keys = redBlackTree!Node();
+ foreach(pair; pairs)
+ {
+ if(pair.key in keys){return true;}
+ keys.insert(pair.key);
+ }
+ return false;
+ }
+
+ Node[] mapToSequence(const Node.Pair[] pairs) @safe
+ {
+ Node[] nodes;
+ nodes.length = pairs.length;
+ foreach(idx, pair; pairs)
+ {
+ Node.Pair value;
+
+ auto bestStyle = value.shouldUseBlockStyle ? CollectionStyle.block : CollectionStyle.flow;
+ value = Node.Pair(representData(pair.key, defaultScalarStyle, defaultCollectionStyle), representData(pair.value, defaultScalarStyle, defaultCollectionStyle));
+
+ auto newNode = Node([value], "tag:yaml.org,2002:map");
+ newNode.collectionStyle = bestStyle;
+ nodes[idx] = newNode;
+ }
+ return nodes;
+ }
+
+ if(node.tag_ == "tag:yaml.org,2002:omap")
+ {
+ enforce(!hasDuplicates(pairs),
+ new RepresenterException("Duplicate entry in an ordered map"));
+ auto sequence = mapToSequence(pairs);
+ Node[] value;
+ value.length = sequence.length;
+
+ auto bestStyle = CollectionStyle.flow;
+ foreach(idx, item; sequence)
+ {
+ value[idx] = representData(item, defaultScalarStyle, defaultCollectionStyle);
+ if(value[idx].shouldUseBlockStyle)
+ {
+ bestStyle = CollectionStyle.block;
+ }
+ }
+
+ auto newNode = Node(value, node.tag_);
+ newNode.collectionStyle = bestStyle;
+ return newNode;
+ }
+ else if(node.tag_ == "tag:yaml.org,2002:pairs")
+ {
+ auto sequence = mapToSequence(pairs);
+ Node[] value;
+ value.length = sequence.length;
+
+ auto bestStyle = CollectionStyle.flow;
+ foreach(idx, item; sequence)
+ {
+ value[idx] = representData(item, defaultScalarStyle, defaultCollectionStyle);
+ if(value[idx].shouldUseBlockStyle)
+ {
+ bestStyle = CollectionStyle.block;
+ }
+ }
+
+ auto newNode = Node(value, node.tag_);
+ newNode.collectionStyle = bestStyle;
+ return newNode;
+ }
+ else
+ {
+ enforce(!hasDuplicates(pairs),
+ new RepresenterException("Duplicate entry in an unordered map"));
+ Node.Pair[] value;
+ value.length = pairs.length;
+
+ auto bestStyle = CollectionStyle.flow;
+ foreach(idx, pair; pairs)
+ {
+ value[idx] = Node.Pair(representData(pair.key, defaultScalarStyle, defaultCollectionStyle), representData(pair.value, defaultScalarStyle, defaultCollectionStyle));
+ if(value[idx].shouldUseBlockStyle)
+ {
+ bestStyle = CollectionStyle.block;
+ }
+ }
+
+ auto newNode = Node(value, "tag:yaml.org,2002:map");
+ newNode.collectionStyle = bestStyle;
+ return newNode;
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/resolver.d b/src/ext_depends/D-YAML/source/dyaml/resolver.d
new file mode 100644
index 0000000..ceed1e5
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/resolver.d
@@ -0,0 +1,261 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * Implements a class that resolves YAML tags. This can be used to implicitly
+ * resolve tags for custom data types, removing the need to explicitly
+ * specify tags in YAML. A tutorial can be found
+ * $(LINK2 ../tutorials/custom_types.html, here).
+ *
+ * Code based on $(LINK2 http://www.pyyaml.org, PyYAML).
+ */
+module dyaml.resolver;
+
+
+import std.conv;
+import std.regex;
+import std.typecons;
+import std.utf;
+
+import dyaml.node;
+import dyaml.exception;
+
+
+/// Type of `regexes`
+private alias RegexType = Tuple!(string, "tag", const Regex!char, "regexp", string, "chars");
+
+private immutable RegexType[] regexes;
+
+shared static this() @safe
+{
+ RegexType[] tmp;
+ tmp ~= RegexType("tag:yaml.org,2002:bool",
+ regex(r"^(?:yes|Yes|YES|no|No|NO|true|True|TRUE" ~
+ "|false|False|FALSE|on|On|ON|off|Off|OFF)$"),
+ "yYnNtTfFoO");
+ tmp ~= RegexType("tag:yaml.org,2002:float",
+ regex(r"^(?:[-+]?([0-9][0-9_]*)\\.[0-9_]*" ~
+ "(?:[eE][-+][0-9]+)?|[-+]?(?:[0-9][0-9_]" ~
+ "*)?\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?" ~
+ "[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]" ~
+ "*|[-+]?\\.(?:inf|Inf|INF)|\\." ~
+ "(?:nan|NaN|NAN))$"),
+ "-+0123456789.");
+ tmp ~= RegexType("tag:yaml.org,2002:int",
+ regex(r"^(?:[-+]?0b[0-1_]+" ~
+ "|[-+]?0[0-7_]+" ~
+ "|[-+]?(?:0|[1-9][0-9_]*)" ~
+ "|[-+]?0x[0-9a-fA-F_]+" ~
+ "|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),
+ "-+0123456789");
+ tmp ~= RegexType("tag:yaml.org,2002:merge", regex(r"^<<$"), "<");
+ tmp ~= RegexType("tag:yaml.org,2002:null",
+ regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0");
+ tmp ~= RegexType("tag:yaml.org,2002:timestamp",
+ regex(r"^[0-9][0-9][0-9][0-9]-[0-9][0-9]-" ~
+ "[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9]" ~
+ "[0-9]?-[0-9][0-9]?[Tt]|[ \t]+[0-9]" ~
+ "[0-9]?:[0-9][0-9]:[0-9][0-9]" ~
+ "(?:\\.[0-9]*)?(?:[ \t]*Z|[-+][0-9]" ~
+ "[0-9]?(?::[0-9][0-9])?)?$"),
+ "0123456789");
+ tmp ~= RegexType("tag:yaml.org,2002:value", regex(r"^=$"), "=");
+
+
+ //The following resolver is only for documentation purposes. It cannot work
+ //because plain scalars cannot start with '!', '&', or '*'.
+ tmp ~= RegexType("tag:yaml.org,2002:yaml", regex(r"^(?:!|&|\*)$"), "!&*");
+
+ regexes = () @trusted { return cast(immutable)tmp; }();
+}
+
+/**
+ * Resolves YAML tags (data types).
+ *
+ * Can be used to implicitly resolve custom data types of scalar values.
+ */
+struct Resolver
+{
+ private:
+ // Default tag to use for scalars.
+ string defaultScalarTag_ = "tag:yaml.org,2002:str";
+ // Default tag to use for sequences.
+ string defaultSequenceTag_ = "tag:yaml.org,2002:seq";
+ // Default tag to use for mappings.
+ string defaultMappingTag_ = "tag:yaml.org,2002:map";
+
+ /*
+ * Arrays of scalar resolver tuples indexed by starting character of a scalar.
+ *
+ * Each tuple stores regular expression the scalar must match,
+ * and tag to assign to it if it matches.
+ */
+ Tuple!(string, const Regex!char)[][dchar] yamlImplicitResolvers_;
+
+ package:
+ static auto withDefaultResolvers() @safe
+ {
+ Resolver resolver;
+ foreach(pair; regexes)
+ {
+ resolver.addImplicitResolver(pair.tag, pair.regexp, pair.chars);
+ }
+ return resolver;
+ }
+
+ public:
+ @disable bool opEquals(ref Resolver);
+ @disable int opCmp(ref Resolver);
+
+ /**
+ * Add an implicit scalar resolver.
+ *
+ * If a scalar matches regexp and starts with any character in first,
+ * its _tag is set to tag. If it matches more than one resolver _regexp
+ * resolvers added _first override ones added later. Default resolvers
+ * override any user specified resolvers, but they can be disabled in
+ * Resolver constructor.
+ *
+ * If a scalar is not resolved to anything, it is assigned the default
+ * YAML _tag for strings.
+ *
+ * Params: tag = Tag to resolve to.
+ * regexp = Regular expression the scalar must match to have this _tag.
+ * first = String of possible starting characters of the scalar.
+ *
+ */
+ void addImplicitResolver(string tag, const Regex!char regexp, string first)
+ pure @safe
+ {
+ foreach(const dchar c; first)
+ {
+ if((c in yamlImplicitResolvers_) is null)
+ {
+ yamlImplicitResolvers_[c] = [];
+ }
+ yamlImplicitResolvers_[c] ~= tuple(tag, regexp);
+ }
+ }
+ /// Resolve scalars starting with 'A' to !_tag
+ @safe unittest
+ {
+ import std.file : write;
+ import std.regex : regex;
+ import dyaml.loader : Loader;
+ import dyaml.resolver : Resolver;
+
+ write("example.yaml", "A");
+
+ auto loader = Loader.fromFile("example.yaml");
+ loader.resolver.addImplicitResolver("!tag", regex("A.*"), "A");
+
+ auto node = loader.load();
+ assert(node.tag == "!tag");
+ }
+
+ package:
+ /**
+ * Resolve tag of a node.
+ *
+ * Params: kind = Type of the node.
+ * tag = Explicit tag of the node, if any.
+ * value = Value of the node, if any.
+ * implicit = Should the node be implicitly resolved?
+ *
+ * If the tag is already specified and not non-specific, that tag will
+ * be returned.
+ *
+ * Returns: Resolved tag.
+ */
+ string resolve(const NodeID kind, const string tag, const string value,
+ const bool implicit) @safe
+ {
+ import std.array : empty, front;
+ if((tag !is null) && (tag != "!"))
+ {
+ return tag;
+ }
+
+ final switch (kind)
+ {
+ case NodeID.scalar:
+ if(!implicit)
+ {
+ return defaultScalarTag_;
+ }
+
+ //Get the first char of the value.
+ const dchar first = value.empty ? '\0' : value.front;
+
+ auto resolvers = (first in yamlImplicitResolvers_) is null ?
+ [] : yamlImplicitResolvers_[first];
+
+ //If regexp matches, return tag.
+ foreach(resolver; resolvers)
+ {
+ if(!(match(value, resolver[1]).empty))
+ {
+ return resolver[0];
+ }
+ }
+ return defaultScalarTag_;
+ case NodeID.sequence:
+ return defaultSequenceTag_;
+ case NodeID.mapping:
+ return defaultMappingTag_;
+ case NodeID.invalid:
+ assert(false, "Cannot resolve an invalid node");
+ }
+ }
+ @safe unittest
+ {
+ auto resolver = Resolver.withDefaultResolvers;
+
+ bool tagMatch(string tag, string[] values) @safe
+ {
+ const string expected = tag;
+ foreach(value; values)
+ {
+ const string resolved = resolver.resolve(NodeID.scalar, null, value, true);
+ if(expected != resolved)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ assert(tagMatch("tag:yaml.org,2002:bool",
+ ["yes", "NO", "True", "on"]));
+ assert(tagMatch("tag:yaml.org,2002:float",
+ ["6.8523015e+5", "685.230_15e+03", "685_230.15",
+ "190:20:30.15", "-.inf", ".NaN"]));
+ assert(tagMatch("tag:yaml.org,2002:int",
+ ["685230", "+685_230", "02472256", "0x_0A_74_AE",
+ "0b1010_0111_0100_1010_1110", "190:20:30"]));
+ assert(tagMatch("tag:yaml.org,2002:merge", ["<<"]));
+ assert(tagMatch("tag:yaml.org,2002:null", ["~", "null", ""]));
+ assert(tagMatch("tag:yaml.org,2002:str",
+ ["abcd", "9a8b", "9.1adsf"]));
+ assert(tagMatch("tag:yaml.org,2002:timestamp",
+ ["2001-12-15T02:59:43.1Z",
+ "2001-12-14t21:59:43.10-05:00",
+ "2001-12-14 21:59:43.10 -5",
+ "2001-12-15 2:59:43.10",
+ "2002-12-14"]));
+ assert(tagMatch("tag:yaml.org,2002:value", ["="]));
+ assert(tagMatch("tag:yaml.org,2002:yaml", ["!", "&", "*"]));
+ }
+
+ ///Returns: Default scalar tag.
+ @property string defaultScalarTag() const pure @safe nothrow {return defaultScalarTag_;}
+
+ ///Returns: Default sequence tag.
+ @property string defaultSequenceTag() const pure @safe nothrow {return defaultSequenceTag_;}
+
+ ///Returns: Default mapping tag.
+ @property string defaultMappingTag() const pure @safe nothrow {return defaultMappingTag_;}
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/scanner.d b/src/ext_depends/D-YAML/source/dyaml/scanner.d
new file mode 100644
index 0000000..2009521
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/scanner.d
@@ -0,0 +1,1788 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/// YAML scanner.
+/// Code based on PyYAML: http://www.pyyaml.org
+module dyaml.scanner;
+
+
+import core.stdc.string;
+
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.ascii : isAlphaNum, isDigit, isHexDigit;
+import std.exception;
+import std.string;
+import std.typecons;
+import std.traits : Unqual;
+import std.utf;
+
+import dyaml.escapes;
+import dyaml.exception;
+import dyaml.queue;
+import dyaml.reader;
+import dyaml.style;
+import dyaml.token;
+
+package:
+/// Scanner produces tokens of the following types:
+/// STREAM-START
+/// STREAM-END
+/// DIRECTIVE(name, value)
+/// DOCUMENT-START
+/// DOCUMENT-END
+/// BLOCK-SEQUENCE-START
+/// BLOCK-MAPPING-START
+/// BLOCK-END
+/// FLOW-SEQUENCE-START
+/// FLOW-MAPPING-START
+/// FLOW-SEQUENCE-END
+/// FLOW-MAPPING-END
+/// BLOCK-ENTRY
+/// FLOW-ENTRY
+/// KEY
+/// VALUE
+/// ALIAS(value)
+/// ANCHOR(value)
+/// TAG(value)
+/// SCALAR(value, plain, style)
+
+alias isBreak = among!('\0', '\n', '\r', '\u0085', '\u2028', '\u2029');
+
+alias isBreakOrSpace = among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029');
+
+alias isWhiteSpace = among!(' ', '\t', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029');
+
+alias isNonLinebreakWhitespace = among!(' ', '\t');
+
+alias isNonScalarStartCharacter = among!('-', '?', ':', ',', '[', ']', '{', '}',
+ '#', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`', ' ', '\t', '\0', '\n',
+ '\r', '\u0085', '\u2028', '\u2029');
+
+alias isURIChar = among!('-', ';', '/', '?', ':', '@', '&', '=', '+', '$', ',',
+ '_', '.', '!', '~', '*', '\'', '(', ')', '[', ']', '%');
+
+alias isNSChar = among!(' ', '\n', '\r', '\u0085', '\u2028', '\u2029');
+
+alias isBChar = among!('\n', '\r', '\u0085', '\u2028', '\u2029');
+
+alias isFlowScalarBreakSpace = among!(' ', '\t', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029', '\'', '"', '\\');
+
+/// Marked exception thrown at scanner errors.
+///
+/// See_Also: MarkedYAMLException
+class ScannerException : MarkedYAMLException
+{
+ mixin MarkedExceptionCtors;
+}
+
+/// Generates tokens from data provided by a Reader.
+struct Scanner
+{
+ private:
+ /// A simple key is a key that is not denoted by the '?' indicator.
+ /// For example:
+ /// ---
+ /// block simple key: value
+ /// ? not a simple key:
+ /// : { flow simple key: value }
+ /// We emit the KEY token before all keys, so when we find a potential simple
+ /// key, we try to locate the corresponding ':' indicator. Simple keys should be
+ /// limited to a single line and 1024 characters.
+ ///
+ /// 16 bytes on 64-bit.
+ static struct SimpleKey
+ {
+ /// Character index in reader where the key starts.
+ uint charIndex = uint.max;
+ /// Index of the key token from start (first token scanned being 0).
+ uint tokenIndex;
+ /// Line the key starts at.
+ uint line;
+ /// Column the key starts at.
+ ushort column;
+ /// Is this required to be a simple key?
+ bool required;
+ /// Is this struct "null" (invalid)?.
+ bool isNull;
+ }
+
+ /// Block chomping types.
+ enum Chomping
+ {
+ /// Strip all trailing line breaks. '-' indicator.
+ strip,
+ /// Line break of the last line is preserved, others discarded. Default.
+ clip,
+ /// All trailing line breaks are preserved. '+' indicator.
+ keep
+ }
+
+ /// Reader used to read from a file/stream.
+ Reader reader_;
+ /// Are we done scanning?
+ bool done_;
+
+ /// Level of nesting in flow context. If 0, we're in block context.
+ uint flowLevel_;
+ /// Current indentation level.
+ int indent_ = -1;
+ /// Past indentation levels. Used as a stack.
+ Appender!(int[]) indents_;
+
+ /// Processed tokens not yet emitted. Used as a queue.
+ Queue!Token tokens_;
+
+ /// Number of tokens emitted through the getToken method.
+ uint tokensTaken_;
+
+ /// Can a simple key start at the current position? A simple key may start:
+ /// - at the beginning of the line, not counting indentation spaces
+ /// (in block context),
+ /// - after '{', '[', ',' (in the flow context),
+ /// - after '?', ':', '-' (in the block context).
+ /// In the block context, this flag also signifies if a block collection
+ /// may start at the current position.
+ bool allowSimpleKey_ = true;
+
+ /// Possible simple keys indexed by flow levels.
+ SimpleKey[] possibleSimpleKeys_;
+
+ public:
+ /// Construct a Scanner using specified Reader.
+ this(Reader reader) @safe nothrow
+ {
+ // Return the next token, but do not delete it from the queue
+ reader_ = reader;
+ fetchStreamStart();
+ }
+
+ /// Advance to the next token
+ void popFront() @safe
+ {
+ ++tokensTaken_;
+ tokens_.pop();
+ }
+
+ /// Return the current token
+ const(Token) front() @safe
+ {
+ enforce(!empty, "No token left to peek");
+ return tokens_.peek();
+ }
+
+ /// Return whether there are any more tokens left.
+ bool empty() @safe
+ {
+ while (needMoreTokens())
+ {
+ fetchToken();
+ }
+ return tokens_.empty;
+ }
+
+ private:
+ /// Most scanning error messages have the same format; so build them with this
+ /// function.
+ string expected(T)(string expected, T found)
+ {
+ return text("expected ", expected, ", but found ", found);
+ }
+
+ /// Determine whether or not we need to fetch more tokens before peeking/getting a token.
+ bool needMoreTokens() @safe pure
+ {
+ if(done_) { return false; }
+ if(tokens_.empty) { return true; }
+
+ /// The current token may be a potential simple key, so we need to look further.
+ stalePossibleSimpleKeys();
+ return nextPossibleSimpleKey() == tokensTaken_;
+ }
+
+ /// Fetch at token, adding it to tokens_.
+ void fetchToken() @safe
+ {
+ // Eat whitespaces and comments until we reach the next token.
+ scanToNextToken();
+
+ // Remove obsolete possible simple keys.
+ stalePossibleSimpleKeys();
+
+ // Compare current indentation and column. It may add some tokens
+ // and decrease the current indentation level.
+ unwindIndent(reader_.column);
+
+ // Get the next character.
+ const dchar c = reader_.peekByte();
+
+ // Fetch the token.
+ if(c == '\0') { return fetchStreamEnd(); }
+ if(checkDirective()) { return fetchDirective(); }
+ if(checkDocumentStart()) { return fetchDocumentStart(); }
+ if(checkDocumentEnd()) { return fetchDocumentEnd(); }
+ // Order of the following checks is NOT significant.
+ switch(c)
+ {
+ case '[': return fetchFlowSequenceStart();
+ case '{': return fetchFlowMappingStart();
+ case ']': return fetchFlowSequenceEnd();
+ case '}': return fetchFlowMappingEnd();
+ case ',': return fetchFlowEntry();
+ case '!': return fetchTag();
+ case '\'': return fetchSingle();
+ case '\"': return fetchDouble();
+ case '*': return fetchAlias();
+ case '&': return fetchAnchor();
+ case '?': if(checkKey()) { return fetchKey(); } goto default;
+ case ':': if(checkValue()) { return fetchValue(); } goto default;
+ case '-': if(checkBlockEntry()) { return fetchBlockEntry(); } goto default;
+ case '|': if(flowLevel_ == 0) { return fetchLiteral(); } break;
+ case '>': if(flowLevel_ == 0) { return fetchFolded(); } break;
+ default: if(checkPlain()) { return fetchPlain(); }
+ }
+
+ throw new ScannerException("While scanning for the next token, found character " ~
+ "\'%s\', index %s that cannot start any token"
+ .format(c, to!int(c)), reader_.mark);
+ }
+
+
+ /// Return the token number of the nearest possible simple key.
+ uint nextPossibleSimpleKey() @safe pure nothrow @nogc
+ {
+ uint minTokenNumber = uint.max;
+ foreach(k, ref simpleKey; possibleSimpleKeys_)
+ {
+ if(simpleKey.isNull) { continue; }
+ minTokenNumber = min(minTokenNumber, simpleKey.tokenIndex);
+ }
+ return minTokenNumber;
+ }
+
+ /// Remove entries that are no longer possible simple keys.
+ ///
+ /// According to the YAML specification, simple keys
+ /// - should be limited to a single line,
+ /// - should be no longer than 1024 characters.
+ /// Disabling this will allow simple keys of any length and
+ /// height (may cause problems if indentation is broken though).
+ void stalePossibleSimpleKeys() @safe pure
+ {
+ foreach(level, ref key; possibleSimpleKeys_)
+ {
+ if(key.isNull) { continue; }
+ if(key.line != reader_.line || reader_.charIndex - key.charIndex > 1024)
+ {
+ enforce(!key.required,
+ new ScannerException("While scanning a simple key",
+ Mark(reader_.name, key.line, key.column),
+ "could not find expected ':'", reader_.mark));
+ key.isNull = true;
+ }
+ }
+ }
+
+ /// Check if the next token starts a possible simple key and if so, save its position.
+ ///
+ /// This function is called for ALIAS, ANCHOR, TAG, SCALAR(flow), '[', and '{'.
+ void savePossibleSimpleKey() @safe pure
+ {
+ // Check if a simple key is required at the current position.
+ const required = (flowLevel_ == 0 && indent_ == reader_.column);
+ assert(allowSimpleKey_ || !required, "A simple key is required only if it is " ~
+ "the first token in the current line. Therefore it is always allowed.");
+
+ if(!allowSimpleKey_) { return; }
+
+ // The next token might be a simple key, so save its number and position.
+ removePossibleSimpleKey();
+ const tokenCount = tokensTaken_ + cast(uint)tokens_.length;
+
+ const line = reader_.line;
+ const column = reader_.column;
+ const key = SimpleKey(cast(uint)reader_.charIndex, tokenCount, line,
+ cast(ushort)min(column, ushort.max), required);
+
+ if(possibleSimpleKeys_.length <= flowLevel_)
+ {
+ const oldLength = possibleSimpleKeys_.length;
+ possibleSimpleKeys_.length = flowLevel_ + 1;
+ //No need to initialize the last element, it's already done in the next line.
+ possibleSimpleKeys_[oldLength .. flowLevel_] = SimpleKey.init;
+ }
+ possibleSimpleKeys_[flowLevel_] = key;
+ }
+
+ /// Remove the saved possible key position at the current flow level.
+ void removePossibleSimpleKey() @safe pure
+ {
+ if(possibleSimpleKeys_.length <= flowLevel_) { return; }
+
+ if(!possibleSimpleKeys_[flowLevel_].isNull)
+ {
+ const key = possibleSimpleKeys_[flowLevel_];
+ enforce(!key.required,
+ new ScannerException("While scanning a simple key",
+ Mark(reader_.name, key.line, key.column),
+ "could not find expected ':'", reader_.mark));
+ possibleSimpleKeys_[flowLevel_].isNull = true;
+ }
+ }
+
+ /// Decrease indentation, removing entries in indents_.
+ ///
+ /// Params: column = Current column in the file/stream.
+ void unwindIndent(const int column) @safe
+ {
+ if(flowLevel_ > 0)
+ {
+ // In flow context, tokens should respect indentation.
+ // The condition should be `indent >= column` according to the spec.
+ // But this condition will prohibit intuitively correct
+ // constructions such as
+ // key : {
+ // }
+
+ // In the flow context, indentation is ignored. We make the scanner less
+ // restrictive than what the specification requires.
+ // if(pedantic_ && flowLevel_ > 0 && indent_ > column)
+ // {
+ // throw new ScannerException("Invalid intendation or unclosed '[' or '{'",
+ // reader_.mark)
+ // }
+ return;
+ }
+
+ // In block context, we may need to issue the BLOCK-END tokens.
+ while(indent_ > column)
+ {
+ indent_ = indents_.data.back;
+ assert(indents_.data.length);
+ indents_.shrinkTo(indents_.data.length - 1);
+ tokens_.push(blockEndToken(reader_.mark, reader_.mark));
+ }
+ }
+
+ /// Increase indentation if needed.
+ ///
+ /// Params: column = Current column in the file/stream.
+ ///
+ /// Returns: true if the indentation was increased, false otherwise.
+ bool addIndent(int column) @safe
+ {
+ if(indent_ >= column){return false;}
+ indents_ ~= indent_;
+ indent_ = column;
+ return true;
+ }
+
+
+ /// Add STREAM-START token.
+ void fetchStreamStart() @safe nothrow
+ {
+ tokens_.push(streamStartToken(reader_.mark, reader_.mark, reader_.encoding));
+ }
+
+ ///Add STREAM-END token.
+ void fetchStreamEnd() @safe
+ {
+ //Set intendation to -1 .
+ unwindIndent(-1);
+ removePossibleSimpleKey();
+ allowSimpleKey_ = false;
+ possibleSimpleKeys_.destroy;
+
+ tokens_.push(streamEndToken(reader_.mark, reader_.mark));
+ done_ = true;
+ }
+
+ /// Add DIRECTIVE token.
+ void fetchDirective() @safe
+ {
+ // Set intendation to -1 .
+ unwindIndent(-1);
+ // Reset simple keys.
+ removePossibleSimpleKey();
+ allowSimpleKey_ = false;
+
+ auto directive = scanDirective();
+ tokens_.push(directive);
+ }
+
+ /// Add DOCUMENT-START or DOCUMENT-END token.
+ void fetchDocumentIndicator(TokenID id)()
+ if(id == TokenID.documentStart || id == TokenID.documentEnd)
+ {
+ // Set indentation to -1 .
+ unwindIndent(-1);
+ // Reset simple keys. Note that there can't be a block collection after '---'.
+ removePossibleSimpleKey();
+ allowSimpleKey_ = false;
+
+ Mark startMark = reader_.mark;
+ reader_.forward(3);
+ tokens_.push(simpleToken!id(startMark, reader_.mark));
+ }
+
+ /// Aliases to add DOCUMENT-START or DOCUMENT-END token.
+ alias fetchDocumentStart = fetchDocumentIndicator!(TokenID.documentStart);
+ alias fetchDocumentEnd = fetchDocumentIndicator!(TokenID.documentEnd);
+
+ /// Add FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+ void fetchFlowCollectionStart(TokenID id)() @safe
+ {
+ // '[' and '{' may start a simple key.
+ savePossibleSimpleKey();
+ // Simple keys are allowed after '[' and '{'.
+ allowSimpleKey_ = true;
+ ++flowLevel_;
+
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(simpleToken!id(startMark, reader_.mark));
+ }
+
+ /// Aliases to add FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+ alias fetchFlowSequenceStart = fetchFlowCollectionStart!(TokenID.flowSequenceStart);
+ alias fetchFlowMappingStart = fetchFlowCollectionStart!(TokenID.flowMappingStart);
+
+ /// Add FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+ void fetchFlowCollectionEnd(TokenID id)()
+ {
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // No simple keys after ']' and '}'.
+ allowSimpleKey_ = false;
+ --flowLevel_;
+
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(simpleToken!id(startMark, reader_.mark));
+ }
+
+ /// Aliases to add FLOW-SEQUENCE-START or FLOW-MAPPING-START token/
+ alias fetchFlowSequenceEnd = fetchFlowCollectionEnd!(TokenID.flowSequenceEnd);
+ alias fetchFlowMappingEnd = fetchFlowCollectionEnd!(TokenID.flowMappingEnd);
+
+ /// Add FLOW-ENTRY token;
+ void fetchFlowEntry() @safe
+ {
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // Simple keys are allowed after ','.
+ allowSimpleKey_ = true;
+
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(flowEntryToken(startMark, reader_.mark));
+ }
+
+ /// Additional checks used in block context in fetchBlockEntry and fetchKey.
+ ///
+ /// Params: type = String representing the token type we might need to add.
+ /// id = Token type we might need to add.
+ void blockChecks(string type, TokenID id)()
+ {
+ enum context = type ~ " keys are not allowed here";
+ // Are we allowed to start a key (not neccesarily a simple one)?
+ enforce(allowSimpleKey_, new ScannerException(context, reader_.mark));
+
+ if(addIndent(reader_.column))
+ {
+ tokens_.push(simpleToken!id(reader_.mark, reader_.mark));
+ }
+ }
+
+ /// Add BLOCK-ENTRY token. Might add BLOCK-SEQUENCE-START in the process.
+ void fetchBlockEntry() @safe
+ {
+ if(flowLevel_ == 0) { blockChecks!("Sequence", TokenID.blockSequenceStart)(); }
+
+ // It's an error for the block entry to occur in the flow context,
+ // but we let the parser detect this.
+
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // Simple keys are allowed after '-'.
+ allowSimpleKey_ = true;
+
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(blockEntryToken(startMark, reader_.mark));
+ }
+
+ /// Add KEY token. Might add BLOCK-MAPPING-START in the process.
+ void fetchKey() @safe
+ {
+ if(flowLevel_ == 0) { blockChecks!("Mapping", TokenID.blockMappingStart)(); }
+
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // Simple keys are allowed after '?' in the block context.
+ allowSimpleKey_ = (flowLevel_ == 0);
+
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(keyToken(startMark, reader_.mark));
+ }
+
+ /// Add VALUE token. Might add KEY and/or BLOCK-MAPPING-START in the process.
+ void fetchValue() @safe
+ {
+ //Do we determine a simple key?
+ if(possibleSimpleKeys_.length > flowLevel_ &&
+ !possibleSimpleKeys_[flowLevel_].isNull)
+ {
+ const key = possibleSimpleKeys_[flowLevel_];
+ possibleSimpleKeys_[flowLevel_].isNull = true;
+ Mark keyMark = Mark(reader_.name, key.line, key.column);
+ const idx = key.tokenIndex - tokensTaken_;
+
+ assert(idx >= 0);
+
+ // Add KEY.
+ // Manually inserting since tokens are immutable (need linked list).
+ tokens_.insert(keyToken(keyMark, keyMark), idx);
+
+ // If this key starts a new block mapping, we need to add BLOCK-MAPPING-START.
+ if(flowLevel_ == 0 && addIndent(key.column))
+ {
+ tokens_.insert(blockMappingStartToken(keyMark, keyMark), idx);
+ }
+
+ // There cannot be two simple keys in a row.
+ allowSimpleKey_ = false;
+ }
+ // Part of a complex key
+ else
+ {
+ // We can start a complex value if and only if we can start a simple key.
+ enforce(flowLevel_ > 0 || allowSimpleKey_,
+ new ScannerException("Mapping values are not allowed here", reader_.mark));
+
+ // If this value starts a new block mapping, we need to add
+ // BLOCK-MAPPING-START. It'll be detected as an error later by the parser.
+ if(flowLevel_ == 0 && addIndent(reader_.column))
+ {
+ tokens_.push(blockMappingStartToken(reader_.mark, reader_.mark));
+ }
+
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // Simple keys are allowed after ':' in the block context.
+ allowSimpleKey_ = (flowLevel_ == 0);
+ }
+
+ // Add VALUE.
+ Mark startMark = reader_.mark;
+ reader_.forward();
+ tokens_.push(valueToken(startMark, reader_.mark));
+ }
+
+ /// Add ALIAS or ANCHOR token.
+ void fetchAnchor_(TokenID id)() @safe
+ if(id == TokenID.alias_ || id == TokenID.anchor)
+ {
+ // ALIAS/ANCHOR could be a simple key.
+ savePossibleSimpleKey();
+ // No simple keys after ALIAS/ANCHOR.
+ allowSimpleKey_ = false;
+
+ auto anchor = scanAnchor(id);
+ tokens_.push(anchor);
+ }
+
+ /// Aliases to add ALIAS or ANCHOR token.
+ alias fetchAlias = fetchAnchor_!(TokenID.alias_);
+ alias fetchAnchor = fetchAnchor_!(TokenID.anchor);
+
+ /// Add TAG token.
+ void fetchTag() @safe
+ {
+ //TAG could start a simple key.
+ savePossibleSimpleKey();
+ //No simple keys after TAG.
+ allowSimpleKey_ = false;
+
+ tokens_.push(scanTag());
+ }
+
+ /// Add block SCALAR token.
+ void fetchBlockScalar(ScalarStyle style)() @safe
+ if(style == ScalarStyle.literal || style == ScalarStyle.folded)
+ {
+ // Reset possible simple key on the current level.
+ removePossibleSimpleKey();
+ // A simple key may follow a block scalar.
+ allowSimpleKey_ = true;
+
+ auto blockScalar = scanBlockScalar(style);
+ tokens_.push(blockScalar);
+ }
+
+ /// Aliases to add literal or folded block scalar.
+ alias fetchLiteral = fetchBlockScalar!(ScalarStyle.literal);
+ alias fetchFolded = fetchBlockScalar!(ScalarStyle.folded);
+
+ /// Add quoted flow SCALAR token.
+ void fetchFlowScalar(ScalarStyle quotes)()
+ {
+ // A flow scalar could be a simple key.
+ savePossibleSimpleKey();
+ // No simple keys after flow scalars.
+ allowSimpleKey_ = false;
+
+ // Scan and add SCALAR.
+ auto scalar = scanFlowScalar(quotes);
+ tokens_.push(scalar);
+ }
+
+ /// Aliases to add single or double quoted block scalar.
+ alias fetchSingle = fetchFlowScalar!(ScalarStyle.singleQuoted);
+ alias fetchDouble = fetchFlowScalar!(ScalarStyle.doubleQuoted);
+
+ /// Add plain SCALAR token.
+ void fetchPlain() @safe
+ {
+ // A plain scalar could be a simple key
+ savePossibleSimpleKey();
+ // No simple keys after plain scalars. But note that scanPlain() will
+ // change this flag if the scan is finished at the beginning of the line.
+ allowSimpleKey_ = false;
+ auto plain = scanPlain();
+
+ // Scan and add SCALAR. May change allowSimpleKey_
+ tokens_.push(plain);
+ }
+
+ pure:
+
+ ///Check if the next token is DIRECTIVE: ^ '%' ...
+ bool checkDirective() @safe
+ {
+ return reader_.peekByte() == '%' && reader_.column == 0;
+ }
+
+ /// Check if the next token is DOCUMENT-START: ^ '---' (' '|'\n')
+ bool checkDocumentStart() @safe
+ {
+ // Check one char first, then all 3, to prevent reading outside the buffer.
+ return reader_.column == 0 &&
+ reader_.peekByte() == '-' &&
+ reader_.prefix(3) == "---" &&
+ reader_.peek(3).isWhiteSpace;
+ }
+
+ /// Check if the next token is DOCUMENT-END: ^ '...' (' '|'\n')
+ bool checkDocumentEnd() @safe
+ {
+ // Check one char first, then all 3, to prevent reading outside the buffer.
+ return reader_.column == 0 &&
+ reader_.peekByte() == '.' &&
+ reader_.prefix(3) == "..." &&
+ reader_.peek(3).isWhiteSpace;
+ }
+
+ /// Check if the next token is BLOCK-ENTRY: '-' (' '|'\n')
+ bool checkBlockEntry() @safe
+ {
+ return !!reader_.peek(1).isWhiteSpace;
+ }
+
+ /// Check if the next token is KEY(flow context): '?'
+ ///
+ /// or KEY(block context): '?' (' '|'\n')
+ bool checkKey() @safe
+ {
+ return (flowLevel_ > 0 || reader_.peek(1).isWhiteSpace);
+ }
+
+ /// Check if the next token is VALUE(flow context): ':'
+ ///
+ /// or VALUE(block context): ':' (' '|'\n')
+ bool checkValue() @safe
+ {
+ return flowLevel_ > 0 || reader_.peek(1).isWhiteSpace;
+ }
+
+ /// Check if the next token is a plain scalar.
+ ///
+ /// A plain scalar may start with any non-space character except:
+ /// '-', '?', ':', ',', '[', ']', '{', '}',
+ /// '#', '&', '*', '!', '|', '>', '\'', '\"',
+ /// '%', '@', '`'.
+ ///
+ /// It may also start with
+ /// '-', '?', ':'
+ /// if it is followed by a non-space character.
+ ///
+ /// Note that we limit the last rule to the block context (except the
+ /// '-' character) because we want the flow context to be space
+ /// independent.
+ bool checkPlain() @safe
+ {
+ const c = reader_.peek();
+ if(!c.isNonScalarStartCharacter)
+ {
+ return true;
+ }
+ return !reader_.peek(1).isWhiteSpace &&
+ (c == '-' || (flowLevel_ == 0 && (c == '?' || c == ':')));
+ }
+
+ /// Move to the next non-space character.
+ void findNextNonSpace() @safe
+ {
+ while(reader_.peekByte() == ' ') { reader_.forward(); }
+ }
+
+ /// Scan a string of alphanumeric or "-_" characters.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanAlphaNumericToSlice(string name)(const Mark startMark)
+ {
+ size_t length;
+ dchar c = reader_.peek();
+ while(c.isAlphaNum || c.among!('-', '_')) { c = reader_.peek(++length); }
+
+ enforce(length > 0, new ScannerException("While scanning " ~ name,
+ startMark, expected("alphanumeric, '-' or '_'", c), reader_.mark));
+
+ reader_.sliceBuilder.write(reader_.get(length));
+ }
+
+ /// Scan and throw away all characters until next line break.
+ void scanToNextBreak() @safe
+ {
+ while(!reader_.peek().isBreak) { reader_.forward(); }
+ }
+
+ /// Scan all characters until next line break.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanToNextBreakToSlice() @safe
+ {
+ uint length;
+ while(!reader_.peek(length).isBreak)
+ {
+ ++length;
+ }
+ reader_.sliceBuilder.write(reader_.get(length));
+ }
+
+
+ /// Move to next token in the file/stream.
+ ///
+ /// We ignore spaces, line breaks and comments.
+ /// If we find a line break in the block context, we set
+ /// allowSimpleKey` on.
+ ///
+ /// We do not yet support BOM inside the stream as the
+ /// specification requires. Any such mark will be considered as a part
+ /// of the document.
+ void scanToNextToken() @safe
+ {
+ // TODO(PyYAML): We need to make tab handling rules more sane. A good rule is:
+ // Tabs cannot precede tokens
+ // BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END,
+ // KEY(block), VALUE(block), BLOCK-ENTRY
+ // So the checking code is
+ // if <TAB>:
+ // allowSimpleKey_ = false
+ // We also need to add the check for `allowSimpleKey_ == true` to
+ // `unwindIndent` before issuing BLOCK-END.
+ // Scanners for block, flow, and plain scalars need to be modified.
+
+ for(;;)
+ {
+ //All whitespace in flow context is ignored, even whitespace
+ // not allowed in other contexts
+ if (flowLevel_ > 0)
+ {
+ while(reader_.peekByte().isNonLinebreakWhitespace) { reader_.forward(); }
+ }
+ else
+ {
+ findNextNonSpace();
+ }
+ if(reader_.peekByte() == '#') { scanToNextBreak(); }
+ if(scanLineBreak() != '\0')
+ {
+ if(flowLevel_ == 0) { allowSimpleKey_ = true; }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /// Scan directive token.
+ Token scanDirective() @safe
+ {
+ Mark startMark = reader_.mark;
+ // Skip the '%'.
+ reader_.forward();
+
+ // Scan directive name
+ reader_.sliceBuilder.begin();
+ scanDirectiveNameToSlice(startMark);
+ const name = reader_.sliceBuilder.finish();
+
+ reader_.sliceBuilder.begin();
+
+ // Index where tag handle ends and suffix starts in a tag directive value.
+ uint tagHandleEnd = uint.max;
+ if(name == "YAML") { scanYAMLDirectiveValueToSlice(startMark); }
+ else if(name == "TAG") { tagHandleEnd = scanTagDirectiveValueToSlice(startMark); }
+ char[] value = reader_.sliceBuilder.finish();
+
+ Mark endMark = reader_.mark;
+
+ DirectiveType directive;
+ if(name == "YAML") { directive = DirectiveType.yaml; }
+ else if(name == "TAG") { directive = DirectiveType.tag; }
+ else
+ {
+ directive = DirectiveType.reserved;
+ scanToNextBreak();
+ }
+
+ scanDirectiveIgnoredLine(startMark);
+
+ return directiveToken(startMark, endMark, value, directive, tagHandleEnd);
+ }
+
+ /// Scan name of a directive token.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanDirectiveNameToSlice(const Mark startMark) @safe
+ {
+ // Scan directive name.
+ scanAlphaNumericToSlice!"a directive"(startMark);
+
+ enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
+ new ScannerException("While scanning a directive", startMark,
+ expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark));
+ }
+
+ /// Scan value of a YAML directive token. Returns major, minor version separated by '.'.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanYAMLDirectiveValueToSlice(const Mark startMark) @safe
+ {
+ findNextNonSpace();
+
+ scanYAMLDirectiveNumberToSlice(startMark);
+
+ enforce(reader_.peekByte() == '.',
+ new ScannerException("While scanning a directive", startMark,
+ expected("digit or '.'", reader_.peek()), reader_.mark));
+ // Skip the '.'.
+ reader_.forward();
+
+ reader_.sliceBuilder.write('.');
+ scanYAMLDirectiveNumberToSlice(startMark);
+
+ enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
+ new ScannerException("While scanning a directive", startMark,
+ expected("digit or '.'", reader_.peek()), reader_.mark));
+ }
+
+ /// Scan a number from a YAML directive.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanYAMLDirectiveNumberToSlice(const Mark startMark) @safe
+ {
+ enforce(isDigit(reader_.peek()),
+ new ScannerException("While scanning a directive", startMark,
+ expected("digit", reader_.peek()), reader_.mark));
+
+ // Already found the first digit in the enforce(), so set length to 1.
+ uint length = 1;
+ while(reader_.peek(length).isDigit) { ++length; }
+
+ reader_.sliceBuilder.write(reader_.get(length));
+ }
+
+ /// Scan value of a tag directive.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ ///
+ /// Returns: Length of tag handle (which is before tag prefix) in scanned data
+ uint scanTagDirectiveValueToSlice(const Mark startMark) @safe
+ {
+ findNextNonSpace();
+ const startLength = reader_.sliceBuilder.length;
+ scanTagDirectiveHandleToSlice(startMark);
+ const handleLength = cast(uint)(reader_.sliceBuilder.length - startLength);
+ findNextNonSpace();
+ scanTagDirectivePrefixToSlice(startMark);
+
+ return handleLength;
+ }
+
+ /// Scan handle of a tag directive.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanTagDirectiveHandleToSlice(const Mark startMark) @safe
+ {
+ scanTagHandleToSlice!"directive"(startMark);
+ enforce(reader_.peekByte() == ' ',
+ new ScannerException("While scanning a directive handle", startMark,
+ expected("' '", reader_.peek()), reader_.mark));
+ }
+
+ /// Scan prefix of a tag directive.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanTagDirectivePrefixToSlice(const Mark startMark) @safe
+ {
+ scanTagURIToSlice!"directive"(startMark);
+ enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
+ new ScannerException("While scanning a directive prefix", startMark,
+ expected("' '", reader_.peek()), reader_.mark));
+ }
+
+ /// Scan (and ignore) ignored line after a directive.
+ void scanDirectiveIgnoredLine(const Mark startMark) @safe
+ {
+ findNextNonSpace();
+ if(reader_.peekByte() == '#') { scanToNextBreak(); }
+ enforce(reader_.peek().isBreak,
+ new ScannerException("While scanning a directive", startMark,
+ expected("comment or a line break", reader_.peek()), reader_.mark));
+ scanLineBreak();
+ }
+
+
+ /// Scan an alias or an anchor.
+ ///
+ /// The specification does not restrict characters for anchors and
+ /// aliases. This may lead to problems, for instance, the document:
+ /// [ *alias, value ]
+ /// can be interpteted in two ways, as
+ /// [ "value" ]
+ /// and
+ /// [ *alias , "value" ]
+ /// Therefore we restrict aliases to ASCII alphanumeric characters.
+ Token scanAnchor(const TokenID id) @safe
+ {
+ const startMark = reader_.mark;
+ const dchar i = reader_.get();
+
+ reader_.sliceBuilder.begin();
+ if(i == '*') { scanAlphaNumericToSlice!"an alias"(startMark); }
+ else { scanAlphaNumericToSlice!"an anchor"(startMark); }
+ // On error, value is discarded as we return immediately
+ char[] value = reader_.sliceBuilder.finish();
+
+ enum anchorCtx = "While scanning an anchor";
+ enum aliasCtx = "While scanning an alias";
+ enforce(reader_.peek().isWhiteSpace ||
+ reader_.peekByte().among!('?', ':', ',', ']', '}', '%', '@'),
+ new ScannerException(i == '*' ? aliasCtx : anchorCtx, startMark,
+ expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark));
+
+ if(id == TokenID.alias_)
+ {
+ return aliasToken(startMark, reader_.mark, value);
+ }
+ if(id == TokenID.anchor)
+ {
+ return anchorToken(startMark, reader_.mark, value);
+ }
+ assert(false, "This code should never be reached");
+ }
+
+ /// Scan a tag token.
+ Token scanTag() @safe
+ {
+ const startMark = reader_.mark;
+ dchar c = reader_.peek(1);
+
+ reader_.sliceBuilder.begin();
+ scope(failure) { reader_.sliceBuilder.finish(); }
+ // Index where tag handle ends and tag suffix starts in the tag value
+ // (slice) we will produce.
+ uint handleEnd;
+
+ if(c == '<')
+ {
+ reader_.forward(2);
+
+ handleEnd = 0;
+ scanTagURIToSlice!"tag"(startMark);
+ enforce(reader_.peekByte() == '>',
+ new ScannerException("While scanning a tag", startMark,
+ expected("'>'", reader_.peek()), reader_.mark));
+ reader_.forward();
+ }
+ else if(c.isWhiteSpace)
+ {
+ reader_.forward();
+ handleEnd = 0;
+ reader_.sliceBuilder.write('!');
+ }
+ else
+ {
+ uint length = 1;
+ bool useHandle;
+
+ while(!c.isBreakOrSpace)
+ {
+ if(c == '!')
+ {
+ useHandle = true;
+ break;
+ }
+ ++length;
+ c = reader_.peek(length);
+ }
+
+ if(useHandle)
+ {
+ scanTagHandleToSlice!"tag"(startMark);
+ handleEnd = cast(uint)reader_.sliceBuilder.length;
+ }
+ else
+ {
+ reader_.forward();
+ reader_.sliceBuilder.write('!');
+ handleEnd = cast(uint)reader_.sliceBuilder.length;
+ }
+
+ scanTagURIToSlice!"tag"(startMark);
+ }
+
+ enforce(reader_.peek().isBreakOrSpace,
+ new ScannerException("While scanning a tag", startMark, expected("' '", reader_.peek()),
+ reader_.mark));
+
+ char[] slice = reader_.sliceBuilder.finish();
+ return tagToken(startMark, reader_.mark, slice, handleEnd);
+ }
+
+ /// Scan a block scalar token with specified style.
+ Token scanBlockScalar(const ScalarStyle style) @safe
+ {
+ const startMark = reader_.mark;
+
+ // Scan the header.
+ reader_.forward();
+
+ const indicators = scanBlockScalarIndicators(startMark);
+
+ const chomping = indicators[0];
+ const increment = indicators[1];
+ scanBlockScalarIgnoredLine(startMark);
+
+ // Determine the indentation level and go to the first non-empty line.
+ Mark endMark;
+ uint indent = max(1, indent_ + 1);
+
+ reader_.sliceBuilder.begin();
+ alias Transaction = SliceBuilder.Transaction;
+ // Used to strip the last line breaks written to the slice at the end of the
+ // scalar, which may be needed based on chomping.
+ Transaction breaksTransaction = Transaction(&reader_.sliceBuilder);
+ // Read the first indentation/line breaks before the scalar.
+ size_t startLen = reader_.sliceBuilder.length;
+ if(increment == int.min)
+ {
+ auto indentation = scanBlockScalarIndentationToSlice();
+ endMark = indentation[1];
+ indent = max(indent, indentation[0]);
+ }
+ else
+ {
+ indent += increment - 1;
+ endMark = scanBlockScalarBreaksToSlice(indent);
+ }
+
+ // int.max means there's no line break (int.max is outside UTF-32).
+ dchar lineBreak = cast(dchar)int.max;
+
+ // Scan the inner part of the block scalar.
+ while(reader_.column == indent && reader_.peekByte() != '\0')
+ {
+ breaksTransaction.commit();
+ const bool leadingNonSpace = !reader_.peekByte().among!(' ', '\t');
+ // This is where the 'interesting' non-whitespace data gets read.
+ scanToNextBreakToSlice();
+ lineBreak = scanLineBreak();
+
+
+ // This transaction serves to rollback data read in the
+ // scanBlockScalarBreaksToSlice() call.
+ breaksTransaction = Transaction(&reader_.sliceBuilder);
+ startLen = reader_.sliceBuilder.length;
+ // The line breaks should actually be written _after_ the if() block
+ // below. We work around that by inserting
+ endMark = scanBlockScalarBreaksToSlice(indent);
+
+ // This will not run during the last iteration (see the if() vs the
+ // while()), hence breaksTransaction rollback (which happens after this
+ // loop) will never roll back data written in this if() block.
+ if(reader_.column == indent && reader_.peekByte() != '\0')
+ {
+ // Unfortunately, folding rules are ambiguous.
+
+ // This is the folding according to the specification:
+ if(style == ScalarStyle.folded && lineBreak == '\n' &&
+ leadingNonSpace && !reader_.peekByte().among!(' ', '\t'))
+ {
+ // No breaks were scanned; no need to insert the space in the
+ // middle of slice.
+ if(startLen == reader_.sliceBuilder.length)
+ {
+ reader_.sliceBuilder.write(' ');
+ }
+ }
+ else
+ {
+ // We need to insert in the middle of the slice in case any line
+ // breaks were scanned.
+ reader_.sliceBuilder.insert(lineBreak, startLen);
+ }
+
+ ////this is Clark Evans's interpretation (also in the spec
+ ////examples):
+ //
+ //if(style == ScalarStyle.folded && lineBreak == '\n')
+ //{
+ // if(startLen == endLen)
+ // {
+ // if(!" \t"d.canFind(reader_.peekByte()))
+ // {
+ // reader_.sliceBuilder.write(' ');
+ // }
+ // else
+ // {
+ // chunks ~= lineBreak;
+ // }
+ // }
+ //}
+ //else
+ //{
+ // reader_.sliceBuilder.insertBack(lineBreak, endLen - startLen);
+ //}
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // If chompint is Keep, we keep (commit) the last scanned line breaks
+ // (which are at the end of the scalar). Otherwise re remove them (end the
+ // transaction).
+ if(chomping == Chomping.keep) { breaksTransaction.commit(); }
+ else { breaksTransaction.end(); }
+ if(chomping != Chomping.strip && lineBreak != int.max)
+ {
+ // If chomping is Keep, we keep the line break but the first line break
+ // that isn't stripped (since chomping isn't Strip in this branch) must
+ // be inserted _before_ the other line breaks.
+ if(chomping == Chomping.keep)
+ {
+ reader_.sliceBuilder.insert(lineBreak, startLen);
+ }
+ // If chomping is not Keep, breaksTransaction was cancelled so we can
+ // directly write the first line break (as it isn't stripped - chomping
+ // is not Strip)
+ else
+ {
+ reader_.sliceBuilder.write(lineBreak);
+ }
+ }
+
+ char[] slice = reader_.sliceBuilder.finish();
+ return scalarToken(startMark, endMark, slice, style);
+ }
+
+ /// Scan chomping and indentation indicators of a scalar token.
+ Tuple!(Chomping, int) scanBlockScalarIndicators(const Mark startMark) @safe
+ {
+ auto chomping = Chomping.clip;
+ int increment = int.min;
+ dchar c = reader_.peek();
+
+ /// Indicators can be in any order.
+ if(getChomping(c, chomping))
+ {
+ getIncrement(c, increment, startMark);
+ }
+ else
+ {
+ const gotIncrement = getIncrement(c, increment, startMark);
+ if(gotIncrement) { getChomping(c, chomping); }
+ }
+
+ enforce(c.among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
+ new ScannerException("While scanning a block scalar", startMark,
+ expected("chomping or indentation indicator", c), reader_.mark));
+
+ return tuple(chomping, increment);
+ }
+
+ /// Get chomping indicator, if detected. Return false otherwise.
+ ///
+ /// Used in scanBlockScalarIndicators.
+ ///
+ /// Params:
+ ///
+ /// c = The character that may be a chomping indicator.
+ /// chomping = Write the chomping value here, if detected.
+ bool getChomping(ref dchar c, ref Chomping chomping) @safe
+ {
+ if(!c.among!('+', '-')) { return false; }
+ chomping = c == '+' ? Chomping.keep : Chomping.strip;
+ reader_.forward();
+ c = reader_.peek();
+ return true;
+ }
+
+ /// Get increment indicator, if detected. Return false otherwise.
+ ///
+ /// Used in scanBlockScalarIndicators.
+ ///
+ /// Params:
+ ///
+ /// c = The character that may be an increment indicator.
+ /// If an increment indicator is detected, this will be updated to
+ /// the next character in the Reader.
+ /// increment = Write the increment value here, if detected.
+ /// startMark = Mark for error messages.
+ bool getIncrement(ref dchar c, ref int increment, const Mark startMark) @safe
+ {
+ if(!c.isDigit) { return false; }
+ // Convert a digit to integer.
+ increment = c - '0';
+ assert(increment < 10 && increment >= 0, "Digit has invalid value");
+
+ enforce(increment > 0,
+ new ScannerException("While scanning a block scalar", startMark,
+ expected("indentation indicator in range 1-9", "0"), reader_.mark));
+
+ reader_.forward();
+ c = reader_.peek();
+ return true;
+ }
+
+ /// Scan (and ignore) ignored line in a block scalar.
+ void scanBlockScalarIgnoredLine(const Mark startMark) @safe
+ {
+ findNextNonSpace();
+ if(reader_.peekByte()== '#') { scanToNextBreak(); }
+
+ enforce(reader_.peek().isBreak,
+ new ScannerException("While scanning a block scalar", startMark,
+ expected("comment or line break", reader_.peek()), reader_.mark));
+
+ scanLineBreak();
+ }
+
+ /// Scan indentation in a block scalar, returning line breaks, max indent and end mark.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ Tuple!(uint, Mark) scanBlockScalarIndentationToSlice() @safe
+ {
+ uint maxIndent;
+ Mark endMark = reader_.mark;
+
+ while(reader_.peek().among!(' ', '\n', '\r', '\u0085', '\u2028', '\u2029'))
+ {
+ if(reader_.peekByte() != ' ')
+ {
+ reader_.sliceBuilder.write(scanLineBreak());
+ endMark = reader_.mark;
+ continue;
+ }
+ reader_.forward();
+ maxIndent = max(reader_.column, maxIndent);
+ }
+
+ return tuple(maxIndent, endMark);
+ }
+
+ /// Scan line breaks at lower or specified indentation in a block scalar.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ Mark scanBlockScalarBreaksToSlice(const uint indent) @safe
+ {
+ Mark endMark = reader_.mark;
+
+ for(;;)
+ {
+ while(reader_.column < indent && reader_.peekByte() == ' ') { reader_.forward(); }
+ if(!reader_.peek().among!('\n', '\r', '\u0085', '\u2028', '\u2029')) { break; }
+ reader_.sliceBuilder.write(scanLineBreak());
+ endMark = reader_.mark;
+ }
+
+ return endMark;
+ }
+
+ /// Scan a qouted flow scalar token with specified quotes.
+ Token scanFlowScalar(const ScalarStyle quotes) @safe
+ {
+ const startMark = reader_.mark;
+ const quote = reader_.get();
+
+ reader_.sliceBuilder.begin();
+
+ scanFlowScalarNonSpacesToSlice(quotes, startMark);
+
+ while(reader_.peek() != quote)
+ {
+ scanFlowScalarSpacesToSlice(startMark);
+ scanFlowScalarNonSpacesToSlice(quotes, startMark);
+ }
+ reader_.forward();
+
+ auto slice = reader_.sliceBuilder.finish();
+ return scalarToken(startMark, reader_.mark, slice, quotes);
+ }
+
+ /// Scan nonspace characters in a flow scalar.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanFlowScalarNonSpacesToSlice(const ScalarStyle quotes, const Mark startMark)
+ @safe
+ {
+ for(;;)
+ {
+ dchar c = reader_.peek();
+
+ size_t numCodePoints;
+ while(!reader_.peek(numCodePoints).isFlowScalarBreakSpace) { ++numCodePoints; }
+
+ if (numCodePoints > 0) { reader_.sliceBuilder.write(reader_.get(numCodePoints)); }
+
+ c = reader_.peek();
+ if(quotes == ScalarStyle.singleQuoted && c == '\'' && reader_.peek(1) == '\'')
+ {
+ reader_.forward(2);
+ reader_.sliceBuilder.write('\'');
+ }
+ else if((quotes == ScalarStyle.doubleQuoted && c == '\'') ||
+ (quotes == ScalarStyle.singleQuoted && c.among!('"', '\\')))
+ {
+ reader_.forward();
+ reader_.sliceBuilder.write(c);
+ }
+ else if(quotes == ScalarStyle.doubleQuoted && c == '\\')
+ {
+ reader_.forward();
+ c = reader_.peek();
+ if(c.among!(escapes))
+ {
+ reader_.forward();
+ // Escaping has been moved to Parser as it can't be done in
+ // place (in a slice) in case of '\P' and '\L' (very uncommon,
+ // but we don't want to break the spec)
+ char[2] escapeSequence = ['\\', cast(char)c];
+ reader_.sliceBuilder.write(escapeSequence);
+ }
+ else if(c.among!(escapeHexCodeList))
+ {
+ const hexLength = dyaml.escapes.escapeHexLength(c);
+ reader_.forward();
+
+ foreach(i; 0 .. hexLength) {
+ enforce(reader_.peek(i).isHexDigit,
+ new ScannerException("While scanning a double quoted scalar", startMark,
+ expected("escape sequence of hexadecimal numbers",
+ reader_.peek(i)), reader_.mark));
+ }
+ char[] hex = reader_.get(hexLength);
+
+ enforce((hex.length > 0) && (hex.length <= 8),
+ new ScannerException("While scanning a double quoted scalar", startMark,
+ "overflow when parsing an escape sequence of " ~
+ "hexadecimal numbers.", reader_.mark));
+
+ char[2] escapeStart = ['\\', cast(char) c];
+ reader_.sliceBuilder.write(escapeStart);
+ reader_.sliceBuilder.write(hex);
+
+ }
+ else if(c.among!('\n', '\r', '\u0085', '\u2028', '\u2029'))
+ {
+ scanLineBreak();
+ scanFlowScalarBreaksToSlice(startMark);
+ }
+ else
+ {
+ throw new ScannerException("While scanning a double quoted scalar", startMark,
+ text("found unsupported escape character ", c),
+ reader_.mark);
+ }
+ }
+ else { return; }
+ }
+ }
+
+ /// Scan space characters in a flow scalar.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// spaces into that slice.
+ void scanFlowScalarSpacesToSlice(const Mark startMark) @safe
+ {
+ // Increase length as long as we see whitespace.
+ size_t length;
+ while(reader_.peekByte(length).among!(' ', '\t')) { ++length; }
+ auto whitespaces = reader_.prefixBytes(length);
+
+ // Can check the last byte without striding because '\0' is ASCII
+ const c = reader_.peek(length);
+ enforce(c != '\0',
+ new ScannerException("While scanning a quoted scalar", startMark,
+ "found unexpected end of buffer", reader_.mark));
+
+ // Spaces not followed by a line break.
+ if(!c.among!('\n', '\r', '\u0085', '\u2028', '\u2029'))
+ {
+ reader_.forward(length);
+ reader_.sliceBuilder.write(whitespaces);
+ return;
+ }
+
+ // There's a line break after the spaces.
+ reader_.forward(length);
+ const lineBreak = scanLineBreak();
+
+ if(lineBreak != '\n') { reader_.sliceBuilder.write(lineBreak); }
+
+ // If we have extra line breaks after the first, scan them into the
+ // slice.
+ const bool extraBreaks = scanFlowScalarBreaksToSlice(startMark);
+
+ // No extra breaks, one normal line break. Replace it with a space.
+ if(lineBreak == '\n' && !extraBreaks) { reader_.sliceBuilder.write(' '); }
+ }
+
+ /// Scan line breaks in a flow scalar.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// line breaks into that slice.
+ bool scanFlowScalarBreaksToSlice(const Mark startMark) @safe
+ {
+ // True if at least one line break was found.
+ bool anyBreaks;
+ for(;;)
+ {
+ // Instead of checking indentation, we check for document separators.
+ const prefix = reader_.prefix(3);
+ enforce(!(prefix == "---" || prefix == "...") ||
+ !reader_.peek(3).isWhiteSpace,
+ new ScannerException("While scanning a quoted scalar", startMark,
+ "found unexpected document separator", reader_.mark));
+
+ // Skip any whitespaces.
+ while(reader_.peekByte().among!(' ', '\t')) { reader_.forward(); }
+
+ // Encountered a non-whitespace non-linebreak character, so we're done.
+ if(!reader_.peek().among!(' ', '\n', '\r', '\u0085', '\u2028', '\u2029')) { break; }
+
+ const lineBreak = scanLineBreak();
+ anyBreaks = true;
+ reader_.sliceBuilder.write(lineBreak);
+ }
+ return anyBreaks;
+ }
+
+ /// Scan plain scalar token (no block, no quotes).
+ Token scanPlain() @safe
+ {
+ // We keep track of the allowSimpleKey_ flag here.
+ // Indentation rules are loosed for the flow context
+ const startMark = reader_.mark;
+ Mark endMark = startMark;
+ const indent = indent_ + 1;
+
+ // We allow zero indentation for scalars, but then we need to check for
+ // document separators at the beginning of the line.
+ // if(indent == 0) { indent = 1; }
+
+ reader_.sliceBuilder.begin();
+
+ alias Transaction = SliceBuilder.Transaction;
+ Transaction spacesTransaction;
+ // Stop at a comment.
+ while(reader_.peekByte() != '#')
+ {
+ // Scan the entire plain scalar.
+ size_t length;
+ dchar c = reader_.peek(length);
+ for(;;)
+ {
+ const cNext = reader_.peek(length + 1);
+ if(c.isWhiteSpace ||
+ (flowLevel_ == 0 && c == ':' && cNext.isWhiteSpace) ||
+ (flowLevel_ > 0 && c.among!(',', ':', '?', '[', ']', '{', '}')))
+ {
+ break;
+ }
+ ++length;
+ c = cNext;
+ }
+
+ // It's not clear what we should do with ':' in the flow context.
+ enforce(flowLevel_ == 0 || c != ':' ||
+ reader_.peek(length + 1).isWhiteSpace ||
+ reader_.peek(length + 1).among!(',', '[', ']', '{', '}'),
+ new ScannerException("While scanning a plain scalar", startMark,
+ "found unexpected ':' . Please check " ~
+ "http://pyyaml.org/wiki/YAMLColonInFlowContext for details.",
+ reader_.mark));
+
+ if(length == 0) { break; }
+
+ allowSimpleKey_ = false;
+
+ reader_.sliceBuilder.write(reader_.get(length));
+
+ endMark = reader_.mark;
+
+ spacesTransaction.commit();
+ spacesTransaction = Transaction(&reader_.sliceBuilder);
+
+ const startLength = reader_.sliceBuilder.length;
+ scanPlainSpacesToSlice();
+ if(startLength == reader_.sliceBuilder.length ||
+ (flowLevel_ == 0 && reader_.column < indent))
+ {
+ break;
+ }
+ }
+
+ spacesTransaction.end();
+ char[] slice = reader_.sliceBuilder.finish();
+
+ return scalarToken(startMark, endMark, slice, ScalarStyle.plain);
+ }
+
+ /// Scan spaces in a plain scalar.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the spaces
+ /// into that slice.
+ void scanPlainSpacesToSlice() @safe
+ {
+ // The specification is really confusing about tabs in plain scalars.
+ // We just forbid them completely. Do not use tabs in YAML!
+
+ // Get as many plain spaces as there are.
+ size_t length;
+ while(reader_.peekByte(length) == ' ') { ++length; }
+ char[] whitespaces = reader_.prefixBytes(length);
+ reader_.forward(length);
+
+ const dchar c = reader_.peek();
+ if(!c.isNSChar)
+ {
+ // We have spaces, but no newline.
+ if(whitespaces.length > 0) { reader_.sliceBuilder.write(whitespaces); }
+ return;
+ }
+
+ // Newline after the spaces (if any)
+ const lineBreak = scanLineBreak();
+ allowSimpleKey_ = true;
+
+ static bool end(Reader reader_) @safe pure
+ {
+ const prefix = reader_.prefix(3);
+ return ("---" == prefix || "..." == prefix)
+ && reader_.peek(3).among!(' ', '\t', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029');
+ }
+
+ if(end(reader_)) { return; }
+
+ bool extraBreaks;
+
+ alias Transaction = SliceBuilder.Transaction;
+ auto transaction = Transaction(&reader_.sliceBuilder);
+ if(lineBreak != '\n') { reader_.sliceBuilder.write(lineBreak); }
+ while(reader_.peek().isNSChar)
+ {
+ if(reader_.peekByte() == ' ') { reader_.forward(); }
+ else
+ {
+ const lBreak = scanLineBreak();
+ extraBreaks = true;
+ reader_.sliceBuilder.write(lBreak);
+
+ if(end(reader_)) { return; }
+ }
+ }
+ transaction.commit();
+
+ // No line breaks, only a space.
+ if(lineBreak == '\n' && !extraBreaks) { reader_.sliceBuilder.write(' '); }
+ }
+
+ /// Scan handle of a tag token.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanTagHandleToSlice(string name)(const Mark startMark)
+ {
+ dchar c = reader_.peek();
+ enum contextMsg = "While scanning a " ~ name;
+ enforce(c == '!',
+ new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark));
+
+ uint length = 1;
+ c = reader_.peek(length);
+ if(c != ' ')
+ {
+ while(c.isAlphaNum || c.among!('-', '_'))
+ {
+ ++length;
+ c = reader_.peek(length);
+ }
+ enforce(c == '!',
+ new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark));
+ ++length;
+ }
+
+ reader_.sliceBuilder.write(reader_.get(length));
+ }
+
+ /// Scan URI in a tag token.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanTagURIToSlice(string name)(const Mark startMark)
+ {
+ // Note: we do not check if URI is well-formed.
+ dchar c = reader_.peek();
+ const startLen = reader_.sliceBuilder.length;
+ {
+ uint length;
+ while(c.isAlphaNum || c.isURIChar)
+ {
+ if(c == '%')
+ {
+ auto chars = reader_.get(length);
+ reader_.sliceBuilder.write(chars);
+ length = 0;
+ scanURIEscapesToSlice!name(startMark);
+ }
+ else { ++length; }
+ c = reader_.peek(length);
+ }
+ if(length > 0)
+ {
+ auto chars = reader_.get(length);
+ reader_.sliceBuilder.write(chars);
+ length = 0;
+ }
+ }
+ // OK if we scanned something, error otherwise.
+ enum contextMsg = "While parsing a " ~ name;
+ enforce(reader_.sliceBuilder.length > startLen,
+ new ScannerException(contextMsg, startMark, expected("URI", c), reader_.mark));
+ }
+
+ // Not @nogc yet because std.utf.decode is not @nogc
+ /// Scan URI escape sequences.
+ ///
+ /// Assumes that the caller is building a slice in Reader, and puts the scanned
+ /// characters into that slice.
+ void scanURIEscapesToSlice(string name)(const Mark startMark)
+ {
+ import core.exception : UnicodeException;
+ // URI escapes encode a UTF-8 string. We store UTF-8 code units here for
+ // decoding into UTF-32.
+ Appender!string buffer;
+
+
+ enum contextMsg = "While scanning a " ~ name;
+ while(reader_.peekByte() == '%')
+ {
+ reader_.forward();
+ char[2] nextByte = [reader_.peekByte(), reader_.peekByte(1)];
+
+ enforce(nextByte[0].isHexDigit && nextByte[1].isHexDigit,
+ new ScannerException(contextMsg, startMark,
+ expected("URI escape sequence of 2 hexadecimal " ~
+ "numbers", nextByte), reader_.mark));
+
+ buffer ~= nextByte[].to!ubyte(16);
+
+ reader_.forward(2);
+ }
+ try
+ {
+ foreach (dchar chr; buffer.data)
+ {
+ reader_.sliceBuilder.write(chr);
+ }
+ }
+ catch (UnicodeException)
+ {
+ throw new ScannerException(contextMsg, startMark,
+ "Invalid UTF-8 data encoded in URI escape sequence",
+ reader_.mark);
+ }
+ }
+
+
+ /// Scan a line break, if any.
+ ///
+ /// Transforms:
+ /// '\r\n' : '\n'
+ /// '\r' : '\n'
+ /// '\n' : '\n'
+ /// '\u0085' : '\n'
+ /// '\u2028' : '\u2028'
+ /// '\u2029 : '\u2029'
+ /// no break : '\0'
+ dchar scanLineBreak() @safe
+ {
+ // Fast path for ASCII line breaks.
+ const b = reader_.peekByte();
+ if(b < 0x80)
+ {
+ if(b == '\n' || b == '\r')
+ {
+ if(reader_.prefix(2) == "\r\n") { reader_.forward(2); }
+ else { reader_.forward(); }
+ return '\n';
+ }
+ return '\0';
+ }
+
+ const c = reader_.peek();
+ if(c == '\x85')
+ {
+ reader_.forward();
+ return '\n';
+ }
+ if(c == '\u2028' || c == '\u2029')
+ {
+ reader_.forward();
+ return c;
+ }
+ return '\0';
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/serializer.d b/src/ext_depends/D-YAML/source/dyaml/serializer.d
new file mode 100644
index 0000000..4100cf3
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/serializer.d
@@ -0,0 +1,322 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/**
+ * YAML serializer.
+ * Code based on PyYAML: http://www.pyyaml.org
+ */
+module dyaml.serializer;
+
+
+import std.array;
+import std.format;
+import std.typecons;
+
+import dyaml.emitter;
+import dyaml.event;
+import dyaml.exception;
+import dyaml.node;
+import dyaml.resolver;
+import dyaml.tagdirective;
+import dyaml.token;
+
+
+package:
+
+///Serializes represented YAML nodes, generating events which are then emitted by Emitter.
+struct Serializer
+{
+ private:
+ ///Resolver used to determine which tags are automaticaly resolvable.
+ Resolver resolver_;
+
+ ///Do all document starts have to be specified explicitly?
+ Flag!"explicitStart" explicitStart_;
+ ///Do all document ends have to be specified explicitly?
+ Flag!"explicitEnd" explicitEnd_;
+ ///YAML version string.
+ string YAMLVersion_;
+
+ ///Tag directives to emit.
+ TagDirective[] tagDirectives_;
+
+ //TODO Use something with more deterministic memory usage.
+ ///Nodes with assigned anchors.
+ string[Node] anchors_;
+ ///Nodes with assigned anchors that are already serialized.
+ bool[Node] serializedNodes_;
+ ///ID of the last anchor generated.
+ uint lastAnchorID_ = 0;
+
+ public:
+ /**
+ * Construct a Serializer.
+ *
+ * Params:
+ * resolver = Resolver used to determine which tags are automaticaly resolvable.
+ * explicitStart = Do all document starts have to be specified explicitly?
+ * explicitEnd = Do all document ends have to be specified explicitly?
+ * YAMLVersion = YAML version string.
+ * tagDirectives = Tag directives to emit.
+ */
+ this(Resolver resolver,
+ const Flag!"explicitStart" explicitStart,
+ const Flag!"explicitEnd" explicitEnd, string YAMLVersion,
+ TagDirective[] tagDirectives) @safe
+ {
+ resolver_ = resolver;
+ explicitStart_ = explicitStart;
+ explicitEnd_ = explicitEnd;
+ YAMLVersion_ = YAMLVersion;
+ tagDirectives_ = tagDirectives;
+ }
+
+ ///Begin the stream.
+ void startStream(EmitterT)(ref EmitterT emitter) @safe
+ {
+ emitter.emit(streamStartEvent(Mark(), Mark()));
+ }
+
+ ///End the stream.
+ void endStream(EmitterT)(ref EmitterT emitter) @safe
+ {
+ emitter.emit(streamEndEvent(Mark(), Mark()));
+ }
+
+ ///Serialize a node, emitting it in the process.
+ void serialize(EmitterT)(ref EmitterT emitter, ref Node node) @safe
+ {
+ emitter.emit(documentStartEvent(Mark(), Mark(), explicitStart_,
+ YAMLVersion_, tagDirectives_));
+ anchorNode(node);
+ serializeNode(emitter, node);
+ emitter.emit(documentEndEvent(Mark(), Mark(), explicitEnd_));
+ serializedNodes_.destroy();
+ anchors_.destroy();
+ string[Node] emptyAnchors;
+ anchors_ = emptyAnchors;
+ lastAnchorID_ = 0;
+ }
+
+ private:
+ /**
+ * Determine if it's a good idea to add an anchor to a node.
+ *
+ * Used to prevent associating every single repeating scalar with an
+ * anchor/alias - only nodes long enough can use anchors.
+ *
+ * Params: node = Node to check for anchorability.
+ *
+ * Returns: True if the node is anchorable, false otherwise.
+ */
+ static bool anchorable(ref Node node) @safe
+ {
+ if(node.nodeID == NodeID.scalar)
+ {
+ return (node.type == NodeType.string) ? node.as!string.length > 64 :
+ (node.type == NodeType.binary) ? node.as!(ubyte[]).length > 64 :
+ false;
+ }
+ return node.length > 2;
+ }
+
+ @safe unittest
+ {
+ import std.string : representation;
+ auto shortString = "not much";
+ auto longString = "A fairly long string that would be a good idea to add an anchor to";
+ auto node1 = Node(shortString);
+ auto node2 = Node(shortString.representation.dup);
+ auto node3 = Node(longString);
+ auto node4 = Node(longString.representation.dup);
+ auto node5 = Node([node1]);
+ auto node6 = Node([node1, node2, node3, node4]);
+ assert(!anchorable(node1));
+ assert(!anchorable(node2));
+ assert(anchorable(node3));
+ assert(anchorable(node4));
+ assert(!anchorable(node5));
+ assert(anchorable(node6));
+ }
+
+ ///Add an anchor to the node if it's anchorable and not anchored yet.
+ void anchorNode(ref Node node) @safe
+ {
+ if(!anchorable(node)){return;}
+
+ if((node in anchors_) !is null)
+ {
+ if(anchors_[node] is null)
+ {
+ anchors_[node] = generateAnchor();
+ }
+ return;
+ }
+
+ anchors_.remove(node);
+ final switch (node.nodeID)
+ {
+ case NodeID.mapping:
+ foreach(ref Node key, ref Node value; node)
+ {
+ anchorNode(key);
+ anchorNode(value);
+ }
+ break;
+ case NodeID.sequence:
+ foreach(ref Node item; node)
+ {
+ anchorNode(item);
+ }
+ break;
+ case NodeID.invalid:
+ assert(0);
+ case NodeID.scalar:
+ }
+ }
+
+ ///Generate and return a new anchor.
+ string generateAnchor() @safe
+ {
+ ++lastAnchorID_;
+ auto appender = appender!string();
+ formattedWrite(appender, "id%03d", lastAnchorID_);
+ return appender.data;
+ }
+
+ ///Serialize a node and all its subnodes.
+ void serializeNode(EmitterT)(ref EmitterT emitter, ref Node node) @safe
+ {
+ //If the node has an anchor, emit an anchor (as aliasEvent) on the
+ //first occurrence, save it in serializedNodes_, and emit an alias
+ //if it reappears.
+ string aliased;
+ if(anchorable(node) && (node in anchors_) !is null)
+ {
+ aliased = anchors_[node];
+ if((node in serializedNodes_) !is null)
+ {
+ emitter.emit(aliasEvent(Mark(), Mark(), aliased));
+ return;
+ }
+ serializedNodes_[node] = true;
+ }
+ final switch (node.nodeID)
+ {
+ case NodeID.mapping:
+ const defaultTag = resolver_.defaultMappingTag;
+ const implicit = node.tag_ == defaultTag;
+ emitter.emit(mappingStartEvent(Mark(), Mark(), aliased, node.tag_,
+ implicit, node.collectionStyle));
+ foreach(ref Node key, ref Node value; node)
+ {
+ serializeNode(emitter, key);
+ serializeNode(emitter, value);
+ }
+ emitter.emit(mappingEndEvent(Mark(), Mark()));
+ return;
+ case NodeID.sequence:
+ const defaultTag = resolver_.defaultSequenceTag;
+ const implicit = node.tag_ == defaultTag;
+ emitter.emit(sequenceStartEvent(Mark(), Mark(), aliased, node.tag_,
+ implicit, node.collectionStyle));
+ foreach(ref Node item; node)
+ {
+ serializeNode(emitter, item);
+ }
+ emitter.emit(sequenceEndEvent(Mark(), Mark()));
+ return;
+ case NodeID.scalar:
+ assert(node.type == NodeType.string, "Scalar node type must be string before serialized");
+ auto value = node.as!string;
+ const detectedTag = resolver_.resolve(NodeID.scalar, null, value, true);
+ const bool isDetected = node.tag_ == detectedTag;
+
+ emitter.emit(scalarEvent(Mark(), Mark(), aliased, node.tag_,
+ isDetected, value, node.scalarStyle));
+ return;
+ case NodeID.invalid:
+ assert(0);
+ }
+ }
+}
+
+// Issue #244
+@safe unittest
+{
+ import dyaml.dumper : dumper;
+ auto node = Node([
+ Node.Pair(
+ Node(""),
+ Node([
+ Node([
+ Node.Pair(
+ Node("d"),
+ Node([
+ Node([
+ Node.Pair(
+ Node("c"),
+ Node("")
+ ),
+ Node.Pair(
+ Node("b"),
+ Node("")
+ ),
+ Node.Pair(
+ Node(""),
+ Node("")
+ )
+ ])
+ ])
+ ),
+ ]),
+ Node([
+ Node.Pair(
+ Node("d"),
+ Node([
+ Node(""),
+ Node(""),
+ Node([
+ Node.Pair(
+ Node("c"),
+ Node("")
+ ),
+ Node.Pair(
+ Node("b"),
+ Node("")
+ ),
+ Node.Pair(
+ Node(""),
+ Node("")
+ )
+ ])
+ ])
+ ),
+ Node.Pair(
+ Node("z"),
+ Node("")
+ ),
+ Node.Pair(
+ Node(""),
+ Node("")
+ )
+ ]),
+ Node("")
+ ])
+ ),
+ Node.Pair(
+ Node("g"),
+ Node("")
+ ),
+ Node.Pair(
+ Node("h"),
+ Node("")
+ ),
+ ]);
+
+ auto stream = appender!string();
+ dumper().dump(stream, node);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/style.d b/src/ext_depends/D-YAML/source/dyaml/style.d
new file mode 100644
index 0000000..319592c
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/style.d
@@ -0,0 +1,37 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+///YAML node formatting styles.
+module dyaml.style;
+
+
+///Scalar styles.
+enum ScalarStyle : ubyte
+{
+ /// Invalid (uninitialized) style
+ invalid = 0,
+ /// `|` (Literal block style)
+ literal,
+ /// `>` (Folded block style)
+ folded,
+ /// Plain scalar
+ plain,
+ /// Single quoted scalar
+ singleQuoted,
+ /// Double quoted scalar
+ doubleQuoted
+}
+
+///Collection styles.
+enum CollectionStyle : ubyte
+{
+ /// Invalid (uninitialized) style
+ invalid = 0,
+ /// Block style.
+ block,
+ /// Flow style.
+ flow
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/tagdirective.d b/src/ext_depends/D-YAML/source/dyaml/tagdirective.d
new file mode 100644
index 0000000..54687fe
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/tagdirective.d
@@ -0,0 +1,15 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+///Tag directives.
+module dyaml.tagdirective;
+
+///Single tag directive. handle is the shortcut, prefix is the prefix that replaces it.
+struct TagDirective
+{
+ string handle;
+ string prefix;
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/common.d b/src/ext_depends/D-YAML/source/dyaml/test/common.d
new file mode 100644
index 0000000..a6bafa9
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/common.d
@@ -0,0 +1,223 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.common;
+
+version(unittest)
+{
+
+import dyaml.node;
+import dyaml.event;
+
+import core.exception;
+import std.algorithm;
+import std.array;
+import std.conv;
+import std.file;
+import std.range;
+import std.path;
+import std.traits;
+import std.typecons;
+
+package:
+
+/**
+Run a test.
+
+Params:
+ testFunction = Unittest function.
+ unittestExt = Extensions of data files needed for the unittest.
+ skipExt = Extensions that must not be used for the unittest.
+ */
+void run(D)(D testFunction, string[] unittestExt, string[] skipExt = [])
+{
+ immutable string dataDir = __FILE_FULL_PATH__.dirName ~ "/../../../test/data";
+ auto testFilenames = findTestFilenames(dataDir);
+
+ if (unittestExt.length > 0)
+ {
+ outer: foreach (base, extensions; testFilenames)
+ {
+ string[] filenames;
+ foreach (ext; unittestExt)
+ {
+ if (!extensions.canFind(ext))
+ {
+ continue outer;
+ }
+ filenames ~= base ~ '.' ~ ext;
+ }
+ foreach (ext; skipExt)
+ {
+ if (extensions.canFind(ext))
+ {
+ continue outer;
+ }
+ }
+
+ execute(testFunction, filenames);
+ }
+ }
+ else
+ {
+ execute(testFunction, string[].init);
+ }
+}
+
+// TODO: remove when a @safe ubyte[] file read can be done.
+/**
+Reads a file as an array of bytes.
+
+Params:
+ filename = Full path to file to read.
+
+Returns: The file's data.
+*/
+ubyte[] readData(string filename) @trusted
+{
+ import std.file : read;
+ return cast(ubyte[])read(filename);
+}
+void assertNodesEqual(const scope Node gotNode, const scope Node expectedNode) @safe
+{
+ import std.format : format;
+ assert(gotNode == expectedNode, format!"got %s, expected %s"(gotNode.debugString, expectedNode.debugString));
+}
+
+/**
+Determine if events in events1 are equivalent to events in events2.
+
+Params:
+ events1 = A range of events to compare with.
+ events2 = A second range of events to compare.
+
+Returns: true if the events are equivalent, false otherwise.
+*/
+bool compareEvents(T, U)(T events1, U events2)
+if (isInputRange!T && isInputRange!U && is(ElementType!T == Event) && is(ElementType!U == Event))
+{
+ foreach (e1, e2; zip(events1, events2))
+ {
+ //Different event types.
+ if (e1.id != e2.id)
+ {
+ return false;
+ }
+ //Different anchor (if applicable).
+ if (e1.id.among!(EventID.sequenceStart, EventID.mappingStart, EventID.alias_, EventID.scalar)
+ && e1.anchor != e2.anchor)
+ {
+ return false;
+ }
+ //Different collection tag (if applicable).
+ if (e1.id.among!(EventID.sequenceStart, EventID.mappingStart) && e1.tag != e2.tag)
+ {
+ return false;
+ }
+ if (e1.id == EventID.scalar)
+ {
+ //Different scalar tag (if applicable).
+ if (!(e1.implicit || e2.implicit) && e1.tag != e2.tag)
+ {
+ return false;
+ }
+ //Different scalar value.
+ if (e1.value != e2.value)
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+/**
+Throw an Error if events in events1 aren't equivalent to events in events2.
+
+Params:
+ events1 = First event array to compare.
+ events2 = Second event array to compare.
+*/
+void assertEventsEqual(T, U)(T events1, U events2)
+if (isInputRange!T && isInputRange!U && is(ElementType!T == Event) && is(ElementType!U == Event))
+{
+ auto events1Copy = events1.array;
+ auto events2Copy = events2.array;
+ assert(compareEvents(events1Copy, events2Copy), text("Got '", events1Copy, "', expected '", events2Copy, "'"));
+}
+
+private:
+
+/**
+Find unittest input filenames.
+
+Params: dir = Directory to look in.
+
+Returns: Test input base filenames and their extensions.
+*/
+ //@trusted due to dirEntries
+string[][string] findTestFilenames(const string dir) @trusted
+{
+ //Groups of extensions indexed by base names.
+ string[][string] names;
+ foreach (string name; dirEntries(dir, SpanMode.shallow))
+ {
+ if (isFile(name))
+ {
+ string base = name.stripExtension();
+ string ext = name.extension();
+ if (ext is null)
+ {
+ ext = "";
+ }
+ if (ext[0] == '.')
+ {
+ ext = ext[1 .. $];
+ }
+
+ //If the base name doesn't exist yet, add it; otherwise add new extension.
+ names[base] = ((base in names) is null) ? [ext] : names[base] ~ ext;
+ }
+ }
+ return names;
+}
+
+/**
+Recursively copy an array of strings to a tuple to use for unittest function input.
+
+Params:
+ index = Current index in the array/tuple.
+ tuple = Tuple to copy to.
+ strings = Strings to copy.
+*/
+void stringsToTuple(uint index, F ...)(ref F tuple, const string[] strings)
+in(F.length == strings.length)
+do
+{
+ tuple[index] = strings[index];
+ static if (index > 0)
+ {
+ stringsToTuple!(index - 1, F)(tuple, strings);
+ }
+}
+
+/**
+Execute an unittest on specified files.
+
+Params:
+ testName = Name of the unittest.
+ testFunction = Unittest function.
+ filenames = Names of input files to test with.
+ */
+void execute(D)(D testFunction, string[] filenames)
+{
+ //Convert filenames to parameters tuple and call the test function.
+ alias F = Parameters!D[0..$];
+ F parameters;
+ stringsToTuple!(F.length - 1, F)(parameters, filenames);
+ testFunction(parameters);
+}
+
+} // version(unittest)
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/compare.d b/src/ext_depends/D-YAML/source/dyaml/test/compare.d
new file mode 100644
index 0000000..5a37fd0
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/compare.d
@@ -0,0 +1,51 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.compare;
+
+@safe unittest
+{
+ import dyaml : Loader;
+ import dyaml.test.common : assertNodesEqual, compareEvents, run;
+
+ /**
+ Test parser by comparing output from parsing two equivalent YAML files.
+
+ Params:
+ dataFilename = YAML file to parse.
+ canonicalFilename = Another file to parse, in canonical YAML format.
+ */
+ static void testParser(string dataFilename, string canonicalFilename) @safe
+ {
+ auto dataEvents = Loader.fromFile(dataFilename).parse();
+ auto canonicalEvents = Loader.fromFile(canonicalFilename).parse();
+
+ //BUG: the return value isn't checked! This test currently fails...
+ compareEvents(dataEvents, canonicalEvents);
+ }
+
+ /**
+ Test loader by comparing output from loading two equivalent YAML files.
+
+ Params:
+ dataFilename = YAML file to load.
+ canonicalFilename = Another file to load, in canonical YAML format.
+ */
+ static void testLoader(string dataFilename, string canonicalFilename) @safe
+ {
+ import std.array : array;
+ auto data = Loader.fromFile(dataFilename).array;
+ auto canonical = Loader.fromFile(canonicalFilename).array;
+
+ assert(data.length == canonical.length, "Unequal node count");
+ foreach (n; 0 .. data.length)
+ {
+ assertNodesEqual(data[n], canonical[n]);
+ }
+ }
+ run(&testParser, ["data", "canonical"]);
+ run(&testLoader, ["data", "canonical"], ["test_loader_skip"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/constructor.d b/src/ext_depends/D-YAML/source/dyaml/test/constructor.d
new file mode 100644
index 0000000..aeb8653
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/constructor.d
@@ -0,0 +1,957 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.constructor;
+
+
+version(unittest)
+{
+
+import std.conv;
+import std.datetime;
+import std.exception;
+import std.path;
+import std.string;
+import std.typecons;
+
+import dyaml : Loader, Node, YAMLNull;
+
+///Expected results of loading test inputs.
+Node[][string] expected;
+
+///Initialize expected.
+static this() @safe
+{
+ expected["aliases-cdumper-bug"] = constructAliasesCDumperBug();
+ expected["construct-binary"] = constructBinary();
+ expected["construct-bool"] = constructBool();
+ expected["construct-custom"] = constructCustom();
+ expected["construct-float"] = constructFloat();
+ expected["construct-int"] = constructInt();
+ expected["construct-map"] = constructMap();
+ expected["construct-merge"] = constructMerge();
+ expected["construct-null"] = constructNull();
+ expected["construct-omap"] = constructOMap();
+ expected["construct-pairs"] = constructPairs();
+ expected["construct-seq"] = constructSeq();
+ expected["construct-set"] = constructSet();
+ expected["construct-str-ascii"] = constructStrASCII();
+ expected["construct-str"] = constructStr();
+ expected["construct-str-utf8"] = constructStrUTF8();
+ expected["construct-timestamp"] = constructTimestamp();
+ expected["construct-value"] = constructValue();
+ expected["duplicate-merge-key"] = duplicateMergeKey();
+ expected["float-representer-2.3-bug"] = floatRepresenterBug();
+ expected["invalid-single-quote-bug"] = invalidSingleQuoteBug();
+ expected["more-floats"] = moreFloats();
+ expected["negative-float-bug"] = negativeFloatBug();
+ expected["single-dot-is-not-float-bug"] = singleDotFloatBug();
+ expected["timestamp-bugs"] = timestampBugs();
+ expected["utf16be"] = utf16be();
+ expected["utf16le"] = utf16le();
+ expected["utf8"] = utf8();
+ expected["utf8-implicit"] = utf8implicit();
+}
+
+///Construct a pair of nodes with specified values.
+Node.Pair pair(A, B)(A a, B b)
+{
+ return Node.Pair(a,b);
+}
+
+///Test cases:
+
+Node[] constructAliasesCDumperBug() @safe
+{
+ return [
+ Node(
+ [
+ Node("today", "tag:yaml.org,2002:str"),
+ Node("today", "tag:yaml.org,2002:str")
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] constructBinary() @safe
+{
+ auto canonical = "GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;".representation.dup;
+ auto generic = "GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;".representation.dup;
+ auto description = "The binary value above is a tiny arrow encoded as a gif image.";
+
+ return [
+ Node(
+ [
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(canonical, "tag:yaml.org,2002:binary")
+ ),
+ pair(
+ Node("generic", "tag:yaml.org,2002:str"),
+ Node(generic, "tag:yaml.org,2002:binary")
+ ),
+ pair(
+ Node("description", "tag:yaml.org,2002:str"),
+ Node(description, "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructBool() @safe
+{
+ const(bool) a = true;
+ immutable(bool) b = true;
+ const bool aa = true;
+ immutable bool bb = true;
+ return [
+ Node(
+ [
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(true, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("answer", "tag:yaml.org,2002:str"),
+ Node(false, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("logical", "tag:yaml.org,2002:str"),
+ Node(true, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("option", "tag:yaml.org,2002:str"),
+ Node(true, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("constbool", "tag:yaml.org,2002:str"),
+ Node(a, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("imutbool", "tag:yaml.org,2002:str"),
+ Node(b, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("const_bool", "tag:yaml.org,2002:str"),
+ Node(aa, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("imut_bool", "tag:yaml.org,2002:str"),
+ Node(bb, "tag:yaml.org,2002:bool")
+ ),
+ pair(
+ Node("but", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node("is a string", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("n", "tag:yaml.org,2002:str"),
+ Node("is a string", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructCustom() @safe
+{
+ return [
+ Node(
+ [
+ Node(new TestClass(1, 2, 3)),
+ Node(TestStruct(10))
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] constructFloat() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(685230.15L, "tag:yaml.org,2002:float")
+ ),
+ pair(
+ Node("exponential", "tag:yaml.org,2002:str"),
+ Node(685230.15L, "tag:yaml.org,2002:float")
+ ),
+ pair(
+ Node("fixed", "tag:yaml.org,2002:str"),
+ Node(685230.15L, "tag:yaml.org,2002:float")
+ ),
+ pair(
+ Node("sexagesimal", "tag:yaml.org,2002:str"),
+ Node(685230.15L, "tag:yaml.org,2002:float")
+ ),
+ pair(
+ Node("negative infinity", "tag:yaml.org,2002:str"),
+ Node(-real.infinity, "tag:yaml.org,2002:float")
+ ),
+ pair(
+ Node("not a number", "tag:yaml.org,2002:str"),
+ Node(real.nan, "tag:yaml.org,2002:float")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructInt() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("decimal", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("octal", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("hexadecimal", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("binary", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("sexagesimal", "tag:yaml.org,2002:str"),
+ Node(685230L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructMap() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("Block style", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(
+ Node("Clark", "tag:yaml.org,2002:str"),
+ Node("Evans", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("Brian", "tag:yaml.org,2002:str"),
+ Node("Ingerson", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("Oren", "tag:yaml.org,2002:str"),
+ Node("Ben-Kiki", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ),
+ pair(
+ Node("Flow style", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(
+ Node("Clark", "tag:yaml.org,2002:str"),
+ Node("Evans", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("Brian", "tag:yaml.org,2002:str"),
+ Node("Ingerson", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("Oren", "tag:yaml.org,2002:str"),
+ Node("Ben-Kiki", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructMerge() @safe
+{
+ return [
+ Node(
+ [
+ Node(
+ [
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(0L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(10L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(10L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("label", "tag:yaml.org,2002:str"),
+ Node("center/big", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(10L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("label", "tag:yaml.org,2002:str"),
+ Node("center/big", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("label", "tag:yaml.org,2002:str"),
+ Node("center/big", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(10L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("label", "tag:yaml.org,2002:str"),
+ Node("center/big", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("r", "tag:yaml.org,2002:str"),
+ Node(10L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] constructNull() @safe
+{
+ return [
+ Node(YAMLNull(), "tag:yaml.org,2002:null"),
+ Node(
+ [
+ pair(
+ Node("empty", "tag:yaml.org,2002:str"),
+ Node(YAMLNull(), "tag:yaml.org,2002:null")
+ ),
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(YAMLNull(), "tag:yaml.org,2002:null")
+ ),
+ pair(
+ Node("english", "tag:yaml.org,2002:str"),
+ Node(YAMLNull(), "tag:yaml.org,2002:null")
+ ),
+ pair(
+ Node(YAMLNull(), "tag:yaml.org,2002:null"),
+ Node("null key", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("sparse", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ Node(YAMLNull(), "tag:yaml.org,2002:null"),
+ Node("2nd entry", "tag:yaml.org,2002:str"),
+ Node(YAMLNull(), "tag:yaml.org,2002:null"),
+ Node("4th entry", "tag:yaml.org,2002:str"),
+ Node(YAMLNull(), "tag:yaml.org,2002:null")
+ ],
+ "tag:yaml.org,2002:seq")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructOMap() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("Bestiary", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(
+ Node("aardvark", "tag:yaml.org,2002:str"),
+ Node("African pig-like ant eater. Ugly.", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("anteater", "tag:yaml.org,2002:str"),
+ Node("South-American ant eater. Two species.", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("anaconda", "tag:yaml.org,2002:str"),
+ Node("South-American constrictor snake. Scaly.", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:omap")
+ ),
+ pair(
+ Node("Numbers", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(
+ Node("one", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("two", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("three", "tag:yaml.org,2002:str"),
+ Node(3L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:omap")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructPairs() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("Block tasks", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(Node("meeting", "tag:yaml.org,2002:str"), Node("with team.", "tag:yaml.org,2002:str")),
+ pair(Node("meeting", "tag:yaml.org,2002:str"), Node("with boss.", "tag:yaml.org,2002:str")),
+ pair(Node("break", "tag:yaml.org,2002:str"), Node("lunch.", "tag:yaml.org,2002:str")),
+ pair(Node("meeting", "tag:yaml.org,2002:str"), Node("with client.", "tag:yaml.org,2002:str"))
+ ],
+ "tag:yaml.org,2002:pairs")
+ ),
+ pair(
+ Node("Flow tasks", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ pair(Node("meeting", "tag:yaml.org,2002:str"), Node("with team", "tag:yaml.org,2002:str")),
+ pair(Node("meeting", "tag:yaml.org,2002:str"), Node("with boss", "tag:yaml.org,2002:str"))
+ ],
+ "tag:yaml.org,2002:pairs")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructSeq() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("Block style", "tag:yaml.org,2002:str"),
+ Node([
+ Node("Mercury", "tag:yaml.org,2002:str"),
+ Node("Venus", "tag:yaml.org,2002:str"),
+ Node("Earth", "tag:yaml.org,2002:str"),
+ Node("Mars", "tag:yaml.org,2002:str"),
+ Node("Jupiter", "tag:yaml.org,2002:str"),
+ Node("Saturn", "tag:yaml.org,2002:str"),
+ Node("Uranus", "tag:yaml.org,2002:str"),
+ Node("Neptune", "tag:yaml.org,2002:str"),
+ Node("Pluto", "tag:yaml.org,2002:str")
+ ], "tag:yaml.org,2002:seq")
+ ),
+ pair(
+ Node("Flow style", "tag:yaml.org,2002:str"),
+ Node([
+ Node("Mercury", "tag:yaml.org,2002:str"),
+ Node("Venus", "tag:yaml.org,2002:str"),
+ Node("Earth", "tag:yaml.org,2002:str"),
+ Node("Mars", "tag:yaml.org,2002:str"),
+ Node("Jupiter", "tag:yaml.org,2002:str"),
+ Node("Saturn", "tag:yaml.org,2002:str"),
+ Node("Uranus", "tag:yaml.org,2002:str"),
+ Node("Neptune", "tag:yaml.org,2002:str"),
+ Node("Pluto", "tag:yaml.org,2002:str")
+ ], "tag:yaml.org,2002:seq")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructSet() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("baseball players", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ Node("Mark McGwire", "tag:yaml.org,2002:str"),
+ Node("Sammy Sosa", "tag:yaml.org,2002:str"),
+ Node("Ken Griffey", "tag:yaml.org,2002:str")
+ ],
+ "tag:yaml.org,2002:set")
+ ),
+ pair(
+ Node("baseball teams", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ Node("Boston Red Sox", "tag:yaml.org,2002:str"),
+ Node("Detroit Tigers", "tag:yaml.org,2002:str"),
+ Node("New York Yankees", "tag:yaml.org,2002:str")
+ ],
+ "tag:yaml.org,2002:set")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructStrASCII() @safe
+{
+ return [
+ Node("ascii string", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] constructStr() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("string", "tag:yaml.org,2002:str"),
+ Node("abcd", "tag:yaml.org,2002:str")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructStrUTF8() @safe
+{
+ return [
+ Node("\u042d\u0442\u043e \u0443\u043d\u0438\u043a\u043e\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] constructTimestamp() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("canonical", "tag:yaml.org,2002:str"),
+ Node(SysTime(DateTime(2001, 12, 15, 2, 59, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp")
+ ),
+ pair(
+ Node("valid iso8601", "tag:yaml.org,2002:str"),
+ Node(SysTime(DateTime(2001, 12, 15, 2, 59, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp")
+ ),
+ pair(
+ Node("space separated", "tag:yaml.org,2002:str"),
+ Node(SysTime(DateTime(2001, 12, 15, 2, 59, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp")
+ ),
+ pair(
+ Node("no time zone (Z)", "tag:yaml.org,2002:str"),
+ Node(SysTime(DateTime(2001, 12, 15, 2, 59, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp")
+ ),
+ pair(
+ Node("date (00:00:00Z)", "tag:yaml.org,2002:str"),
+ Node(SysTime(DateTime(2002, 12, 14), UTC()), "tag:yaml.org,2002:timestamp")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] constructValue() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("link with", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ Node("library1.dll", "tag:yaml.org,2002:str"),
+ Node("library2.dll", "tag:yaml.org,2002:str")
+ ],
+ "tag:yaml.org,2002:seq")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("link with", "tag:yaml.org,2002:str"),
+ Node(
+ [
+ Node(
+ [
+ pair(
+ Node("=", "tag:yaml.org,2002:value"),
+ Node("library1.dll", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("version", "tag:yaml.org,2002:str"),
+ Node(1.2L, "tag:yaml.org,2002:float")
+ )
+ ],
+ "tag:yaml.org,2002:map"),
+ Node(
+ [
+ pair(
+ Node("=", "tag:yaml.org,2002:value"),
+ Node("library2.dll", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("version", "tag:yaml.org,2002:str"),
+ Node(2.3L, "tag:yaml.org,2002:float")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ],
+ "tag:yaml.org,2002:seq")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] duplicateMergeKey() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node("foo", "tag:yaml.org,2002:str"),
+ Node("bar", "tag:yaml.org,2002:str")
+ ),
+ pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(2L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("z", "tag:yaml.org,2002:str"),
+ Node(3L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node("t", "tag:yaml.org,2002:str"),
+ Node(4L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] floatRepresenterBug() @safe
+{
+ return [
+ Node(
+ [
+ pair(
+ Node(1.0L, "tag:yaml.org,2002:float"),
+ Node(1L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node(real.infinity, "tag:yaml.org,2002:float"),
+ Node(10L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node(-real.infinity, "tag:yaml.org,2002:float"),
+ Node(-10L, "tag:yaml.org,2002:int")
+ ),
+ pair(
+ Node(real.nan, "tag:yaml.org,2002:float"),
+ Node(100L, "tag:yaml.org,2002:int")
+ )
+ ],
+ "tag:yaml.org,2002:map")
+ ];
+}
+
+Node[] invalidSingleQuoteBug() @safe
+{
+ return [
+ Node(
+ [
+ Node("foo \'bar\'", "tag:yaml.org,2002:str"),
+ Node("foo\n\'bar\'", "tag:yaml.org,2002:str")
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] moreFloats() @safe
+{
+ return [
+ Node(
+ [
+ Node(0.0L, "tag:yaml.org,2002:float"),
+ Node(1.0L, "tag:yaml.org,2002:float"),
+ Node(-1.0L, "tag:yaml.org,2002:float"),
+ Node(real.infinity, "tag:yaml.org,2002:float"),
+ Node(-real.infinity, "tag:yaml.org,2002:float"),
+ Node(real.nan, "tag:yaml.org,2002:float"),
+ Node(real.nan, "tag:yaml.org,2002:float")
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] negativeFloatBug() @safe
+{
+ return [
+ Node(-1.0L, "tag:yaml.org,2002:float")
+ ];
+}
+
+Node[] singleDotFloatBug() @safe
+{
+ return [
+ Node(".", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] timestampBugs() @safe
+{
+ return [
+ Node(
+ [
+ Node(SysTime(DateTime(2001, 12, 15, 3, 29, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp"),
+ Node(SysTime(DateTime(2001, 12, 14, 16, 29, 43), 1000000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp"),
+ Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), 10100.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp"),
+ Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new immutable SimpleTimeZone(60.dur!"minutes")), "tag:yaml.org,2002:timestamp"),
+ Node(SysTime(DateTime(2001, 12, 14, 21, 59, 43), new immutable SimpleTimeZone(-90.dur!"minutes")), "tag:yaml.org,2002:timestamp"),
+ Node(SysTime(DateTime(2005, 7, 8, 17, 35, 4), 5176000.dur!"hnsecs", UTC()), "tag:yaml.org,2002:timestamp")
+ ],
+ "tag:yaml.org,2002:seq")
+ ];
+}
+
+Node[] utf16be() @safe
+{
+ return [
+ Node("UTF-16-BE", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] utf16le() @safe
+{
+ return [
+ Node("UTF-16-LE", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] utf8() @safe
+{
+ return [
+ Node("UTF-8", "tag:yaml.org,2002:str")
+ ];
+}
+
+Node[] utf8implicit() @safe
+{
+ return [
+ Node("implicit UTF-8", "tag:yaml.org,2002:str")
+ ];
+}
+
+///Testing custom YAML class type.
+class TestClass
+{
+ int x, y, z;
+
+ this(int x, int y, int z) @safe
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ Node opCast(T: Node)() @safe
+ {
+ return Node(
+ [
+ Node.Pair(
+ Node("x", "tag:yaml.org,2002:str"),
+ Node(x, "tag:yaml.org,2002:int")
+ ),
+ Node.Pair(
+ Node("y", "tag:yaml.org,2002:str"),
+ Node(y, "tag:yaml.org,2002:int")
+ ),
+ Node.Pair(
+ Node("z", "tag:yaml.org,2002:str"),
+ Node(z, "tag:yaml.org,2002:int")
+ )
+ ],
+ "!tag1");
+ }
+}
+
+///Testing custom YAML struct type.
+struct TestStruct
+{
+ int value;
+
+ this (int x) @safe
+ {
+ value = x;
+ }
+
+ ///Constructor function for TestStruct.
+ this(ref Node node) @safe
+ {
+ value = node.as!string.to!int;
+ }
+
+ ///Representer function for TestStruct.
+ Node opCast(T: Node)() @safe
+ {
+ return Node(value.to!string, "!tag2");
+ }
+}
+
+} // version(unittest)
+
+
+@safe unittest
+{
+ import dyaml.test.common : assertNodesEqual, run;
+ /**
+ Constructor unittest.
+
+ Params:
+ dataFilename = File name to read from.
+ codeDummy = Dummy .code filename, used to determine that
+ .data file with the same name should be used in this test.
+ */
+ static void testConstructor(string dataFilename, string codeDummy) @safe
+ {
+ string base = dataFilename.baseName.stripExtension;
+ assert((base in expected) !is null, "Unimplemented constructor test: " ~ base);
+
+ auto loader = Loader.fromFile(dataFilename);
+
+ Node[] exp = expected[base];
+
+ //Compare with expected results document by document.
+ size_t i;
+ foreach (node; loader)
+ {
+ assertNodesEqual(node, exp[i]);
+ ++i;
+ }
+ assert(i == exp.length);
+ }
+ run(&testConstructor, ["data", "code"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/emitter.d b/src/ext_depends/D-YAML/source/dyaml/test/emitter.d
new file mode 100644
index 0000000..293f236
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/emitter.d
@@ -0,0 +1,132 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.emitter;
+
+@safe unittest
+{
+ import std.array : Appender;
+ import std.range : ElementType, isInputRange;
+
+ import dyaml : CollectionStyle, LineBreak, Loader, Mark, ScalarStyle;
+ import dyaml.emitter : Emitter;
+ import dyaml.event : Event, EventID, mappingStartEvent, scalarEvent, sequenceStartEvent;
+ import dyaml.test.common : assertEventsEqual, run;
+
+ // Try to emit an event range.
+ static void emitTestCommon(T)(ref Appender!string emitStream, T events, bool canonical = false) @safe
+ if (isInputRange!T && is(ElementType!T == Event))
+ {
+ auto emitter = Emitter!(typeof(emitStream), char)(emitStream, canonical, 2, 80, LineBreak.unix);
+ foreach (ref event; events)
+ {
+ emitter.emit(event);
+ }
+ }
+ /**
+ Test emitter by getting events from parsing a file, emitting them, parsing
+ the emitted result and comparing events from parsing the emitted result with
+ originally parsed events.
+
+ Params:
+ dataFilename = YAML file to parse.
+ canonicalFilename = Canonical YAML file used as dummy to determine
+ which data files to load.
+ */
+ static void testEmitterOnData(string dataFilename, string canonicalFilename) @safe
+ {
+ //Must exist due to Anchor, Tags reference counts.
+ auto loader = Loader.fromFile(dataFilename);
+ auto events = loader.parse();
+ auto emitStream = Appender!string();
+ emitTestCommon(emitStream, events);
+
+ auto loader2 = Loader.fromString(emitStream.data);
+ loader2.name = "TEST";
+ auto newEvents = loader2.parse();
+ assertEventsEqual(events, newEvents);
+ }
+ /**
+ Test emitter by getting events from parsing a canonical YAML file, emitting
+ them both in canonical and normal format, parsing the emitted results and
+ comparing events from parsing the emitted result with originally parsed events.
+
+ Params: canonicalFilename = Canonical YAML file to parse.
+ */
+ static void testEmitterOnCanonical(string canonicalFilename) @safe
+ {
+ //Must exist due to Anchor, Tags reference counts.
+ auto loader = Loader.fromFile(canonicalFilename);
+ auto events = loader.parse();
+ foreach (canonical; [false, true])
+ {
+ auto emitStream = Appender!string();
+ emitTestCommon(emitStream, events, canonical);
+
+ auto loader2 = Loader.fromString(emitStream.data);
+ loader2.name = "TEST";
+ auto newEvents = loader2.parse();
+ assertEventsEqual(events, newEvents);
+ }
+ }
+ /**
+ Test emitter by getting events from parsing a file, emitting them with all
+ possible scalar and collection styles, parsing the emitted results and
+ comparing events from parsing the emitted result with originally parsed events.
+
+ Params:
+ dataFilename = YAML file to parse.
+ canonicalFilename = Canonical YAML file used as dummy to determine
+ which data files to load.
+ */
+ static void testEmitterStyles(string dataFilename, string canonicalFilename) @safe
+ {
+ foreach (filename; [dataFilename, canonicalFilename])
+ {
+ //must exist due to Anchor, Tags reference counts
+ auto loader = Loader.fromFile(canonicalFilename);
+ auto events = loader.parse();
+ foreach (flowStyle; [CollectionStyle.block, CollectionStyle.flow])
+ {
+ foreach (style; [ScalarStyle.literal, ScalarStyle.folded,
+ ScalarStyle.doubleQuoted, ScalarStyle.singleQuoted,
+ ScalarStyle.plain])
+ {
+ Event[] styledEvents;
+ foreach (event; events)
+ {
+ if (event.id == EventID.scalar)
+ {
+ event = scalarEvent(Mark(), Mark(), event.anchor, event.tag,
+ event.implicit,
+ event.value, style);
+ }
+ else if (event.id == EventID.sequenceStart)
+ {
+ event = sequenceStartEvent(Mark(), Mark(), event.anchor,
+ event.tag, event.implicit, flowStyle);
+ }
+ else if (event.id == EventID.mappingStart)
+ {
+ event = mappingStartEvent(Mark(), Mark(), event.anchor,
+ event.tag, event.implicit, flowStyle);
+ }
+ styledEvents ~= event;
+ }
+ auto emitStream = Appender!string();
+ emitTestCommon(emitStream, styledEvents);
+ auto loader2 = Loader.fromString(emitStream.data);
+ loader2.name = "TEST";
+ auto newEvents = loader2.parse();
+ assertEventsEqual(events, newEvents);
+ }
+ }
+ }
+ }
+ run(&testEmitterOnData, ["data", "canonical"]);
+ run(&testEmitterOnCanonical, ["canonical"]);
+ run(&testEmitterStyles, ["data", "canonical"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/errors.d b/src/ext_depends/D-YAML/source/dyaml/test/errors.d
new file mode 100644
index 0000000..43b019c
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/errors.d
@@ -0,0 +1,64 @@
+
+// Copyright Ferdinand Majerech 2011-2014
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.errors;
+
+@safe unittest
+{
+ import std.array : array;
+ import std.exception : assertThrown;
+
+ import dyaml : Loader;
+ import dyaml.test.common : run;
+
+ /**
+ Loader error unittest from file stream.
+
+ Params: errorFilename = File name to read from.
+ */
+ static void testLoaderError(string errorFilename) @safe
+ {
+ assertThrown(Loader.fromFile(errorFilename).array,
+ __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
+ }
+
+ /**
+ Loader error unittest from string.
+
+ Params: errorFilename = File name to read from.
+ */
+ static void testLoaderErrorString(string errorFilename) @safe
+ {
+ assertThrown(Loader.fromFile(errorFilename).array,
+ __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
+ }
+
+ /**
+ Loader error unittest from filename.
+
+ Params: errorFilename = File name to read from.
+ */
+ static void testLoaderErrorFilename(string errorFilename) @safe
+ {
+ assertThrown(Loader.fromFile(errorFilename).array,
+ __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
+ }
+
+ /**
+ Loader error unittest loading a single document from a file.
+
+ Params: errorFilename = File name to read from.
+ */
+ static void testLoaderErrorSingle(string errorFilename) @safe
+ {
+ assertThrown(Loader.fromFile(errorFilename).load(),
+ __FUNCTION__ ~ "(" ~ errorFilename ~ ") Expected an exception");
+ }
+ run(&testLoaderError, ["loader-error"]);
+ run(&testLoaderErrorString, ["loader-error"]);
+ run(&testLoaderErrorFilename, ["loader-error"]);
+ run(&testLoaderErrorSingle, ["single-loader-error"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d b/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d
new file mode 100644
index 0000000..758def8
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/inputoutput.d
@@ -0,0 +1,92 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.inputoutput;
+
+@safe unittest
+{
+ import std.array : join, split;
+ import std.conv : to;
+ import std.exception : assertThrown;
+ import std.file : readText;
+ import std.system : endian, Endian;
+
+ import dyaml : Loader, Node, YAMLException;
+ import dyaml.test.common : run;
+
+ /**
+ Get an UTF-16 byte order mark.
+
+ Params: wrong = Get the incorrect BOM for this system.
+
+ Returns: UTF-16 byte order mark.
+ */
+ static wchar bom16(bool wrong = false) pure @safe
+ {
+ wchar little = '\uFEFF';
+ wchar big = '\uFFFE';
+ if (!wrong)
+ {
+ return endian == Endian.littleEndian ? little : big;
+ }
+ return endian == Endian.littleEndian ? big : little;
+ }
+ /**
+ Get an UTF-32 byte order mark.
+
+ Params: wrong = Get the incorrect BOM for this system.
+
+ Returns: UTF-32 byte order mark.
+ */
+ static dchar bom32(bool wrong = false) pure @safe
+ {
+ dchar little = '\uFEFF';
+ dchar big = '\uFFFE';
+ if (!wrong)
+ {
+ return endian == Endian.littleEndian ? little : big;
+ }
+ return endian == Endian.littleEndian ? big : little;
+ }
+ /**
+ Unicode input unittest. Tests various encodings.
+
+ Params: unicodeFilename = File name to read from.
+ */
+ static void testUnicodeInput(string unicodeFilename) @safe
+ {
+ string data = readText(unicodeFilename);
+ string expected = data.split().join(" ");
+
+ Node output = Loader.fromString(data).load();
+ assert(output.as!string == expected);
+
+ foreach (buffer; [cast(ubyte[]) (bom16() ~ data.to!(wchar[])),
+ cast(ubyte[]) (bom32() ~ data.to!(dchar[]))])
+ {
+ output = Loader.fromBuffer(buffer).load();
+ assert(output.as!string == expected);
+ }
+ }
+ /**
+ Unicode input error unittest. Tests various encodings with incorrect BOMs.
+
+ Params: unicodeFilename = File name to read from.
+ */
+ static void testUnicodeInputErrors(string unicodeFilename) @safe
+ {
+ string data = readText(unicodeFilename);
+ foreach (buffer; [cast(ubyte[]) (data.to!(wchar[])),
+ cast(ubyte[]) (data.to!(dchar[])),
+ cast(ubyte[]) (bom16(true) ~ data.to!(wchar[])),
+ cast(ubyte[]) (bom32(true) ~ data.to!(dchar[]))])
+ {
+ assertThrown(Loader.fromBuffer(buffer).load());
+ }
+ }
+ run(&testUnicodeInput, ["unicode"]);
+ run(&testUnicodeInputErrors, ["unicode"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/reader.d b/src/ext_depends/D-YAML/source/dyaml/test/reader.d
new file mode 100644
index 0000000..c20df6f
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/reader.d
@@ -0,0 +1,37 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.reader;
+
+@safe unittest
+{
+ import std.exception :assertThrown;
+
+ import dyaml.test.common : readData, run;
+ import dyaml.reader : Reader, ReaderException;
+
+ /**
+ Try reading entire file through Reader, expecting an error (the file is invalid).
+
+ Params: data = Stream to read.
+ */
+ static void runReader(ubyte[] fileData) @safe
+ {
+ auto reader = new Reader(fileData);
+ while(reader.peek() != '\0') { reader.forward(); }
+ }
+
+ /**
+ Stream error unittest. Tries to read invalid input files, expecting errors.
+
+ Params: errorFilename = File name to read from.
+ */
+ static void testStreamError(string errorFilename) @safe
+ {
+ assertThrown!ReaderException(runReader(readData(errorFilename)));
+ }
+ run(&testStreamError, ["stream-error"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/representer.d b/src/ext_depends/D-YAML/source/dyaml/test/representer.d
new file mode 100644
index 0000000..4a1ae67
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/representer.d
@@ -0,0 +1,54 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.representer;
+
+@safe unittest
+{
+ import std.array : Appender, array;
+ import std.meta : AliasSeq;
+ import std.path : baseName, stripExtension;
+ import std.utf : toUTF8;
+
+ import dyaml : dumper, Loader, Node;
+ import dyaml.test.common : assertNodesEqual, run;
+ import dyaml.test.constructor : expected;
+
+ /**
+ Representer unittest. Dumps nodes, then loads them again.
+
+ Params:
+ baseName = Nodes in dyaml.test.constructor.expected for roundtripping.
+ */
+ static void testRepresenterTypes(string baseName) @safe
+ {
+ assert((baseName in expected) !is null, "Unimplemented representer test: " ~ baseName);
+
+ Node[] expectedNodes = expected[baseName];
+ foreach (encoding; AliasSeq!(char, wchar, dchar))
+ {
+ auto emitStream = new Appender!(immutable(encoding)[]);
+ auto dumper = dumper();
+ dumper.dump!encoding(emitStream, expectedNodes);
+
+ immutable output = emitStream.data;
+
+ auto loader = Loader.fromString(emitStream.data.toUTF8);
+ loader.name = "TEST";
+ const readNodes = loader.array;
+
+ assert(expectedNodes.length == readNodes.length);
+ foreach (n; 0 .. expectedNodes.length)
+ {
+ assertNodesEqual(expectedNodes[n], readNodes[n]);
+ }
+ }
+ }
+ foreach (key, _; expected)
+ {
+ testRepresenterTypes(key);
+ }
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/resolver.d b/src/ext_depends/D-YAML/source/dyaml/test/resolver.d
new file mode 100644
index 0000000..ea93720
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/resolver.d
@@ -0,0 +1,39 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.resolver;
+
+@safe unittest
+{
+ import std.conv : text;
+ import std.file : readText;
+ import std.string : strip;
+
+ import dyaml : Loader, Node, NodeID;
+ import dyaml.test.common : run;
+
+
+ /**
+ Implicit tag resolution unittest.
+
+ Params:
+ dataFilename = File with unittest data.
+ detectFilename = Dummy filename used to specify which data filenames to use.
+ */
+ static void testImplicitResolver(string dataFilename, string detectFilename) @safe
+ {
+ const correctTag = readText(detectFilename).strip();
+
+ auto node = Loader.fromFile(dataFilename).load();
+ assert(node.nodeID == NodeID.sequence, text("Expected sequence when reading '", dataFilename, "', got ", node.nodeID));
+ foreach (Node scalar; node)
+ {
+ assert(scalar.nodeID == NodeID.scalar, text("Expected sequence of scalars when reading '", dataFilename, "', got sequence of ", scalar.nodeID));
+ assert(scalar.tag == correctTag, text("Expected tag '", correctTag, "' when reading '", dataFilename, "', got '", scalar.tag, "'"));
+ }
+ }
+ run(&testImplicitResolver, ["data", "detect"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/test/tokens.d b/src/ext_depends/D-YAML/source/dyaml/test/tokens.d
new file mode 100644
index 0000000..c099647
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/test/tokens.d
@@ -0,0 +1,93 @@
+
+// Copyright Ferdinand Majerech 2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+module dyaml.test.tokens;
+
+@safe unittest
+{
+ import std.array : split;
+ import std.conv : text;
+ import std.file : readText;
+
+ import dyaml.test.common : run;
+ import dyaml.reader : Reader;
+ import dyaml.scanner : Scanner;
+ import dyaml.token : TokenID;
+
+ // Read and scan a YAML doc, returning a range of tokens.
+ static auto scanTestCommon(string filename) @safe
+ {
+ ubyte[] yamlData = cast(ubyte[])readText(filename).dup;
+ return Scanner(new Reader(yamlData));
+ }
+
+ /**
+ Test tokens output by scanner.
+
+ Params:
+ dataFilename = File to scan.
+ tokensFilename = File containing expected tokens.
+ */
+ static void testTokens(string dataFilename, string tokensFilename) @safe
+ {
+ //representations of YAML tokens in tokens file.
+ auto replace = [
+ TokenID.directive: "%",
+ TokenID.documentStart: "---",
+ TokenID.documentEnd: "...",
+ TokenID.alias_: "*",
+ TokenID.anchor: "&",
+ TokenID.tag: "!",
+ TokenID.scalar: "_",
+ TokenID.blockSequenceStart: "[[",
+ TokenID.blockMappingStart: "{{",
+ TokenID.blockEnd: "]}",
+ TokenID.flowSequenceStart: "[",
+ TokenID.flowSequenceEnd: "]",
+ TokenID.flowMappingStart: "{",
+ TokenID.flowMappingEnd: "}",
+ TokenID.blockEntry: ",",
+ TokenID.flowEntry: ",",
+ TokenID.key: "?",
+ TokenID.value: ":"
+ ];
+
+ string[] tokens;
+ string[] expectedTokens = readText(tokensFilename).split();
+
+ foreach (token; scanTestCommon(dataFilename))
+ {
+ if (token.id != TokenID.streamStart && token.id != TokenID.streamEnd)
+ {
+ tokens ~= replace[token.id];
+ }
+ }
+
+ assert(tokens == expectedTokens,
+ text("In token test for '", tokensFilename, "', expected '", expectedTokens, "', got '", tokens, "'"));
+ }
+
+ /**
+ Test scanner by scanning a file, expecting no errors.
+
+ Params:
+ dataFilename = File to scan.
+ canonicalFilename = Another file to scan, in canonical YAML format.
+ */
+ static void testScanner(string dataFilename, string canonicalFilename) @safe
+ {
+ foreach (filename; [dataFilename, canonicalFilename])
+ {
+ string[] tokens;
+ foreach (token; scanTestCommon(filename))
+ {
+ tokens ~= token.id.text;
+ }
+ }
+ }
+ run(&testTokens, ["data", "tokens"]);
+ run(&testScanner, ["data", "canonical"]);
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/tinyendian.d b/src/ext_depends/D-YAML/source/dyaml/tinyendian.d
new file mode 100644
index 0000000..731b048
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/tinyendian.d
@@ -0,0 +1,213 @@
+// Copyright Ferdinand Majerech 2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/// A minimal library providing functionality for changing the endianness of data.
+module tinyendian;
+
+import std.system : Endian, endian;
+
+/// Unicode UTF encodings.
+enum UTFEncoding : ubyte
+{
+ UTF_8,
+ UTF_16,
+ UTF_32
+}
+///
+@safe unittest
+{
+ const ints = [314, -101];
+ int[2] intsSwapBuffer = ints;
+ swapByteOrder(intsSwapBuffer[]);
+ swapByteOrder(intsSwapBuffer[]);
+ assert(ints == intsSwapBuffer, "Lost information when swapping byte order");
+
+ const floats = [3.14f, 10.1f];
+ float[2] floatsSwapBuffer = floats;
+ swapByteOrder(floatsSwapBuffer[]);
+ swapByteOrder(floatsSwapBuffer[]);
+ assert(floats == floatsSwapBuffer, "Lost information when swapping byte order");
+}
+
+/** Swap byte order of items in an array in place.
+ *
+ * Params:
+ *
+ * T = Item type. Must be either 2 or 4 bytes long.
+ * array = Buffer with values to fix byte order of.
+ */
+void swapByteOrder(T)(T[] array) @trusted @nogc pure nothrow
+if (T.sizeof == 2 || T.sizeof == 4)
+{
+ // Swap the byte order of all read characters.
+ foreach (ref item; array)
+ {
+ static if (T.sizeof == 2)
+ {
+ import std.algorithm.mutation : swap;
+ swap(*cast(ubyte*)&item, *(cast(ubyte*)&item + 1));
+ }
+ else static if (T.sizeof == 4)
+ {
+ import core.bitop : bswap;
+ const swapped = bswap(*cast(uint*)&item);
+ item = *cast(const(T)*)&swapped;
+ }
+ else static assert(false, "Unsupported T: " ~ T.stringof);
+ }
+}
+
+/// See fixUTFByteOrder.
+struct FixUTFByteOrderResult
+{
+ ubyte[] array;
+ UTFEncoding encoding;
+ Endian endian;
+ uint bytesStripped = 0;
+}
+
+/** Convert byte order of an array encoded in UTF(8/16/32) to system endianness in place.
+ *
+ * Uses the UTF byte-order-mark (BOM) to determine UTF encoding. If there is no BOM
+ * at the beginning of array, UTF-8 is assumed (this is compatible with ASCII). The
+ * BOM, if any, will be removed from the buffer.
+ *
+ * If the encoding is determined to be UTF-16 or UTF-32 and there aren't enough bytes
+ * for the last code unit (i.e. if array.length is odd for UTF-16 or not divisible by
+ * 4 for UTF-32), the extra bytes (1 for UTF-16, 1-3 for UTF-32) are stripped.
+ *
+ * Note that this function does $(B not) check if the array is a valid UTF string. It
+ * only works with the BOM and 1,2 or 4-byte items.
+ *
+ * Params:
+ *
+ * array = The array with UTF-data.
+ *
+ * Returns:
+ *
+ * A struct with the following members:
+ *
+ * $(D ubyte[] array) A slice of the input array containing data in correct
+ * byte order, without BOM and in case of UTF-16/UTF-32,
+ * without stripped bytes, if any.
+ * $(D UTFEncoding encoding) Encoding of the result (UTF-8, UTF-16 or UTF-32)
+ * $(D std.system.Endian endian) Endianness of the original array.
+ * $(D uint bytesStripped) Number of bytes stripped from a UTF-16/UTF-32 array, if
+ * any. This is non-zero only if array.length was not
+ * divisible by 2 or 4 for UTF-16 and UTF-32, respectively.
+ *
+ * Complexity: (BIGOH array.length)
+ */
+auto fixUTFByteOrder(ubyte[] array) @safe @nogc pure nothrow
+{
+ // Enumerates UTF BOMs, matching indices to byteOrderMarks/bomEndian.
+ enum BOM: ubyte
+ {
+ UTF_8 = 0,
+ UTF_16_LE = 1,
+ UTF_16_BE = 2,
+ UTF_32_LE = 3,
+ UTF_32_BE = 4,
+ None = ubyte.max
+ }
+
+ // These 2 are from std.stream
+ static immutable ubyte[][5] byteOrderMarks = [ [0xEF, 0xBB, 0xBF],
+ [0xFF, 0xFE],
+ [0xFE, 0xFF],
+ [0xFF, 0xFE, 0x00, 0x00],
+ [0x00, 0x00, 0xFE, 0xFF] ];
+ static immutable Endian[5] bomEndian = [ endian,
+ Endian.littleEndian,
+ Endian.bigEndian,
+ Endian.littleEndian,
+ Endian.bigEndian ];
+
+ // Documented in function ddoc.
+
+ FixUTFByteOrderResult result;
+
+ // Detect BOM, if any, in the bytes we've read. -1 means no BOM.
+ // Need the last match: First 2 bytes of UTF-32LE BOM match the UTF-16LE BOM. If we
+ // used the first match, UTF-16LE would be detected when we have a UTF-32LE BOM.
+ import std.algorithm.searching : startsWith;
+ BOM bomId = BOM.None;
+ foreach (i, bom; byteOrderMarks)
+ if (array.startsWith(bom))
+ bomId = cast(BOM)i;
+
+ result.endian = (bomId != BOM.None) ? bomEndian[bomId] : Endian.init;
+
+ // Start of UTF data (after BOM, if any)
+ size_t start = 0;
+ // If we've read more than just the BOM, put the rest into the array.
+ with(BOM) final switch(bomId)
+ {
+ case None: result.encoding = UTFEncoding.UTF_8; break;
+ case UTF_8:
+ start = 3;
+ result.encoding = UTFEncoding.UTF_8;
+ break;
+ case UTF_16_LE, UTF_16_BE:
+ result.bytesStripped = array.length % 2;
+ start = 2;
+ result.encoding = UTFEncoding.UTF_16;
+ break;
+ case UTF_32_LE, UTF_32_BE:
+ result.bytesStripped = array.length % 4;
+ start = 4;
+ result.encoding = UTFEncoding.UTF_32;
+ break;
+ }
+
+ // If there's a BOM, we need to move data back to ensure it starts at array[0]
+ if (start != 0)
+ {
+ array = array[start .. $ - result.bytesStripped];
+ }
+
+ // We enforce above that array.length is divisible by 2/4 for UTF-16/32
+ if (endian != result.endian)
+ {
+ if (result.encoding == UTFEncoding.UTF_16)
+ swapByteOrder(cast(wchar[])array);
+ else if (result.encoding == UTFEncoding.UTF_32)
+ swapByteOrder(cast(dchar[])array);
+ }
+
+ result.array = array;
+ return result;
+}
+///
+@safe unittest
+{
+ {
+ ubyte[] s = [0xEF, 0xBB, 0xBF, 'a'];
+ FixUTFByteOrderResult r = fixUTFByteOrder(s);
+ assert(r.encoding == UTFEncoding.UTF_8);
+ assert(r.array.length == 1);
+ assert(r.array == ['a']);
+ assert(r.endian == Endian.littleEndian);
+ }
+
+ {
+ ubyte[] s = ['a'];
+ FixUTFByteOrderResult r = fixUTFByteOrder(s);
+ assert(r.encoding == UTFEncoding.UTF_8);
+ assert(r.array.length == 1);
+ assert(r.array == ['a']);
+ assert(r.endian == Endian.bigEndian);
+ }
+
+ {
+ // strip 'a' b/c not complete unit
+ ubyte[] s = [0xFE, 0xFF, 'a'];
+ FixUTFByteOrderResult r = fixUTFByteOrder(s);
+ assert(r.encoding == UTFEncoding.UTF_16);
+ assert(r.array.length == 0);
+ assert(r.endian == Endian.bigEndian);
+ }
+
+}
diff --git a/src/ext_depends/D-YAML/source/dyaml/token.d b/src/ext_depends/D-YAML/source/dyaml/token.d
new file mode 100644
index 0000000..5400a3f
--- /dev/null
+++ b/src/ext_depends/D-YAML/source/dyaml/token.d
@@ -0,0 +1,172 @@
+
+// Copyright Ferdinand Majerech 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/// YAML tokens.
+/// Code based on PyYAML: http://www.pyyaml.org
+module dyaml.token;
+
+
+import std.conv;
+
+import dyaml.encoding;
+import dyaml.exception;
+import dyaml.reader;
+import dyaml.style;
+
+
+package:
+
+/// Token types.
+enum TokenID : ubyte
+{
+ // Invalid (uninitialized) token
+ invalid = 0,
+ directive,
+ documentStart,
+ documentEnd,
+ streamStart,
+ streamEnd,
+ blockSequenceStart,
+ blockMappingStart,
+ blockEnd,
+ flowSequenceStart,
+ flowMappingStart,
+ flowSequenceEnd,
+ flowMappingEnd,
+ key,
+ value,
+ blockEntry,
+ flowEntry,
+ alias_,
+ anchor,
+ tag,
+ scalar
+}
+
+/// Specifies the type of a tag directive token.
+enum DirectiveType : ubyte
+{
+ // YAML version directive.
+ yaml,
+ // Tag directive.
+ tag,
+ // Any other directive is "reserved" for future YAML versions.
+ reserved
+}
+
+/// Token produced by scanner.
+///
+/// 32 bytes on 64-bit.
+struct Token
+{
+ @disable int opCmp(ref Token);
+
+ // 16B
+ /// Value of the token, if any.
+ ///
+ /// Values are char[] instead of string, as Parser may still change them in a few
+ /// cases. Parser casts values to strings when producing Events.
+ char[] value;
+ // 4B
+ /// Start position of the token in file/stream.
+ Mark startMark;
+ // 4B
+ /// End position of the token in file/stream.
+ Mark endMark;
+ // 1B
+ /// Token type.
+ TokenID id;
+ // 1B
+ /// Style of scalar token, if this is a scalar token.
+ ScalarStyle style;
+ // 1B
+ /// Encoding, if this is a stream start token.
+ Encoding encoding;
+ // 1B
+ /// Type of directive for directiveToken.
+ DirectiveType directive;
+ // 4B
+ /// Used to split value into 2 substrings for tokens that need 2 values (tagToken)
+ uint valueDivider;
+
+ /// Get string representation of the token ID.
+ @property string idString() @safe pure const {return id.to!string;}
+}
+
+/// Construct a directive token.
+///
+/// Params: start = Start position of the token.
+/// end = End position of the token.
+/// value = Value of the token.
+/// directive = Directive type (YAML or TAG in YAML 1.1).
+/// nameEnd = Position of the end of the name
+Token directiveToken(const Mark start, const Mark end, char[] value,
+ DirectiveType directive, const uint nameEnd) @safe pure nothrow @nogc
+{
+ return Token(value, start, end, TokenID.directive, ScalarStyle.init, Encoding.init,
+ directive, nameEnd);
+}
+
+/// Construct a simple (no value) token with specified type.
+///
+/// Params: id = Type of the token.
+/// start = Start position of the token.
+/// end = End position of the token.
+Token simpleToken(TokenID id)(const Mark start, const Mark end)
+{
+ return Token(null, start, end, id);
+}
+
+/// Construct a stream start token.
+///
+/// Params: start = Start position of the token.
+/// end = End position of the token.
+/// encoding = Encoding of the stream.
+Token streamStartToken(const Mark start, const Mark end, const Encoding encoding) @safe pure nothrow @nogc
+{
+ return Token(null, start, end, TokenID.streamStart, ScalarStyle.invalid, encoding);
+}
+
+/// Aliases for construction of simple token types.
+alias streamEndToken = simpleToken!(TokenID.streamEnd);
+alias blockSequenceStartToken = simpleToken!(TokenID.blockSequenceStart);
+alias blockMappingStartToken = simpleToken!(TokenID.blockMappingStart);
+alias blockEndToken = simpleToken!(TokenID.blockEnd);
+alias keyToken = simpleToken!(TokenID.key);
+alias valueToken = simpleToken!(TokenID.value);
+alias blockEntryToken = simpleToken!(TokenID.blockEntry);
+alias flowEntryToken = simpleToken!(TokenID.flowEntry);
+
+/// Construct a simple token with value with specified type.
+///
+/// Params: id = Type of the token.
+/// start = Start position of the token.
+/// end = End position of the token.
+/// value = Value of the token.
+/// valueDivider = A hack for TagToken to store 2 values in value; the first
+/// value goes up to valueDivider, the second after it.
+Token simpleValueToken(TokenID id)(const Mark start, const Mark end, char[] value,
+ const uint valueDivider = uint.max)
+{
+ return Token(value, start, end, id, ScalarStyle.invalid, Encoding.init,
+ DirectiveType.init, valueDivider);
+}
+
+/// Alias for construction of tag token.
+alias tagToken = simpleValueToken!(TokenID.tag);
+alias aliasToken = simpleValueToken!(TokenID.alias_);
+alias anchorToken = simpleValueToken!(TokenID.anchor);
+
+/// Construct a scalar token.
+///
+/// Params: start = Start position of the token.
+/// end = End position of the token.
+/// value = Value of the token.
+/// style = Style of the token.
+Token scalarToken(const Mark start, const Mark end, char[] value, const ScalarStyle style) @safe pure nothrow @nogc
+{
+ return Token(value, start, end, TokenID.scalar, style);
+}
diff --git a/src/ext_depends/D-YAML/test/data/a-nasty-libyaml-bug.loader-error b/src/ext_depends/D-YAML/test/data/a-nasty-libyaml-bug.loader-error
new file mode 100644
index 0000000..f97d49f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/a-nasty-libyaml-bug.loader-error
@@ -0,0 +1 @@
+[ [ \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/aliases-cdumper-bug.code b/src/ext_depends/D-YAML/test/data/aliases-cdumper-bug.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/aliases-cdumper-bug.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/aliases.events b/src/ext_depends/D-YAML/test/data/aliases.events
new file mode 100644
index 0000000..9139b51
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/aliases.events
@@ -0,0 +1,8 @@
+- !StreamStart
+- !DocumentStart
+- !SequenceStart
+- !Scalar { anchor: 'myanchor', tag: '!mytag', value: 'data' }
+- !Alias { anchor: 'myanchor' }
+- !SequenceEnd
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/bmpchars.canonical b/src/ext_depends/D-YAML/test/data/bmpchars.canonical
new file mode 100644
index 0000000..9b77b57
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/bmpchars.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "a"
+ : !!str "𒅗"
+}
diff --git a/src/ext_depends/D-YAML/test/data/bmpchars.data b/src/ext_depends/D-YAML/test/data/bmpchars.data
new file mode 100644
index 0000000..28e948e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/bmpchars.data
@@ -0,0 +1 @@
+a: 𒅗 \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/bool.data b/src/ext_depends/D-YAML/test/data/bool.data
new file mode 100644
index 0000000..0988b63
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/bool.data
@@ -0,0 +1,4 @@
+- yes
+- NO
+- True
+- on
diff --git a/src/ext_depends/D-YAML/test/data/bool.detect b/src/ext_depends/D-YAML/test/data/bool.detect
new file mode 100644
index 0000000..947ebbb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/bool.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:bool
diff --git a/src/ext_depends/D-YAML/test/data/colon-in-flow-context.loader-error b/src/ext_depends/D-YAML/test/data/colon-in-flow-context.loader-error
new file mode 100644
index 0000000..13d5087
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/colon-in-flow-context.loader-error
@@ -0,0 +1 @@
+{ foo:bar }
diff --git a/src/ext_depends/D-YAML/test/data/construct-binary.code b/src/ext_depends/D-YAML/test/data/construct-binary.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-binary.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-binary.data b/src/ext_depends/D-YAML/test/data/construct-binary.data
new file mode 100644
index 0000000..dcdb16f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-binary.data
@@ -0,0 +1,12 @@
+canonical: !!binary "\
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\
+ OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\
+ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\
+ AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs="
+generic: !!binary |
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
+ OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
+ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
+ AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
+description:
+ The binary value above is a tiny arrow encoded as a gif image.
diff --git a/src/ext_depends/D-YAML/test/data/construct-bool.code b/src/ext_depends/D-YAML/test/data/construct-bool.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-bool.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-bool.data b/src/ext_depends/D-YAML/test/data/construct-bool.data
new file mode 100644
index 0000000..4c0b757
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-bool.data
@@ -0,0 +1,13 @@
+canonical: yes
+answer: NO
+logical: True
+option: on
+constbool: on
+imutbool: on
+const_bool: on
+imut_bool: on
+
+
+but:
+ y: is a string
+ n: is a string
diff --git a/src/ext_depends/D-YAML/test/data/construct-custom.code b/src/ext_depends/D-YAML/test/data/construct-custom.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-custom.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-custom.data b/src/ext_depends/D-YAML/test/data/construct-custom.data
new file mode 100644
index 0000000..f17e4ed
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-custom.data
@@ -0,0 +1,7 @@
+---
+- !tag1
+ x: 1
+ 'y': 2
+ z: 3
+- !tag2
+ 10
diff --git a/src/ext_depends/D-YAML/test/data/construct-float.code b/src/ext_depends/D-YAML/test/data/construct-float.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-float.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-float.data b/src/ext_depends/D-YAML/test/data/construct-float.data
new file mode 100644
index 0000000..b662c62
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-float.data
@@ -0,0 +1,6 @@
+canonical: 6.8523015e+5
+exponential: 685.230_15e+03
+fixed: 685_230.15
+sexagesimal: 190:20:30.15
+negative infinity: -.inf
+not a number: .NaN
diff --git a/src/ext_depends/D-YAML/test/data/construct-int.code b/src/ext_depends/D-YAML/test/data/construct-int.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-int.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-int.data b/src/ext_depends/D-YAML/test/data/construct-int.data
new file mode 100644
index 0000000..852c314
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-int.data
@@ -0,0 +1,6 @@
+canonical: 685230
+decimal: +685_230
+octal: 02472256
+hexadecimal: 0x_0A_74_AE
+binary: 0b1010_0111_0100_1010_1110
+sexagesimal: 190:20:30
diff --git a/src/ext_depends/D-YAML/test/data/construct-map.code b/src/ext_depends/D-YAML/test/data/construct-map.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-map.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-map.data b/src/ext_depends/D-YAML/test/data/construct-map.data
new file mode 100644
index 0000000..022446d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-map.data
@@ -0,0 +1,6 @@
+# Unordered set of key: value pairs.
+Block style: !!map
+ Clark : Evans
+ Brian : Ingerson
+ Oren : Ben-Kiki
+Flow style: !!map { Clark: Evans, Brian: Ingerson, Oren: Ben-Kiki }
diff --git a/src/ext_depends/D-YAML/test/data/construct-merge.code b/src/ext_depends/D-YAML/test/data/construct-merge.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-merge.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-merge.data b/src/ext_depends/D-YAML/test/data/construct-merge.data
new file mode 100644
index 0000000..3fdb2e2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-merge.data
@@ -0,0 +1,27 @@
+---
+- &CENTER { x: 1, 'y': 2 }
+- &LEFT { x: 0, 'y': 2 }
+- &BIG { r: 10 }
+- &SMALL { r: 1 }
+
+# All the following maps are equal:
+
+- # Explicit keys
+ x: 1
+ 'y': 2
+ r: 10
+ label: center/big
+
+- # Merge one map
+ << : *CENTER
+ r: 10
+ label: center/big
+
+- # Merge multiple maps
+ << : [ *CENTER, *BIG ]
+ label: center/big
+
+- # Override
+ << : [ *BIG, *LEFT, *SMALL ]
+ x: 1
+ label: center/big
diff --git a/src/ext_depends/D-YAML/test/data/construct-null.code b/src/ext_depends/D-YAML/test/data/construct-null.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-null.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-null.data b/src/ext_depends/D-YAML/test/data/construct-null.data
new file mode 100644
index 0000000..9ad0344
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-null.data
@@ -0,0 +1,18 @@
+# A document may be null.
+---
+---
+# This mapping has four keys,
+# one has a value.
+empty:
+canonical: ~
+english: null
+~: null key
+---
+# This sequence has five
+# entries, two have values.
+sparse:
+ - ~
+ - 2nd entry
+ -
+ - 4th entry
+ - Null
diff --git a/src/ext_depends/D-YAML/test/data/construct-omap.code b/src/ext_depends/D-YAML/test/data/construct-omap.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-omap.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-omap.data b/src/ext_depends/D-YAML/test/data/construct-omap.data
new file mode 100644
index 0000000..4fa0f45
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-omap.data
@@ -0,0 +1,8 @@
+# Explicitly typed ordered map (dictionary).
+Bestiary: !!omap
+ - aardvark: African pig-like ant eater. Ugly.
+ - anteater: South-American ant eater. Two species.
+ - anaconda: South-American constrictor snake. Scaly.
+ # Etc.
+# Flow style
+Numbers: !!omap [ one: 1, two: 2, three : 3 ]
diff --git a/src/ext_depends/D-YAML/test/data/construct-pairs.code b/src/ext_depends/D-YAML/test/data/construct-pairs.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-pairs.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-pairs.data b/src/ext_depends/D-YAML/test/data/construct-pairs.data
new file mode 100644
index 0000000..05f55b9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-pairs.data
@@ -0,0 +1,7 @@
+# Explicitly typed pairs.
+Block tasks: !!pairs
+ - meeting: with team.
+ - meeting: with boss.
+ - break: lunch.
+ - meeting: with client.
+Flow tasks: !!pairs [ meeting: with team, meeting: with boss ]
diff --git a/src/ext_depends/D-YAML/test/data/construct-seq.code b/src/ext_depends/D-YAML/test/data/construct-seq.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-seq.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-seq.data b/src/ext_depends/D-YAML/test/data/construct-seq.data
new file mode 100644
index 0000000..bb92fd1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-seq.data
@@ -0,0 +1,15 @@
+# Ordered sequence of nodes
+Block style: !!seq
+- Mercury # Rotates - no light/dark sides.
+- Venus # Deadliest. Aptly named.
+- Earth # Mostly dirt.
+- Mars # Seems empty.
+- Jupiter # The king.
+- Saturn # Pretty.
+- Uranus # Where the sun hardly shines.
+- Neptune # Boring. No rings.
+- Pluto # You call this a planet?
+Flow style: !!seq [ Mercury, Venus, Earth, Mars, # Rocks
+ Jupiter, Saturn, Uranus, Neptune, # Gas
+ Pluto ] # Overrated
+
diff --git a/src/ext_depends/D-YAML/test/data/construct-set.code b/src/ext_depends/D-YAML/test/data/construct-set.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-set.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-set.data b/src/ext_depends/D-YAML/test/data/construct-set.data
new file mode 100644
index 0000000..e05dc88
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-set.data
@@ -0,0 +1,7 @@
+# Explicitly typed set.
+baseball players: !!set
+ ? Mark McGwire
+ ? Sammy Sosa
+ ? Ken Griffey
+# Flow style
+baseball teams: !!set { Boston Red Sox, Detroit Tigers, New York Yankees }
diff --git a/src/ext_depends/D-YAML/test/data/construct-str-ascii.code b/src/ext_depends/D-YAML/test/data/construct-str-ascii.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str-ascii.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-str-ascii.data b/src/ext_depends/D-YAML/test/data/construct-str-ascii.data
new file mode 100644
index 0000000..0d93013
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str-ascii.data
@@ -0,0 +1 @@
+--- !!str "ascii string"
diff --git a/src/ext_depends/D-YAML/test/data/construct-str-utf8.code b/src/ext_depends/D-YAML/test/data/construct-str-utf8.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str-utf8.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-str-utf8.data b/src/ext_depends/D-YAML/test/data/construct-str-utf8.data
new file mode 100644
index 0000000..e355f18
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str-utf8.data
@@ -0,0 +1 @@
+--- !!str "Это уникодная строка"
diff --git a/src/ext_depends/D-YAML/test/data/construct-str.code b/src/ext_depends/D-YAML/test/data/construct-str.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-str.data b/src/ext_depends/D-YAML/test/data/construct-str.data
new file mode 100644
index 0000000..606ac6b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-str.data
@@ -0,0 +1 @@
+string: abcd
diff --git a/src/ext_depends/D-YAML/test/data/construct-timestamp.code b/src/ext_depends/D-YAML/test/data/construct-timestamp.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-timestamp.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-timestamp.data b/src/ext_depends/D-YAML/test/data/construct-timestamp.data
new file mode 100644
index 0000000..840273b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-timestamp.data
@@ -0,0 +1,5 @@
+canonical: 2001-12-15T02:59:43.1Z
+valid iso8601: 2001-12-14t21:59:43.1-05:00
+space separated: 2001-12-14 21:59:43.1 -5
+no time zone (Z): 2001-12-15 2:59:43.1
+date (00:00:00Z): 2002-12-14
diff --git a/src/ext_depends/D-YAML/test/data/construct-value.code b/src/ext_depends/D-YAML/test/data/construct-value.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-value.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/construct-value.data b/src/ext_depends/D-YAML/test/data/construct-value.data
new file mode 100644
index 0000000..3eb7919
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/construct-value.data
@@ -0,0 +1,10 @@
+--- # Old schema
+link with:
+ - library1.dll
+ - library2.dll
+--- # New schema
+link with:
+ - = : library1.dll
+ version: 1.2
+ - = : library2.dll
+ version: 2.3
diff --git a/src/ext_depends/D-YAML/test/data/document-separator-in-quoted-scalar.loader-error b/src/ext_depends/D-YAML/test/data/document-separator-in-quoted-scalar.loader-error
new file mode 100644
index 0000000..9eeb0d6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/document-separator-in-quoted-scalar.loader-error
@@ -0,0 +1,11 @@
+---
+"this --- is correct"
+---
+"this
+...is also
+correct"
+---
+"a quoted scalar
+cannot contain
+---
+document separators"
diff --git a/src/ext_depends/D-YAML/test/data/documents.events b/src/ext_depends/D-YAML/test/data/documents.events
new file mode 100644
index 0000000..775a51a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/documents.events
@@ -0,0 +1,11 @@
+- !StreamStart
+- !DocumentStart { explicit: false }
+- !Scalar { implicit: [true,false], value: 'data' }
+- !DocumentEnd
+- !DocumentStart
+- !Scalar { implicit: [true,false] }
+- !DocumentEnd
+- !DocumentStart { version: [1,1], tags: { '!': '!foo', '!yaml!': 'tag:yaml.org,2002:', '!ugly!': '!!!!!!!' } }
+- !Scalar { implicit: [true,false] }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-anchor-1.loader-error b/src/ext_depends/D-YAML/test/data/duplicate-anchor-1.loader-error
new file mode 100644
index 0000000..906cf29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-anchor-1.loader-error
@@ -0,0 +1,3 @@
+- &foo bar
+- &bar bar
+- &foo bar
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-anchor-2.loader-error b/src/ext_depends/D-YAML/test/data/duplicate-anchor-2.loader-error
new file mode 100644
index 0000000..62b4389
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-anchor-2.loader-error
@@ -0,0 +1 @@
+&foo [1, 2, 3, &foo 4]
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-mapping-key.loader-error b/src/ext_depends/D-YAML/test/data/duplicate-mapping-key.loader-error
new file mode 100644
index 0000000..55bce77
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-mapping-key.loader-error
@@ -0,0 +1,2 @@
+a: 1
+a: 2 \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-merge-key.code b/src/ext_depends/D-YAML/test/data/duplicate-merge-key.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-merge-key.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-merge-key.data b/src/ext_depends/D-YAML/test/data/duplicate-merge-key.data
new file mode 100644
index 0000000..cebc3a1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-merge-key.data
@@ -0,0 +1,4 @@
+---
+<<: {x: 1, y: 2}
+foo: bar
+<<: {z: 3, t: 4}
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-tag-directive.loader-error b/src/ext_depends/D-YAML/test/data/duplicate-tag-directive.loader-error
new file mode 100644
index 0000000..50c81a0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-tag-directive.loader-error
@@ -0,0 +1,3 @@
+%TAG !foo! bar
+%TAG !foo! baz
+--- foo
diff --git a/src/ext_depends/D-YAML/test/data/duplicate-yaml-directive.loader-error b/src/ext_depends/D-YAML/test/data/duplicate-yaml-directive.loader-error
new file mode 100644
index 0000000..9b72390
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/duplicate-yaml-directive.loader-error
@@ -0,0 +1,3 @@
+%YAML 1.1
+%YAML 1.1
+--- foo
diff --git a/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.canonical b/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.canonical
new file mode 100644
index 0000000..473bed5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+--- !!map
+{
+ ? !!str "foo"
+ : !!str "bar"
+}
diff --git a/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.data b/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.data
new file mode 100644
index 0000000..b6b42ba
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/emit-block-scalar-in-simple-key-context-bug.data
@@ -0,0 +1,4 @@
+? |-
+ foo
+: |-
+ bar
diff --git a/src/ext_depends/D-YAML/test/data/empty-anchor.emitter-error b/src/ext_depends/D-YAML/test/data/empty-anchor.emitter-error
new file mode 100644
index 0000000..ce663b6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-anchor.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart
+- !Scalar { anchor: '', value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/empty-document-bug.canonical b/src/ext_depends/D-YAML/test/data/empty-document-bug.canonical
new file mode 100644
index 0000000..28a6cf1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-document-bug.canonical
@@ -0,0 +1 @@
+# This YAML stream contains no YAML documents.
diff --git a/src/ext_depends/D-YAML/test/data/empty-document-bug.data b/src/ext_depends/D-YAML/test/data/empty-document-bug.data
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-document-bug.data
diff --git a/src/ext_depends/D-YAML/test/data/empty-document-bug.empty b/src/ext_depends/D-YAML/test/data/empty-document-bug.empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-document-bug.empty
diff --git a/src/ext_depends/D-YAML/test/data/empty-documents.single-loader-error b/src/ext_depends/D-YAML/test/data/empty-documents.single-loader-error
new file mode 100644
index 0000000..f8dba8d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-documents.single-loader-error
@@ -0,0 +1,2 @@
+--- # first document
+--- # second document
diff --git a/src/ext_depends/D-YAML/test/data/empty-tag-handle.emitter-error b/src/ext_depends/D-YAML/test/data/empty-tag-handle.emitter-error
new file mode 100644
index 0000000..235c899
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-tag-handle.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart { tags: { '': 'bar' } }
+- !Scalar { value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/empty-tag-prefix.emitter-error b/src/ext_depends/D-YAML/test/data/empty-tag-prefix.emitter-error
new file mode 100644
index 0000000..c6c0e95
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-tag-prefix.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart { tags: { '!': '' } }
+- !Scalar { value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/empty-tag.emitter-error b/src/ext_depends/D-YAML/test/data/empty-tag.emitter-error
new file mode 100644
index 0000000..b7ca593
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/empty-tag.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart
+- !Scalar { tag: '', value: 'key', implicit: [false,false] }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-document-end.emitter-error b/src/ext_depends/D-YAML/test/data/expected-document-end.emitter-error
new file mode 100644
index 0000000..0cbab89
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-document-end.emitter-error
@@ -0,0 +1,6 @@
+- !StreamStart
+- !DocumentStart
+- !Scalar { value: 'data 1' }
+- !Scalar { value: 'data 2' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-document-start.emitter-error b/src/ext_depends/D-YAML/test/data/expected-document-start.emitter-error
new file mode 100644
index 0000000..8ce575e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-document-start.emitter-error
@@ -0,0 +1,4 @@
+- !StreamStart
+- !MappingStart
+- !MappingEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-mapping.loader-error b/src/ext_depends/D-YAML/test/data/expected-mapping.loader-error
new file mode 100644
index 0000000..82aed98
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-mapping.loader-error
@@ -0,0 +1 @@
+--- !!map [not, a, map]
diff --git a/src/ext_depends/D-YAML/test/data/expected-node-1.emitter-error b/src/ext_depends/D-YAML/test/data/expected-node-1.emitter-error
new file mode 100644
index 0000000..36ceca3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-node-1.emitter-error
@@ -0,0 +1,4 @@
+- !StreamStart
+- !DocumentStart
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-node-2.emitter-error b/src/ext_depends/D-YAML/test/data/expected-node-2.emitter-error
new file mode 100644
index 0000000..891ee37
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-node-2.emitter-error
@@ -0,0 +1,7 @@
+- !StreamStart
+- !DocumentStart
+- !MappingStart
+- !Scalar { value: 'key' }
+- !MappingEnd
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-nothing.emitter-error b/src/ext_depends/D-YAML/test/data/expected-nothing.emitter-error
new file mode 100644
index 0000000..62c54d3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-nothing.emitter-error
@@ -0,0 +1,4 @@
+- !StreamStart
+- !StreamEnd
+- !StreamStart
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/expected-scalar.loader-error b/src/ext_depends/D-YAML/test/data/expected-scalar.loader-error
new file mode 100644
index 0000000..7b3171e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-scalar.loader-error
@@ -0,0 +1 @@
+--- !!str [not a scalar]
diff --git a/src/ext_depends/D-YAML/test/data/expected-sequence.loader-error b/src/ext_depends/D-YAML/test/data/expected-sequence.loader-error
new file mode 100644
index 0000000..08074ea
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-sequence.loader-error
@@ -0,0 +1 @@
+--- !!seq {foo, bar, baz}
diff --git a/src/ext_depends/D-YAML/test/data/expected-stream-start.emitter-error b/src/ext_depends/D-YAML/test/data/expected-stream-start.emitter-error
new file mode 100644
index 0000000..480dc2e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/expected-stream-start.emitter-error
@@ -0,0 +1,2 @@
+- !DocumentStart
+- !DocumentEnd
diff --git a/src/ext_depends/D-YAML/test/data/explicit-document.single-loader-error b/src/ext_depends/D-YAML/test/data/explicit-document.single-loader-error
new file mode 100644
index 0000000..46c6f8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/explicit-document.single-loader-error
@@ -0,0 +1,4 @@
+---
+foo: bar
+---
+foo: bar
diff --git a/src/ext_depends/D-YAML/test/data/fetch-complex-value-bug.loader-error b/src/ext_depends/D-YAML/test/data/fetch-complex-value-bug.loader-error
new file mode 100644
index 0000000..25fac24
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/fetch-complex-value-bug.loader-error
@@ -0,0 +1,2 @@
+? "foo"
+ : "bar"
diff --git a/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.code b/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.data b/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.data
new file mode 100644
index 0000000..efd1716
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/float-representer-2.3-bug.data
@@ -0,0 +1,5 @@
+#0.0: # hash(0) == hash(nan) and 0 == nan in Python 2.3
+1.0: 1
++.inf: 10
+-.inf: -10
+.nan: 100
diff --git a/src/ext_depends/D-YAML/test/data/float.data b/src/ext_depends/D-YAML/test/data/float.data
new file mode 100644
index 0000000..524d5db
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/float.data
@@ -0,0 +1,6 @@
+- 6.8523015e+5
+- 685.230_15e+03
+- 685_230.15
+- 190:20:30.15
+- -.inf
+- .NaN
diff --git a/src/ext_depends/D-YAML/test/data/float.detect b/src/ext_depends/D-YAML/test/data/float.detect
new file mode 100644
index 0000000..1e12343
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/float.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:float
diff --git a/src/ext_depends/D-YAML/test/data/forbidden-entry.loader-error b/src/ext_depends/D-YAML/test/data/forbidden-entry.loader-error
new file mode 100644
index 0000000..f2e3079
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/forbidden-entry.loader-error
@@ -0,0 +1,2 @@
+test: - foo
+ - bar
diff --git a/src/ext_depends/D-YAML/test/data/forbidden-key.loader-error b/src/ext_depends/D-YAML/test/data/forbidden-key.loader-error
new file mode 100644
index 0000000..da9b471
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/forbidden-key.loader-error
@@ -0,0 +1,2 @@
+test: ? foo
+ : bar
diff --git a/src/ext_depends/D-YAML/test/data/forbidden-value.loader-error b/src/ext_depends/D-YAML/test/data/forbidden-value.loader-error
new file mode 100644
index 0000000..efd7ce5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/forbidden-value.loader-error
@@ -0,0 +1 @@
+test: key: value
diff --git a/src/ext_depends/D-YAML/test/data/implicit-document.single-loader-error b/src/ext_depends/D-YAML/test/data/implicit-document.single-loader-error
new file mode 100644
index 0000000..f8c9a5c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/implicit-document.single-loader-error
@@ -0,0 +1,3 @@
+foo: bar
+---
+foo: bar
diff --git a/src/ext_depends/D-YAML/test/data/int.data b/src/ext_depends/D-YAML/test/data/int.data
new file mode 100644
index 0000000..d44d376
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/int.data
@@ -0,0 +1,6 @@
+- 685230
+- +685_230
+- 02472256
+- 0x_0A_74_AE
+- 0b1010_0111_0100_1010_1110
+- 190:20:30
diff --git a/src/ext_depends/D-YAML/test/data/int.detect b/src/ext_depends/D-YAML/test/data/int.detect
new file mode 100644
index 0000000..575c9eb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/int.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:int
diff --git a/src/ext_depends/D-YAML/test/data/invalid-anchor-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-anchor-1.loader-error
new file mode 100644
index 0000000..fcf7d0f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-anchor-1.loader-error
@@ -0,0 +1 @@
+--- &? foo # we allow only ascii and numeric characters in anchor names.
diff --git a/src/ext_depends/D-YAML/test/data/invalid-anchor-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-anchor-2.loader-error
new file mode 100644
index 0000000..bfc4ff0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-anchor-2.loader-error
@@ -0,0 +1,8 @@
+---
+- [
+ &correct foo,
+ *correct,
+ *correct] # still correct
+- *correct: still correct
+- &correct-or-not[foo, bar]
+
diff --git a/src/ext_depends/D-YAML/test/data/invalid-anchor.emitter-error b/src/ext_depends/D-YAML/test/data/invalid-anchor.emitter-error
new file mode 100644
index 0000000..3d2a814
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-anchor.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart
+- !Scalar { anchor: '5*5=25', value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/invalid-base64-data-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-base64-data-2.loader-error
new file mode 100644
index 0000000..2553a4f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-base64-data-2.loader-error
@@ -0,0 +1,2 @@
+--- !!binary
+ двоичные данные в base64
diff --git a/src/ext_depends/D-YAML/test/data/invalid-base64-data.loader-error b/src/ext_depends/D-YAML/test/data/invalid-base64-data.loader-error
new file mode 100644
index 0000000..798abba
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-base64-data.loader-error
@@ -0,0 +1,2 @@
+--- !!binary
+ binary data encoded in base64 should be here.
diff --git a/src/ext_depends/D-YAML/test/data/invalid-block-scalar-indicator.loader-error b/src/ext_depends/D-YAML/test/data/invalid-block-scalar-indicator.loader-error
new file mode 100644
index 0000000..16a6db1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-block-scalar-indicator.loader-error
@@ -0,0 +1,2 @@
+--- > what is this? # a comment
+data
diff --git a/src/ext_depends/D-YAML/test/data/invalid-character.loader-error b/src/ext_depends/D-YAML/test/data/invalid-character.loader-error
new file mode 100644
index 0000000..03687b0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-character.loader-error
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/invalid-character.stream-error b/src/ext_depends/D-YAML/test/data/invalid-character.stream-error
new file mode 100644
index 0000000..171face
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-character.stream-error
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/invalid-directive-line.loader-error b/src/ext_depends/D-YAML/test/data/invalid-directive-line.loader-error
new file mode 100644
index 0000000..0892eb6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-directive-line.loader-error
@@ -0,0 +1,2 @@
+%YAML 1.1 ? # extra symbol
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-directive-name-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-directive-name-1.loader-error
new file mode 100644
index 0000000..153fd88
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-directive-name-1.loader-error
@@ -0,0 +1,2 @@
+% # no name at all
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-directive-name-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-directive-name-2.loader-error
new file mode 100644
index 0000000..3732a06
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-directive-name-2.loader-error
@@ -0,0 +1,2 @@
+%invalid-characters:in-directive name
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-escape-character.loader-error b/src/ext_depends/D-YAML/test/data/invalid-escape-character.loader-error
new file mode 100644
index 0000000..a95ab76
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-escape-character.loader-error
@@ -0,0 +1 @@
+"some escape characters are \ncorrect, but this one \?\nis not\n"
diff --git a/src/ext_depends/D-YAML/test/data/invalid-escape-numbers.loader-error b/src/ext_depends/D-YAML/test/data/invalid-escape-numbers.loader-error
new file mode 100644
index 0000000..614ec9f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-escape-numbers.loader-error
@@ -0,0 +1 @@
+"hm.... \u123?"
diff --git a/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-1.loader-error
new file mode 100644
index 0000000..a3cd12f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-1.loader-error
@@ -0,0 +1,2 @@
+--- >0 # not valid
+data
diff --git a/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-2.loader-error
new file mode 100644
index 0000000..eefb6ec
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-indentation-indicator-2.loader-error
@@ -0,0 +1,2 @@
+--- >-0
+data
diff --git a/src/ext_depends/D-YAML/test/data/invalid-item-without-trailing-break.loader-error b/src/ext_depends/D-YAML/test/data/invalid-item-without-trailing-break.loader-error
new file mode 100644
index 0000000..fdcf6c6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-item-without-trailing-break.loader-error
@@ -0,0 +1,2 @@
+-
+-0 \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/invalid-merge-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-merge-1.loader-error
new file mode 100644
index 0000000..fc3c284
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-merge-1.loader-error
@@ -0,0 +1,2 @@
+foo: bar
+<<: baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-merge-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-merge-2.loader-error
new file mode 100644
index 0000000..8e88615
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-merge-2.loader-error
@@ -0,0 +1,2 @@
+foo: bar
+<<: [x: 1, y: 2, z, t: 4]
diff --git a/src/ext_depends/D-YAML/test/data/invalid-omap-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-omap-1.loader-error
new file mode 100644
index 0000000..2863392
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-omap-1.loader-error
@@ -0,0 +1,3 @@
+--- !!omap
+foo: bar
+baz: bat
diff --git a/src/ext_depends/D-YAML/test/data/invalid-omap-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-omap-2.loader-error
new file mode 100644
index 0000000..c377dfb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-omap-2.loader-error
@@ -0,0 +1,3 @@
+--- !!omap
+- foo: bar
+- baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-omap-3.loader-error b/src/ext_depends/D-YAML/test/data/invalid-omap-3.loader-error
new file mode 100644
index 0000000..2a4f50d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-omap-3.loader-error
@@ -0,0 +1,4 @@
+--- !!omap
+- foo: bar
+- baz: bar
+ bar: bar
diff --git a/src/ext_depends/D-YAML/test/data/invalid-pairs-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-pairs-1.loader-error
new file mode 100644
index 0000000..42d19ae
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-pairs-1.loader-error
@@ -0,0 +1,3 @@
+--- !!pairs
+foo: bar
+baz: bat
diff --git a/src/ext_depends/D-YAML/test/data/invalid-pairs-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-pairs-2.loader-error
new file mode 100644
index 0000000..31389ea
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-pairs-2.loader-error
@@ -0,0 +1,3 @@
+--- !!pairs
+- foo: bar
+- baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-pairs-3.loader-error b/src/ext_depends/D-YAML/test/data/invalid-pairs-3.loader-error
new file mode 100644
index 0000000..f8d7704
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-pairs-3.loader-error
@@ -0,0 +1,4 @@
+--- !!pairs
+- foo: bar
+- baz: bar
+ bar: bar
diff --git a/src/ext_depends/D-YAML/test/data/invalid-simple-key.loader-error b/src/ext_depends/D-YAML/test/data/invalid-simple-key.loader-error
new file mode 100644
index 0000000..a58deec
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-simple-key.loader-error
@@ -0,0 +1,3 @@
+key: value
+invalid simple key
+next key: next value
diff --git a/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.code b/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.data b/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.data
new file mode 100644
index 0000000..76ef7ae
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-single-quote-bug.data
@@ -0,0 +1,2 @@
+- "foo 'bar'"
+- "foo\n'bar'"
diff --git a/src/ext_depends/D-YAML/test/data/invalid-starting-character.loader-error b/src/ext_depends/D-YAML/test/data/invalid-starting-character.loader-error
new file mode 100644
index 0000000..bb81c60
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-starting-character.loader-error
@@ -0,0 +1 @@
+@@@@@@@@@@@@@@@@@@@
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-1.loader-error
new file mode 100644
index 0000000..a68cd38
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-1.loader-error
@@ -0,0 +1 @@
+- !<foo#bar> baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-2.loader-error
new file mode 100644
index 0000000..3a36700
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-2.loader-error
@@ -0,0 +1 @@
+- !prefix!foo#bar baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-directive-handle.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-directive-handle.loader-error
new file mode 100644
index 0000000..42b5d7e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-directive-handle.loader-error
@@ -0,0 +1,2 @@
+%TAG !!! !!!
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-directive-prefix.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-directive-prefix.loader-error
new file mode 100644
index 0000000..0cb482c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-directive-prefix.loader-error
@@ -0,0 +1,2 @@
+%TAG ! tag:zz.com/foo#bar # '#' is not allowed in URLs
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.emitter-error b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.emitter-error
new file mode 100644
index 0000000..d5df9a2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart { tags: { '!foo': 'bar' } }
+- !Scalar { value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.loader-error
new file mode 100644
index 0000000..ef0d143
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-1.loader-error
@@ -0,0 +1,2 @@
+%TAG foo bar
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.emitter-error b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.emitter-error
new file mode 100644
index 0000000..d1831d5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart { tags: { '!!!': 'bar' } }
+- !Scalar { value: 'foo' }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.loader-error
new file mode 100644
index 0000000..06c7f0e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-tag-handle-2.loader-error
@@ -0,0 +1,2 @@
+%TAG !foo bar
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-1.loader-error
new file mode 100644
index 0000000..a6ecb36
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-1.loader-error
@@ -0,0 +1 @@
+--- !<tag:%x?y> foo
diff --git a/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-2.loader-error
new file mode 100644
index 0000000..b89e8f6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-2.loader-error
@@ -0,0 +1 @@
+--- !<%FF> foo
diff --git a/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-3.loader-error b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-3.loader-error
new file mode 100644
index 0000000..f2e4cb8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-uri-escapes-3.loader-error
@@ -0,0 +1 @@
+--- !<foo%d0%af%d0%af%d0bar> baz
diff --git a/src/ext_depends/D-YAML/test/data/invalid-uri.loader-error b/src/ext_depends/D-YAML/test/data/invalid-uri.loader-error
new file mode 100644
index 0000000..06307e0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-uri.loader-error
@@ -0,0 +1 @@
+--- !foo! bar
diff --git a/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.loader-error b/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.loader-error
new file mode 100644
index 0000000..0a58c70
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.loader-error
@@ -0,0 +1,66 @@
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+Invalid byte ('\xFF'): <--
+###############################################################
diff --git a/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.stream-error b/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.stream-error
new file mode 100644
index 0000000..0a58c70
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-utf8-byte.stream-error
@@ -0,0 +1,66 @@
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+Invalid byte ('\xFF'): <--
+###############################################################
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-1.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-1.loader-error
new file mode 100644
index 0000000..e9b4e3a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-1.loader-error
@@ -0,0 +1,3 @@
+# No version at all.
+%YAML
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-2.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-2.loader-error
new file mode 100644
index 0000000..6aa7740
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-2.loader-error
@@ -0,0 +1,2 @@
+%YAML 1e-5
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-3.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-3.loader-error
new file mode 100644
index 0000000..345e784
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-3.loader-error
@@ -0,0 +1,2 @@
+%YAML 1.
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-4.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-4.loader-error
new file mode 100644
index 0000000..b35ca82
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-4.loader-error
@@ -0,0 +1,2 @@
+%YAML 1.132.435
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-5.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-5.loader-error
new file mode 100644
index 0000000..7c2b49f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-5.loader-error
@@ -0,0 +1,2 @@
+%YAML A.0
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-6.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-6.loader-error
new file mode 100644
index 0000000..bae714f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-directive-version-6.loader-error
@@ -0,0 +1,2 @@
+%YAML 123.C
+---
diff --git a/src/ext_depends/D-YAML/test/data/invalid-yaml-version.loader-error b/src/ext_depends/D-YAML/test/data/invalid-yaml-version.loader-error
new file mode 100644
index 0000000..dd01948
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/invalid-yaml-version.loader-error
@@ -0,0 +1,2 @@
+%YAML 2.0
+--- foo
diff --git a/src/ext_depends/D-YAML/test/data/latin.unicode b/src/ext_depends/D-YAML/test/data/latin.unicode
new file mode 100644
index 0000000..4fb799c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/latin.unicode
@@ -0,0 +1,384 @@
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊ
+ËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎ
+ďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐ
+őŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒ
+ƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƼƽƾƿDŽdžLJljNJnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜ
+ǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯ
+ɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΆΈ
+ΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύ
+ώϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБ
+ВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓ
+єѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝ
+ҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠ
+ӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉ
+ՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևႠႡႢႣႤႥႦႧႨႩႪႫႬႭ
+ႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩ
+ᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḀḁḂḃḄḅḆḇ
+ḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉ
+ṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋ
+ẌẍẎẏẐẑẒẓẔẕẖẗẘẙẚẛẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐố
+ỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹἀἁἂἃἄἅἆἇἈἉἊἋἌἍἎἏἐἑἒἓἔἕἘἙἚἛ
+ἜἝἠἡἢἣἤἥἦἧἨἩἪἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἺἻἼἽἾἿὀὁὂὃὄὅὈὉὊὋὌὍὐὑὒὓὔὕὖὗὙὛὝὟὠὡὢὣὤὥὦὧ
+ὨὩὪὫὬὭὮὯὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷᾸᾹᾺΆιῂῃῄῆῇῈΈῊ
+ΉῐῑῒΐῖῗῘῙῚΊῠῡῢΰῤῥῦῧῨῩῪΎῬῲῳῴῶῷῸΌῺΏⁱⁿℂℇℊℋℌℍℎℏℐℑℒℓℕℙℚℛℜℝℤΩℨKÅℬℭℯℰℱℳℴℹ
diff --git a/src/ext_depends/D-YAML/test/data/mappings.events b/src/ext_depends/D-YAML/test/data/mappings.events
new file mode 100644
index 0000000..3cb5579
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/mappings.events
@@ -0,0 +1,44 @@
+- !StreamStart
+
+- !DocumentStart
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'key' }
+- !Scalar { implicit: [true,true], value: 'value' }
+- !Scalar { implicit: [true,true], value: 'empty mapping' }
+- !MappingStart
+- !MappingEnd
+- !Scalar { implicit: [true,true], value: 'empty mapping with tag' }
+- !MappingStart { tag: '!mytag', implicit: false }
+- !MappingEnd
+- !Scalar { implicit: [true,true], value: 'block mapping' }
+- !MappingStart
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !MappingEnd
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !MappingEnd
+- !MappingEnd
+- !Scalar { implicit: [true,true], value: 'flow mapping' }
+- !MappingStart { flow_style: true }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !Scalar { implicit: [true,true], value: 'value' }
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !MappingEnd
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'complex' }
+- !Scalar { implicit: [true,true], value: 'key' }
+- !MappingEnd
+- !MappingEnd
+- !MappingEnd
+- !DocumentEnd
+
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/merge.data b/src/ext_depends/D-YAML/test/data/merge.data
new file mode 100644
index 0000000..e455bbc
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/merge.data
@@ -0,0 +1 @@
+- <<
diff --git a/src/ext_depends/D-YAML/test/data/merge.detect b/src/ext_depends/D-YAML/test/data/merge.detect
new file mode 100644
index 0000000..1672d0d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/merge.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:merge
diff --git a/src/ext_depends/D-YAML/test/data/more-floats.code b/src/ext_depends/D-YAML/test/data/more-floats.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/more-floats.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/more-floats.data b/src/ext_depends/D-YAML/test/data/more-floats.data
new file mode 100644
index 0000000..399eb17
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/more-floats.data
@@ -0,0 +1 @@
+[0.0, +1.0, -1.0, +.inf, -.inf, .nan, .nan]
diff --git a/src/ext_depends/D-YAML/test/data/negative-float-bug.code b/src/ext_depends/D-YAML/test/data/negative-float-bug.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/negative-float-bug.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/negative-float-bug.data b/src/ext_depends/D-YAML/test/data/negative-float-bug.data
new file mode 100644
index 0000000..18e16e3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/negative-float-bug.data
@@ -0,0 +1 @@
+-1.0
diff --git a/src/ext_depends/D-YAML/test/data/no-alias-anchor.emitter-error b/src/ext_depends/D-YAML/test/data/no-alias-anchor.emitter-error
new file mode 100644
index 0000000..5ff065c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-alias-anchor.emitter-error
@@ -0,0 +1,8 @@
+- !StreamStart
+- !DocumentStart
+- !SequenceStart
+- !Scalar { anchor: A, value: data }
+- !Alias { }
+- !SequenceEnd
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/no-alias-anchor.skip-ext b/src/ext_depends/D-YAML/test/data/no-alias-anchor.skip-ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-alias-anchor.skip-ext
diff --git a/src/ext_depends/D-YAML/test/data/no-block-collection-end.loader-error b/src/ext_depends/D-YAML/test/data/no-block-collection-end.loader-error
new file mode 100644
index 0000000..02d4d37
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-block-collection-end.loader-error
@@ -0,0 +1,3 @@
+- foo
+- bar
+baz: bar
diff --git a/src/ext_depends/D-YAML/test/data/no-block-mapping-end-2.loader-error b/src/ext_depends/D-YAML/test/data/no-block-mapping-end-2.loader-error
new file mode 100644
index 0000000..be63571
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-block-mapping-end-2.loader-error
@@ -0,0 +1,3 @@
+? foo
+: bar
+: baz
diff --git a/src/ext_depends/D-YAML/test/data/no-block-mapping-end.loader-error b/src/ext_depends/D-YAML/test/data/no-block-mapping-end.loader-error
new file mode 100644
index 0000000..1ea921c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-block-mapping-end.loader-error
@@ -0,0 +1 @@
+foo: "bar" "baz"
diff --git a/src/ext_depends/D-YAML/test/data/no-document-start.loader-error b/src/ext_depends/D-YAML/test/data/no-document-start.loader-error
new file mode 100644
index 0000000..c725ec8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-document-start.loader-error
@@ -0,0 +1,3 @@
+%YAML 1.1
+# no ---
+foo: bar
diff --git a/src/ext_depends/D-YAML/test/data/no-flow-mapping-end.loader-error b/src/ext_depends/D-YAML/test/data/no-flow-mapping-end.loader-error
new file mode 100644
index 0000000..8bd1403
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-flow-mapping-end.loader-error
@@ -0,0 +1 @@
+{ foo: bar ]
diff --git a/src/ext_depends/D-YAML/test/data/no-flow-sequence-end.loader-error b/src/ext_depends/D-YAML/test/data/no-flow-sequence-end.loader-error
new file mode 100644
index 0000000..750d973
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-flow-sequence-end.loader-error
@@ -0,0 +1 @@
+[foo, bar}
diff --git a/src/ext_depends/D-YAML/test/data/no-node-1.loader-error b/src/ext_depends/D-YAML/test/data/no-node-1.loader-error
new file mode 100644
index 0000000..07b1500
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-node-1.loader-error
@@ -0,0 +1 @@
+- !foo ]
diff --git a/src/ext_depends/D-YAML/test/data/no-node-2.loader-error b/src/ext_depends/D-YAML/test/data/no-node-2.loader-error
new file mode 100644
index 0000000..563e3b3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-node-2.loader-error
@@ -0,0 +1 @@
+- [ !foo } ]
diff --git a/src/ext_depends/D-YAML/test/data/no-tag.emitter-error b/src/ext_depends/D-YAML/test/data/no-tag.emitter-error
new file mode 100644
index 0000000..384c62f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/no-tag.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart
+- !Scalar { value: 'foo', implicit: [false,false] }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/null.data b/src/ext_depends/D-YAML/test/data/null.data
new file mode 100644
index 0000000..ad12528
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/null.data
@@ -0,0 +1,3 @@
+-
+- ~
+- null
diff --git a/src/ext_depends/D-YAML/test/data/null.detect b/src/ext_depends/D-YAML/test/data/null.detect
new file mode 100644
index 0000000..19110c7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/null.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:null
diff --git a/src/ext_depends/D-YAML/test/data/odd-utf16.stream-error b/src/ext_depends/D-YAML/test/data/odd-utf16.stream-error
new file mode 100644
index 0000000..b59e434
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/odd-utf16.stream-error
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/recursive.former-dumper-error b/src/ext_depends/D-YAML/test/data/recursive.former-dumper-error
new file mode 100644
index 0000000..3c7cc2f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/recursive.former-dumper-error
@@ -0,0 +1,3 @@
+data = []
+data.append(data)
+dump(data)
diff --git a/src/ext_depends/D-YAML/test/data/remove-possible-simple-key-bug.loader-error b/src/ext_depends/D-YAML/test/data/remove-possible-simple-key-bug.loader-error
new file mode 100644
index 0000000..fe1bc6c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/remove-possible-simple-key-bug.loader-error
@@ -0,0 +1,3 @@
+foo: &A bar
+*A ] # The ']' indicator triggers remove_possible_simple_key,
+ # which should raise an error.
diff --git a/src/ext_depends/D-YAML/test/data/resolver.data b/src/ext_depends/D-YAML/test/data/resolver.data
new file mode 100644
index 0000000..a296404
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/resolver.data
@@ -0,0 +1,30 @@
+---
+"this scalar should be selected"
+---
+key11: !foo
+ key12:
+ is: [selected]
+ key22:
+ key13: [not, selected]
+ key23: [not, selected]
+ key32:
+ key31: [not, selected]
+ key32: [not, selected]
+ key33: {not: selected}
+key21: !bar
+ - not selected
+ - selected
+ - not selected
+key31: !baz
+ key12:
+ key13:
+ key14: {selected}
+ key23:
+ key14: [not, selected]
+ key33:
+ key14: {selected}
+ key24: {not: selected}
+ key22:
+ - key14: {selected}
+ key24: {not: selected}
+ - key14: {selected}
diff --git a/src/ext_depends/D-YAML/test/data/resolver.path b/src/ext_depends/D-YAML/test/data/resolver.path
new file mode 100644
index 0000000..ec677d2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/resolver.path
@@ -0,0 +1,30 @@
+--- !root/scalar
+"this scalar should be selected"
+--- !root
+key11: !foo
+ key12: !root/key11/key12/*
+ is: [selected]
+ key22:
+ key13: [not, selected]
+ key23: [not, selected]
+ key32:
+ key31: [not, selected]
+ key32: [not, selected]
+ key33: {not: selected}
+key21: !bar
+ - not selected
+ - !root/key21/1/* selected
+ - not selected
+key31: !baz
+ key12:
+ key13:
+ key14: !root/key31/*/*/key14/map {selected}
+ key23:
+ key14: [not, selected]
+ key33:
+ key14: !root/key31/*/*/key14/map {selected}
+ key24: {not: selected}
+ key22:
+ - key14: !root/key31/*/*/key14/map {selected}
+ key24: {not: selected}
+ - key14: !root/key31/*/*/key14/map {selected}
diff --git a/src/ext_depends/D-YAML/test/data/run-parser-crash-bug.data b/src/ext_depends/D-YAML/test/data/run-parser-crash-bug.data
new file mode 100644
index 0000000..fe01734
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/run-parser-crash-bug.data
@@ -0,0 +1,8 @@
+---
+- Harry Potter and the Prisoner of Azkaban
+- Harry Potter and the Goblet of Fire
+- Harry Potter and the Order of the Phoenix
+---
+- Memoirs Found in a Bathtub
+- Snow Crash
+- Ghost World
diff --git a/src/ext_depends/D-YAML/test/data/scalars.events b/src/ext_depends/D-YAML/test/data/scalars.events
new file mode 100644
index 0000000..32c40f4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/scalars.events
@@ -0,0 +1,28 @@
+- !StreamStart
+
+- !DocumentStart
+- !MappingStart
+- !Scalar { implicit: [true,true], value: 'empty scalar' }
+- !Scalar { implicit: [true,false], value: '' }
+- !Scalar { implicit: [true,true], value: 'implicit scalar' }
+- !Scalar { implicit: [true,true], value: 'data' }
+- !Scalar { implicit: [true,true], value: 'quoted scalar' }
+- !Scalar { value: 'data', style: '"' }
+- !Scalar { implicit: [true,true], value: 'block scalar' }
+- !Scalar { value: 'data', style: '|' }
+- !Scalar { implicit: [true,true], value: 'empty scalar with tag' }
+- !Scalar { implicit: [false,false], tag: '!mytag', value: '' }
+- !Scalar { implicit: [true,true], value: 'implicit scalar with tag' }
+- !Scalar { implicit: [false,false], tag: '!mytag', value: 'data' }
+- !Scalar { implicit: [true,true], value: 'quoted scalar with tag' }
+- !Scalar { value: 'data', style: '"', tag: '!mytag', implicit: [false,false] }
+- !Scalar { implicit: [true,true], value: 'block scalar with tag' }
+- !Scalar { value: 'data', style: '|', tag: '!mytag', implicit: [false,false] }
+- !Scalar { implicit: [true,true], value: 'single character' }
+- !Scalar { value: 'a', implicit: [true,true] }
+- !Scalar { implicit: [true,true], value: 'single digit' }
+- !Scalar { value: '1', implicit: [true,false] }
+- !MappingEnd
+- !DocumentEnd
+
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/scan-document-end-bug.canonical b/src/ext_depends/D-YAML/test/data/scan-document-end-bug.canonical
new file mode 100644
index 0000000..4a0e8a8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/scan-document-end-bug.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!null ""
diff --git a/src/ext_depends/D-YAML/test/data/scan-document-end-bug.data b/src/ext_depends/D-YAML/test/data/scan-document-end-bug.data
new file mode 100644
index 0000000..3c70543
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/scan-document-end-bug.data
@@ -0,0 +1,3 @@
+# Ticket #4
+---
+... \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/scan-line-break-bug.canonical b/src/ext_depends/D-YAML/test/data/scan-line-break-bug.canonical
new file mode 100644
index 0000000..79f08b7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/scan-line-break-bug.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!map { ? !!str "foo" : !!str "bar baz" }
diff --git a/src/ext_depends/D-YAML/test/data/scan-line-break-bug.data b/src/ext_depends/D-YAML/test/data/scan-line-break-bug.data
new file mode 100644
index 0000000..c974fab
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/scan-line-break-bug.data
@@ -0,0 +1,3 @@
+foo:
+ bar
+ baz
diff --git a/src/ext_depends/D-YAML/test/data/sequences.events b/src/ext_depends/D-YAML/test/data/sequences.events
new file mode 100644
index 0000000..692a329
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/sequences.events
@@ -0,0 +1,81 @@
+- !StreamStart
+
+- !DocumentStart
+- !SequenceStart
+- !SequenceEnd
+- !DocumentEnd
+
+- !DocumentStart
+- !SequenceStart { tag: '!mytag', implicit: false }
+- !SequenceEnd
+- !DocumentEnd
+
+- !DocumentStart
+- !SequenceStart
+- !SequenceStart
+- !SequenceEnd
+- !SequenceStart { tag: '!mytag', implicit: false }
+- !SequenceEnd
+- !SequenceStart
+- !Scalar
+- !Scalar { value: 'data' }
+- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' }
+- !SequenceEnd
+- !SequenceStart
+- !SequenceStart
+- !SequenceStart
+- !Scalar
+- !SequenceEnd
+- !SequenceEnd
+- !SequenceEnd
+- !SequenceStart
+- !SequenceStart { tag: '!mytag', implicit: false }
+- !SequenceStart
+- !Scalar { value: 'data' }
+- !SequenceEnd
+- !SequenceEnd
+- !SequenceEnd
+- !SequenceEnd
+- !DocumentEnd
+
+- !DocumentStart
+- !SequenceStart
+- !MappingStart
+- !Scalar { value: 'key1' }
+- !SequenceStart
+- !Scalar { value: 'data1' }
+- !Scalar { value: 'data2' }
+- !SequenceEnd
+- !Scalar { value: 'key2' }
+- !SequenceStart { tag: '!mytag1', implicit: false }
+- !Scalar { value: 'data3' }
+- !SequenceStart
+- !Scalar { value: 'data4' }
+- !Scalar { value: 'data5' }
+- !SequenceEnd
+- !SequenceStart { tag: '!mytag2', implicit: false }
+- !Scalar { value: 'data6' }
+- !Scalar { value: 'data7' }
+- !SequenceEnd
+- !SequenceEnd
+- !MappingEnd
+- !SequenceEnd
+- !DocumentEnd
+
+- !DocumentStart
+- !SequenceStart
+- !SequenceStart { flow_style: true }
+- !SequenceStart
+- !SequenceEnd
+- !Scalar
+- !Scalar { value: 'data' }
+- !Scalar { tag: '!mytag', implicit: [false,false], value: 'data' }
+- !SequenceStart { tag: '!mytag', implicit: false }
+- !Scalar { value: 'data' }
+- !Scalar { value: 'data' }
+- !SequenceEnd
+- !SequenceEnd
+- !SequenceEnd
+- !DocumentEnd
+
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.code b/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.data b/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.data
new file mode 100644
index 0000000..9c558e3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/single-dot-is-not-float-bug.data
@@ -0,0 +1 @@
+.
diff --git a/src/ext_depends/D-YAML/test/data/sloppy-indentation.canonical b/src/ext_depends/D-YAML/test/data/sloppy-indentation.canonical
new file mode 100644
index 0000000..438bc04
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/sloppy-indentation.canonical
@@ -0,0 +1,18 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "in the block context"
+ : !!map {
+ ? !!str "indentation should be kept"
+ : !!map {
+ ? !!str "but in the flow context"
+ : !!seq [ !!str "it may be violated" ]
+ }
+ }
+}
+--- !!str
+"the parser does not require scalars to be indented with at least one space"
+--- !!str
+"the parser does not require scalars to be indented with at least one space"
+--- !!map
+{ ? !!str "foo": { ? !!str "bar" : !!str "quoted scalars may not adhere indentation" } }
diff --git a/src/ext_depends/D-YAML/test/data/sloppy-indentation.data b/src/ext_depends/D-YAML/test/data/sloppy-indentation.data
new file mode 100644
index 0000000..2eb4f5a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/sloppy-indentation.data
@@ -0,0 +1,17 @@
+---
+in the block context:
+ indentation should be kept: {
+ but in the flow context: [
+it may be violated]
+}
+---
+the parser does not require scalars
+to be indented with at least one space
+...
+---
+"the parser does not require scalars
+to be indented with at least one space"
+---
+foo:
+ bar: 'quoted scalars
+may not adhere indentation'
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-01.data b/src/ext_depends/D-YAML/test/data/spec-02-01.data
new file mode 100644
index 0000000..d12e671
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-01.data
@@ -0,0 +1,3 @@
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-01.structure b/src/ext_depends/D-YAML/test/data/spec-02-01.structure
new file mode 100644
index 0000000..f532f4a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-01.structure
@@ -0,0 +1 @@
+[True, True, True]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-01.tokens b/src/ext_depends/D-YAML/test/data/spec-02-01.tokens
new file mode 100644
index 0000000..ce44cac
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-01.tokens
@@ -0,0 +1 @@
+[[ , _ , _ , _ ]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-02.data b/src/ext_depends/D-YAML/test/data/spec-02-02.data
new file mode 100644
index 0000000..7b7ec94
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-02.data
@@ -0,0 +1,3 @@
+hr: 65 # Home runs
+avg: 0.278 # Batting average
+rbi: 147 # Runs Batted In
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-02.structure b/src/ext_depends/D-YAML/test/data/spec-02-02.structure
new file mode 100644
index 0000000..aba1ced
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-02.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-02.tokens b/src/ext_depends/D-YAML/test/data/spec-02-02.tokens
new file mode 100644
index 0000000..e4e381b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-02.tokens
@@ -0,0 +1,5 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-03.data b/src/ext_depends/D-YAML/test/data/spec-02-03.data
new file mode 100644
index 0000000..656d628
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-03.data
@@ -0,0 +1,8 @@
+american:
+ - Boston Red Sox
+ - Detroit Tigers
+ - New York Yankees
+national:
+ - New York Mets
+ - Chicago Cubs
+ - Atlanta Braves
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-03.structure b/src/ext_depends/D-YAML/test/data/spec-02-03.structure
new file mode 100644
index 0000000..25de5d2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-03.structure
@@ -0,0 +1 @@
+[(True, [True, True, True]), (True, [True, True, True])]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-03.tokens b/src/ext_depends/D-YAML/test/data/spec-02-03.tokens
new file mode 100644
index 0000000..89815f2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-03.tokens
@@ -0,0 +1,4 @@
+{{
+? _ : [[ , _ , _ , _ ]}
+? _ : [[ , _ , _ , _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-04.data b/src/ext_depends/D-YAML/test/data/spec-02-04.data
new file mode 100644
index 0000000..430f6b3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-04.data
@@ -0,0 +1,8 @@
+-
+ name: Mark McGwire
+ hr: 65
+ avg: 0.278
+-
+ name: Sammy Sosa
+ hr: 63
+ avg: 0.288
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-04.structure b/src/ext_depends/D-YAML/test/data/spec-02-04.structure
new file mode 100644
index 0000000..e7b526c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-04.structure
@@ -0,0 +1,4 @@
+[
+ [(True, True), (True, True), (True, True)],
+ [(True, True), (True, True), (True, True)],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-04.tokens b/src/ext_depends/D-YAML/test/data/spec-02-04.tokens
new file mode 100644
index 0000000..9cb9815
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-04.tokens
@@ -0,0 +1,4 @@
+[[
+, {{ ? _ : _ ? _ : _ ? _ : _ ]}
+, {{ ? _ : _ ? _ : _ ? _ : _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-05.data b/src/ext_depends/D-YAML/test/data/spec-02-05.data
new file mode 100644
index 0000000..cdd7770
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-05.data
@@ -0,0 +1,3 @@
+- [name , hr, avg ]
+- [Mark McGwire, 65, 0.278]
+- [Sammy Sosa , 63, 0.288]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-05.structure b/src/ext_depends/D-YAML/test/data/spec-02-05.structure
new file mode 100644
index 0000000..e06b75a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-05.structure
@@ -0,0 +1,5 @@
+[
+ [True, True, True],
+ [True, True, True],
+ [True, True, True],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-05.tokens b/src/ext_depends/D-YAML/test/data/spec-02-05.tokens
new file mode 100644
index 0000000..3f6f1ab
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-05.tokens
@@ -0,0 +1,5 @@
+[[
+, [ _ , _ , _ ]
+, [ _ , _ , _ ]
+, [ _ , _ , _ ]
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-06.data b/src/ext_depends/D-YAML/test/data/spec-02-06.data
new file mode 100644
index 0000000..7a957b2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-06.data
@@ -0,0 +1,5 @@
+Mark McGwire: {hr: 65, avg: 0.278}
+Sammy Sosa: {
+ hr: 63,
+ avg: 0.288
+ }
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-06.structure b/src/ext_depends/D-YAML/test/data/spec-02-06.structure
new file mode 100644
index 0000000..3ef0f4b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-06.structure
@@ -0,0 +1,4 @@
+[
+ (True, [(True, True), (True, True)]),
+ (True, [(True, True), (True, True)]),
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-06.tokens b/src/ext_depends/D-YAML/test/data/spec-02-06.tokens
new file mode 100644
index 0000000..a1a5eef
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-06.tokens
@@ -0,0 +1,4 @@
+{{
+? _ : { ? _ : _ , ? _ : _ }
+? _ : { ? _ : _ , ? _ : _ }
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-07.data b/src/ext_depends/D-YAML/test/data/spec-02-07.data
new file mode 100644
index 0000000..bc711d5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-07.data
@@ -0,0 +1,10 @@
+# Ranking of 1998 home runs
+---
+- Mark McGwire
+- Sammy Sosa
+- Ken Griffey
+
+# Team ranking
+---
+- Chicago Cubs
+- St Louis Cardinals
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-07.structure b/src/ext_depends/D-YAML/test/data/spec-02-07.structure
new file mode 100644
index 0000000..c5d72a3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-07.structure
@@ -0,0 +1,4 @@
+[
+[True, True, True],
+[True, True],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-07.tokens b/src/ext_depends/D-YAML/test/data/spec-02-07.tokens
new file mode 100644
index 0000000..ed48883
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-07.tokens
@@ -0,0 +1,12 @@
+---
+[[
+, _
+, _
+, _
+]}
+
+---
+[[
+, _
+, _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-08.data b/src/ext_depends/D-YAML/test/data/spec-02-08.data
new file mode 100644
index 0000000..05e102d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-08.data
@@ -0,0 +1,10 @@
+---
+time: 20:03:20
+player: Sammy Sosa
+action: strike (miss)
+...
+---
+time: 20:03:47
+player: Sammy Sosa
+action: grand slam
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-08.structure b/src/ext_depends/D-YAML/test/data/spec-02-08.structure
new file mode 100644
index 0000000..24cff73
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-08.structure
@@ -0,0 +1,4 @@
+[
+[(True, True), (True, True), (True, True)],
+[(True, True), (True, True), (True, True)],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-08.tokens b/src/ext_depends/D-YAML/test/data/spec-02-08.tokens
new file mode 100644
index 0000000..7d2c03d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-08.tokens
@@ -0,0 +1,15 @@
+---
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
+...
+
+---
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-09.data b/src/ext_depends/D-YAML/test/data/spec-02-09.data
new file mode 100644
index 0000000..e264180
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-09.data
@@ -0,0 +1,8 @@
+---
+hr: # 1998 hr ranking
+ - Mark McGwire
+ - Sammy Sosa
+rbi:
+ # 1998 rbi ranking
+ - Sammy Sosa
+ - Ken Griffey
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-09.structure b/src/ext_depends/D-YAML/test/data/spec-02-09.structure
new file mode 100644
index 0000000..b4c9914
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-09.structure
@@ -0,0 +1 @@
+[(True, [True, True]), (True, [True, True])]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-09.tokens b/src/ext_depends/D-YAML/test/data/spec-02-09.tokens
new file mode 100644
index 0000000..b2ec10e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-09.tokens
@@ -0,0 +1,5 @@
+---
+{{
+? _ : [[ , _ , _ ]}
+? _ : [[ , _ , _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-10.data b/src/ext_depends/D-YAML/test/data/spec-02-10.data
new file mode 100644
index 0000000..61808f6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-10.data
@@ -0,0 +1,8 @@
+---
+hr:
+ - Mark McGwire
+ # Following node labeled SS
+ - &SS Sammy Sosa
+rbi:
+ - *SS # Subsequent occurrence
+ - Ken Griffey
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-10.structure b/src/ext_depends/D-YAML/test/data/spec-02-10.structure
new file mode 100644
index 0000000..ff8f4c3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-10.structure
@@ -0,0 +1 @@
+[(True, [True, True]), (True, ['*', True])]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-10.tokens b/src/ext_depends/D-YAML/test/data/spec-02-10.tokens
new file mode 100644
index 0000000..26caa2b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-10.tokens
@@ -0,0 +1,5 @@
+---
+{{
+? _ : [[ , _ , & _ ]}
+? _ : [[ , * , _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-11.data b/src/ext_depends/D-YAML/test/data/spec-02-11.data
new file mode 100644
index 0000000..9123ce2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-11.data
@@ -0,0 +1,9 @@
+? - Detroit Tigers
+ - Chicago cubs
+:
+ - 2001-07-23
+
+? [ New York Yankees,
+ Atlanta Braves ]
+: [ 2001-07-02, 2001-08-12,
+ 2001-08-14 ]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-11.structure b/src/ext_depends/D-YAML/test/data/spec-02-11.structure
new file mode 100644
index 0000000..3d8f1ff
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-11.structure
@@ -0,0 +1,4 @@
+[
+([True, True], [True]),
+([True, True], [True, True, True]),
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-11.tokens b/src/ext_depends/D-YAML/test/data/spec-02-11.tokens
new file mode 100644
index 0000000..fe24203
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-11.tokens
@@ -0,0 +1,6 @@
+{{
+? [[ , _ , _ ]}
+: [[ , _ ]}
+? [ _ , _ ]
+: [ _ , _ , _ ]
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-12.data b/src/ext_depends/D-YAML/test/data/spec-02-12.data
new file mode 100644
index 0000000..1fc33f9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-12.data
@@ -0,0 +1,8 @@
+---
+# products purchased
+- item : Super Hoop
+ quantity: 1
+- item : Basketball
+ quantity: 4
+- item : Big Shoes
+ quantity: 1
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-12.structure b/src/ext_depends/D-YAML/test/data/spec-02-12.structure
new file mode 100644
index 0000000..e9c5359
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-12.structure
@@ -0,0 +1,5 @@
+[
+[(True, True), (True, True)],
+[(True, True), (True, True)],
+[(True, True), (True, True)],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-12.tokens b/src/ext_depends/D-YAML/test/data/spec-02-12.tokens
new file mode 100644
index 0000000..ea21e50
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-12.tokens
@@ -0,0 +1,6 @@
+---
+[[
+, {{ ? _ : _ ? _ : _ ]}
+, {{ ? _ : _ ? _ : _ ]}
+, {{ ? _ : _ ? _ : _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-13.data b/src/ext_depends/D-YAML/test/data/spec-02-13.data
new file mode 100644
index 0000000..13fb656
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-13.data
@@ -0,0 +1,4 @@
+# ASCII Art
+--- |
+ \//||\/||
+ // || ||__
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-13.structure b/src/ext_depends/D-YAML/test/data/spec-02-13.structure
new file mode 100644
index 0000000..0ca9514
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-13.structure
@@ -0,0 +1 @@
+True
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-13.tokens b/src/ext_depends/D-YAML/test/data/spec-02-13.tokens
new file mode 100644
index 0000000..7456c05
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-13.tokens
@@ -0,0 +1 @@
+--- _
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-14.data b/src/ext_depends/D-YAML/test/data/spec-02-14.data
new file mode 100644
index 0000000..59943de
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-14.data
@@ -0,0 +1,4 @@
+---
+ Mark McGwire's
+ year was crippled
+ by a knee injury.
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-14.structure b/src/ext_depends/D-YAML/test/data/spec-02-14.structure
new file mode 100644
index 0000000..0ca9514
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-14.structure
@@ -0,0 +1 @@
+True
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-14.tokens b/src/ext_depends/D-YAML/test/data/spec-02-14.tokens
new file mode 100644
index 0000000..7456c05
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-14.tokens
@@ -0,0 +1 @@
+--- _
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-15.data b/src/ext_depends/D-YAML/test/data/spec-02-15.data
new file mode 100644
index 0000000..80b89a6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-15.data
@@ -0,0 +1,8 @@
+>
+ Sammy Sosa completed another
+ fine season with great stats.
+
+ 63 Home Runs
+ 0.288 Batting Average
+
+ What a year!
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-15.structure b/src/ext_depends/D-YAML/test/data/spec-02-15.structure
new file mode 100644
index 0000000..0ca9514
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-15.structure
@@ -0,0 +1 @@
+True
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-15.tokens b/src/ext_depends/D-YAML/test/data/spec-02-15.tokens
new file mode 100644
index 0000000..31354ec
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-15.tokens
@@ -0,0 +1 @@
+_
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-16.data b/src/ext_depends/D-YAML/test/data/spec-02-16.data
new file mode 100644
index 0000000..9f66d88
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-16.data
@@ -0,0 +1,7 @@
+name: Mark McGwire
+accomplishment: >
+ Mark set a major league
+ home run record in 1998.
+stats: |
+ 65 Home Runs
+ 0.278 Batting Average
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-16.structure b/src/ext_depends/D-YAML/test/data/spec-02-16.structure
new file mode 100644
index 0000000..aba1ced
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-16.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-16.tokens b/src/ext_depends/D-YAML/test/data/spec-02-16.tokens
new file mode 100644
index 0000000..e4e381b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-16.tokens
@@ -0,0 +1,5 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-17.data b/src/ext_depends/D-YAML/test/data/spec-02-17.data
new file mode 100644
index 0000000..b2870c5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-17.data
@@ -0,0 +1,7 @@
+unicode: "Sosa did fine.\u263A"
+control: "\b1998\t1999\t2000\n"
+hexesc: "\x13\x10 is \r\n"
+
+single: '"Howdy!" he cried.'
+quoted: ' # not a ''comment''.'
+tie-fighter: '|\-*-/|'
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-17.structure b/src/ext_depends/D-YAML/test/data/spec-02-17.structure
new file mode 100644
index 0000000..933646d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-17.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True), (True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-17.tokens b/src/ext_depends/D-YAML/test/data/spec-02-17.tokens
new file mode 100644
index 0000000..db65540
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-17.tokens
@@ -0,0 +1,8 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-18.data b/src/ext_depends/D-YAML/test/data/spec-02-18.data
new file mode 100644
index 0000000..e0a8bfa
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-18.data
@@ -0,0 +1,6 @@
+plain:
+ This unquoted scalar
+ spans many lines.
+
+quoted: "So does this
+ quoted scalar.\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-18.structure b/src/ext_depends/D-YAML/test/data/spec-02-18.structure
new file mode 100644
index 0000000..0ca4991
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-18.structure
@@ -0,0 +1 @@
+[(True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-18.tokens b/src/ext_depends/D-YAML/test/data/spec-02-18.tokens
new file mode 100644
index 0000000..83b31dc
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-18.tokens
@@ -0,0 +1,4 @@
+{{
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-19.data b/src/ext_depends/D-YAML/test/data/spec-02-19.data
new file mode 100644
index 0000000..bf69de6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-19.data
@@ -0,0 +1,5 @@
+canonical: 12345
+decimal: +12,345
+sexagesimal: 3:25:45
+octal: 014
+hexadecimal: 0xC
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-19.structure b/src/ext_depends/D-YAML/test/data/spec-02-19.structure
new file mode 100644
index 0000000..48ca99d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-19.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-19.tokens b/src/ext_depends/D-YAML/test/data/spec-02-19.tokens
new file mode 100644
index 0000000..5bda68f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-19.tokens
@@ -0,0 +1,7 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-20.data b/src/ext_depends/D-YAML/test/data/spec-02-20.data
new file mode 100644
index 0000000..1d4897f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-20.data
@@ -0,0 +1,6 @@
+canonical: 1.23015e+3
+exponential: 12.3015e+02
+sexagesimal: 20:30.15
+fixed: 1,230.15
+negative infinity: -.inf
+not a number: .NaN
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-20.structure b/src/ext_depends/D-YAML/test/data/spec-02-20.structure
new file mode 100644
index 0000000..933646d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-20.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True), (True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-20.tokens b/src/ext_depends/D-YAML/test/data/spec-02-20.tokens
new file mode 100644
index 0000000..db65540
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-20.tokens
@@ -0,0 +1,8 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-21.data b/src/ext_depends/D-YAML/test/data/spec-02-21.data
new file mode 100644
index 0000000..dec6a56
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-21.data
@@ -0,0 +1,4 @@
+null: ~
+true: y
+false: n
+string: '12345'
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-21.structure b/src/ext_depends/D-YAML/test/data/spec-02-21.structure
new file mode 100644
index 0000000..021635f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-21.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-21.tokens b/src/ext_depends/D-YAML/test/data/spec-02-21.tokens
new file mode 100644
index 0000000..aeccbaf
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-21.tokens
@@ -0,0 +1,6 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-22.data b/src/ext_depends/D-YAML/test/data/spec-02-22.data
new file mode 100644
index 0000000..aaac185
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-22.data
@@ -0,0 +1,4 @@
+canonical: 2001-12-15T02:59:43.1Z
+iso8601: 2001-12-14t21:59:43.10-05:00
+spaced: 2001-12-14 21:59:43.10 -5
+date: 2002-12-14
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-22.structure b/src/ext_depends/D-YAML/test/data/spec-02-22.structure
new file mode 100644
index 0000000..021635f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-22.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-22.tokens b/src/ext_depends/D-YAML/test/data/spec-02-22.tokens
new file mode 100644
index 0000000..aeccbaf
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-22.tokens
@@ -0,0 +1,6 @@
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-23.data b/src/ext_depends/D-YAML/test/data/spec-02-23.data
new file mode 100644
index 0000000..5dbd992
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-23.data
@@ -0,0 +1,13 @@
+---
+not-date: !!str 2002-04-28
+
+picture: !!binary |
+ R0lGODlhDAAMAIQAAP//9/X
+ 17unp5WZmZgAAAOfn515eXv
+ Pz7Y6OjuDg4J+fn5OTk6enp
+ 56enmleECcgggoBADs=
+
+application specific tag: !something |
+ The semantics of the tag
+ above may be different for
+ different documents.
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-23.structure b/src/ext_depends/D-YAML/test/data/spec-02-23.structure
new file mode 100644
index 0000000..aba1ced
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-23.structure
@@ -0,0 +1 @@
+[(True, True), (True, True), (True, True)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-23.tokens b/src/ext_depends/D-YAML/test/data/spec-02-23.tokens
new file mode 100644
index 0000000..9ac54aa
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-23.tokens
@@ -0,0 +1,6 @@
+---
+{{
+? _ : ! _
+? _ : ! _
+? _ : ! _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-24.data b/src/ext_depends/D-YAML/test/data/spec-02-24.data
new file mode 100644
index 0000000..1180757
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-24.data
@@ -0,0 +1,14 @@
+%TAG ! tag:clarkevans.com,2002:
+--- !shape
+ # Use the ! handle for presenting
+ # tag:clarkevans.com,2002:circle
+- !circle
+ center: &ORIGIN {x: 73, y: 129}
+ radius: 7
+- !line
+ start: *ORIGIN
+ finish: { x: 89, y: 102 }
+- !label
+ start: *ORIGIN
+ color: 0xFFEEBB
+ text: Pretty vector drawing.
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-24.structure b/src/ext_depends/D-YAML/test/data/spec-02-24.structure
new file mode 100644
index 0000000..a800729
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-24.structure
@@ -0,0 +1,5 @@
+[
+[(True, [(True, True), (True, True)]), (True, True)],
+[(True, '*'), (True, [(True, True), (True, True)])],
+[(True, '*'), (True, True), (True, True)],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-24.tokens b/src/ext_depends/D-YAML/test/data/spec-02-24.tokens
new file mode 100644
index 0000000..039c385
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-24.tokens
@@ -0,0 +1,20 @@
+%
+--- !
+[[
+, !
+ {{
+ ? _ : & { ? _ : _ , ? _ : _ }
+ ? _ : _
+ ]}
+, !
+ {{
+ ? _ : *
+ ? _ : { ? _ : _ , ? _ : _ }
+ ]}
+, !
+ {{
+ ? _ : *
+ ? _ : _
+ ? _ : _
+ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-25.data b/src/ext_depends/D-YAML/test/data/spec-02-25.data
new file mode 100644
index 0000000..769ac31
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-25.data
@@ -0,0 +1,7 @@
+# sets are represented as a
+# mapping where each key is
+# associated with the empty string
+--- !!set
+? Mark McGwire
+? Sammy Sosa
+? Ken Griff
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-25.structure b/src/ext_depends/D-YAML/test/data/spec-02-25.structure
new file mode 100644
index 0000000..0b40e61
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-25.structure
@@ -0,0 +1 @@
+[(True, None), (True, None), (True, None)]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-25.tokens b/src/ext_depends/D-YAML/test/data/spec-02-25.tokens
new file mode 100644
index 0000000..b700236
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-25.tokens
@@ -0,0 +1,6 @@
+--- !
+{{
+? _
+? _
+? _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-26.data b/src/ext_depends/D-YAML/test/data/spec-02-26.data
new file mode 100644
index 0000000..3143763
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-26.data
@@ -0,0 +1,7 @@
+# ordered maps are represented as
+# a sequence of mappings, with
+# each mapping having one key
+--- !!omap
+- Mark McGwire: 65
+- Sammy Sosa: 63
+- Ken Griffy: 58
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-26.structure b/src/ext_depends/D-YAML/test/data/spec-02-26.structure
new file mode 100644
index 0000000..cf429b9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-26.structure
@@ -0,0 +1,5 @@
+[
+[(True, True)],
+[(True, True)],
+[(True, True)],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-26.tokens b/src/ext_depends/D-YAML/test/data/spec-02-26.tokens
new file mode 100644
index 0000000..7bee492
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-26.tokens
@@ -0,0 +1,6 @@
+--- !
+[[
+, {{ ? _ : _ ]}
+, {{ ? _ : _ ]}
+, {{ ? _ : _ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-27.data b/src/ext_depends/D-YAML/test/data/spec-02-27.data
new file mode 100644
index 0000000..4625739
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-27.data
@@ -0,0 +1,29 @@
+--- !<tag:clarkevans.com,2002:invoice>
+invoice: 34843
+date : 2001-01-23
+bill-to: &id001
+ given : Chris
+ family : Dumars
+ address:
+ lines: |
+ 458 Walkman Dr.
+ Suite #292
+ city : Royal Oak
+ state : MI
+ postal : 48046
+ship-to: *id001
+product:
+ - sku : BL394D
+ quantity : 4
+ description : Basketball
+ price : 450.00
+ - sku : BL4438H
+ quantity : 1
+ description : Super Hoop
+ price : 2392.00
+tax : 251.42
+total: 4443.52
+comments:
+ Late afternoon is best.
+ Backup contact is Nancy
+ Billsmer @ 338-4338.
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-27.structure b/src/ext_depends/D-YAML/test/data/spec-02-27.structure
new file mode 100644
index 0000000..a2113b9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-27.structure
@@ -0,0 +1,17 @@
+[
+(True, True),
+(True, True),
+(True, [
+ (True, True),
+ (True, True),
+ (True, [(True, True), (True, True), (True, True), (True, True)]),
+ ]),
+(True, '*'),
+(True, [
+ [(True, True), (True, True), (True, True), (True, True)],
+ [(True, True), (True, True), (True, True), (True, True)],
+ ]),
+(True, True),
+(True, True),
+(True, True),
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-27.tokens b/src/ext_depends/D-YAML/test/data/spec-02-27.tokens
new file mode 100644
index 0000000..2dc1c25
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-27.tokens
@@ -0,0 +1,20 @@
+--- !
+{{
+? _ : _
+? _ : _
+? _ : &
+ {{
+ ? _ : _
+ ? _ : _
+ ? _ : {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]}
+ ]}
+? _ : *
+? _ :
+ [[
+ , {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]}
+ , {{ ? _ : _ ? _ : _ ? _ : _ ? _ : _ ]}
+ ]}
+? _ : _
+? _ : _
+? _ : _
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-28.data b/src/ext_depends/D-YAML/test/data/spec-02-28.data
new file mode 100644
index 0000000..a5c8dc8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-28.data
@@ -0,0 +1,26 @@
+---
+Time: 2001-11-23 15:01:42 -5
+User: ed
+Warning:
+ This is an error message
+ for the log file
+---
+Time: 2001-11-23 15:02:31 -5
+User: ed
+Warning:
+ A slightly different error
+ message.
+---
+Date: 2001-11-23 15:03:17 -5
+User: ed
+Fatal:
+ Unknown variable "bar"
+Stack:
+ - file: TopClass.py
+ line: 23
+ code: |
+ x = MoreObject("345\n")
+ - file: MoreClass.py
+ line: 58
+ code: |-
+ foo = bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-28.structure b/src/ext_depends/D-YAML/test/data/spec-02-28.structure
new file mode 100644
index 0000000..8ec0b56
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-28.structure
@@ -0,0 +1,10 @@
+[
+[(True, True), (True, True), (True, True)],
+[(True, True), (True, True), (True, True)],
+[(True, True), (True, True), (True, True),
+(True, [
+ [(True, True), (True, True), (True, True)],
+ [(True, True), (True, True), (True, True)],
+ ]),
+]
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-02-28.tokens b/src/ext_depends/D-YAML/test/data/spec-02-28.tokens
new file mode 100644
index 0000000..8d5e1bc
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-02-28.tokens
@@ -0,0 +1,23 @@
+---
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
+---
+{{
+? _ : _
+? _ : _
+? _ : _
+]}
+---
+{{
+? _ : _
+? _ : _
+? _ : _
+? _ :
+ [[
+ , {{ ? _ : _ ? _ : _ ? _ : _ ]}
+ , {{ ? _ : _ ? _ : _ ? _ : _ ]}
+ ]}
+]}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.data b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.data
new file mode 100644
index 0000000..3525062
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.empty b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.data b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.data
new file mode 100644
index 0000000..0823f74
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.empty b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.data b/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.data
new file mode 100644
index 0000000..780d25b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.data
@@ -0,0 +1 @@
+# Comment only.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.empty b/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf8.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.data b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.data
new file mode 100644
index 0000000..5ebbb04
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.error b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.error
new file mode 100644
index 0000000..1df3616
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.error
@@ -0,0 +1,3 @@
+ERROR:
+ A BOM must not appear
+ inside a document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.data b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.data
new file mode 100644
index 0000000..0cd90a2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.error b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.error
new file mode 100644
index 0000000..1df3616
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.error
@@ -0,0 +1,3 @@
+ERROR:
+ A BOM must not appear
+ inside a document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.data b/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.data
new file mode 100644
index 0000000..fb74866
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.data
@@ -0,0 +1,3 @@
+# Invalid use of BOM
+# inside a
+# document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.error b/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.error
new file mode 100644
index 0000000..1df3616
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf8.error
@@ -0,0 +1,3 @@
+ERROR:
+ A BOM must not appear
+ inside a document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-03.canonical b/src/ext_depends/D-YAML/test/data/spec-05-03.canonical
new file mode 100644
index 0000000..a143a73
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-03.canonical
@@ -0,0 +1,14 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "sequence"
+ : !!seq [
+ !!str "one", !!str "two"
+ ],
+ ? !!str "mapping"
+ : !!map {
+ ? !!str "sky" : !!str "blue",
+# ? !!str "sea" : !!str "green",
+ ? !!map { ? !!str "sea" : !!str "green" } : !!null "",
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-03.data b/src/ext_depends/D-YAML/test/data/spec-05-03.data
new file mode 100644
index 0000000..4661f33
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-03.data
@@ -0,0 +1,7 @@
+sequence:
+- one
+- two
+mapping:
+ ? sky
+ : blue
+ ? sea : green
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-04.canonical b/src/ext_depends/D-YAML/test/data/spec-05-04.canonical
new file mode 100644
index 0000000..00c9723
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-04.canonical
@@ -0,0 +1,13 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "sequence"
+ : !!seq [
+ !!str "one", !!str "two"
+ ],
+ ? !!str "mapping"
+ : !!map {
+ ? !!str "sky" : !!str "blue",
+ ? !!str "sea" : !!str "green",
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-04.data b/src/ext_depends/D-YAML/test/data/spec-05-04.data
new file mode 100644
index 0000000..df33847
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-04.data
@@ -0,0 +1,2 @@
+sequence: [ one, two, ]
+mapping: { sky: blue, sea: green }
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-05.data b/src/ext_depends/D-YAML/test/data/spec-05-05.data
new file mode 100644
index 0000000..62524c0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-05.data
@@ -0,0 +1 @@
+# Comment only.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-05.empty b/src/ext_depends/D-YAML/test/data/spec-05-05.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-05.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-06.canonical b/src/ext_depends/D-YAML/test/data/spec-05-06.canonical
new file mode 100644
index 0000000..4f30c11
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-06.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "anchored"
+ : &A1 !local "value",
+ ? !!str "alias"
+ : *A1,
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-06.data b/src/ext_depends/D-YAML/test/data/spec-05-06.data
new file mode 100644
index 0000000..7a1f9b3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-06.data
@@ -0,0 +1,2 @@
+anchored: !local &anchor value
+alias: *anchor
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-06.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-05-06.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-06.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-07.canonical b/src/ext_depends/D-YAML/test/data/spec-05-07.canonical
new file mode 100644
index 0000000..dc3732a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-07.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "literal"
+ : !!str "text\n",
+ ? !!str "folded"
+ : !!str "text\n",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-07.data b/src/ext_depends/D-YAML/test/data/spec-05-07.data
new file mode 100644
index 0000000..97eb3a3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-07.data
@@ -0,0 +1,4 @@
+literal: |
+ text
+folded: >
+ text
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-08.canonical b/src/ext_depends/D-YAML/test/data/spec-05-08.canonical
new file mode 100644
index 0000000..610bd68
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-08.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "single"
+ : !!str "text",
+ ? !!str "double"
+ : !!str "text",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-08.data b/src/ext_depends/D-YAML/test/data/spec-05-08.data
new file mode 100644
index 0000000..04ebf69
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-08.data
@@ -0,0 +1,2 @@
+single: 'text'
+double: "text"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-09.canonical b/src/ext_depends/D-YAML/test/data/spec-05-09.canonical
new file mode 100644
index 0000000..597e3de
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-09.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "text"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-09.data b/src/ext_depends/D-YAML/test/data/spec-05-09.data
new file mode 100644
index 0000000..a43431b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-09.data
@@ -0,0 +1,2 @@
+%YAML 1.1
+--- text
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-10.data b/src/ext_depends/D-YAML/test/data/spec-05-10.data
new file mode 100644
index 0000000..a4caf91
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-10.data
@@ -0,0 +1,2 @@
+commercial-at: @text
+grave-accent: `text
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-10.error b/src/ext_depends/D-YAML/test/data/spec-05-10.error
new file mode 100644
index 0000000..46f776e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-10.error
@@ -0,0 +1,3 @@
+ERROR:
+ Reserved indicators can't
+ start a plain scalar.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-11.canonical b/src/ext_depends/D-YAML/test/data/spec-05-11.canonical
new file mode 100644
index 0000000..fc25bef
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-11.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+--- !!str
+"Generic line break (no glyph)\n\
+ Generic line break (glyphed)\n\
+ Line separator\u2028\
+ Paragraph separator\u2029"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-11.data b/src/ext_depends/D-YAML/test/data/spec-05-11.data
new file mode 100644
index 0000000..b448b75
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-11.data
@@ -0,0 +1,3 @@
+|
+ Generic line break (no glyph)
+ Generic line break (glyphed)… Line separator
 Paragraph separator
 \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-12.data b/src/ext_depends/D-YAML/test/data/spec-05-12.data
new file mode 100644
index 0000000..7c3ad7f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-12.data
@@ -0,0 +1,9 @@
+# Tabs do's and don'ts:
+# comment:
+quoted: "Quoted "
+block: |
+ void main() {
+ printf("Hello, world!\n");
+ }
+elsewhere: # separation
+ indentation, in plain scalar
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-12.error b/src/ext_depends/D-YAML/test/data/spec-05-12.error
new file mode 100644
index 0000000..8aad4c8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-12.error
@@ -0,0 +1,8 @@
+ERROR:
+ Tabs may appear inside
+ comments and quoted or
+ block scalar content.
+ Tabs must not appear
+ elsewhere, such as
+ in indentation and
+ separation spaces.
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-13.canonical b/src/ext_depends/D-YAML/test/data/spec-05-13.canonical
new file mode 100644
index 0000000..90c1c5c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-13.canonical
@@ -0,0 +1,5 @@
+%YAML 1.1
+--- !!str
+"Text containing \
+ both space and \
+ tab characters"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-13.data b/src/ext_depends/D-YAML/test/data/spec-05-13.data
new file mode 100644
index 0000000..fce7951
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-13.data
@@ -0,0 +1,3 @@
+ "Text containing
+ both space and
+ tab characters"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-14.canonical b/src/ext_depends/D-YAML/test/data/spec-05-14.canonical
new file mode 100644
index 0000000..4bff01c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-14.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+"Fun with \x5C
+ \x22 \x07 \x08 \x1B \x0C
+ \x0A \x0D \x09 \x0B \x00
+ \x20 \xA0 \x85 \u2028 \u2029
+ A A A"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-14.data b/src/ext_depends/D-YAML/test/data/spec-05-14.data
new file mode 100644
index 0000000..d6e8ce4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-14.data
@@ -0,0 +1,2 @@
+"Fun with \\
+ \" \a \b \e \f \… \n \r \t \v \0 \
 \ \_ \N \L \P \
 \x41 \u0041 \U00000041"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-15.data b/src/ext_depends/D-YAML/test/data/spec-05-15.data
new file mode 100644
index 0000000..7bf12b6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-15.data
@@ -0,0 +1,3 @@
+Bad escapes:
+ "\c
+ \xq-"
diff --git a/src/ext_depends/D-YAML/test/data/spec-05-15.error b/src/ext_depends/D-YAML/test/data/spec-05-15.error
new file mode 100644
index 0000000..71ffbd9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-05-15.error
@@ -0,0 +1,3 @@
+ERROR:
+- c is an invalid escaped character.
+- q and - are invalid hex digits.
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-01.canonical b/src/ext_depends/D-YAML/test/data/spec-06-01.canonical
new file mode 100644
index 0000000..f17ec92
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-01.canonical
@@ -0,0 +1,15 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "Not indented"
+ : !!map {
+ ? !!str "By one space"
+ : !!str "By four\n spaces\n",
+ ? !!str "Flow style"
+ : !!seq [
+ !!str "By two",
+ !!str "Also by two",
+ !!str "Still by two",
+ ]
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-01.data b/src/ext_depends/D-YAML/test/data/spec-06-01.data
new file mode 100644
index 0000000..6134ba1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-01.data
@@ -0,0 +1,14 @@
+ # Leading comment line spaces are
+ # neither content nor indentation.
+
+Not indented:
+ By one space: |
+ By four
+ spaces
+ Flow style: [ # Leading spaces
+ By two, # in flow style
+ Also by two, # are neither
+# Tabs are not allowed:
+# Still by two # content nor
+ Still by two # content nor
+ ] # indentation.
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-02.data b/src/ext_depends/D-YAML/test/data/spec-06-02.data
new file mode 100644
index 0000000..ff741e5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-02.data
@@ -0,0 +1,3 @@
+ # Comment
+
+
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-02.empty b/src/ext_depends/D-YAML/test/data/spec-06-02.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-02.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-03.canonical b/src/ext_depends/D-YAML/test/data/spec-06-03.canonical
new file mode 100644
index 0000000..ec26902
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-03.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "key"
+ : !!str "value"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-03.data b/src/ext_depends/D-YAML/test/data/spec-06-03.data
new file mode 100644
index 0000000..9db0912
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-03.data
@@ -0,0 +1,2 @@
+key: # Comment
+ value
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-04.canonical b/src/ext_depends/D-YAML/test/data/spec-06-04.canonical
new file mode 100644
index 0000000..ec26902
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-04.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "key"
+ : !!str "value"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-04.data b/src/ext_depends/D-YAML/test/data/spec-06-04.data
new file mode 100644
index 0000000..86308dd
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-04.data
@@ -0,0 +1,4 @@
+key: # Comment
+ # lines
+ value
+
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-05.canonical b/src/ext_depends/D-YAML/test/data/spec-06-05.canonical
new file mode 100644
index 0000000..8da431d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-05.canonical
@@ -0,0 +1,16 @@
+%YAML 1.1
+---
+!!map {
+ ? !!map {
+ ? !!str "first"
+ : !!str "Sammy",
+ ? !!str "last"
+ : !!str "Sosa"
+ }
+ : !!map {
+ ? !!str "hr"
+ : !!int "65",
+ ? !!str "avg"
+ : !!float "0.278"
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-05.data b/src/ext_depends/D-YAML/test/data/spec-06-05.data
new file mode 100644
index 0000000..37613f5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-05.data
@@ -0,0 +1,6 @@
+{ first: Sammy, last: Sosa }:
+# Statistics:
+ hr: # Home runs
+ 65
+ avg: # Average
+ 0.278
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-06.canonical b/src/ext_depends/D-YAML/test/data/spec-06-06.canonical
new file mode 100644
index 0000000..513d07a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-06.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "plain"
+ : !!str "text lines",
+ ? !!str "quoted"
+ : !!str "text lines",
+ ? !!str "block"
+ : !!str "text\n lines\n"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-06.data b/src/ext_depends/D-YAML/test/data/spec-06-06.data
new file mode 100644
index 0000000..2f62d08
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-06.data
@@ -0,0 +1,7 @@
+plain: text
+ lines
+quoted: "text
+ lines"
+block: |
+ text
+ lines
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-07.canonical b/src/ext_depends/D-YAML/test/data/spec-06-07.canonical
new file mode 100644
index 0000000..11357e4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-07.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "foo\nbar",
+ !!str "foo\n\nbar"
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-07.data b/src/ext_depends/D-YAML/test/data/spec-06-07.data
new file mode 100644
index 0000000..130cfa7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-07.data
@@ -0,0 +1,8 @@
+- foo
+
+ bar
+- |-
+ foo
+
+ bar
+
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-08.canonical b/src/ext_depends/D-YAML/test/data/spec-06-08.canonical
new file mode 100644
index 0000000..cc72bc8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-08.canonical
@@ -0,0 +1,5 @@
+%YAML 1.1
+--- !!str
+"specific\L\
+ trimmed\n\n\n\
+ as space"
diff --git a/src/ext_depends/D-YAML/test/data/spec-06-08.data b/src/ext_depends/D-YAML/test/data/spec-06-08.data
new file mode 100644
index 0000000..f2896ed
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-06-08.data
@@ -0,0 +1,2 @@
+>-
+ specific
 trimmed… … …… as… space
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-01.canonical b/src/ext_depends/D-YAML/test/data/spec-07-01.canonical
new file mode 100644
index 0000000..8c8c48d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-01.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+--- !!str
+"foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-01.data b/src/ext_depends/D-YAML/test/data/spec-07-01.data
new file mode 100644
index 0000000..2113eb6
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-01.data
@@ -0,0 +1,3 @@
+%FOO bar baz # Should be ignored
+ # with a warning.
+--- "foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-01.skip-ext b/src/ext_depends/D-YAML/test/data/spec-07-01.skip-ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-01.skip-ext
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-02.canonical b/src/ext_depends/D-YAML/test/data/spec-07-02.canonical
new file mode 100644
index 0000000..cb7dd1c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-02.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-02.data b/src/ext_depends/D-YAML/test/data/spec-07-02.data
new file mode 100644
index 0000000..c8b7322
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-02.data
@@ -0,0 +1,4 @@
+%YAML 1.2 # Attempt parsing
+ # with a warning
+---
+"foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-02.skip-ext b/src/ext_depends/D-YAML/test/data/spec-07-02.skip-ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-02.skip-ext
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-03.data b/src/ext_depends/D-YAML/test/data/spec-07-03.data
new file mode 100644
index 0000000..4bfa07a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-03.data
@@ -0,0 +1,3 @@
+%YAML 1.1
+%YAML 1.1
+foo
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-03.error b/src/ext_depends/D-YAML/test/data/spec-07-03.error
new file mode 100644
index 0000000..b0ac446
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-03.error
@@ -0,0 +1,3 @@
+ERROR:
+The YAML directive must only be
+given at most once per document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-04.canonical b/src/ext_depends/D-YAML/test/data/spec-07-04.canonical
new file mode 100644
index 0000000..cb7dd1c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-04.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-04.data b/src/ext_depends/D-YAML/test/data/spec-07-04.data
new file mode 100644
index 0000000..50f5ab9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-04.data
@@ -0,0 +1,3 @@
+%TAG !yaml! tag:yaml.org,2002:
+---
+!yaml!str "foo"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-05.data b/src/ext_depends/D-YAML/test/data/spec-07-05.data
new file mode 100644
index 0000000..7276eae
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-05.data
@@ -0,0 +1,3 @@
+%TAG ! !foo
+%TAG ! !foo
+bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-05.error b/src/ext_depends/D-YAML/test/data/spec-07-05.error
new file mode 100644
index 0000000..5601b19
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-05.error
@@ -0,0 +1,4 @@
+ERROR:
+The TAG directive must only
+be given at most once per
+handle in the same document.
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-06.canonical b/src/ext_depends/D-YAML/test/data/spec-07-06.canonical
new file mode 100644
index 0000000..bddf616
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-06.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!seq [
+ !<!foobar> "baz",
+ !<tag:yaml.org,2002:str> "string"
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-06.data b/src/ext_depends/D-YAML/test/data/spec-07-06.data
new file mode 100644
index 0000000..d9854cb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-06.data
@@ -0,0 +1,5 @@
+%TAG ! !foo
+%TAG !yaml! tag:yaml.org,2002:
+---
+- !bar "baz"
+- !yaml!str "string"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-06.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-07-06.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-06.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07a.canonical b/src/ext_depends/D-YAML/test/data/spec-07-07a.canonical
new file mode 100644
index 0000000..fa086df
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07a.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!<!foo> "bar"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07a.data b/src/ext_depends/D-YAML/test/data/spec-07-07a.data
new file mode 100644
index 0000000..9d42ec3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07a.data
@@ -0,0 +1,2 @@
+# Private application:
+!foo "bar"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07a.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-07-07a.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07a.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07b.canonical b/src/ext_depends/D-YAML/test/data/spec-07-07b.canonical
new file mode 100644
index 0000000..fe917d8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07b.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!<tag:ben-kiki.org,2000:app/foo> "bar"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07b.data b/src/ext_depends/D-YAML/test/data/spec-07-07b.data
new file mode 100644
index 0000000..2d36d0e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07b.data
@@ -0,0 +1,4 @@
+# Migrated to global:
+%TAG ! tag:ben-kiki.org,2000:app/
+---
+!foo "bar"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-07b.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-07-07b.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-07b.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-08.canonical b/src/ext_depends/D-YAML/test/data/spec-07-08.canonical
new file mode 100644
index 0000000..703aa7b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-08.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!seq [
+ !<!foo> "bar",
+ !<tag:yaml.org,2002:str> "string",
+ !<tag:ben-kiki.org,2000:type> "baz"
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-08.data b/src/ext_depends/D-YAML/test/data/spec-07-08.data
new file mode 100644
index 0000000..e2c6d9e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-08.data
@@ -0,0 +1,9 @@
+# Explicitly specify default settings:
+%TAG ! !
+%TAG !! tag:yaml.org,2002:
+# Named handles have no default:
+%TAG !o! tag:ben-kiki.org,2000:
+---
+- !foo "bar"
+- !!str "string"
+- !o!type "baz"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-08.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-07-08.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-08.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-09.canonical b/src/ext_depends/D-YAML/test/data/spec-07-09.canonical
new file mode 100644
index 0000000..32d9e94
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-09.canonical
@@ -0,0 +1,9 @@
+%YAML 1.1
+---
+!!str "foo"
+%YAML 1.1
+---
+!!str "bar"
+%YAML 1.1
+---
+!!str "baz"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-09.data b/src/ext_depends/D-YAML/test/data/spec-07-09.data
new file mode 100644
index 0000000..1209d47
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-09.data
@@ -0,0 +1,11 @@
+---
+foo
+...
+# Repeated end marker.
+...
+---
+bar
+# No end marker.
+---
+baz
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-10.canonical b/src/ext_depends/D-YAML/test/data/spec-07-10.canonical
new file mode 100644
index 0000000..1db650a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-10.canonical
@@ -0,0 +1,15 @@
+%YAML 1.1
+---
+!!str "Root flow scalar"
+%YAML 1.1
+---
+!!str "Root block scalar\n"
+%YAML 1.1
+---
+!!map {
+ ? !!str "foo"
+ : !!str "bar"
+}
+---
+#!!str ""
+!!null ""
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-10.data b/src/ext_depends/D-YAML/test/data/spec-07-10.data
new file mode 100644
index 0000000..6939b39
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-10.data
@@ -0,0 +1,11 @@
+"Root flow
+ scalar"
+--- !!str >
+ Root block
+ scalar
+---
+# Root collection:
+foo : bar
+... # Is optional.
+---
+# Explicit document may be empty.
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-11.data b/src/ext_depends/D-YAML/test/data/spec-07-11.data
new file mode 100644
index 0000000..d11302d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-11.data
@@ -0,0 +1,2 @@
+# A stream may contain
+# no documents.
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-11.empty b/src/ext_depends/D-YAML/test/data/spec-07-11.empty
new file mode 100644
index 0000000..bfffa8b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-11.empty
@@ -0,0 +1,2 @@
+# This stream contains no
+# documents, only comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-12a.canonical b/src/ext_depends/D-YAML/test/data/spec-07-12a.canonical
new file mode 100644
index 0000000..efc116f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-12a.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "foo"
+ : !!str "bar"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-12a.data b/src/ext_depends/D-YAML/test/data/spec-07-12a.data
new file mode 100644
index 0000000..3807d57
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-12a.data
@@ -0,0 +1,3 @@
+# Implicit document. Root
+# collection (mapping) node.
+foo : bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-12b.canonical b/src/ext_depends/D-YAML/test/data/spec-07-12b.canonical
new file mode 100644
index 0000000..04bcffc
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-12b.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "Text content\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-12b.data b/src/ext_depends/D-YAML/test/data/spec-07-12b.data
new file mode 100644
index 0000000..43250db
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-12b.data
@@ -0,0 +1,4 @@
+# Explicit document. Root
+# scalar (literal) node.
+--- |
+ Text content
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-13.canonical b/src/ext_depends/D-YAML/test/data/spec-07-13.canonical
new file mode 100644
index 0000000..5af71e9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-13.canonical
@@ -0,0 +1,9 @@
+%YAML 1.1
+---
+!!str "First document"
+---
+!<!foo> "No directives"
+---
+!<!foobar> "With directives"
+---
+!<!baz> "Reset settings"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-13.data b/src/ext_depends/D-YAML/test/data/spec-07-13.data
new file mode 100644
index 0000000..ba7ec63
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-13.data
@@ -0,0 +1,9 @@
+! "First document"
+---
+!foo "No directives"
+%TAG ! !foo
+---
+!bar "With directives"
+%YAML 1.1
+---
+!baz "Reset settings"
diff --git a/src/ext_depends/D-YAML/test/data/spec-07-13.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-07-13.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-07-13.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-01.canonical b/src/ext_depends/D-YAML/test/data/spec-08-01.canonical
new file mode 100644
index 0000000..69e4161
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-01.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? &A1 !!str "foo"
+ : !!str "bar",
+ ? &A2 !!str "baz"
+ : *A1
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-01.data b/src/ext_depends/D-YAML/test/data/spec-08-01.data
new file mode 100644
index 0000000..48986ec
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-01.data
@@ -0,0 +1,2 @@
+!!str &a1 "foo" : !!str bar
+&a2 baz : *a1
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-02.canonical b/src/ext_depends/D-YAML/test/data/spec-08-02.canonical
new file mode 100644
index 0000000..dd6f76e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-02.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "First occurrence"
+ : &A !!str "Value",
+ ? !!str "Second occurrence"
+ : *A
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-02.data b/src/ext_depends/D-YAML/test/data/spec-08-02.data
new file mode 100644
index 0000000..600d179
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-02.data
@@ -0,0 +1,2 @@
+First occurrence: &anchor Value
+Second occurrence: *anchor
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-03.canonical b/src/ext_depends/D-YAML/test/data/spec-08-03.canonical
new file mode 100644
index 0000000..be7ea8f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-03.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!map {
+ ? !<tag:yaml.org,2002:str> "foo"
+ : !<!bar> "baz"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-03.data b/src/ext_depends/D-YAML/test/data/spec-08-03.data
new file mode 100644
index 0000000..8e51f52
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-03.data
@@ -0,0 +1,2 @@
+!<tag:yaml.org,2002:str> foo :
+ !<!bar> baz
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-03.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-08-03.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-03.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-04.data b/src/ext_depends/D-YAML/test/data/spec-08-04.data
new file mode 100644
index 0000000..f7d1b01
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-04.data
@@ -0,0 +1,2 @@
+- !<!> foo
+- !<$:?> bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-04.error b/src/ext_depends/D-YAML/test/data/spec-08-04.error
new file mode 100644
index 0000000..6066375
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-04.error
@@ -0,0 +1,6 @@
+ERROR:
+- Verbatim tags aren't resolved,
+ so ! is invalid.
+- The $:? tag is neither a global
+ URI tag nor a local tag starting
+ with “!”.
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-05.canonical b/src/ext_depends/D-YAML/test/data/spec-08-05.canonical
new file mode 100644
index 0000000..a5c710a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-05.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!seq [
+ !<!local> "foo",
+ !<tag:yaml.org,2002:str> "bar",
+ !<tag:ben-kiki.org,2000:type> "baz",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-05.data b/src/ext_depends/D-YAML/test/data/spec-08-05.data
new file mode 100644
index 0000000..93576ed
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-05.data
@@ -0,0 +1,5 @@
+%TAG !o! tag:ben-kiki.org,2000:
+---
+- !local foo
+- !!str bar
+- !o!type baz
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-05.test_loader_skip b/src/ext_depends/D-YAML/test/data/spec-08-05.test_loader_skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-05.test_loader_skip
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-06.data b/src/ext_depends/D-YAML/test/data/spec-08-06.data
new file mode 100644
index 0000000..8580010
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-06.data
@@ -0,0 +1,5 @@
+%TAG !o! tag:ben-kiki.org,2000:
+---
+- !$a!b foo
+- !o! bar
+- !h!type baz
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-06.error b/src/ext_depends/D-YAML/test/data/spec-08-06.error
new file mode 100644
index 0000000..fb76f42
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-06.error
@@ -0,0 +1,4 @@
+ERROR:
+- The !$a! looks like a handle.
+- The !o! handle has no suffix.
+- The !h! handle wasn't declared.
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-07.canonical b/src/ext_depends/D-YAML/test/data/spec-08-07.canonical
new file mode 100644
index 0000000..e2f43d9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-07.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!seq [
+ !<tag:yaml.org,2002:str> "12",
+ !<tag:yaml.org,2002:int> "12",
+# !<tag:yaml.org,2002:str> "12",
+ !<tag:yaml.org,2002:int> "12",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-07.data b/src/ext_depends/D-YAML/test/data/spec-08-07.data
new file mode 100644
index 0000000..98aa565
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-07.data
@@ -0,0 +1,4 @@
+# Assuming conventional resolution:
+- "12"
+- 12
+- ! 12
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-08.canonical b/src/ext_depends/D-YAML/test/data/spec-08-08.canonical
new file mode 100644
index 0000000..d3f8b1a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-08.canonical
@@ -0,0 +1,15 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "foo"
+ : !!str "bar baz"
+}
+%YAML 1.1
+---
+!!str "foo bar"
+%YAML 1.1
+---
+!!str "foo bar"
+%YAML 1.1
+---
+!!str "foo\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-08.data b/src/ext_depends/D-YAML/test/data/spec-08-08.data
new file mode 100644
index 0000000..757a93d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-08.data
@@ -0,0 +1,13 @@
+---
+foo:
+ "bar
+ baz"
+---
+"foo
+ bar"
+---
+foo
+ bar
+--- |
+ foo
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-09.canonical b/src/ext_depends/D-YAML/test/data/spec-08-09.canonical
new file mode 100644
index 0000000..3805daf
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-09.canonical
@@ -0,0 +1,21 @@
+%YAML 1.1
+--- !!map {
+ ? !!str "scalars" : !!map {
+ ? !!str "plain"
+ : !!str "some text",
+ ? !!str "quoted"
+ : !!map {
+ ? !!str "single"
+ : !!str "some text",
+ ? !!str "double"
+ : !!str "some text"
+ } },
+ ? !!str "collections" : !!map {
+ ? !!str "sequence" : !!seq [
+ !!str "entry",
+ !!map {
+ ? !!str "key" : !!str "value"
+ } ],
+ ? !!str "mapping" : !!map {
+ ? !!str "key" : !!str "value"
+} } }
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-09.data b/src/ext_depends/D-YAML/test/data/spec-08-09.data
new file mode 100644
index 0000000..69da042
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-09.data
@@ -0,0 +1,11 @@
+---
+scalars:
+ plain: !!str some text
+ quoted:
+ single: 'some text'
+ double: "some text"
+collections:
+ sequence: !!seq [ !!str entry,
+ # Mapping entry:
+ key: value ]
+ mapping: { key: value }
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-10.canonical b/src/ext_depends/D-YAML/test/data/spec-08-10.canonical
new file mode 100644
index 0000000..8281c5e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-10.canonical
@@ -0,0 +1,23 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "block styles" : !!map {
+ ? !!str "scalars" : !!map {
+ ? !!str "literal"
+ : !!str "#!/usr/bin/perl\n\
+ print \"Hello,
+ world!\\n\";\n",
+ ? !!str "folded"
+ : !!str "This sentence
+ is false.\n"
+ },
+ ? !!str "collections" : !!map {
+ ? !!str "sequence" : !!seq [
+ !!str "entry",
+ !!map {
+ ? !!str "key" : !!str "value"
+ }
+ ],
+ ? !!str "mapping" : !!map {
+ ? !!str "key" : !!str "value"
+} } } }
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-10.data b/src/ext_depends/D-YAML/test/data/spec-08-10.data
new file mode 100644
index 0000000..72acc56
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-10.data
@@ -0,0 +1,15 @@
+block styles:
+ scalars:
+ literal: !!str |
+ #!/usr/bin/perl
+ print "Hello, world!\n";
+ folded: >
+ This sentence
+ is false.
+ collections: !!map
+ sequence: !!seq # Entry:
+ - entry # Plain
+ # Mapping entry:
+ - key: value
+ mapping:
+ key: value
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-11.canonical b/src/ext_depends/D-YAML/test/data/spec-08-11.canonical
new file mode 100644
index 0000000..dd6f76e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-11.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "First occurrence"
+ : &A !!str "Value",
+ ? !!str "Second occurrence"
+ : *A
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-11.data b/src/ext_depends/D-YAML/test/data/spec-08-11.data
new file mode 100644
index 0000000..600d179
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-11.data
@@ -0,0 +1,2 @@
+First occurrence: &anchor Value
+Second occurrence: *anchor
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-12.canonical b/src/ext_depends/D-YAML/test/data/spec-08-12.canonical
new file mode 100644
index 0000000..93899f4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-12.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "Without properties",
+ &A !!str "Anchored",
+ !!str "Tagged",
+ *A,
+ !!str "",
+ !!str "",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-12.data b/src/ext_depends/D-YAML/test/data/spec-08-12.data
new file mode 100644
index 0000000..3d4c6b7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-12.data
@@ -0,0 +1,8 @@
+[
+ Without properties,
+ &anchor "Anchored",
+ !!str 'Tagged',
+ *anchor, # Alias node
+ !!str , # Empty plain scalar
+ '', # Empty plain scalar
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-13.canonical b/src/ext_depends/D-YAML/test/data/spec-08-13.canonical
new file mode 100644
index 0000000..618bb7b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-13.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "foo"
+# : !!str "",
+# ? !!str ""
+ : !!null "",
+ ? !!null ""
+ : !!str "bar",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-13.data b/src/ext_depends/D-YAML/test/data/spec-08-13.data
new file mode 100644
index 0000000..ebe663a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-13.data
@@ -0,0 +1,4 @@
+{
+ ? foo :,
+ ? : bar,
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-13.skip-ext b/src/ext_depends/D-YAML/test/data/spec-08-13.skip-ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-13.skip-ext
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-14.canonical b/src/ext_depends/D-YAML/test/data/spec-08-14.canonical
new file mode 100644
index 0000000..11db439
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-14.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "flow in block",
+ !!str "Block scalar\n",
+ !!map {
+ ? !!str "foo"
+ : !!str "bar"
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-14.data b/src/ext_depends/D-YAML/test/data/spec-08-14.data
new file mode 100644
index 0000000..2fbb1f7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-14.data
@@ -0,0 +1,5 @@
+- "flow in block"
+- >
+ Block scalar
+- !!map # Block collection
+ foo : bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-15.canonical b/src/ext_depends/D-YAML/test/data/spec-08-15.canonical
new file mode 100644
index 0000000..76f028e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-15.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!seq [
+ !!null "",
+ !!map {
+ ? !!str "foo"
+ : !!null "",
+ ? !!null ""
+ : !!str "bar",
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-08-15.data b/src/ext_depends/D-YAML/test/data/spec-08-15.data
new file mode 100644
index 0000000..7c86bcf
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-08-15.data
@@ -0,0 +1,5 @@
+- # Empty plain scalar
+- ? foo
+ :
+ ?
+ : bar
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-01.canonical b/src/ext_depends/D-YAML/test/data/spec-09-01.canonical
new file mode 100644
index 0000000..e71a548
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-01.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "simple key"
+ : !!map {
+ ? !!str "also simple"
+ : !!str "value",
+ ? !!str "not a simple key"
+ : !!str "any value"
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-01.data b/src/ext_depends/D-YAML/test/data/spec-09-01.data
new file mode 100644
index 0000000..9e83eaf
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-01.data
@@ -0,0 +1,6 @@
+"simple key" : {
+ "also simple" : value,
+ ? "not a
+ simple key" : "any
+ value"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-02.canonical b/src/ext_depends/D-YAML/test/data/spec-09-02.canonical
new file mode 100644
index 0000000..6f8f41a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-02.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!str "as space \
+ trimmed\n\
+ specific\L\n\
+ escaped\t\n\
+ none"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-02.data b/src/ext_depends/D-YAML/test/data/spec-09-02.data
new file mode 100644
index 0000000..d84883d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-02.data
@@ -0,0 +1,6 @@
+ "as space
+ trimmed
+
+ specific

+ escaped \

+ none"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-03.canonical b/src/ext_depends/D-YAML/test/data/spec-09-03.canonical
new file mode 100644
index 0000000..658c6df
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-03.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!seq [
+ !!str " last",
+ !!str " last",
+ !!str " \tfirst last",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-03.data b/src/ext_depends/D-YAML/test/data/spec-09-03.data
new file mode 100644
index 0000000..e0b914d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-03.data
@@ -0,0 +1,6 @@
+- "
+ last"
+- "
+ last"
+- " first
+ last"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-04.canonical b/src/ext_depends/D-YAML/test/data/spec-09-04.canonical
new file mode 100644
index 0000000..fa46632
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-04.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!str "first \
+ inner 1 \
+ inner 2 \
+ last"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-04.data b/src/ext_depends/D-YAML/test/data/spec-09-04.data
new file mode 100644
index 0000000..313a91b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-04.data
@@ -0,0 +1,4 @@
+ "first
+ inner 1
+ \ inner 2 \
+ last"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-05.canonical b/src/ext_depends/D-YAML/test/data/spec-09-05.canonical
new file mode 100644
index 0000000..24d1052
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-05.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "first ",
+ !!str "first\nlast",
+ !!str "first inner \tlast",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-05.data b/src/ext_depends/D-YAML/test/data/spec-09-05.data
new file mode 100644
index 0000000..624c30e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-05.data
@@ -0,0 +1,8 @@
+- "first
+ "
+- "first
+
+ last"
+- "first
+ inner
+ \ last"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-06.canonical b/src/ext_depends/D-YAML/test/data/spec-09-06.canonical
new file mode 100644
index 0000000..5028772
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-06.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "here's to \"quotes\""
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-06.data b/src/ext_depends/D-YAML/test/data/spec-09-06.data
new file mode 100644
index 0000000..b038078
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-06.data
@@ -0,0 +1 @@
+ 'here''s to "quotes"'
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-07.canonical b/src/ext_depends/D-YAML/test/data/spec-09-07.canonical
new file mode 100644
index 0000000..e71a548
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-07.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "simple key"
+ : !!map {
+ ? !!str "also simple"
+ : !!str "value",
+ ? !!str "not a simple key"
+ : !!str "any value"
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-07.data b/src/ext_depends/D-YAML/test/data/spec-09-07.data
new file mode 100644
index 0000000..755b54a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-07.data
@@ -0,0 +1,6 @@
+'simple key' : {
+ 'also simple' : value,
+ ? 'not a
+ simple key' : 'any
+ value'
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-08.canonical b/src/ext_depends/D-YAML/test/data/spec-09-08.canonical
new file mode 100644
index 0000000..06abdb5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-08.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!str "as space \
+ trimmed\n\
+ specific\L\n\
+ none"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-08.data b/src/ext_depends/D-YAML/test/data/spec-09-08.data
new file mode 100644
index 0000000..aa4d458
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-08.data
@@ -0,0 +1 @@
+ 'as space … trimmed …… specific
… none'
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-09.canonical b/src/ext_depends/D-YAML/test/data/spec-09-09.canonical
new file mode 100644
index 0000000..658c6df
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-09.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!seq [
+ !!str " last",
+ !!str " last",
+ !!str " \tfirst last",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-09.data b/src/ext_depends/D-YAML/test/data/spec-09-09.data
new file mode 100644
index 0000000..52171df
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-09.data
@@ -0,0 +1,6 @@
+- '
+ last'
+- '
+ last'
+- ' first
+ last'
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-10.canonical b/src/ext_depends/D-YAML/test/data/spec-09-10.canonical
new file mode 100644
index 0000000..2028d04
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-10.canonical
@@ -0,0 +1,5 @@
+%YAML 1.1
+---
+!!str "first \
+ inner \
+ last"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-10.data b/src/ext_depends/D-YAML/test/data/spec-09-10.data
new file mode 100644
index 0000000..0e41449
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-10.data
@@ -0,0 +1,3 @@
+ 'first
+ inner
+ last'
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-11.canonical b/src/ext_depends/D-YAML/test/data/spec-09-11.canonical
new file mode 100644
index 0000000..4eb222c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-11.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "first ",
+ !!str "first\nlast",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-11.data b/src/ext_depends/D-YAML/test/data/spec-09-11.data
new file mode 100644
index 0000000..5efa873
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-11.data
@@ -0,0 +1,5 @@
+- 'first
+ '
+- 'first
+
+ last'
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-12.canonical b/src/ext_depends/D-YAML/test/data/spec-09-12.canonical
new file mode 100644
index 0000000..d8e6dce
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-12.canonical
@@ -0,0 +1,12 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "::std::vector",
+ !!str "Up, up, and away!",
+ !!int "-123",
+ !!seq [
+ !!str "::std::vector",
+ !!str "Up, up, and away!",
+ !!int "-123",
+ ]
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-12.data b/src/ext_depends/D-YAML/test/data/spec-09-12.data
new file mode 100644
index 0000000..b9a3ac5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-12.data
@@ -0,0 +1,8 @@
+# Outside flow collection:
+- ::std::vector
+- Up, up, and away!
+- -123
+# Inside flow collection:
+- [ '::std::vector',
+ "Up, up, and away!",
+ -123 ]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-13.canonical b/src/ext_depends/D-YAML/test/data/spec-09-13.canonical
new file mode 100644
index 0000000..e71a548
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-13.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "simple key"
+ : !!map {
+ ? !!str "also simple"
+ : !!str "value",
+ ? !!str "not a simple key"
+ : !!str "any value"
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-13.data b/src/ext_depends/D-YAML/test/data/spec-09-13.data
new file mode 100644
index 0000000..b156386
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-13.data
@@ -0,0 +1,6 @@
+simple key : {
+ also simple : value,
+ ? not a
+ simple key : any
+ value
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-14.data b/src/ext_depends/D-YAML/test/data/spec-09-14.data
new file mode 100644
index 0000000..97f2316
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-14.data
@@ -0,0 +1,14 @@
+---
+--- ||| : foo
+... >>>: bar
+---
+[
+---
+,
+... ,
+{
+--- :
+... # Nested
+}
+]
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-14.error b/src/ext_depends/D-YAML/test/data/spec-09-14.error
new file mode 100644
index 0000000..9f3db7b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-14.error
@@ -0,0 +1,6 @@
+ERROR:
+ The --- and ... document
+ start and end markers must
+ not be specified as the
+ first content line of a
+ non-indented plain scalar.
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-15.canonical b/src/ext_depends/D-YAML/test/data/spec-09-15.canonical
new file mode 100644
index 0000000..df02040
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-15.canonical
@@ -0,0 +1,18 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "---"
+ : !!str "foo",
+ ? !!str "..."
+ : !!str "bar"
+}
+%YAML 1.1
+---
+!!seq [
+ !!str "---",
+ !!str "...",
+ !!map {
+ ? !!str "---"
+ : !!str "..."
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-15.data b/src/ext_depends/D-YAML/test/data/spec-09-15.data
new file mode 100644
index 0000000..e6863b0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-15.data
@@ -0,0 +1,13 @@
+---
+"---" : foo
+...: bar
+---
+[
+---,
+...,
+{
+? ---
+: ...
+}
+]
+...
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-16.canonical b/src/ext_depends/D-YAML/test/data/spec-09-16.canonical
new file mode 100644
index 0000000..06abdb5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-16.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!str "as space \
+ trimmed\n\
+ specific\L\n\
+ none"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-16.data b/src/ext_depends/D-YAML/test/data/spec-09-16.data
new file mode 100644
index 0000000..473beb9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-16.data
@@ -0,0 +1,3 @@
+# Tabs are confusing:
+# as space/trimmed/specific/none
+ as space … trimmed …… specific
… none
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-17.canonical b/src/ext_depends/D-YAML/test/data/spec-09-17.canonical
new file mode 100644
index 0000000..68cb70d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-17.canonical
@@ -0,0 +1,4 @@
+%YAML 1.1
+---
+!!str "first line\n\
+ more line"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-17.data b/src/ext_depends/D-YAML/test/data/spec-09-17.data
new file mode 100644
index 0000000..97bc46c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-17.data
@@ -0,0 +1,3 @@
+ first line
+
+ more line
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-18.canonical b/src/ext_depends/D-YAML/test/data/spec-09-18.canonical
new file mode 100644
index 0000000..f21428f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-18.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "literal\n",
+ !!str " folded\n",
+ !!str "keep\n\n",
+ !!str " strip",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-18.data b/src/ext_depends/D-YAML/test/data/spec-09-18.data
new file mode 100644
index 0000000..68c5d7c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-18.data
@@ -0,0 +1,9 @@
+- | # Just the style
+ literal
+- >1 # Indentation indicator
+ folded
+- |+ # Chomping indicator
+ keep
+
+- >-1 # Both indicators
+ strip
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-19.canonical b/src/ext_depends/D-YAML/test/data/spec-09-19.canonical
new file mode 100644
index 0000000..3e828d7
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-19.canonical
@@ -0,0 +1,6 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "literal\n",
+ !!str "folded\n",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-19.data b/src/ext_depends/D-YAML/test/data/spec-09-19.data
new file mode 100644
index 0000000..f0e589d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-19.data
@@ -0,0 +1,4 @@
+- |
+ literal
+- >
+ folded
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-20.canonical b/src/ext_depends/D-YAML/test/data/spec-09-20.canonical
new file mode 100644
index 0000000..d03bef5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-20.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "detected\n",
+ !!str "\n\n# detected\n",
+ !!str " explicit\n",
+ !!str "\t\ndetected\n",
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-20.data b/src/ext_depends/D-YAML/test/data/spec-09-20.data
new file mode 100644
index 0000000..39bee04
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-20.data
@@ -0,0 +1,11 @@
+- |
+ detected
+- >
+
+
+ # detected
+- |1
+ explicit
+- >
+
+ detected
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-20.skip-ext b/src/ext_depends/D-YAML/test/data/spec-09-20.skip-ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-20.skip-ext
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-21.data b/src/ext_depends/D-YAML/test/data/spec-09-21.data
new file mode 100644
index 0000000..0fdd14f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-21.data
@@ -0,0 +1,8 @@
+- |
+
+ text
+- >
+ text
+ text
+- |1
+ text
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-21.error b/src/ext_depends/D-YAML/test/data/spec-09-21.error
new file mode 100644
index 0000000..1379ca5
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-21.error
@@ -0,0 +1,7 @@
+ERROR:
+- A leading all-space line must
+ not have too many spaces.
+- A following text line must
+ not be less indented.
+- The text is less indented
+ than the indicated level.
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-22.canonical b/src/ext_depends/D-YAML/test/data/spec-09-22.canonical
new file mode 100644
index 0000000..c1bbcd2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-22.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "strip"
+ : !!str "text",
+ ? !!str "clip"
+ : !!str "text\n",
+ ? !!str "keep"
+ : !!str "text\L",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-22.data b/src/ext_depends/D-YAML/test/data/spec-09-22.data
new file mode 100644
index 0000000..0dd51eb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-22.data
@@ -0,0 +1,4 @@
+strip: |-
+ text
clip: |
+ text…keep: |+
+ text
 \ No newline at end of file
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-23.canonical b/src/ext_depends/D-YAML/test/data/spec-09-23.canonical
new file mode 100644
index 0000000..c4444ca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-23.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "strip"
+ : !!str "# text",
+ ? !!str "clip"
+ : !!str "# text\n",
+ ? !!str "keep"
+ : !!str "# text\L\n",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-23.data b/src/ext_depends/D-YAML/test/data/spec-09-23.data
new file mode 100644
index 0000000..8972d2b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-23.data
@@ -0,0 +1,11 @@
+ # Strip
+ # Comments:
+strip: |-
+ # text
 
 # Clip
+ # comments:
+…clip: |
+ # text… 
 # Keep
+ # comments:
+…keep: |+
+ # text
… # Trail
+ # comments.
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-24.canonical b/src/ext_depends/D-YAML/test/data/spec-09-24.canonical
new file mode 100644
index 0000000..45a99b0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-24.canonical
@@ -0,0 +1,10 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "strip"
+ : !!str "",
+ ? !!str "clip"
+ : !!str "",
+ ? !!str "keep"
+ : !!str "\n",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-24.data b/src/ext_depends/D-YAML/test/data/spec-09-24.data
new file mode 100644
index 0000000..de0b64b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-24.data
@@ -0,0 +1,6 @@
+strip: >-
+
+clip: >
+
+keep: |+
+
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-25.canonical b/src/ext_depends/D-YAML/test/data/spec-09-25.canonical
new file mode 100644
index 0000000..9d2327b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-25.canonical
@@ -0,0 +1,4 @@
+%YAML 1.1
+---
+!!str "literal\n\
+ \ttext\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-25.data b/src/ext_depends/D-YAML/test/data/spec-09-25.data
new file mode 100644
index 0000000..f6303a1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-25.data
@@ -0,0 +1,3 @@
+| # Simple block scalar
+ literal
+ text
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-26.canonical b/src/ext_depends/D-YAML/test/data/spec-09-26.canonical
new file mode 100644
index 0000000..3029a11
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-26.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "\n\nliteral\n\ntext\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-26.data b/src/ext_depends/D-YAML/test/data/spec-09-26.data
new file mode 100644
index 0000000..f28555a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-26.data
@@ -0,0 +1,8 @@
+|
+
+
+ literal
+
+ text
+
+ # Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-27.canonical b/src/ext_depends/D-YAML/test/data/spec-09-27.canonical
new file mode 100644
index 0000000..3029a11
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-27.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "\n\nliteral\n\ntext\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-27.data b/src/ext_depends/D-YAML/test/data/spec-09-27.data
new file mode 100644
index 0000000..f28555a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-27.data
@@ -0,0 +1,8 @@
+|
+
+
+ literal
+
+ text
+
+ # Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-28.canonical b/src/ext_depends/D-YAML/test/data/spec-09-28.canonical
new file mode 100644
index 0000000..3029a11
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-28.canonical
@@ -0,0 +1,3 @@
+%YAML 1.1
+---
+!!str "\n\nliteral\n\ntext\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-28.data b/src/ext_depends/D-YAML/test/data/spec-09-28.data
new file mode 100644
index 0000000..f28555a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-28.data
@@ -0,0 +1,8 @@
+|
+
+
+ literal
+
+ text
+
+ # Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-29.canonical b/src/ext_depends/D-YAML/test/data/spec-09-29.canonical
new file mode 100644
index 0000000..0980789
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-29.canonical
@@ -0,0 +1,4 @@
+%YAML 1.1
+---
+!!str "folded text\n\
+ \tlines\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-29.data b/src/ext_depends/D-YAML/test/data/spec-09-29.data
new file mode 100644
index 0000000..82e611f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-29.data
@@ -0,0 +1,4 @@
+> # Simple folded scalar
+ folded
+ text
+ lines
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-30.canonical b/src/ext_depends/D-YAML/test/data/spec-09-30.canonical
new file mode 100644
index 0000000..fc37db1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-30.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!str "folded line\n\
+ next line\n\n\
+ \ * bullet\n\
+ \ * list\n\n\
+ last line\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-30.data b/src/ext_depends/D-YAML/test/data/spec-09-30.data
new file mode 100644
index 0000000..a4d8c36
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-30.data
@@ -0,0 +1,14 @@
+>
+ folded
+ line
+
+ next
+ line
+
+ * bullet
+ * list
+
+ last
+ line
+
+# Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-31.canonical b/src/ext_depends/D-YAML/test/data/spec-09-31.canonical
new file mode 100644
index 0000000..fc37db1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-31.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!str "folded line\n\
+ next line\n\n\
+ \ * bullet\n\
+ \ * list\n\n\
+ last line\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-31.data b/src/ext_depends/D-YAML/test/data/spec-09-31.data
new file mode 100644
index 0000000..a4d8c36
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-31.data
@@ -0,0 +1,14 @@
+>
+ folded
+ line
+
+ next
+ line
+
+ * bullet
+ * list
+
+ last
+ line
+
+# Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-32.canonical b/src/ext_depends/D-YAML/test/data/spec-09-32.canonical
new file mode 100644
index 0000000..fc37db1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-32.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!str "folded line\n\
+ next line\n\n\
+ \ * bullet\n\
+ \ * list\n\n\
+ last line\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-32.data b/src/ext_depends/D-YAML/test/data/spec-09-32.data
new file mode 100644
index 0000000..a4d8c36
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-32.data
@@ -0,0 +1,14 @@
+>
+ folded
+ line
+
+ next
+ line
+
+ * bullet
+ * list
+
+ last
+ line
+
+# Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-33.canonical b/src/ext_depends/D-YAML/test/data/spec-09-33.canonical
new file mode 100644
index 0000000..fc37db1
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-33.canonical
@@ -0,0 +1,7 @@
+%YAML 1.1
+---
+!!str "folded line\n\
+ next line\n\n\
+ \ * bullet\n\
+ \ * list\n\n\
+ last line\n"
diff --git a/src/ext_depends/D-YAML/test/data/spec-09-33.data b/src/ext_depends/D-YAML/test/data/spec-09-33.data
new file mode 100644
index 0000000..a4d8c36
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-09-33.data
@@ -0,0 +1,14 @@
+>
+ folded
+ line
+
+ next
+ line
+
+ * bullet
+ * list
+
+ last
+ line
+
+# Comment
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-01.canonical b/src/ext_depends/D-YAML/test/data/spec-10-01.canonical
new file mode 100644
index 0000000..d08cdd4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-01.canonical
@@ -0,0 +1,12 @@
+%YAML 1.1
+---
+!!seq [
+ !!seq [
+ !!str "inner",
+ !!str "inner",
+ ],
+ !!seq [
+ !!str "inner",
+ !!str "last",
+ ],
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-01.data b/src/ext_depends/D-YAML/test/data/spec-10-01.data
new file mode 100644
index 0000000..e668d38
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-01.data
@@ -0,0 +1,2 @@
+- [ inner, inner, ]
+- [inner,last]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-02.canonical b/src/ext_depends/D-YAML/test/data/spec-10-02.canonical
new file mode 100644
index 0000000..82fe0d9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-02.canonical
@@ -0,0 +1,14 @@
+%YAML 1.1
+---
+!!seq [
+ !!str "double quoted",
+ !!str "single quoted",
+ !!str "plain text",
+ !!seq [
+ !!str "nested",
+ ],
+ !!map {
+ ? !!str "single"
+ : !!str "pair"
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-02.data b/src/ext_depends/D-YAML/test/data/spec-10-02.data
new file mode 100644
index 0000000..3b23351
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-02.data
@@ -0,0 +1,8 @@
+[
+"double
+ quoted", 'single
+ quoted',
+plain
+ text, [ nested ],
+single: pair ,
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-03.canonical b/src/ext_depends/D-YAML/test/data/spec-10-03.canonical
new file mode 100644
index 0000000..1443395
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-03.canonical
@@ -0,0 +1,12 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "block"
+ : !!seq [
+ !!str "one",
+ !!map {
+ ? !!str "two"
+ : !!str "three"
+ }
+ ]
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-03.data b/src/ext_depends/D-YAML/test/data/spec-10-03.data
new file mode 100644
index 0000000..9e15f83
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-03.data
@@ -0,0 +1,4 @@
+block: # Block
+ # sequence
+- one
+- two : three
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-04.canonical b/src/ext_depends/D-YAML/test/data/spec-10-04.canonical
new file mode 100644
index 0000000..ae486a3
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-04.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "block"
+ : !!seq [
+ !!str "one",
+ !!seq [
+ !!str "two"
+ ]
+ ]
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-04.data b/src/ext_depends/D-YAML/test/data/spec-10-04.data
new file mode 100644
index 0000000..2905b0d
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-04.data
@@ -0,0 +1,4 @@
+block:
+- one
+-
+ - two
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-05.canonical b/src/ext_depends/D-YAML/test/data/spec-10-05.canonical
new file mode 100644
index 0000000..07cc0c9
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-05.canonical
@@ -0,0 +1,14 @@
+%YAML 1.1
+---
+!!seq [
+ !!null "",
+ !!str "block node\n",
+ !!seq [
+ !!str "one",
+ !!str "two",
+ ],
+ !!map {
+ ? !!str "one"
+ : !!str "two",
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-05.data b/src/ext_depends/D-YAML/test/data/spec-10-05.data
new file mode 100644
index 0000000..f19a99e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-05.data
@@ -0,0 +1,7 @@
+- # Empty
+- |
+ block node
+- - one # in-line
+ - two # sequence
+- one: two # in-line
+ # mapping
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-06.canonical b/src/ext_depends/D-YAML/test/data/spec-10-06.canonical
new file mode 100644
index 0000000..d9986c2
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-06.canonical
@@ -0,0 +1,16 @@
+%YAML 1.1
+---
+!!seq [
+ !!map {
+ ? !!str "inner"
+ : !!str "entry",
+ ? !!str "also"
+ : !!str "inner"
+ },
+ !!map {
+ ? !!str "inner"
+ : !!str "entry",
+ ? !!str "last"
+ : !!str "entry"
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-06.data b/src/ext_depends/D-YAML/test/data/spec-10-06.data
new file mode 100644
index 0000000..860ba25
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-06.data
@@ -0,0 +1,2 @@
+- { inner : entry , also: inner , }
+- {inner: entry,last : entry}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-07.canonical b/src/ext_depends/D-YAML/test/data/spec-10-07.canonical
new file mode 100644
index 0000000..ec74230
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-07.canonical
@@ -0,0 +1,16 @@
+%YAML 1.1
+---
+!!map {
+ ? !!null ""
+ : !!str "value",
+ ? !!str "explicit key"
+ : !!str "value",
+ ? !!str "simple key"
+ : !!str "value",
+ ? !!seq [
+ !!str "collection",
+ !!str "simple",
+ !!str "key"
+ ]
+ : !!str "value"
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-07.data b/src/ext_depends/D-YAML/test/data/spec-10-07.data
new file mode 100644
index 0000000..ff943fb
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-07.data
@@ -0,0 +1,7 @@
+{
+? : value, # Empty key
+? explicit
+ key: value,
+simple key : value,
+[ collection, simple, key ]: value
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-08.data b/src/ext_depends/D-YAML/test/data/spec-10-08.data
new file mode 100644
index 0000000..55bd788
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-08.data
@@ -0,0 +1,5 @@
+{
+multi-line
+ simple key : value,
+very long ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................(>1KB)................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... key: value
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-08.error b/src/ext_depends/D-YAML/test/data/spec-10-08.error
new file mode 100644
index 0000000..3979e1f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-08.error
@@ -0,0 +1,5 @@
+ERROR:
+- A simple key is restricted
+ to only one line.
+- A simple key must not be
+ longer than 1024 characters.
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-09.canonical b/src/ext_depends/D-YAML/test/data/spec-10-09.canonical
new file mode 100644
index 0000000..4d9827b
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-09.canonical
@@ -0,0 +1,8 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "key"
+ : !!str "value",
+ ? !!str "empty"
+ : !!null "",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-09.data b/src/ext_depends/D-YAML/test/data/spec-10-09.data
new file mode 100644
index 0000000..4d55e21
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-09.data
@@ -0,0 +1,4 @@
+{
+key : value,
+empty: # empty value↓
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-10.canonical b/src/ext_depends/D-YAML/test/data/spec-10-10.canonical
new file mode 100644
index 0000000..016fb64
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-10.canonical
@@ -0,0 +1,16 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "explicit key1"
+ : !!str "explicit value",
+ ? !!str "explicit key2"
+ : !!null "",
+ ? !!str "explicit key3"
+ : !!null "",
+ ? !!str "simple key1"
+ : !!str "explicit value",
+ ? !!str "simple key2"
+ : !!null "",
+ ? !!str "simple key3"
+ : !!null "",
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-10.data b/src/ext_depends/D-YAML/test/data/spec-10-10.data
new file mode 100644
index 0000000..0888b05
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-10.data
@@ -0,0 +1,8 @@
+{
+? explicit key1 : explicit value,
+? explicit key2 : , # Explicit empty
+? explicit key3, # Empty value
+simple key1 : explicit value,
+simple key2 : , # Explicit empty
+simple key3, # Empty value
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-11.canonical b/src/ext_depends/D-YAML/test/data/spec-10-11.canonical
new file mode 100644
index 0000000..7309544
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-11.canonical
@@ -0,0 +1,24 @@
+%YAML 1.1
+---
+!!seq [
+ !!map {
+ ? !!str "explicit key1"
+ : !!str "explicit value",
+ },
+ !!map {
+ ? !!str "explicit key2"
+ : !!null "",
+ },
+ !!map {
+ ? !!str "explicit key3"
+ : !!null "",
+ },
+ !!map {
+ ? !!str "simple key1"
+ : !!str "explicit value",
+ },
+ !!map {
+ ? !!str "simple key2"
+ : !!null "",
+ },
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-11.data b/src/ext_depends/D-YAML/test/data/spec-10-11.data
new file mode 100644
index 0000000..9f05568
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-11.data
@@ -0,0 +1,7 @@
+[
+? explicit key1 : explicit value,
+? explicit key2 : , # Explicit empty
+? explicit key3, # Implicit empty
+simple key1 : explicit value,
+simple key2 : , # Explicit empty
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-12.canonical b/src/ext_depends/D-YAML/test/data/spec-10-12.canonical
new file mode 100644
index 0000000..a95dd40
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-12.canonical
@@ -0,0 +1,9 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "block"
+ : !!map {
+ ? !!str "key"
+ : !!str "value"
+ }
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-12.data b/src/ext_depends/D-YAML/test/data/spec-10-12.data
new file mode 100644
index 0000000..5521443
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-12.data
@@ -0,0 +1,3 @@
+block: # Block
+ # mapping
+ key: value
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-13.canonical b/src/ext_depends/D-YAML/test/data/spec-10-13.canonical
new file mode 100644
index 0000000..e183c50
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-13.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "explicit key"
+ : !!null "",
+ ? !!str "block key\n"
+ : !!seq [
+ !!str "one",
+ !!str "two",
+ ]
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-13.data b/src/ext_depends/D-YAML/test/data/spec-10-13.data
new file mode 100644
index 0000000..b5b97db
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-13.data
@@ -0,0 +1,5 @@
+? explicit key # implicit value
+? |
+ block key
+: - one # explicit in-line
+ - two # block value
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-14.canonical b/src/ext_depends/D-YAML/test/data/spec-10-14.canonical
new file mode 100644
index 0000000..e87c880
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-14.canonical
@@ -0,0 +1,11 @@
+%YAML 1.1
+---
+!!map {
+ ? !!str "plain key"
+ : !!null "",
+ ? !!str "quoted key"
+ : !!seq [
+ !!str "one",
+ !!str "two",
+ ]
+}
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-14.data b/src/ext_depends/D-YAML/test/data/spec-10-14.data
new file mode 100644
index 0000000..7f5995c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-14.data
@@ -0,0 +1,4 @@
+plain key: # empty value
+"quoted key":
+- one # explicit next-line
+- two # block value
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-15.canonical b/src/ext_depends/D-YAML/test/data/spec-10-15.canonical
new file mode 100644
index 0000000..85fbbd0
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-15.canonical
@@ -0,0 +1,18 @@
+%YAML 1.1
+---
+!!seq [
+ !!map {
+ ? !!str "sun"
+ : !!str "yellow"
+ },
+ !!map {
+ ? !!map {
+ ? !!str "earth"
+ : !!str "blue"
+ }
+ : !!map {
+ ? !!str "moon"
+ : !!str "white"
+ }
+ }
+]
diff --git a/src/ext_depends/D-YAML/test/data/spec-10-15.data b/src/ext_depends/D-YAML/test/data/spec-10-15.data
new file mode 100644
index 0000000..d675cfd
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/spec-10-15.data
@@ -0,0 +1,3 @@
+- sun: yellow
+- ? earth: blue
+ : moon: white
diff --git a/src/ext_depends/D-YAML/test/data/str.data b/src/ext_depends/D-YAML/test/data/str.data
new file mode 100644
index 0000000..7cbdb7c
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/str.data
@@ -0,0 +1 @@
+- abcd
diff --git a/src/ext_depends/D-YAML/test/data/str.detect b/src/ext_depends/D-YAML/test/data/str.detect
new file mode 100644
index 0000000..7d5026f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/str.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:str
diff --git a/src/ext_depends/D-YAML/test/data/tags.events b/src/ext_depends/D-YAML/test/data/tags.events
new file mode 100644
index 0000000..bb93dce
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/tags.events
@@ -0,0 +1,12 @@
+- !StreamStart
+- !DocumentStart
+- !SequenceStart
+- !Scalar { value: 'data' }
+#- !Scalar { tag: '!', value: 'data' }
+- !Scalar { tag: 'tag:yaml.org,2002:str', value: 'data' }
+- !Scalar { tag: '!myfunnytag', value: 'data' }
+- !Scalar { tag: '!my!ugly!tag', value: 'data' }
+- !Scalar { tag: 'tag:my.domain.org,2002:data!? #', value: 'data' }
+- !SequenceEnd
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/test_mark.marks b/src/ext_depends/D-YAML/test/data/test_mark.marks
new file mode 100644
index 0000000..7b08ee4
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/test_mark.marks
@@ -0,0 +1,38 @@
+---
+*The first line.
+The last line.
+---
+The first*line.
+The last line.
+---
+The first line.*
+The last line.
+---
+The first line.
+*The last line.
+---
+The first line.
+The last*line.
+---
+The first line.
+The last line.*
+---
+The first line.
+*The selected line.
+The last line.
+---
+The first line.
+The selected*line.
+The last line.
+---
+The first line.
+The selected line.*
+The last line.
+---
+*The only line.
+---
+The only*line.
+---
+The only line.*
+---
+Loooooooooooooooooooooooooooooooooooooooooooooong*Liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiine
diff --git a/src/ext_depends/D-YAML/test/data/timestamp-bugs.code b/src/ext_depends/D-YAML/test/data/timestamp-bugs.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/timestamp-bugs.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/timestamp-bugs.data b/src/ext_depends/D-YAML/test/data/timestamp-bugs.data
new file mode 100644
index 0000000..503f1ce
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/timestamp-bugs.data
@@ -0,0 +1,6 @@
+- 2001-12-14 21:59:43.1 -5:30
+- 2001-12-14 21:59:43.1 +5:30
+- 2001-12-14 21:59:43.00101
+- 2001-12-14 21:59:43+1
+- 2001-12-14 21:59:43-1:30
+- 2005-07-08 17:35:04.517600
diff --git a/src/ext_depends/D-YAML/test/data/timestamp.data b/src/ext_depends/D-YAML/test/data/timestamp.data
new file mode 100644
index 0000000..7d214ce
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/timestamp.data
@@ -0,0 +1,5 @@
+- 2001-12-15T02:59:43.1Z
+- 2001-12-14t21:59:43.10-05:00
+- 2001-12-14 21:59:43.10 -5
+- 2001-12-15 2:59:43.10
+- 2002-12-14
diff --git a/src/ext_depends/D-YAML/test/data/timestamp.detect b/src/ext_depends/D-YAML/test/data/timestamp.detect
new file mode 100644
index 0000000..2013936
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/timestamp.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:timestamp
diff --git a/src/ext_depends/D-YAML/test/data/unclosed-bracket.loader-error b/src/ext_depends/D-YAML/test/data/unclosed-bracket.loader-error
new file mode 100644
index 0000000..8c82077
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/unclosed-bracket.loader-error
@@ -0,0 +1,6 @@
+test:
+ - [ foo: bar
+# comment the rest of the stream to let the scanner detect the problem.
+# - baz
+#"we could have detected the unclosed bracket on the above line, but this would forbid such syntax as": {
+#}
diff --git a/src/ext_depends/D-YAML/test/data/unclosed-quoted-scalar.loader-error b/src/ext_depends/D-YAML/test/data/unclosed-quoted-scalar.loader-error
new file mode 100644
index 0000000..8537429
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/unclosed-quoted-scalar.loader-error
@@ -0,0 +1,2 @@
+'foo
+ bar
diff --git a/src/ext_depends/D-YAML/test/data/undefined-anchor.loader-error b/src/ext_depends/D-YAML/test/data/undefined-anchor.loader-error
new file mode 100644
index 0000000..9469103
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/undefined-anchor.loader-error
@@ -0,0 +1,3 @@
+- foo
+- &bar baz
+- *bat
diff --git a/src/ext_depends/D-YAML/test/data/undefined-tag-handle.loader-error b/src/ext_depends/D-YAML/test/data/undefined-tag-handle.loader-error
new file mode 100644
index 0000000..82ba335
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/undefined-tag-handle.loader-error
@@ -0,0 +1 @@
+--- !foo!bar baz
diff --git a/src/ext_depends/D-YAML/test/data/unsupported-version.emitter-error b/src/ext_depends/D-YAML/test/data/unsupported-version.emitter-error
new file mode 100644
index 0000000..f9c6197
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/unsupported-version.emitter-error
@@ -0,0 +1,5 @@
+- !StreamStart
+- !DocumentStart { version: [5,6] }
+- !Scalar { value: foo }
+- !DocumentEnd
+- !StreamEnd
diff --git a/src/ext_depends/D-YAML/test/data/uri.data b/src/ext_depends/D-YAML/test/data/uri.data
new file mode 100644
index 0000000..4532bd8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/uri.data
@@ -0,0 +1,3 @@
+%TAG !e! tag:example.com,2000:app/
+---
+- !e!tag%F0%9F%A4%94 baz
diff --git a/src/ext_depends/D-YAML/test/data/uri.detect b/src/ext_depends/D-YAML/test/data/uri.detect
new file mode 100644
index 0000000..981dd7f
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/uri.detect
@@ -0,0 +1 @@
+tag:example.com,2000:app/tag🤔
diff --git a/src/ext_depends/D-YAML/test/data/utf16be.code b/src/ext_depends/D-YAML/test/data/utf16be.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf16be.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/utf16be.data b/src/ext_depends/D-YAML/test/data/utf16be.data
new file mode 100644
index 0000000..50dcfae
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf16be.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/utf16le.code b/src/ext_depends/D-YAML/test/data/utf16le.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf16le.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/utf16le.data b/src/ext_depends/D-YAML/test/data/utf16le.data
new file mode 100644
index 0000000..76f5e73
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf16le.data
Binary files differ
diff --git a/src/ext_depends/D-YAML/test/data/utf8-implicit.code b/src/ext_depends/D-YAML/test/data/utf8-implicit.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf8-implicit.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/utf8-implicit.data b/src/ext_depends/D-YAML/test/data/utf8-implicit.data
new file mode 100644
index 0000000..9d8081e
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf8-implicit.data
@@ -0,0 +1 @@
+--- implicit UTF-8
diff --git a/src/ext_depends/D-YAML/test/data/utf8.code b/src/ext_depends/D-YAML/test/data/utf8.code
new file mode 100644
index 0000000..97e0aca
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf8.code
@@ -0,0 +1 @@
+#dummy used in constructor test
diff --git a/src/ext_depends/D-YAML/test/data/utf8.data b/src/ext_depends/D-YAML/test/data/utf8.data
new file mode 100644
index 0000000..686f48a
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/utf8.data
@@ -0,0 +1 @@
+--- UTF-8
diff --git a/src/ext_depends/D-YAML/test/data/value.data b/src/ext_depends/D-YAML/test/data/value.data
new file mode 100644
index 0000000..c5b7680
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/value.data
@@ -0,0 +1 @@
+- =
diff --git a/src/ext_depends/D-YAML/test/data/value.detect b/src/ext_depends/D-YAML/test/data/value.detect
new file mode 100644
index 0000000..7c37d02
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/value.detect
@@ -0,0 +1 @@
+tag:yaml.org,2002:value
diff --git a/src/ext_depends/D-YAML/test/data/yaml.data b/src/ext_depends/D-YAML/test/data/yaml.data
new file mode 100644
index 0000000..a4bb3f8
--- /dev/null
+++ b/src/ext_depends/D-YAML/test/data/yaml.data
@@ -0,0 +1,3 @@
+- !!yaml '!'
+- !!yaml '&'
+- !!yaml '*'
diff --git a/src/ext_depends/D-YAML/testsuite/dub.json b/src/ext_depends/D-YAML/testsuite/dub.json
new file mode 100644
index 0000000..fece639
--- /dev/null
+++ b/src/ext_depends/D-YAML/testsuite/dub.json
@@ -0,0 +1,8 @@
+{
+ "name": "testsuite",
+ "targetType": "executable",
+ "dependencies":
+ {
+ "dyaml": "*"
+ }
+}
diff --git a/src/ext_depends/D-YAML/testsuite/source/app.d b/src/ext_depends/D-YAML/testsuite/source/app.d
new file mode 100644
index 0000000..6c26b32
--- /dev/null
+++ b/src/ext_depends/D-YAML/testsuite/source/app.d
@@ -0,0 +1,323 @@
+module dyaml.testsuite;
+
+import dyaml;
+import dyaml.event;
+
+import std.algorithm;
+import std.conv;
+import std.file;
+import std.format;
+import std.json;
+import std.path;
+import std.range;
+import std.stdio;
+import std.string;
+import std.typecons;
+import std.utf;
+
+auto dumpEventString(string str) @safe
+{
+ string[] output;
+ try
+ {
+ auto events = Loader.fromString(str).parse();
+ foreach (event; events)
+ {
+ string line;
+ final switch (event.id)
+ {
+ case EventID.scalar:
+ line = "=VAL ";
+ if (event.anchor != "")
+ {
+ line ~= text("&", event.anchor, " ");
+ }
+ if (event.tag != "")
+ {
+ line ~= text("<", event.tag, "> ");
+ }
+ switch(event.scalarStyle)
+ {
+ case ScalarStyle.singleQuoted:
+ line ~= "'";
+ break;
+ case ScalarStyle.doubleQuoted:
+ line ~= '"';
+ break;
+ case ScalarStyle.literal:
+ line ~= "|";
+ break;
+ case ScalarStyle.folded:
+ line ~= ">";
+ break;
+ default:
+ line ~= ":";
+ break;
+ }
+ if (event.value != "")
+ {
+ line ~= text(event.value.substitute("\n", "\\n", `\`, `\\`, "\r", "\\r", "\t", "\\t", "\b", "\\b"));
+ }
+ break;
+ case EventID.streamStart:
+ line = "+STR";
+ break;
+ case EventID.documentStart:
+ line = "+DOC";
+ if (event.explicitDocument)
+ {
+ line ~= text(" ---");
+ }
+ break;
+ case EventID.mappingStart:
+ line = "+MAP";
+ if (event.anchor != "")
+ {
+ line ~= text(" &", event.anchor);
+ }
+ if (event.tag != "")
+ {
+ line ~= text(" <", event.tag, ">");
+ }
+ break;
+ case EventID.sequenceStart:
+ line = "+SEQ";
+ if (event.anchor != "")
+ {
+ line ~= text(" &", event.anchor);
+ }
+ if (event.tag != "")
+ {
+ line ~= text(" <", event.tag, ">");
+ }
+ break;
+ case EventID.streamEnd:
+ line = "-STR";
+ break;
+ case EventID.documentEnd:
+ line = "-DOC";
+ if (event.explicitDocument)
+ {
+ line ~= " ...";
+ }
+ break;
+ case EventID.mappingEnd:
+ line = "-MAP";
+ break;
+ case EventID.sequenceEnd:
+ line = "-SEQ";
+ break;
+ case EventID.alias_:
+ line = text("=ALI *", event.anchor);
+ break;
+ case EventID.invalid:
+ assert(0, "Invalid EventID produced");
+ }
+ output ~= line;
+ }
+ }
+ catch (Exception) {} //Exceptions should just stop adding output
+ return output.join("\n");
+}
+
+enum TestState
+{
+ success,
+ skipped,
+ failure
+}
+
+struct TestResult
+{
+ string name;
+ TestState state;
+ string failMsg;
+
+ const void toString(OutputRange)(ref OutputRange writer)
+ if (isOutputRange!(OutputRange, char))
+ {
+ ubyte statusColour;
+ string statusString;
+ final switch (state) {
+ case TestState.success:
+ statusColour = 32;
+ statusString = "Succeeded";
+ break;
+ case TestState.failure:
+ statusColour = 31;
+ statusString = "Failed";
+ break;
+ case TestState.skipped:
+ statusColour = 93;
+ statusString = "Skipped";
+ break;
+ }
+ writer.formattedWrite!"[\033[%s;1m%s\033[0m] %s"(statusColour, statusString, name);
+ if (state != TestState.success)
+ {
+ writer.formattedWrite!" (%s)"(failMsg.replace("\n", " "));
+ }
+ }
+}
+
+TestResult runTests(string tml) @safe
+{
+ TestResult output;
+ output.state = TestState.success;
+ auto splitFile = tml.splitter("\n--- ");
+ output.name = splitFile.front.findSplit("=== ")[2];
+ bool loadFailed, shouldFail;
+ string failMsg;
+ JSONValue json;
+ Node[] nodes;
+ string yamlString;
+ Nullable!string compareYAMLString;
+ Nullable!string events;
+ ulong testsRun;
+
+ void fail(string msg) @safe
+ {
+ output.state = TestState.failure;
+ output.failMsg = msg;
+ }
+ void skip(string msg) @safe
+ {
+ output.state = TestState.skipped;
+ output.failMsg = msg;
+ }
+ void parseYAML(string yaml) @safe
+ {
+ yamlString = yaml;
+ try {
+ nodes = Loader.fromString(yamlString).array;
+ }
+ catch (Exception e)
+ {
+ loadFailed = true;
+ failMsg = e.msg;
+ }
+ }
+ void compareLineByLine(const string a, const string b, const string msg) @safe
+ {
+ foreach (line1, line2; zip(a.lineSplitter, b.lineSplitter))
+ {
+ if (line1 != line2)
+ {
+ fail(text(msg, " Got ", line1, ", expected ", line2));
+ break;
+ }
+ }
+ }
+ foreach (section; splitFile.drop(1))
+ {
+ auto splitSection = section.findSplit("\n");
+ auto splitSectionHeader = splitSection[0].findSplit(":");
+ const splitSectionName = splitSectionHeader[0].findSplit("(");
+ const sectionName = splitSectionName[0];
+ const sectionParams = splitSectionName[2].findSplit(")")[0];
+ string sectionData = splitSection[2];
+ if (sectionData != "")
+ {
+ //< means dedent.
+ if (sectionParams.canFind("<"))
+ {
+ sectionData = sectionData[4..$].substitute("\n ", "\n", "<SPC>", " ", "<TAB>", "\t").toUTF8;
+ }
+ else
+ {
+ sectionData = sectionData.substitute("<SPC>", " ", "<TAB>", "\t").toUTF8;
+ }
+ //Not sure what + means.
+ }
+ switch(sectionName)
+ {
+ case "in-yaml":
+ parseYAML(sectionData);
+ break;
+ case "in-json":
+ json = parseJSON(sectionData);
+ break;
+ case "test-event":
+ events = sectionData;
+ break;
+ case "error":
+ shouldFail = true;
+ testsRun++;
+ break;
+ case "out-yaml":
+ compareYAMLString = sectionData;
+ break;
+ case "emit-yaml":
+ // TODO: Figure out how/if to implement this
+ //fail("Unhandled test - emit-yaml");
+ break;
+ case "lex-token":
+ // TODO: Should this be implemented?
+ //fail("Unhandled test - lex-token");
+ break;
+ case "from": break;
+ case "tags": break;
+ default: assert(false, text("Unhandled section ", sectionName, "in ", output.name));
+ }
+ }
+ if (!loadFailed && !compareYAMLString.isNull && !shouldFail)
+ {
+ Appender!string buf;
+ dumper().dump(buf);
+ compareLineByLine(buf.data, compareYAMLString.get, "Dumped YAML mismatch");
+ testsRun++;
+ }
+ if (!loadFailed && !events.isNull && !shouldFail)
+ {
+ const compare = dumpEventString(yamlString);
+ compareLineByLine(compare, events.get, "Event mismatch");
+ testsRun++;
+ }
+ if (loadFailed && !shouldFail)
+ {
+ fail(failMsg);
+ }
+ if (shouldFail && !loadFailed)
+ {
+ fail("Invalid YAML accepted");
+ }
+ if ((testsRun == 0) && (output.state != TestState.failure))
+ {
+ skip("No tests run");
+ }
+ return output;
+}
+
+// Can't be @safe due to dirEntries()
+void main(string[] args) @system
+{
+ string path = "yaml-test-suite/test";
+
+ void printResult(string id, TestResult result)
+ {
+ writeln(id, " ", result);
+ }
+
+ if (args.length > 1)
+ {
+ path = args[1];
+ }
+
+ ulong total;
+ ulong successes;
+ foreach (file; dirEntries(path, "*.tml", SpanMode.shallow))
+ {
+ auto result = runTests(readText(file));
+ if (result.state == TestState.success)
+ {
+ debug(verbose) printResult(file.baseName, result);
+ successes++;
+ }
+ else
+ {
+ printResult(file.baseName, result);
+ }
+ total++;
+ }
+ writefln!"%d/%d tests passed"(successes, total);
+}