Implemented the resolver unittest.

Changed Loader API to be in line with Dumper,
and updated examples, tutorials and docs.
This commit is contained in:
Ferdinand Majerech 2011-10-12 23:49:42 +02:00
parent 934df763ad
commit 34b11405d4
16 changed files with 262 additions and 279 deletions

View file

@ -9,7 +9,7 @@ are caused by difficulty of implementation of some features, such as multiple
Unicode encodings within single stream, and some by unnecessary restrictions or
ambiguities in the specification.
Still, D:YAML tries to be as close to the specification as possible. D:YAML should
Still, D:YAML tries to be as close to the specification as possible. It should
never load documents with different meaning than according to the specification,
and documents that fail to load should be very rare (for instance, very few
files use multiple Unicode encodings).
@ -21,10 +21,6 @@ List of known differences:
Differences that can cause valid YAML documents not to load:
* At the moment, all mappings in the internal representation are ordered,
and a comparison for equality between equal mappings with differing order
will return false. This will be fixed once Phobos has a usable map type or
D associative arrays work with variants.
* No support for byte order marks and multiple Unicode encodings in a stream.
* Plain scalars in flow context cannot contain ``,``, ``:`` and ``?``.
This might change with ``:`` in the future.

View file

@ -2,10 +2,10 @@
Custom YAML data types
======================
Often you will want to serialize complex data types such as classes. You can use
functions to process nodes; e.g. a mapping containing class data members indexed
by name. Alternatively, YAML supports custom data types using identifiers called
*tags*. That is the topic of this tutorial.
Often you might want to serialize complex data types such as classes. You can
use functions to process nodes such as a mapping containing class data members
indexed by name. Alternatively, YAML supports custom data types using
identifiers called *tags*. That is the topic of this tutorial.
Each YAML node has a tag specifying its type. For instance: strings use the tag
``tag:yaml.org,2002:str``. Tags of most default types are *implicitly resolved*
@ -19,9 +19,9 @@ Constructor
D:YAML uses the *Constructor* class to process each node to hold data type
corresponding to its tag. *Constructor* stores a function for each supported
tag to process it. These functions can be supplied by the user using the
*addConstructor()* method. *Constructor* is then passed to *Loader*, which will
parse YAML input.
tag to process it. These functions are supplied by the user using the
*addConstructor()* method. *Constructor* is then passed to *Loader*, which
parses YAML input.
We will implement support for an RGB color type. It is implemented as the
following struct:
@ -111,7 +111,7 @@ RRGGBB, or from a mapping, where we use the following format:
return Color(cast(ubyte)r, cast(ubyte)g, cast(ubyte)b);
}
Next, we need some YAML code using our new tag. Create a file called input.yaml
Next, we need some YAML data using our new tag. Create a file called input.yaml
with the following contents:
.. code-block:: yaml
@ -144,9 +144,10 @@ Finally, the code to put it all together:
constructor.addConstructor("!color", &constructColorScalar);
constructor.addConstructor("!color-mapping", &constructColorMapping);
auto loader = new Loader("input.yaml", constructor, new Resolver);
auto loader = Loader("input.yaml");
loader.constructor = constructor;
auto root = loader.loadSingleDocument();
auto root = loader.load();
if(root["scalar-red"].get!Color == red &&
root["mapping-red"].get!Color == red &&
@ -166,10 +167,9 @@ Finally, the code to put it all together:
}
First, we create a *Constructor* and pass functions to handle the ``!color``
and ``!color-mapping`` tag. We construct a *Loader* using the *Constructor*.
We also need a *Resolver*, but for now we just default-construct it. We then
load the YAML document, and finally, read the colors using *get()* method to
test if they were loaded as expected.
and ``!color-mapping`` tag. We construct a *Loader*m and pass the *Constructor*
to it. We then load the YAML document, and finally, read the colors using
*get()* method to test if they were loaded as expected.
You can find the source code for what we've done so far in the
``examples/constructor`` directory in the D:YAML package.
@ -180,8 +180,8 @@ Resolver
--------
Specifying tag for every color value can be tedious. D:YAML can implicitly
resolve tag of a scalar using a regular expression. This is how default types,
e.g. int, are resolved. We will use the *Resolver* class to add implicit tag
resolve scalar tags using regular expressions. This is how default types such as
int are resolved. We will use the *Resolver* class to add implicit tag
resolution for the Color data type (in its scalar form).
We use the *addImplicitResolver* method of *Resolver*, passing the tag, regular
@ -203,11 +203,14 @@ Add this to your code to add implicit resolution of ``!color``.
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}",
"0123456789abcdefABCDEF"));
auto loader = new Loader("input.yaml", constructor, resolver);
auto loader = Loader("input.yaml");
loader.constructor = constructor;
loader.resolver = resolver;
//code from the previous example...
Now, change contents of input.dyaml to this:
Now, change contents of input.yaml to this:
.. code-block:: yaml

