2011-08-16 12:53:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
|
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
|
|
<head>
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
|
|
2011-10-18 19:46:05 +00:00
|
|
|
<title>Custom YAML data types — D:YAML v0.3 documentation</title>
|
2011-08-16 12:53:13 +00:00
|
|
|
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
|
|
|
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|
|
|
<script type="text/javascript">
|
|
|
|
var DOCUMENTATION_OPTIONS = {
|
|
|
|
URL_ROOT: '../',
|
2011-10-18 19:46:05 +00:00
|
|
|
VERSION: '0.3',
|
2011-08-16 12:53:13 +00:00
|
|
|
COLLAPSE_INDEX: false,
|
|
|
|
FILE_SUFFIX: '.html',
|
|
|
|
HAS_SOURCE: true
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|
|
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|
|
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
2011-10-18 19:46:05 +00:00
|
|
|
<link rel="top" title="D:YAML v0.3 documentation" href="../index.html" />
|
2011-08-16 12:53:13 +00:00
|
|
|
<link rel="next" title="YAML syntax" href="yaml_syntax.html" />
|
|
|
|
<link rel="prev" title="Getting started" href="getting_started.html" />
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div class="related">
|
|
|
|
<h3>Navigation</h3>
|
|
|
|
<ul>
|
|
|
|
<li class="right" style="margin-right: 10px">
|
|
|
|
<a href="yaml_syntax.html" title="YAML syntax"
|
|
|
|
accesskey="N">next</a></li>
|
|
|
|
<li class="right" >
|
|
|
|
<a href="getting_started.html" title="Getting started"
|
|
|
|
accesskey="P">previous</a> |</li>
|
2011-10-18 19:46:05 +00:00
|
|
|
<li><a href="../index.html">D:YAML v0.3 documentation</a> »</li>
|
2011-08-16 12:53:13 +00:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="document">
|
|
|
|
<div class="documentwrapper">
|
|
|
|
<div class="bodywrapper">
|
|
|
|
<div class="body">
|
|
|
|
|
|
|
|
<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>
|
2011-10-29 18:43:30 +00:00
|
|
|
<p>Sometimes you need to serialize complex data types such as classes. To do this
|
2011-11-17 22:53:24 +00:00
|
|
|
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>
|
2011-08-16 12:53:13 +00:00
|
|
|
<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>
|
2011-11-17 22:53:24 +00:00
|
|
|
during parsing - you don’t need to specify tag for each float, integer, etc.
|
2011-10-29 18:43:30 +00:00
|
|
|
D:YAML can also implicitly resolve custom tags, as we will show later.</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<div class="section" id="constructor">
|
|
|
|
<h2>Constructor<a class="headerlink" href="#constructor" title="Permalink to this headline">¶</a></h2>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>D:YAML uses the <a class="reference external" href="../api/dyaml.constructor.html">Constructor</a> class to process
|
2011-10-29 18:43:30 +00:00
|
|
|
each node to hold data type corresponding to its tag. <em>Constructor</em> stores
|
|
|
|
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>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>Struct types have no specific requirements for YAML support. Class types should
|
2011-11-17 22:53:24 +00:00
|
|
|
define the <em>opEquals()</em> operator - this is used in equality comparisons of
|
2011-10-15 14:31:23 +00:00
|
|
|
nodes. Default class <em>opEquals()</em> compares references, which means two identical
|
2011-10-29 18:43:30 +00:00
|
|
|
objects might be considered unequal. (Default struct <em>opEquals()</em> compares
|
|
|
|
byte-by-byte, sometimes you might want to override that as well.)</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<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>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<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="p">}</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
2011-11-17 22:53:24 +00:00
|
|
|
<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’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>
|
2011-08-16 12:53:13 +00:00
|
|
|
<span class="p">{</span>
|
2011-10-22 15:06:32 +00:00
|
|
|
<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>
|
2011-10-17 10:53:38 +00:00
|
|
|
|
2011-08-16 12:53:13 +00:00
|
|
|
<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>
|
2011-11-17 22:53:24 +00:00
|
|
|
<span class="k">throw</span> <span class="k">new</span> <span class="n">Exception</span><span class="p">(</span><span class="s">"Invalid color: "</span> <span class="p">~</span> <span class="n">value</span><span class="p">);</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1">//We don'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>
|
|
|
|
|
|
|
|
<span class="c1">//Get value of a hex digit.</span>
|
|
|
|
<span class="kt">uint</span> <span class="n">hex</span><span class="p">(</span><span class="kt">char</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">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>
|
2011-11-17 22:53:24 +00:00
|
|
|
<span class="k">throw</span> <span class="k">new</span> <span class="n">Exception</span><span class="p">(</span><span class="s">"Invalid color: "</span> <span class="p">~</span> <span class="n">value</span><span class="p">);</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
<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>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="k">return</span> <span class="n">c</span> <span class="p">-</span> <span class="sc">'0'</span><span class="p">;</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="n">c</span> <span class="p">-</span> <span class="sc">'a'</span> <span class="p">+</span> <span class="mi">10</span><span class="p">;</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
|
|
|
|
<span class="n">Color</span> <span class="n">result</span><span class="p">;</span>
|
|
|
|
<span class="n">result</span><span class="p">.</span><span class="n">red</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="mi">16</span> <span class="p">*</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">+</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">1</span><span class="p">]));</span>
|
|
|
|
<span class="n">result</span><span class="p">.</span><span class="n">green</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="mi">16</span> <span class="p">*</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="p">+</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">3</span><span class="p">]));</span>
|
|
|
|
<span class="n">result</span><span class="p">.</span><span class="n">blue</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="mi">16</span> <span class="p">*</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">4</span><span class="p">])</span> <span class="p">+</span> <span class="n">hex</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">5</span><span class="p">]));</span>
|
|
|
|
|
|
|
|
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
|
2011-11-17 22:53:24 +00:00
|
|
|
<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>
|
2011-08-16 12:53:13 +00:00
|
|
|
<span class="p">{</span>
|
2011-10-17 11:13:02 +00:00
|
|
|
<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>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-17 11:13:02 +00:00
|
|
|
<span class="c1">//Might throw if a value is missing is not an integer, or is out of range.</span>
|
2011-11-17 22:53:24 +00:00
|
|
|
<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">"r"</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">"g"</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">"b"</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="kt">ubyte</span><span class="p">;</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
|
|
|
<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>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>Next, we need some YAML data using our new tag. Create a file called
|
|
|
|
<tt class="docutils literal"><span class="pre">input.yaml</span></tt> with the following contents:</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<div class="highlight-yaml"><div class="highlight"><pre><span class="l-Scalar-Plain">scalar-red</span><span class="p-Indicator">:</span> <span class="kt">!color</span> <span class="l-Scalar-Plain">FF0000</span>
|
|
|
|
<span class="l-Scalar-Plain">scalar-orange</span><span class="p-Indicator">:</span> <span class="kt">!color</span> <span class="l-Scalar-Plain">FFFF00</span>
|
|
|
|
<span class="l-Scalar-Plain">mapping-red</span><span class="p-Indicator">:</span> <span class="kt">!color-mapping</span> <span class="p-Indicator">{</span><span class="nv">r</span><span class="p-Indicator">:</span> <span class="nv">255</span><span class="p-Indicator">,</span> <span class="nv">g</span><span class="p-Indicator">:</span> <span class="nv">0</span><span class="p-Indicator">,</span> <span class="nv">b</span><span class="p-Indicator">:</span> <span class="nv">0</span><span class="p-Indicator">}</span>
|
|
|
|
<span class="l-Scalar-Plain">mapping-orange</span><span class="p-Indicator">:</span>
|
|
|
|
<span class="kt">!color-mapping</span>
|
|
|
|
<span class="l-Scalar-Plain">r</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">255</span>
|
|
|
|
<span class="l-Scalar-Plain">g</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">255</span>
|
|
|
|
<span class="l-Scalar-Plain">b</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">0</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
<p>You can see that we’re using tag <tt class="docutils literal"><span class="pre">!color</span></tt> for scalar colors, and
|
|
|
|
<tt class="docutils literal"><span class="pre">!color-mapping</span></tt> for colors expressed as mappings.</p>
|
|
|
|
<p>Finally, the code to put it all together:</p>
|
|
|
|
<div class="highlight-d"><div class="highlight"><pre><span class="kt">void</span> <span class="n">main</span><span class="p">()</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="k">auto</span> <span class="n">red</span> <span class="p">=</span> <span class="n">Color</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
|
|
|
|
<span class="k">auto</span> <span class="n">orange</span> <span class="p">=</span> <span class="n">Color</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
|
|
|
|
|
|
|
|
<span class="k">try</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="k">auto</span> <span class="n">constructor</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Constructor</span><span class="p">;</span>
|
|
|
|
<span class="c1">//both functions handle the same tag, but one handles scalar, one mapping.</span>
|
2011-10-17 10:53:38 +00:00
|
|
|
<span class="n">constructor</span><span class="p">.</span><span class="n">addConstructorScalar</span><span class="p">(</span><span class="s">"!color"</span><span class="p">,</span> <span class="p">&</span><span class="n">constructColorScalar</span><span class="p">);</span>
|
|
|
|
<span class="n">constructor</span><span class="p">.</span><span class="n">addConstructorMapping</span><span class="p">(</span><span class="s">"!color-mapping"</span><span class="p">,</span> <span class="p">&</span><span class="n">constructColorMapping</span><span class="p">);</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-14 08:34:53 +00:00
|
|
|
<span class="k">auto</span> <span class="n">loader</span> <span class="p">=</span> <span class="n">Loader</span><span class="p">(</span><span class="s">"input.yaml"</span><span class="p">);</span>
|
|
|
|
<span class="n">loader</span><span class="p">.</span><span class="n">constructor</span> <span class="p">=</span> <span class="n">constructor</span><span class="p">;</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-14 08:34:53 +00:00
|
|
|
<span class="k">auto</span> <span class="n">root</span> <span class="p">=</span> <span class="n">loader</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-22 15:06:32 +00:00
|
|
|
<span class="k">if</span><span class="p">(</span><span class="n">root</span><span class="p">[</span><span class="s">"scalar-red"</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="n">Color</span> <span class="p">==</span> <span class="n">red</span> <span class="p">&&</span>
|
|
|
|
<span class="n">root</span><span class="p">[</span><span class="s">"mapping-red"</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="n">Color</span> <span class="p">==</span> <span class="n">red</span> <span class="p">&&</span>
|
|
|
|
<span class="n">root</span><span class="p">[</span><span class="s">"scalar-orange"</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="n">Color</span> <span class="p">==</span> <span class="n">orange</span> <span class="p">&&</span>
|
|
|
|
<span class="n">root</span><span class="p">[</span><span class="s">"mapping-orange"</span><span class="p">].</span><span class="n">as</span><span class="p">!</span><span class="n">Color</span> <span class="p">==</span> <span class="n">orange</span><span class="p">)</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="n">writeln</span><span class="p">(</span><span class="s">"SUCCESS"</span><span class="p">);</span>
|
|
|
|
<span class="k">return</span><span class="p">;</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">catch</span><span class="p">(</span><span class="n">YAMLException</span> <span class="n">e</span><span class="p">)</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="n">writeln</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="p">}</span>
|
|
|
|
|
|
|
|
<span class="n">writeln</span><span class="p">(</span><span class="s">"FAILURE"</span><span class="p">);</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
<p>First, we create a <em>Constructor</em> and pass functions to handle the <tt class="docutils literal"><span class="pre">!color</span></tt>
|
2011-10-15 14:31:23 +00:00
|
|
|
and <tt class="docutils literal"><span class="pre">!color-mapping</span></tt> tag. We construct a <em>Loader</em> and pass the <em>Constructor</em>
|
2011-10-22 15:06:32 +00:00
|
|
|
to it. We then load the YAML document, and finally, read the colors to test if
|
|
|
|
they were loaded as expected.</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<p>You can find the source code for what we’ve done so far in the
|
|
|
|
<tt class="docutils literal"><span class="pre">examples/constructor</span></tt> directory in the D:YAML package.</p>
|
|
|
|
</div>
|
|
|
|
<div class="section" id="resolver">
|
|
|
|
<h2>Resolver<a class="headerlink" href="#resolver" title="Permalink to this headline">¶</a></h2>
|
2011-10-29 18:43:30 +00:00
|
|
|
<p>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 <a class="reference external" href="../api/dyaml.resolver.html">Resolver</a> class to add implicit
|
|
|
|
tag resolution for the Color data type (in its scalar form).</p>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>We use the <em>addImplicitResolver()</em> method of <em>Resolver</em>, 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 <em>Resolver</em> to
|
|
|
|
<em>Loader</em>.</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<p>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.</p>
|
|
|
|
<p>Add this to your code to add implicit resolution of <tt class="docutils literal"><span class="pre">!color</span></tt>.</p>
|
|
|
|
<div class="highlight-d"><div class="highlight"><pre><span class="c1">//code from the previous example...</span>
|
|
|
|
|
|
|
|
<span class="k">auto</span> <span class="n">resolver</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Resolver</span><span class="p">;</span>
|
2011-10-15 14:31:23 +00:00
|
|
|
<span class="n">resolver</span><span class="p">.</span><span class="n">addImplicitResolver</span><span class="p">(</span><span class="s">"!color"</span><span class="p">,</span> <span class="n">std</span><span class="p">.</span><span class="n">regex</span><span class="p">.</span><span class="n">regex</span><span class="p">(</span><span class="s">"[0-9a-fA-F]{6}"</span><span class="p">),</span>
|
|
|
|
<span class="s">"0123456789abcdefABCDEF"</span><span class="p">);</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-14 08:34:53 +00:00
|
|
|
<span class="k">auto</span> <span class="n">loader</span> <span class="p">=</span> <span class="n">Loader</span><span class="p">(</span><span class="s">"input.yaml"</span><span class="p">);</span>
|
|
|
|
|
|
|
|
<span class="n">loader</span><span class="p">.</span><span class="n">constructor</span> <span class="p">=</span> <span class="n">constructor</span><span class="p">;</span>
|
|
|
|
<span class="n">loader</span><span class="p">.</span><span class="n">resolver</span> <span class="p">=</span> <span class="n">resolver</span><span class="p">;</span>
|
2011-08-16 12:53:13 +00:00
|
|
|
|
|
|
|
<span class="c1">//code from the previous example...</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>Now, change contents of <tt class="docutils literal"><span class="pre">input.yaml</span></tt> to this:</p>
|
2011-08-16 12:53:13 +00:00
|
|
|
<div class="highlight-yaml"><div class="highlight"><pre><span class="l-Scalar-Plain">scalar-red</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">FF0000</span>
|
|
|
|
<span class="l-Scalar-Plain">scalar-orange</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">FFFF00</span>
|
|
|
|
<span class="l-Scalar-Plain">mapping-red</span><span class="p-Indicator">:</span> <span class="kt">!color-mapping</span> <span class="p-Indicator">{</span><span class="nv">r</span><span class="p-Indicator">:</span> <span class="nv">255</span><span class="p-Indicator">,</span> <span class="nv">g</span><span class="p-Indicator">:</span> <span class="nv">0</span><span class="p-Indicator">,</span> <span class="nv">b</span><span class="p-Indicator">:</span> <span class="nv">0</span><span class="p-Indicator">}</span>
|
|
|
|
<span class="l-Scalar-Plain">mapping-orange</span><span class="p-Indicator">:</span>
|
|
|
|
<span class="kt">!color-mapping</span>
|
|
|
|
<span class="l-Scalar-Plain">r</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">255</span>
|
|
|
|
<span class="l-Scalar-Plain">g</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">255</span>
|
|
|
|
<span class="l-Scalar-Plain">b</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">0</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
<p>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.</p>
|
|
|
|
<p>You can find the complete code in the <tt class="docutils literal"><span class="pre">examples/resolver</span></tt> directory in the
|
|
|
|
D:YAML package.</p>
|
|
|
|
</div>
|
2011-10-15 14:31:23 +00:00
|
|
|
<div class="section" id="representer">
|
|
|
|
<h2>Representer<a class="headerlink" href="#representer" title="Permalink to this headline">¶</a></h2>
|
2011-10-29 18:43:30 +00:00
|
|
|
<p>Now that you can load custom data types, it might be good to know how to dump
|
|
|
|
them. D:YAML uses the <a class="reference external" href="../api/dyaml.representer.html">Representer</a> class for
|
|
|
|
this purpose.</p>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p><em>Representer</em> processes YAML nodes into plain mapping, sequence or scalar nodes
|
|
|
|
ready for output. Just like with <em>Constructor</em>, this is done by user specified
|
|
|
|
functions. These functions take references to a node to process and to the
|
|
|
|
<em>Representer</em>, and return the processed node.</p>
|
|
|
|
<p>Representer functions can be added with the <em>addRepresenter()</em> method. The
|
|
|
|
<em>Representer</em> is then passed to <em>Dumper</em>, which dumps YAML documents. Only one
|
2011-10-29 18:43:30 +00:00
|
|
|
function per type can be specified. This is asserted in <em>addRepresenter()</em>
|
|
|
|
preconditions. Default YAML types already have representer functions specified,
|
|
|
|
but you can disable them by constructing <em>Representer</em> with the
|
2011-10-15 14:31:23 +00:00
|
|
|
<em>useDefaultRepresenters</em> parameter set to false.</p>
|
2011-10-29 18:43:30 +00:00
|
|
|
<p>By default, tags are explicitly output for all non-default types. To make dumped
|
|
|
|
tags implicit, you can pass a <em>Resolver</em> that will resolve them implicitly. Of
|
|
|
|
course, you will need to use an identical <em>Resolver</em> when loading the output.</p>
|
2011-10-15 14:31:23 +00:00
|
|
|
<p>With the following code, we will add support for dumping the our Color type.</p>
|
|
|
|
<div class="highlight-d"><div class="highlight"><pre><span class="n">Node</span> <span class="n">representColor</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">Representer</span> <span class="n">representer</span><span class="p">)</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="c1">//The node is guaranteed to be Color as we add representer for Color.</span>
|
2011-10-22 15:06:32 +00:00
|
|
|
<span class="n">Color</span> <span class="n">color</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="n">Color</span><span class="p">;</span>
|
2011-10-15 14:31:23 +00:00
|
|
|
|
|
|
|
<span class="k">static</span> <span class="n">immutable</span> <span class="n">hex</span> <span class="p">=</span> <span class="s">"0123456789ABCDEF"</span><span class="p">;</span>
|
|
|
|
|
|
|
|
<span class="c1">//Using the color format from the Constructor example.</span>
|
|
|
|
<span class="nb">string</span> <span class="n">scalar</span><span class="p">;</span>
|
|
|
|
<span class="k">foreach</span><span class="p">(</span><span class="n">channel</span><span class="p">;</span> <span class="p">[</span><span class="n">color</span><span class="p">.</span><span class="n">red</span><span class="p">,</span> <span class="n">color</span><span class="p">.</span><span class="n">green</span><span class="p">,</span> <span class="n">color</span><span class="p">.</span><span class="n">blue</span><span class="p">])</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="n">scalar</span> <span class="p">~=</span> <span class="n">hex</span><span class="p">[</span><span class="n">channel</span> <span class="p">/</span> <span class="mi">16</span><span class="p">];</span>
|
|
|
|
<span class="n">scalar</span> <span class="p">~=</span> <span class="n">hex</span><span class="p">[</span><span class="n">channel</span> <span class="p">%</span> <span class="mi">16</span><span class="p">];</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
|
|
|
|
<span class="c1">//Representing as a scalar, with custom tag to specify this data type.</span>
|
|
|
|
<span class="k">return</span> <span class="n">representer</span><span class="p">.</span><span class="n">representScalar</span><span class="p">(</span><span class="s">"!color"</span><span class="p">,</span> <span class="n">scalar</span><span class="p">);</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
<p>First we get the <em>Color</em> from the node. Then we convert it to a string with the
|
2011-10-17 10:53:38 +00:00
|
|
|
CSS-like format we’ve used before. Finally, we use the <em>representScalar()</em>
|
2011-10-29 18:43:30 +00:00
|
|
|
method of <em>Representer</em> to get a scalar node ready for output. There are
|
|
|
|
corresponding <em>representMapping()</em> and <em>representSequence()</em> methods
|
2011-10-15 14:31:23 +00:00
|
|
|
as well, with examples in the
|
|
|
|
<a class="reference external" href="../api/dyaml.resolver.html">Resolver API documentation</a>.</p>
|
|
|
|
<p>Since a type can only have one representer function, we don’t dump <em>Color</em> 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 representer function itself.
|
|
|
|
E.g. you could dump the Color as a mapping based on some arbitrary condition,
|
|
|
|
such as the color being white.</p>
|
|
|
|
<div class="highlight-d"><div class="highlight"><pre><span class="kt">void</span> <span class="n">main</span><span class="p">()</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="k">try</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="k">auto</span> <span class="n">representer</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Representer</span><span class="p">;</span>
|
|
|
|
<span class="n">representer</span><span class="p">.</span><span class="n">addRepresenter</span><span class="p">!</span><span class="n">Color</span><span class="p">(&</span><span class="n">representColor</span><span class="p">);</span>
|
|
|
|
|
|
|
|
<span class="k">auto</span> <span class="n">resolver</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Resolver</span><span class="p">;</span>
|
|
|
|
<span class="n">resolver</span><span class="p">.</span><span class="n">addImplicitResolver</span><span class="p">(</span><span class="s">"!color"</span><span class="p">,</span> <span class="n">std</span><span class="p">.</span><span class="n">regex</span><span class="p">.</span><span class="n">regex</span><span class="p">(</span><span class="s">"[0-9a-fA-F]{6}"</span><span class="p">),</span>
|
|
|
|
<span class="s">"0123456789abcdefABCDEF"</span><span class="p">);</span>
|
|
|
|
|
|
|
|
<span class="k">auto</span> <span class="n">dumper</span> <span class="p">=</span> <span class="n">Dumper</span><span class="p">(</span><span class="s">"output.yaml"</span><span class="p">);</span>
|
|
|
|
<span class="n">dumper</span><span class="p">.</span><span class="n">representer</span> <span class="p">=</span> <span class="n">representer</span><span class="p">;</span>
|
|
|
|
<span class="n">dumper</span><span class="p">.</span><span class="n">resolver</span> <span class="p">=</span> <span class="n">resolver</span><span class="p">;</span>
|
|
|
|
|
|
|
|
<span class="k">auto</span> <span class="n">document</span> <span class="p">=</span> <span class="n">Node</span><span class="p">([</span><span class="n">Color</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
|
|
<span class="n">Color</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
|
|
<span class="n">Color</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">)]);</span>
|
|
|
|
|
|
|
|
<span class="n">dumper</span><span class="p">.</span><span class="n">dump</span><span class="p">(</span><span class="n">document</span><span class="p">);</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">catch</span><span class="p">(</span><span class="n">YAMLException</span> <span class="n">e</span><span class="p">)</span>
|
|
|
|
<span class="p">{</span>
|
|
|
|
<span class="n">writeln</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="p">}</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
|
|
<p>We construct a new <em>Representer</em>, and specify a representer function for the
|
|
|
|
<em>Color</em> (the template argument) type. We also construct a <em>Resolver</em>, same as in
|
|
|
|
the previous section, so the <tt class="docutils literal"><span class="pre">!color</span></tt> tag will be implicit. Of course,
|
|
|
|
identical <em>Resolver</em> would then have to be used when loading the file.
|
|
|
|
You don’t need to do this if you want the tag to be explicit.</p>
|
|
|
|
<p>We construct a <em>Dumper</em> to file <tt class="docutils literal"><span class="pre">output.yaml</span></tt> and pass the <em>Representer</em> and
|
|
|
|
<em>Resolver</em> to it. Then, we create a simple node containing a sequence of colors
|
|
|
|
and finally, we dump it.</p>
|
|
|
|
<p>Source code for this section can be found in the <tt class="docutils literal"><span class="pre">examples/representer</span></tt>
|
|
|
|
directory of the D:YAML package.</p>
|
|
|
|
</div>
|
2011-08-16 12:53:13 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="sphinxsidebar">
|
|
|
|
<div class="sphinxsidebarwrapper">
|
|
|
|
<p class="logo"><a href="../index.html">
|
|
|
|
<img class="logo" src="../_static/logo210.png" alt="Logo"/>
|
|
|
|
</a></p>
|
|
|
|
<h3><a href="../index.html">Table Of Contents</a></h3>
|
|
|
|
<ul>
|
|
|
|
<li><a class="reference internal" href="#">Custom YAML data types</a><ul>
|
|
|
|
<li><a class="reference internal" href="#constructor">Constructor</a></li>
|
|
|
|
<li><a class="reference internal" href="#resolver">Resolver</a></li>
|
2011-10-15 14:31:23 +00:00
|
|
|
<li><a class="reference internal" href="#representer">Representer</a></li>
|
2011-08-16 12:53:13 +00:00
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="clearer"></div>
|
|
|
|
</div>
|
|
|
|
<div class="related">
|
|
|
|
<h3>Navigation</h3>
|
|
|
|
<ul>
|
|
|
|
<li class="right" style="margin-right: 10px">
|
|
|
|
<a href="yaml_syntax.html" title="YAML syntax"
|
|
|
|
>next</a></li>
|
|
|
|
<li class="right" >
|
|
|
|
<a href="getting_started.html" title="Getting started"
|
|
|
|
>previous</a> |</li>
|
2011-10-18 19:46:05 +00:00
|
|
|
<li><a href="../index.html">D:YAML v0.3 documentation</a> »</li>
|
2011-08-16 12:53:13 +00:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="footer">
|
|
|
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
2011-11-18 11:28:29 +00:00
|
|
|
Last updated on Nov 18, 2011.
|
2011-10-14 08:34:53 +00:00
|
|
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
2011-08-16 12:53:13 +00:00
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|