diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2021-02-19 17:10:51 -0500 | 
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2021-02-24 16:46:47 -0500 | 
| commit | 02ca32ae0a5bc290918d2b2a3288e385b9cc6b11 (patch) | |
| tree | 06379785e8a0165a7deb981c2eba362894820634 /src/ext_depends/D-YAML/docs/tutorials | |
| parent | build from static source-tree pre fetch depends (diff) | |
external & build dependences in src tree
- external & build dependences boost licensed
  - ext_depends (external depends)
    - D-YAML
      - tinyendian
    - d2sqlite3
    - imageformats
  - build_depends
    - dub2nix
Diffstat (limited to 'src/ext_depends/D-YAML/docs/tutorials')
| -rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/custom_types.md | 258 | ||||
| -rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/getting_started.md | 140 | ||||
| -rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md | 241 | 
3 files changed, 639 insertions, 0 deletions
| 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                 | | 
