diff options
Diffstat (limited to 'src/ext_depends/D-YAML')
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 + +[](https://travis-ci.org/dlang-community/D-YAML) +[](https://codecov.io/gh/dlang-community/D-YAML) +[](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 Binary files differnew file mode 100644 index 0000000..f00ae05 --- /dev/null +++ b/src/ext_depends/D-YAML/docs/logo128.png diff --git a/src/ext_depends/D-YAML/docs/logo210.png b/src/ext_depends/D-YAML/docs/logo210.png Binary files differnew file mode 100644 index 0000000..66bef66 --- /dev/null +++ b/src/ext_depends/D-YAML/docs/logo210.png 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 Binary files differnew file mode 100644 index 0000000..03687b0 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/invalid-character.loader-error 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 Binary files differnew file mode 100644 index 0000000..171face --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/invalid-character.stream-error 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 Binary files differnew file mode 100644 index 0000000..b59e434 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/odd-utf16.stream-error 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 Binary files differnew file mode 100644 index 0000000..3525062 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16be.data 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 Binary files differnew file mode 100644 index 0000000..0823f74 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/spec-05-01-utf16le.data 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 Binary files differnew file mode 100644 index 0000000..5ebbb04 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16be.data 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 Binary files differnew file mode 100644 index 0000000..0cd90a2 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/spec-05-02-utf16le.data 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 Binary files differnew file mode 100644 index 0000000..50dcfae --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/utf16be.data 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 Binary files differnew file mode 100644 index 0000000..76f5e73 --- /dev/null +++ b/src/ext_depends/D-YAML/test/data/utf16le.data 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); +}  | 
