diff options
Diffstat (limited to 'src/ext_depends/D-YAML/source/dyaml/loader.d')
-rw-r--r-- | src/ext_depends/D-YAML/source/dyaml/loader.d | 175 |
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()); + } +} |