Red-Black Trees are now used for duplicate detection, and planned
to be used for unordered map storage. This is because AAs still don't work correctly and even if they did, require the user to define both toHash and opCmp/opEquals for every YAML struct/class. Now only opCmp needs to be defined. Documentation/tutorials/examples have been updated accordingly.
This commit is contained in:
parent
07eadc9403
commit
9596806644
34 changed files with 623 additions and 250 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@ 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 class data members. YAML also
|
||||
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.
|
||||
|
||||
|
@ -23,11 +23,13 @@ functions to process each supported tag. These are supplied by the user using
|
|||
the *addConstructorXXX()* methods, where *XXX* is *Scalar*, *Sequence* or
|
||||
*Mapping*. *Constructor* is then passed to *Loader*, which parses YAML input.
|
||||
|
||||
Struct types have no specific requirements for YAML support. Class types should
|
||||
define the *opEquals()* operator - this is used in equality comparisons of
|
||||
nodes. Default class *opEquals()* compares references, which means two identical
|
||||
objects might be considered unequal. (Default struct *opEquals()* compares
|
||||
byte-by-byte, sometimes you might want to override that as well.)
|
||||
Structs and classes must implement the *opCmp()* operator for YAML support. This
|
||||
is used for duplicate detection in mappings, sorting and equality comparisons of
|
||||
nodes. The signature of the operator that must be implemented is
|
||||
``const int opCmp(ref const MyStruct s)`` for structs where *MyStruct* is the
|
||||
struct type, and ``int opCmp(Object o)`` for classes. Note that the class
|
||||
*opCmp()* should not alter the compared values - it is not const for compatibility
|
||||
reasons.
|
||||
|
||||
We will implement support for an RGB color type. It is implemented as the
|
||||
following struct:
|
||||
|
@ -39,6 +41,14 @@ following struct:
|
|||
ubyte red;
|
||||
ubyte green;
|
||||
ubyte blue;
|
||||
|
||||
const int opCmp(ref const Color c)
|
||||
{
|
||||
if(red != c.red) {return red - c.red;}
|
||||
if(green != c.green){return green - c.green;}
|
||||
if(blue != c.blue) {return blue - c.blue;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
First, we need a function to construct our data type. The function will take a
|
||||
|
|
|
@ -43,7 +43,7 @@ Do this by typing the following command into the console::
|
|||
|
||||
dmd cdc.d
|
||||
|
||||
Now you can use CDC to compile D:YAML.
|
||||
Now compile D:YAML with CDC.
|
||||
To do this on Unix/Linux, use the following command::
|
||||
|
||||
./cdc
|
||||
|
@ -101,8 +101,8 @@ into the file:
|
|||
Explanation of the code
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
First, we import the *yaml* module. This is the only module you need to import
|
||||
to use D:YAML - it automatically imports all needed modules.
|
||||
First, we import the *yaml* 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.load()* method. *Loader* is a struct
|
||||
used for parsing YAML documents. The *load()* method loads the file as
|
||||
|
@ -146,18 +146,18 @@ formatted differently. Comments are not preserved, either.
|
|||
Compiling
|
||||
^^^^^^^^^
|
||||
|
||||
To compile your project, you must give DMD the directories containing import
|
||||
modules and the library. You also need to tell it to link with D:YAML. The import
|
||||
directory should be the D:YAML package directory. You can specify it using the
|
||||
``-I`` option of DMD. The library directory should be where you put the compiled
|
||||
D:YAML library. On Unix/Linux you can specify it using the ``-L-L`` option, and
|
||||
link with D:YAML using the ``-L-l`` option. On Windows, the import directory is
|
||||
used as the library directory. To link with the library on Windows, just add the
|
||||
path to it relative to the current directory.
|
||||
To compile your project, DMD needs to know which directories contain the
|
||||
imported modules and the library. You also need to tell it to link with D:YAML.
|
||||
The import directory should be the D:YAML package directory. You can specify it
|
||||
using the ``-I`` option of DMD. The library directory should point to the
|
||||
compiled library. On Unix/Linux you can specify it using the ``-L-L`` option,
|
||||
and link with D:YAML using the ``-L-l`` option. On Windows, the import directory
|
||||
is used as the library directory. To link with the library on Windows, just add
|
||||
the path to it relative to the current directory.
|
||||
|
||||
For example, if you extracted and compiled D:YAML in ``/home/xxx/dyaml``, your
|
||||
project is in ``/home/xxx/dyaml-project``, and you are currently in that
|
||||
directory, you can compile the project with the following command on Unix/Linux::
|
||||
directory, compile the project with the following command on Unix/Linux::
|
||||
|
||||
dmd -I../dyaml -L-L../dyaml -L-ldyaml main.d
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ div#content
|
|||
border: 0.6em solid #cccccc;
|
||||
background-color: #f6f6f6;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.4em;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
div#content li{padding-bottom: .7ex;}
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<p>Each YAML scalar, sequence or mapping has a tag specifying its data type.
|
||||
<a name="Constructor"></a><span class="ddoc_psymbol">Constructor</span> uses user-specifyable functions to create a node of desired
|
||||
data type from a scalar, sequence or mapping.
|
||||
<br>
|
||||
|
||||
<br>
|
||||
|
||||
Each of these functions is associated with a tag, and can process either
|
||||
|
@ -82,7 +84,7 @@
|
|||
|
||||
If a tag is detected with no known constructor function, it is considered an error.</p>
|
||||
|
||||
<dl><dt class="d_decl">this(in const(bool) <b>defaultConstructors</b> = true);
|
||||
<dl><dt class="d_decl">this(const(bool) <b>defaultConstructors</b> = true);
|
||||
</dt>
|
||||
<dd><p>Construct a Constructor.
|
||||
</p>
|
||||
|
@ -107,12 +109,24 @@
|
|||
Any exception thrown by this function will be caught by D:YAML and
|
||||
its message will be added to a YAMLException that will also tell the
|
||||
user which type failed to construct, and position in the file.
|
||||
<br>
|
||||
|
||||
<br>
|
||||
|
||||
The value returned by this function will be stored in the resulting node.
|
||||
<br>
|
||||
|
||||
Only one constructor function can be set for one tag.
|
||||
<br>
|
||||
|
||||
<br>
|
||||
|
||||
Structs and classes must implement the <span class="d_inlinecode">opCmp()</span> operator for D:YAML
|
||||
support. The signature of the operator that must be implemented
|
||||
is <span class="d_inlinecode">const int opCmp(ref const MyStruct s)</span> for structs where
|
||||
<i>MyStruct</i> is the struct type, and <span class="d_inlinecode">int opCmp(Object o)</span> for
|
||||
classes. Note that the class <span class="d_inlinecode">opCmp()</span> should not alter the compared
|
||||
values - it is not const for compatibility reasons.
|
||||
|
||||
</p>
|
||||
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>tag</td>
|
||||
|
@ -128,6 +142,16 @@
|
|||
<span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
MyStruct constructMyStructScalar(<span class="d_keyword">ref</span> Node node)
|
||||
|
@ -166,6 +190,16 @@
|
|||
<span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
MyStruct constructMyStructSequence(<span class="d_keyword">ref</span> Node node)
|
||||
|
@ -202,6 +236,16 @@
|
|||
<span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
MyStruct constructMyStructMapping(<span class="d_keyword">ref</span> Node node)
|
||||
|
@ -227,42 +271,42 @@
|
|||
</dd>
|
||||
<dt class="d_decl">YAMLNull <a name="constructNull"></a><span class="ddoc_psymbol">constructNull</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a <b>null</b> <b>node</b>.</p>
|
||||
<dd><p>Construct a null node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">YAMLMerge <a name="constructMerge"></a><span class="ddoc_psymbol">constructMerge</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a merge <b>node</b> - a <b>node</b> that merges another <b>node</b> into a mapping.</p>
|
||||
<dd><p>Construct a merge node - a node that merges another node into a mapping.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">bool <a name="constructBool"></a><span class="ddoc_psymbol">constructBool</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a boolean <b>node</b>.</p>
|
||||
<dd><p>Construct a boolean node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">long <a name="constructLong"></a><span class="ddoc_psymbol">constructLong</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct an integer (long) <b>node</b>.</p>
|
||||
<dd><p>Construct an integer (long) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">real <a name="constructReal"></a><span class="ddoc_psymbol">constructReal</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a floating point (real) <b>node</b>.</p>
|
||||
<dd><p>Construct a floating point (real) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">ubyte[] <a name="constructBinary"></a><span class="ddoc_psymbol">constructBinary</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a binary (base64) <b>node</b>.</p>
|
||||
<dd><p>Construct a binary (base64) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">SysTime <a name="constructTimestamp"></a><span class="ddoc_psymbol">constructTimestamp</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a timestamp (SysTime) <b>node</b>.</p>
|
||||
<dd><p>Construct a timestamp (SysTime) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">string <a name="constructString"></a><span class="ddoc_psymbol">constructString</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a string <b>node</b>.</p>
|
||||
<dd><p>Construct a string node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">Pair[] <a name="getPairs"></a><span class="ddoc_psymbol">getPairs</span>(string <b>type</b>, Node[] <b>nodes</b>);
|
||||
|
@ -272,27 +316,27 @@
|
|||
</dd>
|
||||
<dt class="d_decl">Pair[] <a name="constructOrderedMap"></a><span class="ddoc_psymbol">constructOrderedMap</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct an ordered map (ordered sequence of key:value pairs without duplicates) <b>node</b>.</p>
|
||||
<dd><p>Construct an ordered map (ordered sequence of key:value pairs without duplicates) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">Pair[] <a name="constructPairs"></a><span class="ddoc_psymbol">constructPairs</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a pairs (ordered sequence of key: value pairs allowing duplicates) <b>node</b>.</p>
|
||||
<dd><p>Construct a pairs (ordered sequence of key: value pairs allowing duplicates) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">Node[] <a name="constructSet"></a><span class="ddoc_psymbol">constructSet</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a set <b>node</b>.</p>
|
||||
<dd><p>Construct a set node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">Node[] <a name="constructSequence"></a><span class="ddoc_psymbol">constructSequence</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a sequence (array) <b>node</b>.</p>
|
||||
<dd><p>Construct a sequence (array) node.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">Pair[] <a name="constructMap"></a><span class="ddoc_psymbol">constructMap</span>(ref Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Construct an unordered map (unordered set of key: value pairs without duplicates) <b>node</b>.</p>
|
||||
<dd><p>Construct an unordered map (unordered set of key:value pairs without duplicates) node.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
@ -301,7 +345,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
</dt>
|
||||
<dd><p>Position in a YAML stream, used for error messages.</p>
|
||||
|
||||
<dl><dt class="d_decl">this(in const(uint) <b>line</b>, in const(uint) <b>column</b>);
|
||||
<dl><dt class="d_decl">this(const(uint) <b>line</b>, const(uint) <b>column</b>);
|
||||
</dt>
|
||||
<dd><p>Construct a Mark with specified <b>line</b> and <b>column</b> in the file.</p>
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -190,7 +190,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -400,7 +400,7 @@
|
|||
</dd>
|
||||
<dt class="d_decl">int <a name="opApply"></a><span class="ddoc_psymbol">opApply</span>(T)(int delegate(ref T) <b>dg</b>);
|
||||
</dt>
|
||||
<dd><p>Iterate over a sequence, getting each element as T.
|
||||
<dd><p>Foreach over a sequence, getting each element as T.
|
||||
</p>
|
||||
<p>If T is Node, simply iterate over the nodes in the sequence.
|
||||
Otherwise, convert each node to T during iteration.
|
||||
|
@ -412,7 +412,7 @@
|
|||
</dd>
|
||||
<dt class="d_decl">int <a name="opApply"></a><span class="ddoc_psymbol">opApply</span>(K, V)(int delegate(ref K, ref V) <b>dg</b>);
|
||||
</dt>
|
||||
<dd><p>Iterate over a mapping, getting each key/value as K/V.
|
||||
<dd><p>Foreach over a mapping, getting each key/value as K/V.
|
||||
</p>
|
||||
<p>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.
|
||||
|
@ -512,6 +512,11 @@
|
|||
<b>Throws:</b><div class="pbr">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.</div>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">const const int <a name="opCmp"></a><span class="ddoc_psymbol">opCmp</span>(ref const Node <b>node</b>);
|
||||
</dt>
|
||||
<dd><p>Compare with another node.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
@ -521,7 +526,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</dd>
|
||||
<dt class="d_decl">class <a name="Representer"></a><span class="ddoc_psymbol">Representer</span>;
|
||||
</dt>
|
||||
<dd><p>Represents YAML nodes of various data types as scalar, sequence and mapping nodes ready for output.
|
||||
<dd><p>Represents YAML nodes as scalar, sequence and mapping nodes ready for output.
|
||||
</p>
|
||||
<p>This class is used to add support for dumping of custom data types.
|
||||
<br>
|
||||
|
@ -73,26 +73,38 @@
|
|||
</dd>
|
||||
<dt class="d_decl">@property void <a name="defaultScalarStyle"></a><span class="ddoc_psymbol">defaultScalarStyle</span>(ScalarStyle <b>style</b>);
|
||||
</dt>
|
||||
<dd><p>Set default style for scalars. Invalid means the style is chosen automatically.</p>
|
||||
<dd><p>Set default style for scalars. If <b>style</b> is <span class="d_inlinecode">ScalarStyle.Invalid</span>, the style is chosen automatically.</p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">@property void <a name="defaultCollectionStyle"></a><span class="ddoc_psymbol">defaultCollectionStyle</span>(CollectionStyle <b>style</b>);
|
||||
</dt>
|
||||
<dd><p>Set default style for collections. Invalid means the style is chosen automatically. </p>
|
||||
<dd><p>Set default style for collections. If <b>style</b> is <span class="d_inlinecode">CollectionStyle.Invalid</span>, the style is chosen automatically. </p>
|
||||
|
||||
</dd>
|
||||
<dt class="d_decl">void <a name="addRepresenter"></a><span class="ddoc_psymbol">addRepresenter</span>(T)(Node function(ref Node, Representer) <b>representer</b>);
|
||||
</dt>
|
||||
<dd><p>Add a function to represent nodes with a specific data type.
|
||||
</p>
|
||||
<p>The representer function takes references to a Node storing the data
|
||||
type and to the Representer. It returns the represented node and may
|
||||
throw a RepresenterException. See the example for more information.
|
||||
<p>The representer function takes references to a <span class="d_inlinecode">Node</span> storing the data
|
||||
type and to the <span class="d_inlinecode">Representer</span>. It returns the represented node and may
|
||||
throw a <span class="d_inlinecode">RepresenterException</span>. See the example for more information.
|
||||
<br>
|
||||
|
||||
<br>
|
||||
|
||||
Only one function may be specified for one data type. Default data
|
||||
types already have representer functions unless disabled in the
|
||||
Representer constructor.
|
||||
<span class="d_inlinecode">Representer</span> constructor.
|
||||
<br>
|
||||
|
||||
<br>
|
||||
|
||||
Structs and classes must implement the <span class="d_inlinecode">opCmp()</span> operator for D:YAML
|
||||
support. The signature of the operator that must be implemented
|
||||
is <span class="d_inlinecode">const int opCmp(ref const MyStruct s)</span> for structs where
|
||||
<i>MyStruct</i> is the struct type, and <span class="d_inlinecode">int opCmp(Object o)</span> for
|
||||
classes. Note that the class <span class="d_inlinecode">opCmp()</span> should not alter the compared
|
||||
values - it is not const for compatibility reasons.
|
||||
|
||||
</p>
|
||||
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>representer</td>
|
||||
|
@ -106,6 +118,16 @@
|
|||
<span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
Node representMyStruct(<span class="d_keyword">ref</span> Node node, Representer representer)
|
||||
|
@ -144,12 +166,16 @@
|
|||
<span class="d_keyword">this</span>.z = z;
|
||||
}
|
||||
|
||||
<span class="d_comment">///We need custom opEquals for node equality, as default opEquals compares references.
|
||||
</span> <span class="d_keyword">override</span> <span class="d_keyword">bool</span> opEquals(Object rhs)
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">override</span> <span class="d_keyword">int</span> opCmp(Object o)
|
||||
{
|
||||
<span class="d_keyword">if</span>(<span class="d_keyword">typeid</span>(rhs) != <span class="d_keyword">typeid</span>(MyClass)){<span class="d_keyword">return</span> <span class="d_keyword">false</span>;}
|
||||
<span class="d_keyword">auto</span> t = <span class="d_keyword">cast</span>(MyClass)rhs;
|
||||
<span class="d_keyword">return</span> x == t.x && y == t.y && z == t.z;
|
||||
MyClass s = <span class="d_keyword">cast</span>(MyClass)o;
|
||||
<span class="d_keyword">if</span>(s <span class="d_keyword">is</span> <span class="d_keyword">null</span>){<span class="d_keyword">return</span> -1;}
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
|
||||
<span class="d_comment">///Useful for Node.as!string .
|
||||
|
@ -204,6 +230,16 @@
|
|||
<pre class="d_code"> <span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
Node representMyStruct(<span class="d_keyword">ref</span> Node node, Representer representer)
|
||||
|
@ -211,7 +247,6 @@
|
|||
<span class="d_keyword">auto</span> value = node.as!MyStruct;
|
||||
<span class="d_keyword">auto</span> <span class="d_param">scalar</span> = format(value.x, <span class="d_string">":"</span>, value.y, <span class="d_string">":"</span>, value.z);
|
||||
<span class="d_keyword">return</span> representer.<span class="d_psymbol">representScalar</span>(<span class="d_string">"!mystruct.tag"</span>, <span class="d_param">scalar</span>);
|
||||
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
@ -225,7 +260,7 @@
|
|||
|
||||
</p>
|
||||
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>string <b>tag</b></td>
|
||||
<td valign=top>Tag of the <b>sequence</b>.</td></tr>
|
||||
<td valign=top>Tag of the sequence.</td></tr>
|
||||
<tr><td valign=top>Node[] <b>sequence</b></td>
|
||||
<td valign=top>Sequence of nodes.</td></tr>
|
||||
<tr><td valign=top>CollectionStyle <b>style</b></td>
|
||||
|
@ -235,13 +270,23 @@
|
|||
<b>Returns:</b><div class="pbr">The represented node.
|
||||
|
||||
</div>
|
||||
<b>Throws:</b><div class="pbr">RepresenterException if a child could not be represented.
|
||||
<b>Throws:</b><div class="pbr"><span class="d_inlinecode">RepresenterException</span> if a child could not be represented.
|
||||
|
||||
</div>
|
||||
<p><b>Example:</b><br>
|
||||
<pre class="d_code"> <span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
Node representMyStruct(<span class="d_keyword">ref</span> Node node, Representer representer)
|
||||
|
@ -274,13 +319,23 @@
|
|||
<b>Returns:</b><div class="pbr">The represented node.
|
||||
|
||||
</div>
|
||||
<b>Throws:</b><div class="pbr">RepresenterException if a child could not be represented.
|
||||
<b>Throws:</b><div class="pbr"><span class="d_inlinecode">RepresenterException</span> if a child could not be represented.
|
||||
|
||||
</div>
|
||||
<p><b>Example:</b><br>
|
||||
<pre class="d_code"> <span class="d_keyword">struct</span> MyStruct
|
||||
{
|
||||
<span class="d_keyword">int</span> x, y, z;
|
||||
|
||||
<span class="d_comment">//Any D:YAML type must have a custom opCmp operator.
|
||||
</span> <span class="d_comment">//This is used for ordering in mappings.
|
||||
</span> <span class="d_keyword">const</span> <span class="d_keyword">int</span> opCmp(<span class="d_keyword">ref</span> <span class="d_keyword">const</span> MyStruct s)
|
||||
{
|
||||
<span class="d_keyword">if</span>(x != s.x){<span class="d_keyword">return</span> x - s.x;}
|
||||
<span class="d_keyword">if</span>(y != s.y){<span class="d_keyword">return</span> y - s.y;}
|
||||
<span class="d_keyword">if</span>(z != s.z){<span class="d_keyword">return</span> z - s.z;}
|
||||
<span class="d_keyword">return</span> 0;
|
||||
}
|
||||
}
|
||||
|
||||
Node representMyStruct(<span class="d_keyword">ref</span> Node node, Representer representer)
|
||||
|
@ -348,7 +403,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -59,7 +59,7 @@ import the <i>yaml</i> module, which will import all needed modules.
|
|||
|
||||
<div id="copyright">
|
||||
Copyright © Ferdinand Majerech 2011. Based on <a href="http://www.pyyaml.org">PyYAML</a> by Kirill Simonov. |
|
||||
Page generated by Autodoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
Page generated by AutoDDoc and <a href="http://www.digitalmars.com/d/2.0/ddoc.html">Ddoc</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -138,7 +138,7 @@ struct appears in Phobos.</p>
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -48,7 +48,7 @@
|
|||
<div class="section" id="custom-yaml-data-types">
|
||||
<h1>Custom YAML data types<a class="headerlink" href="#custom-yaml-data-types" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Sometimes you need to serialize complex data types such as classes. To do this
|
||||
you could use plain nodes such as mappings with class data members. YAML also
|
||||
you could use plain nodes such as mappings with classes’ fields. YAML also
|
||||
supports custom types with identifiers called <em>tags</em>. That is the topic of this
|
||||
tutorial.</p>
|
||||
<p>Each YAML node has a tag specifying its type. For instance: strings use the tag
|
||||
|
@ -62,11 +62,13 @@ each node to hold data type corresponding to its tag. <em>Constructor</em> store
|
|||
functions to process each supported tag. These are supplied by the user using
|
||||
the <em>addConstructorXXX()</em> methods, where <em>XXX</em> is <em>Scalar</em>, <em>Sequence</em> or
|
||||
<em>Mapping</em>. <em>Constructor</em> is then passed to <em>Loader</em>, which parses YAML input.</p>
|
||||
<p>Struct types have no specific requirements for YAML support. Class types should
|
||||
define the <em>opEquals()</em> operator - this is used in equality comparisons of
|
||||
nodes. Default class <em>opEquals()</em> compares references, which means two identical
|
||||
objects might be considered unequal. (Default struct <em>opEquals()</em> compares
|
||||
byte-by-byte, sometimes you might want to override that as well.)</p>
|
||||
<p>Structs and classes must implement the <em>opCmp()</em> operator for YAML support. This
|
||||
is used for duplicate detection in mappings, sorting and equality comparisons of
|
||||
nodes. The signature of the operator that must be implemented is
|
||||
<tt class="docutils literal"><span class="pre">const</span> <span class="pre">int</span> <span class="pre">opCmp(ref</span> <span class="pre">const</span> <span class="pre">MyStruct</span> <span class="pre">s)</span></tt> for structs where <em>MyStruct</em> is the
|
||||
struct type, and <tt class="docutils literal"><span class="pre">int</span> <span class="pre">opCmp(Object</span> <span class="pre">o)</span></tt> for classes. Note that the class
|
||||
<em>opCmp()</em> should not alter the compared values - it is not const for compatibility
|
||||
reasons.</p>
|
||||
<p>We will implement support for an RGB color type. It is implemented as the
|
||||
following struct:</p>
|
||||
<div class="highlight-d"><div class="highlight"><pre><span class="k">struct</span> <span class="n">Color</span>
|
||||
|
@ -74,6 +76,14 @@ following struct:</p>
|
|||
<span class="kt">ubyte</span> <span class="n">red</span><span class="p">;</span>
|
||||
<span class="kt">ubyte</span> <span class="n">green</span><span class="p">;</span>
|
||||
<span class="kt">ubyte</span> <span class="n">blue</span><span class="p">;</span>
|
||||
|
||||
<span class="k">const</span> <span class="kt">int</span> <span class="n">opCmp</span><span class="p">(</span><span class="k">ref</span> <span class="k">const</span> <span class="n">Color</span> <span class="n">c</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="k">if</span><span class="p">(</span><span class="n">red</span> <span class="p">!=</span> <span class="n">c</span><span class="p">.</span><span class="n">red</span><span class="p">)</span> <span class="p">{</span><span class="k">return</span> <span class="n">red</span> <span class="p">-</span> <span class="n">c</span><span class="p">.</span><span class="n">red</span><span class="p">;}</span>
|
||||
<span class="k">if</span><span class="p">(</span><span class="n">green</span> <span class="p">!=</span> <span class="n">c</span><span class="p">.</span><span class="n">green</span><span class="p">){</span><span class="k">return</span> <span class="n">green</span> <span class="p">-</span> <span class="n">c</span><span class="p">.</span><span class="n">green</span><span class="p">;}</span>
|
||||
<span class="k">if</span><span class="p">(</span><span class="n">blue</span> <span class="p">!=</span> <span class="n">c</span><span class="p">.</span><span class="n">blue</span><span class="p">)</span> <span class="p">{</span><span class="k">return</span> <span class="n">blue</span> <span class="p">-</span> <span class="n">c</span><span class="p">.</span><span class="n">blue</span><span class="p">;}</span>
|
||||
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
|
@ -364,7 +374,7 @@ directory of the D:YAML package.</p>
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -78,7 +78,7 @@ script for compilation. To compile D:YAML, you first need to build CDC.
|
|||
Do this by typing the following command into the console:</p>
|
||||
<div class="highlight-python"><pre>dmd cdc.d</pre>
|
||||
</div>
|
||||
<p>Now you can use CDC to compile D:YAML.
|
||||
<p>Now compile D:YAML with CDC.
|
||||
To do this on Unix/Linux, use the following command:</p>
|
||||
<div class="highlight-python"><pre>./cdc</pre>
|
||||
</div>
|
||||
|
@ -125,8 +125,8 @@ into the file:</p>
|
|||
</div>
|
||||
<div class="section" id="explanation-of-the-code">
|
||||
<h3>Explanation of the code<a class="headerlink" href="#explanation-of-the-code" title="Permalink to this headline">¶</a></h3>
|
||||
<p>First, we import the <em>yaml</em> module. This is the only module you need to import
|
||||
to use D:YAML - it automatically imports all needed modules.</p>
|
||||
<p>First, we import the <em>yaml</em> module. This is the only D:YAML module you need to
|
||||
import - it automatically imports all needed modules.</p>
|
||||
<p>Next we load the file using the <em>Loader.load()</em> method. <em>Loader</em> is a struct
|
||||
used for parsing YAML documents. The <em>load()</em> method loads the file as
|
||||
<strong>one</strong> YAML document, or throws <em>YAMLException</em>, D:YAML exception type, if the
|
||||
|
@ -160,17 +160,17 @@ formatted differently. Comments are not preserved, either.</p>
|
|||
</div>
|
||||
<div class="section" id="compiling">
|
||||
<h3>Compiling<a class="headerlink" href="#compiling" title="Permalink to this headline">¶</a></h3>
|
||||
<p>To compile your project, you must give DMD the directories containing import
|
||||
modules and the library. You also need to tell it to link with D:YAML. The import
|
||||
directory should be the D:YAML package directory. You can specify it using the
|
||||
<tt class="docutils literal"><span class="pre">-I</span></tt> option of DMD. The library directory should be where you put the compiled
|
||||
D:YAML library. On Unix/Linux you can specify it using the <tt class="docutils literal"><span class="pre">-L-L</span></tt> option, and
|
||||
link with D:YAML using the <tt class="docutils literal"><span class="pre">-L-l</span></tt> option. On Windows, the import directory is
|
||||
used as the library directory. To link with the library on Windows, just add the
|
||||
path to it relative to the current directory.</p>
|
||||
<p>To compile your project, DMD needs to know which directories contain the
|
||||
imported modules and the library. You also need to tell it to link with D:YAML.
|
||||
The import directory should be the D:YAML package directory. You can specify it
|
||||
using the <tt class="docutils literal"><span class="pre">-I</span></tt> option of DMD. The library directory should point to the
|
||||
compiled library. On Unix/Linux you can specify it using the <tt class="docutils literal"><span class="pre">-L-L</span></tt> option,
|
||||
and link with D:YAML using the <tt class="docutils literal"><span class="pre">-L-l</span></tt> option. On Windows, the import directory
|
||||
is used as the library directory. To link with the library on Windows, just add
|
||||
the path to it relative to the current directory.</p>
|
||||
<p>For example, if you extracted and compiled D:YAML in <tt class="docutils literal"><span class="pre">/home/xxx/dyaml</span></tt>, your
|
||||
project is in <tt class="docutils literal"><span class="pre">/home/xxx/dyaml-project</span></tt>, and you are currently in that
|
||||
directory, you can compile the project with the following command on Unix/Linux:</p>
|
||||
directory, compile the project with the following command on Unix/Linux:</p>
|
||||
<div class="highlight-python"><pre>dmd -I../dyaml -L-L../dyaml -L-ldyaml main.d</pre>
|
||||
</div>
|
||||
<p>And the following on Windows:</p>
|
||||
|
@ -237,7 +237,7 @@ example in the <tt class="docutils literal"><span class="pre">example/getting_st
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -330,7 +330,7 @@ Some of these might change in the future (especially !!map and !!set).</p>
|
|||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||
Last updated on Nov 18, 2011.
|
||||
Last updated on Jan 23, 2012.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||
</div>
|
||||
</body>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue