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">
2013-12-17 14:19:01 +00:00
2011-08-16 12:53:13 +00:00
< html xmlns = "http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" / >
2013-12-17 14:19:01 +00:00
< title > Custom YAML data types — D:YAML 0.4 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" / >
2013-12-17 14:19:01 +00:00
2011-08-16 12:53:13 +00:00
< script type = "text/javascript" >
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
2012-01-23 17:40:05 +00:00
VERSION: '0.4',
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 >
2013-12-17 14:19:01 +00:00
< link rel = "top" title = "D:YAML 0.4 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 >
2013-12-17 14:19:01 +00:00
< li > < a href = "../index.html" > D:YAML 0.4 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
2012-01-23 14:57:26 +00:00
you could use plain nodes such as mappings with classes’ fields. YAML also
2011-11-17 22:53:24 +00:00
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 >
2012-01-23 14:57:26 +00:00
< 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 >
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 >
2012-01-23 14:57:26 +00:00
< 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 >
2011-08-16 12:53:13 +00:00
< 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 >
2013-12-17 14:19:01 +00:00
< li > < a href = "../index.html" > D:YAML 0.4 documentation< / a > » < / li >
2011-08-16 12:53:13 +00:00
< / ul >
< / div >
< div class = "footer" >
2014-05-19 17:54:48 +00:00
© Copyright 2011-2014, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
Last updated on May 19, 2014.
2013-12-17 14:19:01 +00:00
Created using < a href = "http://sphinx.pocoo.org/" > Sphinx< / a > 1.1.3.
2011-08-16 12:53:13 +00:00
< / div >
< / body >
< / html >