View file

@ -26,10 +26,8 @@ Download the version of DMD for your operating system and install it.
.. note::
Other D compilers exist, such as
`GDC <http://bitbucket.org/goshawk/gdc/wiki/Home>`_ and
`LDC <http://www.dsource.org/projects/ldc/>`_.
Setting up with either one of them should be similar to DMD,
however, at the moment they are not as up to date as DMD.
`LDC <http://www.dsource.org/projects/ldc/>`_. Setting up with either one of
them should be similar to DMD, but they are not yet as stable as DMD.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Download and compile D:YAML
@ -84,7 +82,7 @@ into the file:
void main()
{
yaml.Node root = yaml.load("input.yaml");
Node root = Loader("input.yaml").load();
foreach(string word; root["Hello World"])
{
writeln(word);
@ -100,22 +98,23 @@ Explanation of the code
First, we import the *yaml* module. This is the only module you need to import
to use D:YAML - it automatically imports all needed modules.
Next we load the file using the *yaml.load()* function - this loads the file as
Next we load the file using the *Loader.load()* method. *Loader* is the struct
used for parsing YAML documents, and *load()* is a method that loads the file as
**one** YAML document and throws *YAMLException*, D:YAML exception type, if the
file could not be parsed or does not contain exactly one document. Note that we
don't do any error checking here in order to keep the example as simple as
possible.
*yaml.Node* represents a node in a YAML document. It can be a sequence (array),
*Node* represents a node in a YAML document. It can be a sequence (array),
mapping (associative array) or a scalar (value). Here the root node is a
mapping, and we use the index operator to get subnodes with keys "Hello World"
and "Answer". We iterate over the first, as it is a sequence, and use the
*yaml.Node.get()* method on the second to get its value as an integer.
*Node.get()* method on the second to get its value as an integer.
You can iterate over a mapping or sequence as if it was an associative or normal
array. If you try to iterate over a scalar, it will throw a *YAMLException*.
You can iterate over subnodes using yaml.Node as the iterated type, or specify
You can iterate over subnodes using *Node* as the iterated type, or specify
the type subnodes are expected to have. D:YAML will automatically convert
iterated subnodes to that type if possible. Here we specify the *string* type,
so we iterate over the "Hello World" sequence as an array of strings. If it is
@ -123,8 +122,8 @@ not possible to convert to iterated type, a *YAMLException* is thrown. For
instance, if we specified *int* here, we would get an error, as "Hello"
cannot be converted to an integer.
The *yaml.Node.get()* method is used to get value of a scalar node as specified
type. D:YAML will try to return the scalar as specified type, converting if
The *Node.get()* method is used to get value of a scalar node, allowing to
specify type. D:YAML will try to return the scalar as this type, converting if
needed, throwing *YAMLException* if not possible.
@ -135,16 +134,15 @@ Compiling
To compile your project, you must give DMD the directories containing import
modules and the library. You also need to tell it to link with D:YAML. The import
directory should be the D:YAML package directory. You can specify it using the
``-I`` option of DMD. The library directory should point to where you put the
compiled D:YAML library. On Unix/Linux you can specify it using the ``-L-L``
option, and link with D:YAML using the ``-L-l`` option. On Windows, the import
directory is used as the library directory. To link with the library on Windows,
just add the path to it relative to the current directory.
``-I`` option of DMD. The library directory should be where you put the compiled
D:YAML library. On Unix/Linux you can specify it using the ``-L-L`` option, and
link with D:YAML using the ``-L-l`` option. On Windows, the import directory is
used as the library directory. To link with the library on Windows, just add the
path to it relative to the current directory.
For example, if you extracted D:YAML to ``/home/xxx/dyaml`` and compiled it in
that directory, your project is in ``/home/xxx/dyaml-project``, and you are
currently in that directory, you can compile the project with the following
command on Unix/Linux::
For example, if you extracted and compiled D:YAML in ``/home/xxx/dyaml``, your
project is in ``/home/xxx/dyaml-project``, and you are currently in that
directory, you can compile the project with the following command on Unix/Linux::
dmd -I../dyaml -L-L../dyaml -L-ldyaml main.d

View file

@ -8,14 +8,14 @@ which this article is based on,
`Chapter 2 of the YAML specification <http://yaml.org/spec/1.1/#id857168>`_
or the `Wikipedia page <http://en.wikipedia.org/wiki/YAML>`_.
YAML is a data serialization format designed to be as human readable as
possible. YAML is a recursive acronym for "YAML Ain't Markup Language".
YAML is a data serialization format designed for human readability. YAML is a
recursive acronym for "YAML Ain't Markup Language".
YAML is similar to JSON, and in fact, JSON is a subset of YAML 1.2; but YAML has
some more advanced features and is easier to read. However, YAML is also more
some more advanced features and is easier to read. However, it is also more
difficult to parse (and probably somewhat slower). Data is stored in mappings
(associative arrays), sequences (lists) and scalars (single values). Data
structure hierarchy either depends on indentation (block context, similar to
structure hierarchy depends either on indentation (block context, similar to
Python code), or nesting of brackets and braces (flow context, similar to JSON).
YAML comments begin with ``#`` and continue until the end of line.
@ -25,8 +25,7 @@ Documents
---------
A YAML stream consists of one or more documents starting with ``---`` and
optionally ending with ``...`` . If there is only one document, ``---`` can be
left out.
optionally ending with ``...`` . ``---`` can be left out for the first document.
Single document with no explicit start or end:

View file

@ -40,14 +40,14 @@ import dyaml.tagdirectives;
* Write to a file:
* --------------------
* auto node = Node([1, 2, 3, 4, 5]);
* Dumper("file.txt").dump(node);
* Dumper("file.yaml").dump(node);
* --------------------
*
* Write multiple YAML documents to a file:
* --------------------
* auto node1 = Node([1, 2, 3, 4, 5]);
* auto node2 = Node("This document contains only one string");
* Dumper("file.txt").dump(node1, node2);
* Dumper("file.yaml").dump(node1, node2);
* --------------------
*
* Write to memory:
@ -65,8 +65,8 @@ import dyaml.tagdirectives;
* auto resolver = new Resolver();
*
* //Add representer functions / resolver expressions here...
* --------------------
* auto dumper = Dumper("file.txt");
*
* auto dumper = Dumper("file.yaml");
* dumper.representer = representer;
* dumper.resolver = resolver;
* dumper.dump(node);
@ -259,7 +259,7 @@ struct Dumper
*
* Example:
* --------------------
* Dumper dumper = Dumper("file.txt");
* Dumper dumper = Dumper("file.yaml");
* //This will emit tags starting with "tag:long.org,2011"
* //with a "!short!" prefix instead.
* dumper.tags("short", "tag:long.org,2011:");

View file

@ -28,43 +28,36 @@ import dyaml.token;
/**
* Load single YAML document from a file.
* Loads YAML documents from files or streams.
*
* If there is no or more than one YAML document in the file, this will throw.
* Use $(LREF loadAll) for such files.
*
* Params: filename = Name of the file to _load from.
*
* Returns: Root node of the document.
*
* Throws: YAMLException if there wasn't exactly one document in the file,
* the file could not be opened or on a YAML parsing error.
*/
Node load(in string filename)
{
auto loader = Loader(filename);
return loader.loadSingleDocument();
}
/**
* Load single YAML document from a stream.
*
* You can use this to e.g _load YAML from memory.
*
* If there is no or more than one YAML document in the stream, this will throw.
* Use $(LREF loadAll) for such files.
*
* Params: input = Stream to read from. Must be readable.
* name = Name of the stream, used in error messages.
*
* Returns: Root node of the document.
*
* Throws: YAMLException if there wasn't exactly one document in the stream,
* the stream could not be read from or on a YAML parsing error.
* User specified Constructor and/or Resolver can be used to support new
* tags / data types.
*
* Examples:
*
* Loading YAML from memory:
* Load single YAML document from a file:
* --------------------
* auto rootNode = Loader("file.yaml").load();
* ...
* --------------------
*
* Load all YAML documents from a file:
* --------------------
* auto nodes = Loader("file.yaml").loadAll();
* ...
* --------------------
*
* Iterate over YAML documents in a file, lazily loading them:
* --------------------
* auto loader = Loader("file.yaml");
*
* foreach(ref node; loader)
* {
* ...
* }
* --------------------
*
* Load YAML from memory:
* --------------------
* import std.stream;
* import std.stdio;
@ -73,74 +66,27 @@ Node load(in string filename)
* "green: '#00ff00'\n"
* "blue: '#0000ff'";
*
* auto colors = yaml.load(new MemoryStream(cast(char[])yaml_input));
* auto colors = Loader(new MemoryStream(cast(char[])yaml_input)).load();
*
* foreach(string color, string value; colors)
* {
* writeln(color, " is ", value, " in HTML/CSS");
* }
* --------------------
*
* Use a custom constructor/resolver to support custom data types and/or implicit tags:
* --------------------
* auto constructor = new Constructor();
* auto resolver = new Resolver();
*
* //Add constructor functions / resolver expressions here...
*
* auto loader = Loader("file.yaml");
* loader.constructor = constructor;
* loader.resolver = resolver;
* auto rootNode = loader.load(node);
* --------------------
*/
Node load(Stream input, in string name = "<unknown>")
{
auto loader = Loader(input, name, new Constructor, new Resolver);
return loader.loadSingleDocument();
}
unittest
{
import std.stream;
import std.stdio;
string yaml_input = "red: '#ff0000'\n"
"green: '#00ff00'\n"
"blue: '#0000ff'";
auto colors = load(new MemoryStream(cast(char[])yaml_input));
foreach(string color, string value; colors)
{
writeln(color, " is ", value, " in HTML/CSS");
}
}
/**
* Load all YAML documents from a file.
*
* Params: filename = Name of the file to load from.
*
* Returns: Array of root nodes of documents in the stream.
* If the stream is empty, empty array will be returned.
*
* Throws: YAMLException if the file could not be opened or on a YAML parsing error.
*/
Node[] loadAll(in string filename)
{
auto loader = Loader(filename);
Node[] result;
foreach(ref node; loader){result ~= node;}
return result;
}
/**
* Load all YAML documents from a stream.
*
* Params: input = Stream to read from. Must be readable.
* name = Name of the stream, used in error messages.
*
* Returns: Array of root nodes of documents in the file.
* If the file is empty, empty array will be returned.
*
* Throws: YAMLException if the stream could not be read from or on a YAML parsing error.
*/
Node[] loadAll(Stream input, in string name = "<unknown>")
{
auto loader = Loader(input, name, new Constructor, new Resolver);
Node[] result;
foreach(ref node; loader){result ~= node;}
return result;
}
///Loads YAML documents from files or streams.
struct Loader
{
private:
@ -154,12 +100,8 @@ struct Loader
Resolver resolver_;
///Constructs YAML data types.
Constructor constructor_;
///Composes YAML nodes.
Composer composer_;
///Name of the input file or stream, used in error messages.
string name_;
///Input file stream, if the stream is created by Loader itself.
File file_ = null;
string name_ = "<unknown>";
public:
/**
@ -171,60 +113,33 @@ struct Loader
*/
this(in string filename)
{
try{file_ = new File(filename);}
try
{
name = filename;
this(new File(filename));
}
catch(StreamException e)
{
throw new YAMLException("Unable to load YAML file " ~ filename ~ " : " ~ e.msg);
}
this(file_, filename, new Constructor, new Resolver);
}
/**
* Construct a Loader to load YAML from a file, with provided _constructor and _resolver.
* Construct a Loader to load YAML from a stream.
*
* Constructor and _resolver can be used to implement custom data types in YAML.
*
* Params: filename = Name of the file to load from.
* constructor = Constructor to use.
* resolver = Resolver to use.
*
* Throws: YAMLException if the file could not be opened or read from.
*/
this(in string filename, Constructor constructor, Resolver resolver)
{
try{file_ = new File(filename);}
catch(StreamException e)
{
throw new YAMLException("Unable to load YAML file " ~ filename ~ " : " ~ e.msg);
}
this(file_, filename, constructor, resolver);
}
/**
* Construct a Loader to load YAML from a stream with provided _constructor and _resolver.
*
* Stream can be used to load YAML from memory and other sources.
* Constructor and _resolver can be used to implement custom data types in YAML.
*
* Params: input = Stream to read from. Must be readable.
* name = Name of the stream. Used in error messages.
* constructor = Constructor to use.
* resolver = Resolver to use.
* Params: stream = Stream to read from. Must be readable.
*
* Throws: YAMLException if the stream could not be read from.
*/
this(Stream input, in string name, Constructor constructor, Resolver resolver)
this(Stream stream)
{
try
{
reader_ = new Reader(input);
reader_ = new Reader(stream);
scanner_ = new Scanner(reader_);
parser_ = new Parser(scanner_);
resolver_ = resolver;
constructor_ = constructor;
composer_ = new Composer(parser_, resolver_, constructor_);
name_ = name;
resolver_ = new Resolver;
constructor_ = new Constructor;
Anchor.addReference();
TagDirectives.addReference();
}
@ -235,58 +150,6 @@ struct Loader
}
}
/**
* Load single YAML document.
*
* If no or more than one YAML document is found, this will throw a YAMLException.
*
* Returns: Root node of the document.
*
* Throws: YAMLException if there wasn't exactly one document
* or on a YAML parsing error.
*/
Node loadSingleDocument()
{
try
{
enforce(composer_.checkNode(), new YAMLException("No YAML document to load"));
return composer_.getSingleNode();
}
catch(YAMLException e)
{
e.name = name_;
throw e;
}
}
/**
* Foreach over YAML documents.
*
* Parses documents lazily, as they are needed.
*
* Throws: YAMLException on a parsing error.
*/
int opApply(int delegate(ref Node) dg)
{
try
{
int result = 0;
while(composer_.checkNode())
{
auto node = composer_.getNode();
result = dg(node);
if(result){break;}
}
return result;
}
catch(YAMLException e)
{
e.name = name_;
throw e;
}
}
///Destroy the Loader.
~this()
{
@ -295,9 +158,97 @@ struct Loader
clear(reader_);
clear(scanner_);
clear(parser_);
clear(composer_);
//Can't clear constructor, resolver: they might be supplied by the user.
if(file_ !is null){file_.close();}
}
///Set stream name. Used in debugging messages.
@property void name(string name)
{
name_ = name;
}
///Set Resolver to use.
@property void resolver(Resolver resolver)
{
resolver_ = resolver;
}
///Set Constructor to use.
@property void constructor(Constructor constructor)
{
constructor_ = constructor;
}
/**
* Load single YAML document.
*
* If no or more than one YAML document is found, this will throw a YAMLException.
*
* Returns: Root node of the document.
*
* Throws: YAMLException if there wasn't exactly one document
* or on a YAML parsing error.
*/
Node load()
{
try
{
auto composer = new Composer(parser_, resolver_, constructor_);
enforce(composer.checkNode(), new YAMLException("No YAML document to load"));
return composer.getSingleNode();
}
catch(YAMLException e)
{
e.name = name_;
throw e;
}
}
/**
* Load all YAML documents.
*
* Returns: Array of root nodes of all documents in the file/stream.
*
* Throws: YAMLException if there wasn't exactly one document
* or on a YAML parsing error.
*/
Node[] loadAll()
{
Node[] nodes;
foreach(ref node; this)
{
nodes ~= node;
}
return nodes;
}
/**
* Foreach over YAML documents.
*
* Parses documents lazily, as they are needed.
*
* Throws: YAMLException on a parsing error.
*/
int opApply(int delegate(ref Node) dg)
{
try
{
auto composer = new Composer(parser_, resolver_, constructor_);
int result = 0;
while(composer.checkNode())
{
auto node = composer.getNode();
result = dg(node);
if(result){break;}
}
return result;
}
catch(YAMLException e)
{
e.name = name_;
throw e;
}
}
package:
@ -333,3 +284,20 @@ struct Loader
}
}
}
unittest
{
import std.stream;
import std.stdio;
string yaml_input = "red: '#ff0000'\n"
"green: '#00ff00'\n"
"blue: '#0000ff'";
auto colors = Loader(new MemoryStream(cast(char[])yaml_input)).load();
foreach(string color, string value; colors)
{
writeln(color, " is ", value, " in HTML/CSS");
}
}

