Skip to content

Commit

Permalink
Replace stream-based dumping interface with an outputrange-based inte…
Browse files Browse the repository at this point in the history
…rface (#154)

Replace stream-based dumping interface with an outputrange-based interface
merged-on-behalf-of: Cameron Ross <[email protected]>
  • Loading branch information
Herringway authored and dlang-bot committed Jun 22, 2018
1 parent 8f9dafd commit 8e0ca41
Show file tree
Hide file tree
Showing 17 changed files with 117 additions and 314 deletions.
2 changes: 1 addition & 1 deletion examples/getting_started/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ void main()
writeln("The answer is ", root["Answer"].as!int);

//Dump the loaded document to output.yaml.
Dumper("output.yaml").dump(root);
dumper(File("output.yaml", "w").lockingTextWriter).dump(root);
}
2 changes: 1 addition & 1 deletion examples/representer/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void main()
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
"0123456789abcdefABCDEF");

auto dumper = Dumper("output.yaml");
auto dumper = dumper(File("output.yaml", "w").lockingTextWriter);
dumper.representer = representer;
dumper.resolver = resolver;

Expand Down
2 changes: 1 addition & 1 deletion examples/yaml_bench/yaml_bench.d
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ void main(string[] args) //@safe
{
if(dump)
{
Dumper(file ~ ".dump").dump(nodes);
dumper(File(file ~ ".dump", "w").lockingTextWriter).dump(nodes);
}
}
void runGetBenchmark() @safe
Expand Down
12 changes: 7 additions & 5 deletions examples/yaml_gen/yaml_gen.d
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,17 @@ void main(string[] args)
//Generate and dump the nodes.
Node[] generated = generate(configFile);

auto dumper = Dumper(args[1]);
auto dumper = dumper(File(args[1], "w").lockingTextWriter);
auto encoding = config["encoding"];
dumper.encoding = encoding == "utf-16" ? Encoding.UTF_16:
encoding == "utf-32" ? Encoding.UTF_32:
Encoding.UTF_8;

