From a0ac38fbd7d1e50ade9a320a886c6bc3c2b637ec Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Thu, 31 May 2018 04:02:21 -0300 Subject: [PATCH] make Loader interface a bit more consistent (#124) make Loader interface a bit more consistent merged-on-behalf-of: BBasile --- examples/constructor/main.d | 2 +- examples/getting_started/main.d | 2 +- examples/resolver/main.d | 2 +- examples/yaml_bench/yaml_bench.d | 2 +- examples/yaml_gen/yaml_gen.d | 2 +- examples/yaml_stats/yaml_stats.d | 2 +- source/dyaml/constructor.d | 18 ++++----- source/dyaml/hacks.d | 2 +- source/dyaml/loader.d | 65 ++++++++++++++++++++++---------- source/dyaml/resolver.d | 2 +- source/dyaml/stream.d | 8 ++-- source/dyaml/test/compare.d | 8 ++-- source/dyaml/test/constructor.d | 2 +- source/dyaml/test/emitter.d | 12 +++--- source/dyaml/test/errors.d | 13 ++----- source/dyaml/test/inputoutput.d | 18 ++++----- source/dyaml/test/representer.d | 2 +- source/dyaml/test/resolver.d | 2 +- source/dyaml/test/tokens.d | 4 +- 19 files changed, 94 insertions(+), 74 deletions(-) diff --git a/examples/constructor/main.d b/examples/constructor/main.d index 9cde7f7..4e572a2 100644 --- a/examples/constructor/main.d +++ b/examples/constructor/main.d @@ -78,7 +78,7 @@ void main() constructor.addConstructorScalar("!color", &constructColorScalar); constructor.addConstructorMapping("!color-mapping", &constructColorMapping); - auto loader = Loader("input.yaml"); + auto loader = Loader.fromFile("input.yaml"); loader.constructor = constructor; auto root = loader.load(); diff --git a/examples/getting_started/main.d b/examples/getting_started/main.d index f268d52..6bf575c 100644 --- a/examples/getting_started/main.d +++ b/examples/getting_started/main.d @@ -4,7 +4,7 @@ import dyaml; void main() { //Read the input. - Node root = Loader("input.yaml").load(); + Node root = Loader.fromFile("input.yaml").load(); //Display the data read. foreach(string word; root["Hello World"]) diff --git a/examples/resolver/main.d b/examples/resolver/main.d index 09b21f3..7276552 100644 --- a/examples/resolver/main.d +++ b/examples/resolver/main.d @@ -83,7 +83,7 @@ void main() resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"), "0123456789abcdefABCDEF"); - auto loader = Loader("input.yaml"); + auto loader = Loader.fromFile("input.yaml"); loader.constructor = constructor; loader.resolver = resolver; diff --git a/examples/yaml_bench/yaml_bench.d b/examples/yaml_bench/yaml_bench.d index 44ac46d..a0ec76c 100644 --- a/examples/yaml_bench/yaml_bench.d +++ b/examples/yaml_bench/yaml_bench.d @@ -104,7 +104,7 @@ void main(string[] args) //@safe else { fileWorkingCopy[] = fileInMemory[]; } void[] fileToLoad = reload ? fileInMemory : fileWorkingCopy; - auto loader = Loader(fileToLoad); + auto loader = Loader.fromBuffer(fileToLoad); if(scanOnly) { loader.scanBench(); diff --git a/examples/yaml_gen/yaml_gen.d b/examples/yaml_gen/yaml_gen.d index d987415..48e0408 100644 --- a/examples/yaml_gen/yaml_gen.d +++ b/examples/yaml_gen/yaml_gen.d @@ -264,7 +264,7 @@ Node generateNode(const string type, bool root = false) Node[] generate(const string configFileName) { - config = Loader(configFileName).load(); + config = Loader.fromFile(configFileName).load(); minNodesDocument = config["min-nodes-per-document"].as!long; diff --git a/examples/yaml_stats/yaml_stats.d b/examples/yaml_stats/yaml_stats.d index 3e88d20..190afc0 100644 --- a/examples/yaml_stats/yaml_stats.d +++ b/examples/yaml_stats/yaml_stats.d @@ -90,7 +90,7 @@ void main(string[] args) writeln("------------------------------------------------------------"); try { - auto loader = Loader(file); + auto loader = Loader.fromFile(file); size_t idx = 0; foreach(ref document; loader) diff --git a/source/dyaml/constructor.d b/source/dyaml/constructor.d index 2396f6c..6db1dda 100644 --- a/source/dyaml/constructor.d +++ b/source/dyaml/constructor.d @@ -159,7 +159,7 @@ final class Constructor return MyStruct(to!int(parts[0]), to!int(parts[1]), to!int(parts[2])); } - auto loader = Loader.fromString("!mystruct 12:34:56".dup); + auto loader = Loader.fromString("!mystruct 12:34:56"); auto constructor = new Constructor; constructor.addConstructorScalar("!mystruct", &constructMyStructScalar); loader.constructor = constructor; @@ -200,7 +200,7 @@ final class Constructor //!mystruct [x, y, z] return MyStruct(node[0].as!int, node[1].as!int, node[2].as!int); } - auto loader = Loader.fromString("!mystruct [1,2,3]".dup); + auto loader = Loader.fromString("!mystruct [1,2,3]"); auto constructor = new Constructor; constructor.addConstructorSequence("!mystruct", &constructMyStructSequence); loader.constructor = constructor; @@ -241,7 +241,7 @@ final class Constructor //!mystruct {"x": x, "y": y, "z": z} return MyStruct(node["x"].as!int, node["y"].as!int, node["z"].as!int); } - auto loader = Loader.fromString(`!mystruct {"x": 11, "y": 22, "z": 33}`.dup); + auto loader = Loader.fromString(`!mystruct {"x": 11, "y": 22, "z": 33}`); auto constructor = new Constructor; constructor.addConstructorMapping("!mystruct", &constructMyStructMapping); loader.constructor = constructor; @@ -836,8 +836,8 @@ MyStruct constructMyStructMapping(ref Node node) @safe @safe unittest { - char[] data = "!mystruct 1:2:3".dup; - auto loader = Loader(data); + string data = "!mystruct 1:2:3"; + auto loader = Loader.fromString(data); auto constructor = new Constructor; constructor.addConstructorScalar("!mystruct", &constructMyStructScalar); loader.constructor = constructor; @@ -848,8 +848,8 @@ MyStruct constructMyStructMapping(ref Node node) @safe @safe unittest { - char[] data = "!mystruct [1, 2, 3]".dup; - auto loader = Loader(data); + string data = "!mystruct [1, 2, 3]"; + auto loader = Loader.fromString(data); auto constructor = new Constructor; constructor.addConstructorSequence("!mystruct", &constructMyStructSequence); loader.constructor = constructor; @@ -860,8 +860,8 @@ MyStruct constructMyStructMapping(ref Node node) @safe @safe unittest { - char[] data = "!mystruct {x: 1, y: 2, z: 3}".dup; - auto loader = Loader(data); + string data = "!mystruct {x: 1, y: 2, z: 3}"; + auto loader = Loader.fromString(data); auto constructor = new Constructor; constructor.addConstructorMapping("!mystruct", &constructMyStructMapping); loader.constructor = constructor; diff --git a/source/dyaml/hacks.d b/source/dyaml/hacks.d index 5b811ee..8502648 100644 --- a/source/dyaml/hacks.d +++ b/source/dyaml/hacks.d @@ -30,7 +30,7 @@ ScalarStyle scalarStyleHack(ref const(Node) node) @safe nothrow @safe unittest { import dyaml; - Node node = Loader.fromString(`"42"`.dup).load(); // loaded from a file + Node node = Loader.fromString(`"42"`).load(); // loaded from a file if(node.isScalar) { assert(node.scalarStyleHack() == ScalarStyle.DoubleQuoted); diff --git a/source/dyaml/loader.d b/source/dyaml/loader.d index dcd4da8..d8f1891 100644 --- a/source/dyaml/loader.d +++ b/source/dyaml/loader.d @@ -58,25 +58,25 @@ struct Loader * * Throws: YAMLException if the file could not be opened or read. */ - this(string filename) @trusted - { - name_ = filename; + static Loader fromFile(string filename) @trusted + { try { - this(std.file.read(filename)); + auto loader = Loader(std.file.read(filename)); + loader.name_ = filename; + return loader; } catch(FileException e) { throw new YAMLException("Unable to open file %s for YAML loading: %s" .format(filename, e.msg)); } - } + } - /** Construct a Loader to load YAML from a string (char []). + /** Construct a Loader to load YAML from a string. * - * Params: data = String to load YAML from. $(B will) be overwritten during - * parsing as D:YAML reuses memory. Use data.dup if you don't - * want to modify the original string. + * Params: data = String to load YAML from. The char[] version $(B will) + * overwrite its input during parsing as D:YAML reuses memory. * * Returns: Loader loading YAML from given string. * @@ -88,11 +88,21 @@ struct Loader { return Loader(cast(ubyte[])data); } - /// + /// Ditto + static Loader fromString(string data) @safe + { + return fromString(data.dup); + } + /// Load a char[]. @safe unittest { assert(Loader.fromString("42".dup).load().as!int == 42); } + /// Load a string. + @safe unittest + { + assert(Loader.fromString("42").load().as!int == 42); + } /** Construct a Loader to load YAML from a buffer. * @@ -111,11 +121,26 @@ struct Loader * * Throws: YAMLException if yamlData contains data illegal in YAML. */ - this(void[] yamlData) @trusted + static Loader fromBuffer(ubyte[] yamlData) @safe + { + return Loader(yamlData); + } + /// Ditto + static Loader fromBuffer(void[] yamlData) @system + { + return Loader(yamlData); + } + /// Ditto + private this(void[] yamlData) @system + { + this(cast(ubyte[])yamlData); + } + /// Ditto + private this(ubyte[] yamlData) @safe { try { - reader_ = new Reader(cast(ubyte[])yamlData); + reader_ = new Reader(yamlData); scanner_ = new Scanner(reader_); parser_ = new Parser(scanner_); } @@ -304,7 +329,7 @@ struct Loader @safe unittest { write("example.yaml", "Hello world!"); - auto rootNode = Loader("example.yaml").load(); + auto rootNode = Loader.fromFile("example.yaml").load(); assert(rootNode == "Hello world!"); } /// Load all YAML documents from a file: @@ -319,7 +344,7 @@ struct Loader "Hello world 2!\n"~ "...\n" ); - auto nodes = Loader("example.yaml").loadAll(); + auto nodes = Loader.fromFile("example.yaml").loadAll(); assert(nodes.length == 2); } /// Iterate over YAML documents in a file, lazily loading them: @@ -334,7 +359,7 @@ struct Loader "Hello world 2!\n"~ "...\n" ); - auto loader = Loader("example.yaml"); + auto loader = Loader.fromFile("example.yaml"); foreach(ref node; loader) { @@ -344,9 +369,9 @@ struct Loader /// Load YAML from a string: @safe unittest { - char[] yaml_input = ("red: '#ff0000'\n" ~ + string yaml_input = ("red: '#ff0000'\n" ~ "green: '#00ff00'\n" ~ - "blue: '#0000ff'").dup; + "blue: '#0000ff'"); auto colors = Loader.fromString(yaml_input).load(); @@ -372,8 +397,8 @@ struct Loader ); try { - void[] buffer = read("example.yaml"); - auto yamlNode = Loader(buffer); + string buffer = readText("example.yaml"); + auto yamlNode = Loader.fromString(buffer); // Read data from yamlNode here... } @@ -397,7 +422,7 @@ struct Loader // Add constructor functions / resolver expressions here... - auto loader = Loader("example.yaml"); + auto loader = Loader.fromFile("example.yaml"); loader.constructor = constructor; loader.resolver = resolver; auto rootNode = loader.load(); diff --git a/source/dyaml/resolver.d b/source/dyaml/resolver.d index 5eae47f..d2cae7d 100644 --- a/source/dyaml/resolver.d +++ b/source/dyaml/resolver.d @@ -106,7 +106,7 @@ final class Resolver write("example.yaml", "A"); - auto loader = Loader("example.yaml"); + auto loader = Loader.fromFile("example.yaml"); auto resolver = new Resolver(); resolver.addImplicitResolver("!tag", regex("A.*"), "A"); loader.resolver = resolver; diff --git a/source/dyaml/stream.d b/source/dyaml/stream.d index 88af68a..27ae25d 100644 --- a/source/dyaml/stream.d +++ b/source/dyaml/stream.d @@ -96,8 +96,8 @@ class YFile : YStream import dyaml.dumper, dyaml.loader, dyaml.node; import std.file : readText, remove; - char[] test = ("Hello World : [Hello, World]\n" ~ - "Answer: 42").dup; + string test = "Hello World : [Hello, World]\n" ~ + "Answer: 42"; //Read the input. Node expected = Loader.fromString(test).load(); assert(expected["Hello World"][0] == "Hello"); @@ -108,7 +108,7 @@ class YFile : YStream Dumper("output.yaml").dump(expected); // Load the file and verify that it was saved correctly. - Node actual = Loader("output.yaml").load(); + Node actual = Loader.fromFile("output.yaml").load(); assert(actual["Hello World"][0] == "Hello"); assert(actual["Hello World"][1] == "World"); assert(actual["Answer"].as!int == 42); @@ -128,7 +128,7 @@ class YFile : YStream auto dumper = Dumper(fn); dumper.YAMLVersion = null; // supress directive - dumper.dump(Loader.fromString("Hello world".dup).load); + dumper.dump(Loader.fromString("Hello world").load); assert (fn.read()[0..3] == "Hel"); } diff --git a/source/dyaml/test/compare.d b/source/dyaml/test/compare.d index 2c27987..d8a4b80 100644 --- a/source/dyaml/test/compare.d +++ b/source/dyaml/test/compare.d @@ -20,8 +20,8 @@ import dyaml.token; /// canonicalFilename = Another file to parse, in canonical YAML format. void testParser(string dataFilename, string canonicalFilename) @safe { - auto dataEvents = Loader(dataFilename).parse(); - auto canonicalEvents = Loader(canonicalFilename).parse(); + auto dataEvents = Loader.fromFile(dataFilename).parse(); + auto canonicalEvents = Loader.fromFile(canonicalFilename).parse(); assert(dataEvents.length == canonicalEvents.length); @@ -38,8 +38,8 @@ void testParser(string dataFilename, string canonicalFilename) @safe /// canonicalFilename = Another file to load, in canonical YAML format. void testLoader(string dataFilename, string canonicalFilename) @safe { - auto data = Loader(dataFilename).loadAll(); - auto canonical = Loader(canonicalFilename).loadAll(); + auto data = Loader.fromFile(dataFilename).loadAll(); + auto canonical = Loader.fromFile(canonicalFilename).loadAll(); assert(data.length == canonical.length, "Unequal node count"); foreach(n; 0 .. data.length) diff --git a/source/dyaml/test/constructor.d b/source/dyaml/test/constructor.d index f8fbafb..e0a61cd 100644 --- a/source/dyaml/test/constructor.d +++ b/source/dyaml/test/constructor.d @@ -407,7 +407,7 @@ void testConstructor(string dataFilename, string codeDummy) @safe constructor.addConstructorMapping("!tag1", &constructClass); constructor.addConstructorScalar("!tag2", &constructStruct); - auto loader = Loader(dataFilename); + auto loader = Loader.fromFile(dataFilename); loader.constructor = constructor; loader.resolver = new Resolver; diff --git a/source/dyaml/test/emitter.d b/source/dyaml/test/emitter.d index 015125e..d1fb3c0 100644 --- a/source/dyaml/test/emitter.d +++ b/source/dyaml/test/emitter.d @@ -81,7 +81,7 @@ bool compareEvents(Event[] events1, Event[] events2) @system void testEmitterOnData(string dataFilename, string canonicalFilename) @system { //Must exist due to Anchor, Tags reference counts. - auto loader = Loader(dataFilename); + auto loader = Loader.fromFile(dataFilename); auto events = cast(Event[])loader.parse(); auto emitStream = new YMemoryStream; Dumper(emitStream).emit(events); @@ -93,7 +93,7 @@ void testEmitterOnData(string dataFilename, string canonicalFilename) @system writeln("OUTPUT:\n", cast(string)emitStream.data); } - auto loader2 = Loader(emitStream.data.dup); + auto loader2 = Loader.fromBuffer(emitStream.data); loader2.name = "TEST"; loader2.constructor = new Constructor; loader2.resolver = new Resolver; @@ -109,7 +109,7 @@ void testEmitterOnData(string dataFilename, string canonicalFilename) @system void testEmitterOnCanonical(string canonicalFilename) @system { //Must exist due to Anchor, Tags reference counts. - auto loader = Loader(canonicalFilename); + auto loader = Loader.fromFile(canonicalFilename); auto events = cast(Event[])loader.parse(); foreach(canonical; [false, true]) { @@ -122,7 +122,7 @@ void testEmitterOnCanonical(string canonicalFilename) @system writeln("OUTPUT (canonical=", canonical, "):\n", cast(string)emitStream.data); } - auto loader2 = Loader(emitStream.data.dup); + auto loader2 = Loader.fromBuffer(emitStream.data); loader2.name = "TEST"; loader2.constructor = new Constructor; loader2.resolver = new Resolver; @@ -143,7 +143,7 @@ void testEmitterStyles(string dataFilename, string canonicalFilename) @system foreach(filename; [dataFilename, canonicalFilename]) { //must exist due to Anchor, Tags reference counts - auto loader = Loader(canonicalFilename); + auto loader = Loader.fromFile(canonicalFilename); auto events = cast(Event[])loader.parse(); foreach(flowStyle; [CollectionStyle.Block, CollectionStyle.Flow]) { @@ -180,7 +180,7 @@ void testEmitterStyles(string dataFilename, string canonicalFilename) @system to!string(style), ")"); writeln(emitStream.data); } - auto loader2 = Loader(emitStream.data.dup); + auto loader2 = Loader.fromBuffer(emitStream.data); loader2.name = "TEST"; loader2.constructor = new Constructor; loader2.resolver = new Resolver; diff --git a/source/dyaml/test/errors.d b/source/dyaml/test/errors.d index d56f3e8..dfd9ae0 100644 --- a/source/dyaml/test/errors.d +++ b/source/dyaml/test/errors.d @@ -20,10 +20,8 @@ import dyaml.test.common; /// Params: errorFilename = File name to read from. void testLoaderError(string errorFilename) @safe { - auto buffer = std.file.read(errorFilename); - Node[] nodes; - try { nodes = Loader(buffer).loadAll(); } + try { nodes = Loader.fromFile(errorFilename).loadAll(); } catch(YAMLException e) { printException(e); @@ -37,12 +35,9 @@ void testLoaderError(string errorFilename) @safe /// Params: errorFilename = File name to read from. void testLoaderErrorString(string errorFilename) @safe { - // Load file to a buffer, then pass that to the YAML loader. - auto buffer = std.file.read(errorFilename); - try { - auto nodes = Loader(buffer).loadAll(); + auto nodes = Loader.fromFile(errorFilename).loadAll(); } catch(YAMLException e) { @@ -57,7 +52,7 @@ void testLoaderErrorString(string errorFilename) @safe /// Params: errorFilename = File name to read from. void testLoaderErrorFilename(string errorFilename) @safe { - try { auto nodes = Loader(errorFilename).loadAll(); } + try { auto nodes = Loader.fromFile(errorFilename).loadAll(); } catch(YAMLException e) { printException(e); @@ -72,7 +67,7 @@ void testLoaderErrorFilename(string errorFilename) @safe /// Params: errorFilename = File name to read from. void testLoaderErrorSingle(string errorFilename) @safe { - try { auto nodes = Loader(errorFilename).load(); } + try { auto nodes = Loader.fromFile(errorFilename).load(); } catch(YAMLException e) { printException(e); diff --git a/source/dyaml/test/inputoutput.d b/source/dyaml/test/inputoutput.d index cadf7d6..c4b3a8c 100644 --- a/source/dyaml/test/inputoutput.d +++ b/source/dyaml/test/inputoutput.d @@ -54,13 +54,13 @@ void testUnicodeInput(string unicodeFilename) @safe string data = readText(unicodeFilename); string expected = data.split().join(" "); - Node output = Loader(cast(void[])data.to!(char[])).load(); + Node output = Loader.fromBuffer(cast(ubyte[])data.to!(char[])).load(); assert(output.as!string == expected); - foreach(buffer; [cast(void[])(bom16() ~ data.to!(wchar[])), - cast(void[])(bom32() ~ data.to!(dchar[]))]) + foreach(buffer; [cast(ubyte[])(bom16() ~ data.to!(wchar[])), + cast(ubyte[])(bom32() ~ data.to!(dchar[]))]) { - output = Loader(buffer).load(); + output = Loader.fromBuffer(buffer).load(); assert(output.as!string == expected); } } @@ -71,12 +71,12 @@ void testUnicodeInput(string unicodeFilename) @safe void testUnicodeInputErrors(string unicodeFilename) @safe { string data = readText(unicodeFilename); - foreach(buffer; [cast(void[])(data.to!(wchar[])), - cast(void[])(data.to!(dchar[])), - cast(void[])(bom16(true) ~ data.to!(wchar[])), - cast(void[])(bom32(true) ~ data.to!(dchar[]))]) + foreach(buffer; [cast(ubyte[])(data.to!(wchar[])), + cast(ubyte[])(data.to!(dchar[])), + cast(ubyte[])(bom16(true) ~ data.to!(wchar[])), + cast(ubyte[])(bom32(true) ~ data.to!(dchar[]))]) { - try { Loader(buffer).load(); } + try { Loader.fromBuffer(buffer).load(); } catch(YAMLException e) { printException(e); diff --git a/source/dyaml/test/representer.d b/source/dyaml/test/representer.d index d7f8334..6ef3ace 100644 --- a/source/dyaml/test/representer.d +++ b/source/dyaml/test/representer.d @@ -65,7 +65,7 @@ void testRepresenterTypes(string codeFilename) @safe constructor.addConstructorMapping("!tag1", &constructClass); constructor.addConstructorScalar("!tag2", &constructStruct); - auto loader = Loader(emitStream.data.dup); + auto loader = Loader.fromBuffer(emitStream.data); loader.name = "TEST"; loader.constructor = constructor; readNodes = loader.loadAll(); diff --git a/source/dyaml/test/resolver.d b/source/dyaml/test/resolver.d index 5ad435f..ba4434e 100644 --- a/source/dyaml/test/resolver.d +++ b/source/dyaml/test/resolver.d @@ -37,7 +37,7 @@ void testImplicitResolver(string dataFilename, string detectFilename) @safe } correctTag = readText(detectFilename).strip(); - node = Loader(dataFilename).load(); + node = Loader.fromFile(dataFilename).load(); assert(node.isSequence); foreach(ref Node scalar; node) { diff --git a/source/dyaml/test/tokens.d b/source/dyaml/test/tokens.d index 9a26ac8..c1acc00 100644 --- a/source/dyaml/test/tokens.d +++ b/source/dyaml/test/tokens.d @@ -52,7 +52,7 @@ void testTokens(string dataFilename, string tokensFilename) @safe static if(verbose){writeln("tokens1: ", tokens1, "\ntokens2: ", tokens2);} } - auto loader = Loader(dataFilename); + auto loader = Loader.fromFile(dataFilename); foreach(token; loader.scan()) { if(token.id != TokenID.StreamStart && token.id != TokenID.StreamEnd) @@ -79,7 +79,7 @@ void testScanner(string dataFilename, string canonicalFilename) @safe { static if(verbose){writeln(tokens);} } - auto loader = Loader(filename); + auto loader = Loader.fromFile(filename); foreach(ref token; loader.scan()){tokens ~= to!string(token.id);} } }