View file

@ -88,9 +88,10 @@ void main()
constructor.addConstructor("!color", &constructColorScalar);
constructor.addConstructor("!color-mapping", &constructColorMapping);
auto loader = new Loader("input.yaml", constructor, new Resolver);
auto loader = Loader("input.yaml");
loader.constructor = constructor;
auto root = loader.loadSingleDocument();
auto root = loader.load();
if(root["scalar-red"].get!Color == red &&
root["mapping-red"].get!Color == red &&

View file

@ -3,7 +3,7 @@ import yaml;
void main()
{
yaml.Node root = yaml.load("input.yaml");
yaml.Node root = Loader("input.yaml").load();
foreach(string word; root["Hello World"])
{
writeln(word);

View file

@ -92,9 +92,11 @@ void main()
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
"0123456789abcdefABCDEF");
auto loader = new Loader("input.yaml", constructor, resolver);
auto loader = Loader("input.yaml");
loader.constructor = constructor;
loader.resolver = resolver;
auto root = loader.loadSingleDocument();
auto root = loader.load();
if(root["scalar-red"].get!Color == red &&
root["mapping-red"].get!Color == red &&

View file

@ -42,8 +42,8 @@ void testParser(bool verbose, string dataFilename, string canonicalFilename)
*/
void testLoader(bool verbose, string dataFilename, string canonicalFilename)
{
auto data = loadAll(dataFilename);
auto canonical = loadAll(canonicalFilename);
auto data = Loader(dataFilename).loadAll;
auto canonical = Loader(canonicalFilename).loadAll;
assert(data.length == canonical.length, "Unequal node count");
foreach(n; 0 .. data.length)

View file

@ -398,8 +398,9 @@ void testConstructor(bool verbose, string dataFilename, string codeDummy)
constructor.addConstructor("!tag1", &constructClass);
constructor.addConstructor("!tag2", &constructStruct);
auto resolver = new Resolver;
auto loader = Loader(dataFilename, constructor, resolver);
auto loader = Loader(dataFilename);
loader.constructor = constructor;
loader.resolver = new Resolver;
Node[] exp = expected[base];

View file

@ -92,8 +92,12 @@ void testEmitterOnData(bool verbose, string dataFilename, string canonicalFilena
writeln("ORIGINAL:\n", readText(dataFilename));
writeln("OUTPUT:\n", cast(string)emitStream.data);
}
auto loadStream = new MemoryStream(emitStream.data);
auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse();
auto loader2 = Loader(new MemoryStream(emitStream.data));
loader2.name = "TEST";
loader2.constructor = new Constructor;
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}
@ -121,8 +125,11 @@ void testEmitterOnCanonical(bool verbose, string canonicalFilename)
writeln("OUTPUT (canonical=", canonical, "):\n",
cast(string)emitStream.data);
}
auto loadStream = new MemoryStream(emitStream.data);
auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse();
auto loader2 = Loader(new MemoryStream(emitStream.data));
loader2.name = "TEST";
loader2.constructor = new Constructor;
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}
}
@ -179,8 +186,11 @@ void testEmitterStyles(bool verbose, string dataFilename, string canonicalFilena
to!string(style), ")");
writeln(emitStream.data);
}
auto loadStream = new MemoryStream(emitStream.data);
auto newEvents = Loader(loadStream, "DUMMY", new Constructor, new Resolver).parse();
auto loader2 = Loader(new MemoryStream(emitStream.data));
loader2.name = "TEST";
loader2.constructor = new Constructor;
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}
}