dumper.indent = config["indent"].as!uint;
dumper.textWidth = config["text-width"].as!uint;
dumper.dump(generated);
switch(encoding.as!string)
{
case "utf-16": dumper.dump!wchar(generated); break;
case "utf-32": dumper.dump!dchar(generated); break;
default: dumper.dump!char(generated); break;
}
}
catch(YAMLException e)
{
Expand Down
1 change: 0 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ dyaml_src = [
'source/dyaml/resolver.d',
'source/dyaml/scanner.d',
'source/dyaml/serializer.d',
'source/dyaml/stream.d',
'source/dyaml/style.d',
'source/dyaml/tagdirective.d',
'source/dyaml/test/common.d',
Expand Down
94 changes: 31 additions & 63 deletions source/dyaml/dumper.d
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
*/
module dyaml.dumper;


//import std.stream;
import std.array;
import std.range.primitives;
import std.typecons;

import dyaml.stream;
import dyaml.emitter;
import dyaml.encoding;
import dyaml.event;
import dyaml.exception;
import dyaml.linebreak;
Expand All @@ -34,9 +32,15 @@ import dyaml.tagdirective;
* User specified Representer and/or Resolver can be used to support new
* tags / data types.
*
* Setters are provided to affect output details (style, encoding, etc.).
* Setters are provided to affect output details (style, etc.).
*/
struct Dumper
auto dumper(Range)(auto ref Range output)
if (isOutputRange!(Range, char) || isOutputRange!(Range, wchar) || isOutputRange!(Range, dchar))
{
return Dumper!Range(output);
}

struct Dumper(Range)
{
private:
//Resolver to resolve tags.
Expand All @@ -45,9 +49,7 @@ struct Dumper
Representer representer_;

//Stream to write to.
YStream stream_;
//True if this Dumper owns stream_ and needs to destroy it in the destructor.
bool weOwnStream_;
Range stream_;

//Write scalars in canonical form?
bool canonical_;
Expand All @@ -57,8 +59,6 @@ struct Dumper
uint textWidth_ = 80;
//Line break to use.
LineBreak lineBreak_ = LineBreak.Unix;
//Character encoding to use.
Encoding encoding_ = Encoding.UTF_8;
//YAML version string.
string YAMLVersion_ = "1.1";
//Tag directives to use.
Expand All @@ -73,45 +73,21 @@ struct Dumper

public:
@disable this();
@disable bool opEquals(ref Dumper);
@disable int opCmp(ref Dumper);
@disable bool opEquals(ref Dumper!Range);
@disable int opCmp(ref Dumper!Range);

/**
* Construct a Dumper writing to a file.
*
* Params: filename = File name to write to.
*
* Throws: YAMLException if the file can not be dumped to (e.g. cannot be opened).
*/
this(string filename) @safe
{
name_ = filename;
//try{this(new File(filename, FileMode.OutNew));}
try{this(new YFile(filename));}
//catch(StreamException e)
catch(Exception e)
{
throw new YAMLException("Unable to open file " ~ filename ~
" for YAML dumping: " ~ e.msg);
}
// need to destroy the File we constructed.
weOwnStream_ = true;
}

///Construct a Dumper writing to a _stream. This is useful to e.g. write to memory.
this(YStream stream) @safe
this(Range stream) @safe
{
resolver_ = new Resolver();
representer_ = new Representer();
stream_ = stream;
}

///Destroy the Dumper.
@trusted ~this()
{
if(weOwnStream_) { destroy(stream_); }
}

///Set stream _name. Used in debugging messages.
@property void name(string name) pure @safe nothrow
{
Expand Down Expand Up @@ -159,12 +135,6 @@ struct Dumper
lineBreak_ = lineBreak;
}

///Set character _encoding to use. UTF-8 by default.
@property void encoding(Encoding encoding) pure @safe nothrow
{
encoding_ = encoding;
}

///Always explicitly write document start?
@property void explicitStart(bool explicit) pure @safe nothrow
{
Expand Down Expand Up @@ -218,7 +188,7 @@ struct Dumper
///
@safe unittest
{
Dumper dumper = Dumper("example.yaml");
auto dumper = dumper(new Appender!string());
string[string] directives;
directives["!short!"] = "tag:long.org,2011:";
//This will emit tags starting with "tag:long.org,2011"
Expand All @@ -239,12 +209,13 @@ struct Dumper
* Throws: YAMLException on error (e.g. invalid nodes,
* unable to write to file/stream).
*/
void dump(Node[] documents ...) @safe
void dump(CharacterType = char)(Node[] documents ...) @trusted
if (isOutputRange!(Range, CharacterType))
{
try
{
auto emitter = new Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_);
auto serializer = Serializer(emitter, resolver_, encoding_, explicitStart_,
auto emitter = new Emitter!(Range, CharacterType)(stream_, canonical_, indent_, textWidth_, lineBreak_);
auto serializer = Serializer!(Range, CharacterType)(emitter, resolver_, explicitStart_,
explicitEnd_, YAMLVersion_, tags_);
foreach(ref document; documents)
{
Expand All @@ -266,11 +237,11 @@ struct Dumper
*
* Throws: YAMLException if unable to emit.
*/
void emit(Event[] events) @safe
void emit(CharacterType = char)(Event[] events) @safe
{
try
{
auto emitter = Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_);
auto emitter = Emitter!(Range, CharacterType)(stream_, canonical_, indent_, textWidth_, lineBreak_);
foreach(ref event; events)
{
emitter.emit(event);
Expand All @@ -287,24 +258,23 @@ struct Dumper
@safe unittest
{
auto node = Node([1, 2, 3, 4, 5]);
Dumper("example.yaml").dump(node);
dumper(new Appender!string()).dump(node);
}
///Write multiple YAML documents to a file
@safe unittest
{
auto node1 = Node([1, 2, 3, 4, 5]);
auto node2 = Node("This document contains only one string");
Dumper("example.yaml").dump(node1, node2);
dumper(new Appender!string()).dump(node1, node2);
//Or with an array:
Dumper("example.yaml").dump([node1, node2]);
dumper(new Appender!string()).dump([node1, node2]);
}
///Write to memory
@safe unittest
{
import dyaml.stream;
auto stream = new YMemoryStream();
auto stream = new Appender!string();
auto node = Node([1, 2, 3, 4, 5]);
Dumper(stream).dump(node);
dumper(stream).dump(node);
}
///Use a custom representer/resolver to support custom data types and/or implicit tags
@safe unittest
Expand All @@ -313,18 +283,17 @@ struct Dumper
auto representer = new Representer();
auto resolver = new Resolver();
//Add representer functions / resolver expressions here...
auto dumper = Dumper("example.yaml");
auto dumper = dumper(new Appender!string());
dumper.representer = representer;
dumper.resolver = resolver;
dumper.dump(node);
}
// Explicit document start/end markers
@safe unittest
{
import dyaml.stream;
auto stream = new YMemoryStream();
auto stream = new Appender!string();
auto node = Node([1, 2, 3, 4, 5]);
auto dumper = Dumper(stream);
auto dumper = dumper(stream);
dumper.explicitEnd = true;
dumper.explicitStart = true;
dumper.YAMLVersion = null;
Expand All @@ -337,10 +306,9 @@ struct Dumper
// No explicit document start/end markers
@safe unittest
{
import dyaml.stream;
auto stream = new YMemoryStream();
auto stream = new Appender!string();
auto node = Node([1, 2, 3, 4, 5]);
auto dumper = Dumper(stream);
auto dumper = dumper(stream);
dumper.explicitEnd = false;
dumper.explicitStart = false;
dumper.YAMLVersion = null;
Expand Down
Loading

0 comments on commit 8e0ca41

Please sign in to comment.