aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/D-YAML/source/dyaml/loader.d
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext_depends/D-YAML/source/dyaml/loader.d')
-rw-r--r--src/ext_depends/D-YAML/source/dyaml/loader.d175
1 files changed, 112 insertions, 63 deletions
diff --git a/src/ext_depends/D-YAML/source/dyaml/loader.d b/src/ext_depends/D-YAML/source/dyaml/loader.d
index 6638dfc..358855a 100644
--- a/src/ext_depends/D-YAML/source/dyaml/loader.d
+++ b/src/ext_depends/D-YAML/source/dyaml/loader.d
@@ -33,14 +33,8 @@ import dyaml.token;
struct Loader
{
private:
- // Processes character data to YAML tokens.
- Scanner scanner_;
- // Processes tokens to YAML events.
- Parser parser_;
- // Resolves tags (data types).
- Resolver resolver_;
- // Name of the input file or stream, used in error messages.
- string name_ = "<unknown>";
+ // Assembles YAML documents
+ Composer composer_;
// Are we done loading?
bool done_;
// Last node read from stream
@@ -49,10 +43,6 @@ struct Loader
bool rangeInitialized;
public:
- @disable this();
- @disable int opCmp(ref Loader);
- @disable bool opEquals(ref Loader);
-
/** Construct a Loader to load YAML from a file.
*
* Params: filename = Name of the file to load from.
@@ -147,33 +137,30 @@ struct Loader
/// Ditto
private this(ubyte[] yamlData, string name = "<unknown>") @safe
{
- resolver_ = Resolver.withDefaultResolvers;
- name_ = name;
try
{
- auto reader_ = new Reader(yamlData, name);
- scanner_ = Scanner(reader_);
- parser_ = new Parser(scanner_);
+ auto reader = Reader(yamlData, name);
+ auto parser = new Parser(Scanner(reader));
+ composer_ = Composer(parser, Resolver.withDefaultResolvers);
}
- catch(YAMLException e)
+ catch(MarkedYAMLException e)
{
- throw new YAMLException("Unable to open %s for YAML loading: %s"
- .format(name_, e.msg), e.file, e.line);
+ throw new LoaderException("Unable to open %s for YAML loading: %s"
+ .format(name, e.msg), e.mark, e.file, e.line);
}
}
/// Set stream _name. Used in debugging messages.
- void name(string name) pure @safe nothrow @nogc
+ ref inout(string) name() inout @safe return pure nothrow @nogc
{
- name_ = name;
- scanner_.name = name;
+ return composer_.name;
}
/// Specify custom Resolver to use.
auto ref resolver() pure @safe nothrow @nogc
{
- return resolver_;
+ return composer_.resolver;
}
/** Load single YAML document.
@@ -189,10 +176,12 @@ struct Loader
*/
Node load() @safe
{
- enforce!YAMLException(!empty, "Zero documents in stream");
+ enforce(!empty,
+ new LoaderException("Zero documents in stream", composer_.mark));
auto output = front;
popFront();
- enforce!YAMLException(empty, "More than one document in stream");
+ enforce(empty,
+ new LoaderException("More than one document in stream", composer_.mark));
return output;
}
@@ -217,22 +206,23 @@ struct Loader
*/
void popFront() @safe
{
- // Composer initialization is done here in case the constructor is
- // modified, which is a pretty common case.
- static Composer composer;
- if (!rangeInitialized)
- {
- composer = Composer(parser_, resolver_);
- rangeInitialized = true;
- }
+ scope(success) rangeInitialized = true;
assert(!done_, "Loader.popFront called on empty range");
- if (composer.checkNode())
+ try
{
- currentNode = composer.getNode();
+ if (composer_.checkNode())
+ {
+ currentNode = composer_.getNode();
+ }
+ else
+ {
+ done_ = true;
+ }
}
- else
+ catch(MarkedYAMLException e)
{
- done_ = true;
+ throw new LoaderException("Unable to load %s: %s"
+ .format(name, e.msg), e.mark, e.mark2Label, e.mark2, e.file, e.line);
}
}
/** Implements the front range primitive.
@@ -248,30 +238,6 @@ struct Loader
}
return currentNode;
}
-
- // Scan all tokens, throwing them away. Used for benchmarking.
- void scanBench() @safe
- {
- try
- {
- while(!scanner_.empty)
- {
- scanner_.popFront();
- }
- }
- catch(YAMLException e)
- {
- throw new YAMLException("Unable to scan YAML from stream " ~
- name_ ~ " : " ~ e.msg, e.file, e.line);
- }
- }
-
-
- // Parse and return all events. Used for debugging.
- auto parse() @safe
- {
- return parser_;
- }
}
/// Load single YAML document from a file:
@safe unittest
@@ -408,6 +374,89 @@ EOS";
loader.name = filename;
Node unused;
- auto e = loader.load().collectException!ScannerException(unused);
+ auto e = loader.load().collectException!LoaderException(unused);
assert(e.mark.name == filename);
}
+/// https://github.com/dlang-community/D-YAML/issues/325
+@safe unittest
+{
+ assert(Loader.fromString("--- {x: a}").load()["x"] == "a");
+}
+
+// Ensure exceptions are thrown as appropriate
+@safe unittest
+{
+ LoaderException e;
+ // No documents
+ e = collectException!LoaderException(Loader.fromString("", "filename.yaml").load());
+ assert(e);
+ with(e)
+ {
+ assert(mark.name == "filename.yaml");
+ assert(mark.line == 0);
+ assert(mark.column == 0);
+ }
+ // Too many documents
+ e = collectException!LoaderException(Loader.fromString("--- 4\n--- 6\n--- 5", "filename.yaml").load());
+ assert(e, "No exception thrown");
+ with(e)
+ {
+ assert(mark.name == "filename.yaml");
+ // FIXME: should be position of second document, not end of file
+ //assert(mark.line == 1);
+ //assert(mark.column == 0);
+ }
+ // Invalid document
+ e = collectException!LoaderException(Loader.fromString("[", "filename.yaml").load());
+ assert(e, "No exception thrown");
+ with(e)
+ {
+ assert(mark.name == "filename.yaml");
+ // FIXME: should be position of second document, not end of file
+ assert(mark.line == 0);
+ assert(mark.column == 1);
+ }
+}
+
+@safe unittest
+{
+ assertThrown(Loader.fromString("Invalid character: \xFF").load());
+}
+
+@safe unittest
+{
+ assertThrown(Loader.fromFile("test/data/odd-utf16.stream-error").load());
+}
+
+// UTF-16 and 32 test
+@safe unittest
+{
+ import std.conv : to;
+ import std.range : only;
+ enum string yaml = `ABCDØ`;
+ enum bom = '\uFEFF';
+ foreach (doc; only(
+ cast(ubyte[])(bom~yaml.to!(wchar[])),
+ cast(ubyte[])(bom~yaml.to!(dchar[])),
+ ))
+ {
+ assert(Loader.fromBuffer(doc).load().as!string == yaml);
+ }
+}
+// Invalid unicode test
+@safe unittest
+{
+ import std.conv : to;
+ import std.range : only;
+ enum string yaml = `ABCDØ`;
+ enum badBOM = '\uFFFE';
+ foreach (doc; only(
+ cast(ubyte[])yaml.to!(wchar[]),
+ cast(ubyte[])yaml.to!(dchar[]),
+ cast(ubyte[])(badBOM~yaml.to!(wchar[])),
+ cast(ubyte[])(badBOM~yaml.to!(dchar[])),
+ ))
+ {
+ assertThrown(Loader.fromBuffer(doc).load());
+ }
+}