View file

@ -22,7 +22,7 @@ void testLoaderError(bool verbose, string errorFilename)
scope(exit){file.close();}
Node[] nodes;
try{nodes = loadAll(file, errorFilename);}
try{nodes = Loader(file).loadAll();}
catch(YAMLException e)
{
if(verbose){writeln(typeid(e).toString(), "\n", e);}
@ -48,7 +48,7 @@ void testLoaderErrorString(bool verbose, string errorFilename)
try
{
auto nodes = loadAll(new MemoryStream(buffer), errorFilename);
auto nodes = Loader(new MemoryStream(buffer)).loadAll();
}
catch(YAMLException e)
{
@ -66,7 +66,7 @@ void testLoaderErrorString(bool verbose, string errorFilename)
*/
void testLoaderErrorFilename(bool verbose, string errorFilename)
{
try{auto nodes = loadAll(errorFilename);}
try{auto nodes = Loader(errorFilename).loadAll();}
catch(YAMLException e)
{
if(verbose){writeln(typeid(e).toString(), "\n", e);}
@ -83,7 +83,7 @@ void testLoaderErrorFilename(bool verbose, string errorFilename)
*/
void testLoaderErrorSingle(bool verbose, string errorFilename)
{
try{auto nodes = load(errorFilename);}
try{auto nodes = Loader(errorFilename).load();}
catch(YAMLException e)
{
if(verbose){writeln(typeid(e).toString(), "\n", e);}

View file

@ -57,13 +57,13 @@ void testUnicodeInput(bool verbose, string unicodeFilename)
string data = readText(unicodeFilename);
string expected = data.split().join(" ");
Node output = load(new MemoryStream(to!(char[])(data)), unicodeFilename);
Node output = Loader(new MemoryStream(to!(char[])(data))).load();
assert(output.get!string == expected);
foreach(stream; [new MemoryStream(cast(byte[])(bom16() ~ to!(wchar[])(data))),
new MemoryStream(cast(byte[])(bom32() ~ to!(dchar[])(data)))])
{
output = load(stream, unicodeFilename);
output = Loader(stream).load();
assert(output.get!string == expected);
}
}
@ -82,7 +82,7 @@ void testUnicodeInputErrors(bool verbose, string unicodeFilename)
new MemoryStream(cast(byte[])(bom16(true) ~ to!(wchar[])(data))),
new MemoryStream(cast(byte[])(bom32(true) ~ to!(dchar[])(data)))])
{
try{load(stream, unicodeFilename);}
try{Loader(stream).load();}
catch(YAMLException e)
{
if(verbose){writeln(typeid(e).toString(), "\n", e);}

View file

@ -61,9 +61,10 @@ void testRepresenterTypes(bool verbose, string codeFilename)
constructor.addConstructor("!tag1", &constructClass);
constructor.addConstructor("!tag2", &constructStruct);
auto resolver = new Resolver;
auto loader = Loader(loadStream, "DUMMY", constructor, resolver);
foreach(node; loader){readNodes ~= node;}
auto loader = Loader(loadStream);
loader.name = "TEST";
loader.constructor = constructor;
readNodes = loader.loadAll();
assert(expectedNodes.length == readNodes.length);
foreach(n; 0 .. expectedNodes.length)

View file

@ -17,27 +17,31 @@ import dyaml.testcommon;
* Implicit tag resolution unittest.
*
* Params: verbose = Print verbose output?
* dataFilename = TODO
* detectFilename = TODO
* dataFilename = File with unittest data.
* detectFilename = Dummy filename used to specify which data filenames to use.
*/
void testImplicitResolver(bool verbose, string dataFilename, string detectFilename)
{
string correctTag;
Node node;
scope(exit)
scope(failure)
{
if(verbose)
if(true)
{
writeln("Correct tag: ", correctTag);
writeln("Node: ", node.debugString);
assert(node.isSequence);
assert(node.tag.get == correctTag);
}
}
correctTag = readText(dataFilename).strip();
node = yaml.load(dataFilename);
correctTag = readText(detectFilename).strip();
node = Loader(dataFilename).load();
assert(node.isSequence);
foreach(ref Node scalar; node)
{
assert(scalar.isScalar);
assert(scalar.tag.get == correctTag);
}
}