Simplified the Constructor API.

This commit is contained in:
Ferdinand Majerech 2011-11-17 23:53:24 +01:00
parent ab154480fb
commit fbc962623d
16 changed files with 217 additions and 297 deletions

View file

@ -48,12 +48,12 @@
<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. However,
YAML supports custom types with identifiers called <em>tags</em>. That is the topic of
this tutorial.</p>
you could use plain nodes such as mappings with class data members. 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
<tt class="docutils literal"><span class="pre">tag:yaml.org,2002:str</span></tt>. Tags of most default types are <em>implicitly resolved</em>
during parsing, so you don&#8217;t need to specify tag for each float, integer, etc.
during parsing - you don&#8217;t need to specify tag for each float, integer, etc.
D:YAML can also implicitly resolve custom tags, as we will show later.</p>
<div class="section" id="constructor">
<h2>Constructor<a class="headerlink" href="#constructor" title="Permalink to this headline"></a></h2>
@ -63,7 +63,7 @@ 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, as this is used in equality comparisons of
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>
@ -77,21 +77,22 @@ following struct:</p>
<span class="p">}</span>
</pre></div>
</div>
<p>First, we need a function to construct our data type. It must take two <em>Mark</em>
structs, which store position of the node in the file, and a reference to <em>Node</em>
to construct from. The node is guaranteed to contain either a <em>string</em>, an array
of <em>Node</em> or of <em>Node.Pair</em>, depending on whether we&#8217;re constructing our value
from a scalar, sequence, or mapping, respectively. In this tutorial, we have
functions 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:</p>
<div class="highlight-d"><div class="highlight"><pre><span class="n">Color</span> <span class="n">constructColorScalar</span><span class="p">(</span><span class="n">Mark</span> <span class="n">start</span><span class="p">,</span> <span class="n">Mark</span> <span class="n">end</span><span class="p">,</span> <span class="k">ref</span> <span class="n">Node</span> <span class="n">node</span><span class="p">)</span>
<p>First, we need a function to construct our data type. The function will take a
reference to <em>Node</em> to construct from. The node is guaranteed to contain either
a <em>string</em>, an array of <em>Node</em> or of <em>Node.Pair</em>, depending on whether we&#8217;re
constructing our value from a scalar, sequence, or mapping, respectively.
If this function throws any exception, D:YAML handles it and adds its message
to a <em>YAMLException</em> that will be thrown when loading the file.</p>
<p>In this tutorial, we have functions 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:</p>
<div class="highlight-d"><div class="highlight"><pre><span class="n">Color</span> <span class="n">constructColorScalar</span><span class="p">(</span><span class="k">ref</span> <span class="n">Node</span> <span class="n">node</span><span class="p">)</span>
<span class="p">{</span>
<span class="nb">string</span> <span class="n">value</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">as</span><span class="p">!</span><span class="nb">string</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">length</span> <span class="p">!=</span> <span class="mi">6</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">ConstructorException</span><span class="p">(</span><span class="s">&quot;Invalid color: &quot;</span> <span class="p">~</span> <span class="n">value</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">Exception</span><span class="p">(</span><span class="s">&quot;Invalid color: &quot;</span> <span class="p">~</span> <span class="n">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//We don&#39;t need to check for uppercase chars this way.</span>
<span class="n">value</span> <span class="p">=</span> <span class="n">value</span><span class="p">.</span><span class="n">toLower</span><span class="p">();</span>
@ -101,7 +102,7 @@ of these functions:</p>
<span class="p">{</span>
<span class="k">if</span><span class="p">(!</span><span class="n">std</span><span class="p">.</span><span class="n">ascii</span><span class="p">.</span><span class="n">isHexDigit</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">ConstructorException</span><span class="p">(</span><span class="s">&quot;Invalid color: &quot;</span> <span class="p">~</span> <span class="n">value</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">Exception</span><span class="p">(</span><span class="s">&quot;Invalid color: &quot;</span> <span class="p">~</span> <span class="n">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">std</span><span class="p">.</span><span class="n">ascii</span><span class="p">.</span><span class="n">isDigit</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
@ -119,21 +120,16 @@ of these functions:</p>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">Color</span> <span class="n">constructColorMapping</span><span class="p">(</span><span class="n">Mark</span> <span class="n">start</span><span class="p">,</span> <span class="n">Mark</span> <span class="n">end</span><span class="p">,</span> <span class="k">ref</span> <span class="n">Node</span> <span class="n">node</span><span class="p">)</span>
<span class="n">Color</span> <span class="n">constructColorMapping</span><span class="p">(</span><span class="k">ref</span> <span class="n">Node</span> <span class="n">node</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">ubyte</span> <span class="n">r</span><span class="p">,</span><span class="n">g</span><span class="p">,</span><span class="n">b</span><span class="p">;</span>
<span class="c1">//Might throw if a value is missing is not an integer, or is out of range.</span>
<span class="k">try</span>
<span class="p">{</span>
<span class="n">r</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;r&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="n">g</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;g&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="n">b</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;b&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">catch</span><span class="p">(</span><span class="n">NodeException</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="n">ConstructorException</span><span class="p">(</span><span class="s">&quot;Invalid color: &quot;</span> <span class="p">~</span> <span class="n">e</span><span class="p">.</span><span class="n">msg</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//If this happens, D:YAML will handle the exception and use its message</span>
<span class="c1">//in a YAMLException thrown when loading.</span>
<span class="n">r</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;r&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="n">g</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;g&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="n">b</span> <span class="p">=</span> <span class="n">node</span><span class="p">[</span><span class="s">&quot;b&quot;</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
<span class="k">return</span> <span class="n">Color</span><span class="p">(</span><span class="k">cast</span><span class="p">(</span><span class="kt">ubyte</span><span class="p">)</span><span class="n">r</span><span class="p">,</span> <span class="k">cast</span><span class="p">(</span><span class="kt">ubyte</span><span class="p">)</span><span class="n">g</span><span class="p">,</span> <span class="k">cast</span><span class="p">(</span><span class="kt">ubyte</span><span class="p">)</span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
@ -368,7 +364,7 @@ directory of the D:YAML package.</p>
</div>
<div class="footer">
&copy; Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
Last updated on Nov 16, 2011.
Last updated on Nov 17, 2011.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
</div>
</body>

View file

@ -237,7 +237,7 @@ example in the <tt class="docutils literal"><span class="pre">example/getting_st
</div>
<div class="footer">
&copy; Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
Last updated on Nov 16, 2011.
Last updated on Nov 17, 2011.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
</div>
</body>

View file

@ -330,7 +330,7 @@ Some of these might change in the future (especially !!map and !!set).</p>
</div>
<div class="footer">
&copy; Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
Last updated on Nov 16, 2011.
Last updated on Nov 17, 2011.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
</div>
</body>