Replace stream-based dumping interface with an outputrange-based interface (#154)
Replace stream-based dumping interface with an outputrange-based interface merged-on-behalf-of: Cameron Ross <elpenguino@gmail.com>
This commit is contained in:
parent
8f9dafdef3
commit
8e0ca41eb5
|
@ -14,5 +14,5 @@ void main()
|
||||||
writeln("The answer is ", root["Answer"].as!int);
|
writeln("The answer is ", root["Answer"].as!int);
|
||||||
|
|
||||||
//Dump the loaded document to output.yaml.
|
//Dump the loaded document to output.yaml.
|
||||||
Dumper("output.yaml").dump(root);
|
dumper(File("output.yaml", "w").lockingTextWriter).dump(root);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ void main()
|
||||||
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
|
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
|
||||||
"0123456789abcdefABCDEF");
|
"0123456789abcdefABCDEF");
|
||||||
|
|
||||||
auto dumper = Dumper("output.yaml");
|
auto dumper = dumper(File("output.yaml", "w").lockingTextWriter);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
dumper.resolver = resolver;
|
dumper.resolver = resolver;
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ void main(string[] args) //@safe
|
||||||
{
|
{
|
||||||
if(dump)
|
if(dump)
|
||||||
{
|
{
|
||||||
Dumper(file ~ ".dump").dump(nodes);
|
dumper(File(file ~ ".dump", "w").lockingTextWriter).dump(nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void runGetBenchmark() @safe
|
void runGetBenchmark() @safe
|
||||||
|
|
|
@ -297,15 +297,17 @@ void main(string[] args)
|
||||||
//Generate and dump the nodes.
|
//Generate and dump the nodes.
|
||||||
Node[] generated = generate(configFile);
|
Node[] generated = generate(configFile);
|
||||||
|
|
||||||
auto dumper = Dumper(args[1]);
|
auto dumper = dumper(File(args[1], "w").lockingTextWriter);
|
||||||
auto encoding = config["encoding"];
|
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.indent = config["indent"].as!uint;
|
||||||
dumper.textWidth = config["text-width"].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)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,6 @@ dyaml_src = [
|
||||||
'source/dyaml/resolver.d',
|
'source/dyaml/resolver.d',
|
||||||
'source/dyaml/scanner.d',
|
'source/dyaml/scanner.d',
|
||||||
'source/dyaml/serializer.d',
|
'source/dyaml/serializer.d',
|
||||||
'source/dyaml/stream.d',
|
|
||||||
'source/dyaml/style.d',
|
'source/dyaml/style.d',
|
||||||
'source/dyaml/tagdirective.d',
|
'source/dyaml/tagdirective.d',
|
||||||
'source/dyaml/test/common.d',
|
'source/dyaml/test/common.d',
|
||||||
|
|
|
@ -11,13 +11,11 @@
|
||||||
*/
|
*/
|
||||||
module dyaml.dumper;
|
module dyaml.dumper;
|
||||||
|
|
||||||
|
import std.array;
|
||||||
//import std.stream;
|
import std.range.primitives;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
|
||||||
import dyaml.stream;
|
|
||||||
import dyaml.emitter;
|
import dyaml.emitter;
|
||||||
import dyaml.encoding;
|
|
||||||
import dyaml.event;
|
import dyaml.event;
|
||||||
import dyaml.exception;
|
import dyaml.exception;
|
||||||
import dyaml.linebreak;
|
import dyaml.linebreak;
|
||||||
|
@ -34,9 +32,15 @@ import dyaml.tagdirective;
|
||||||
* User specified Representer and/or Resolver can be used to support new
|
* User specified Representer and/or Resolver can be used to support new
|
||||||
* tags / data types.
|
* 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:
|
private:
|
||||||
//Resolver to resolve tags.
|
//Resolver to resolve tags.
|
||||||
|
@ -45,9 +49,7 @@ struct Dumper
|
||||||
Representer representer_;
|
Representer representer_;
|
||||||
|
|
||||||
//Stream to write to.
|
//Stream to write to.
|
||||||
YStream stream_;
|
Range stream_;
|
||||||
//True if this Dumper owns stream_ and needs to destroy it in the destructor.
|
|
||||||
bool weOwnStream_;
|
|
||||||
|
|
||||||
//Write scalars in canonical form?
|
//Write scalars in canonical form?
|
||||||
bool canonical_;
|
bool canonical_;
|
||||||
|
@ -57,8 +59,6 @@ struct Dumper
|
||||||
uint textWidth_ = 80;
|
uint textWidth_ = 80;
|
||||||
//Line break to use.
|
//Line break to use.
|
||||||
LineBreak lineBreak_ = LineBreak.Unix;
|
LineBreak lineBreak_ = LineBreak.Unix;
|
||||||
//Character encoding to use.
|
|
||||||
Encoding encoding_ = Encoding.UTF_8;
|
|
||||||
//YAML version string.
|
//YAML version string.
|
||||||
string YAMLVersion_ = "1.1";
|
string YAMLVersion_ = "1.1";
|
||||||
//Tag directives to use.
|
//Tag directives to use.
|
||||||
|
@ -73,45 +73,21 @@ struct Dumper
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@disable this();
|
@disable this();
|
||||||
@disable bool opEquals(ref Dumper);
|
@disable bool opEquals(ref Dumper!Range);
|
||||||
@disable int opCmp(ref Dumper);
|
@disable int opCmp(ref Dumper!Range);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Dumper writing to a file.
|
* Construct a Dumper writing to a file.
|
||||||
*
|
*
|
||||||
* Params: filename = File name to write to.
|
* 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
|
this(Range stream) @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
|
|
||||||
{
|
{
|
||||||
resolver_ = new Resolver();
|
resolver_ = new Resolver();
|
||||||
representer_ = new Representer();
|
representer_ = new Representer();
|
||||||
stream_ = stream;
|
stream_ = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Destroy the Dumper.
|
|
||||||
@trusted ~this()
|
|
||||||
{
|
|
||||||
if(weOwnStream_) { destroy(stream_); }
|
|
||||||
}
|
|
||||||
|
|
||||||
///Set stream _name. Used in debugging messages.
|
///Set stream _name. Used in debugging messages.
|
||||||
@property void name(string name) pure @safe nothrow
|
@property void name(string name) pure @safe nothrow
|
||||||
{
|
{
|
||||||
|
@ -159,12 +135,6 @@ struct Dumper
|
||||||
lineBreak_ = lineBreak;
|
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?
|
///Always explicitly write document start?
|
||||||
@property void explicitStart(bool explicit) pure @safe nothrow
|
@property void explicitStart(bool explicit) pure @safe nothrow
|
||||||
{
|
{
|
||||||
|
@ -218,7 +188,7 @@ struct Dumper
|
||||||
///
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
Dumper dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string());
|
||||||
string[string] directives;
|
string[string] directives;
|
||||||
directives["!short!"] = "tag:long.org,2011:";
|
directives["!short!"] = "tag:long.org,2011:";
|
||||||
//This will emit tags starting with "tag:long.org,2011"
|
//This will emit tags starting with "tag:long.org,2011"
|
||||||
|
@ -239,12 +209,13 @@ struct Dumper
|
||||||
* Throws: YAMLException on error (e.g. invalid nodes,
|
* Throws: YAMLException on error (e.g. invalid nodes,
|
||||||
* unable to write to file/stream).
|
* unable to write to file/stream).
|
||||||
*/
|
*/
|
||||||
void dump(Node[] documents ...) @safe
|
void dump(CharacterType = char)(Node[] documents ...) @trusted
|
||||||
|
if (isOutputRange!(Range, CharacterType))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto emitter = new Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_);
|
auto emitter = new Emitter!(Range, CharacterType)(stream_, canonical_, indent_, textWidth_, lineBreak_);
|
||||||
auto serializer = Serializer(emitter, resolver_, encoding_, explicitStart_,
|
auto serializer = Serializer!(Range, CharacterType)(emitter, resolver_, explicitStart_,
|
||||||
explicitEnd_, YAMLVersion_, tags_);
|
explicitEnd_, YAMLVersion_, tags_);
|
||||||
foreach(ref document; documents)
|
foreach(ref document; documents)
|
||||||
{
|
{
|
||||||
|
@ -266,11 +237,11 @@ struct Dumper
|
||||||
*
|
*
|
||||||
* Throws: YAMLException if unable to emit.
|
* Throws: YAMLException if unable to emit.
|
||||||
*/
|
*/
|
||||||
void emit(Event[] events) @safe
|
void emit(CharacterType = char)(Event[] events) @safe
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto emitter = Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_);
|
auto emitter = Emitter!(Range, CharacterType)(stream_, canonical_, indent_, textWidth_, lineBreak_);
|
||||||
foreach(ref event; events)
|
foreach(ref event; events)
|
||||||
{
|
{
|
||||||
emitter.emit(event);
|
emitter.emit(event);
|
||||||
|
@ -287,24 +258,23 @@ struct Dumper
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
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
|
///Write multiple YAML documents to a file
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
auto node1 = Node([1, 2, 3, 4, 5]);
|
auto node1 = Node([1, 2, 3, 4, 5]);
|
||||||
auto node2 = Node("This document contains only one string");
|
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:
|
//Or with an array:
|
||||||
Dumper("example.yaml").dump([node1, node2]);
|
dumper(new Appender!string()).dump([node1, node2]);
|
||||||
}
|
}
|
||||||
///Write to memory
|
///Write to memory
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.stream;
|
auto stream = new Appender!string();
|
||||||
auto stream = new YMemoryStream();
|
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
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
|
///Use a custom representer/resolver to support custom data types and/or implicit tags
|
||||||
@safe unittest
|
@safe unittest
|
||||||
|
@ -313,7 +283,7 @@ struct Dumper
|
||||||
auto representer = new Representer();
|
auto representer = new Representer();
|
||||||
auto resolver = new Resolver();
|
auto resolver = new Resolver();
|
||||||
//Add representer functions / resolver expressions here...
|
//Add representer functions / resolver expressions here...
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string());
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
dumper.resolver = resolver;
|
dumper.resolver = resolver;
|
||||||
dumper.dump(node);
|
dumper.dump(node);
|
||||||
|
@ -321,10 +291,9 @@ struct Dumper
|
||||||
// Explicit document start/end markers
|
// Explicit document start/end markers
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.stream;
|
auto stream = new Appender!string();
|
||||||
auto stream = new YMemoryStream();
|
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
auto node = Node([1, 2, 3, 4, 5]);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = true;
|
dumper.explicitEnd = true;
|
||||||
dumper.explicitStart = true;
|
dumper.explicitStart = true;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
@ -337,10 +306,9 @@ struct Dumper
|
||||||
// No explicit document start/end markers
|
// No explicit document start/end markers
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.stream;
|
auto stream = new Appender!string();
|
||||||
auto stream = new YMemoryStream();
|
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
auto node = Node([1, 2, 3, 4, 5]);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = false;
|
dumper.explicitEnd = false;
|
||||||
dumper.explicitStart = false;
|
dumper.explicitStart = false;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import std.system;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import std.utf;
|
import std.utf;
|
||||||
|
|
||||||
import dyaml.stream;
|
|
||||||
import dyaml.encoding;
|
import dyaml.encoding;
|
||||||
import dyaml.escapes;
|
import dyaml.escapes;
|
||||||
import dyaml.event;
|
import dyaml.event;
|
||||||
|
@ -68,7 +67,7 @@ private alias isFlowIndicator = among!(',', '?', '[', ']', '{', '}');
|
||||||
private alias isSpace = among!('\0', '\n', '\r', '\u0085', '\u2028', '\u2029', ' ', '\t');
|
private alias isSpace = among!('\0', '\n', '\r', '\u0085', '\u2028', '\u2029', ' ', '\t');
|
||||||
|
|
||||||
//Emits YAML events into a file/stream.
|
//Emits YAML events into a file/stream.
|
||||||
struct Emitter
|
struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
///Default tag handle shortcuts and replacements.
|
///Default tag handle shortcuts and replacements.
|
||||||
|
@ -76,9 +75,7 @@ struct Emitter
|
||||||
[TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
|
[TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
|
||||||
|
|
||||||
///Stream to write to.
|
///Stream to write to.
|
||||||
YStream stream_;
|
Range stream_;
|
||||||
///Encoding can be overriden by STREAM-START.
|
|
||||||
Encoding encoding_ = Encoding.UTF_8;
|
|
||||||
|
|
||||||
///Stack of states.
|
///Stack of states.
|
||||||
Appender!(void function() @safe[]) states_;
|
Appender!(void function() @safe[]) states_;
|
||||||
|
@ -159,15 +156,13 @@ struct Emitter
|
||||||
/**
|
/**
|
||||||
* Construct an emitter.
|
* Construct an emitter.
|
||||||
*
|
*
|
||||||
* Params: stream = YStream to write to. Must be writable.
|
* Params: stream = Output range to write to.
|
||||||
* canonical = Write scalars in canonical form?
|
* canonical = Write scalars in canonical form?
|
||||||
* indent = Indentation width.
|
* indent = Indentation width.
|
||||||
* lineBreak = Line break character/s.
|
* lineBreak = Line break character/s.
|
||||||
*/
|
*/
|
||||||
this(YStream stream, const bool canonical, const int indent, const int width,
|
this(Range stream, const bool canonical, const int indent, const int width,
|
||||||
const LineBreak lineBreak) @trusted
|
const LineBreak lineBreak) @trusted
|
||||||
in{assert(stream.writeable, "Can't emit YAML to a non-writable stream");}
|
|
||||||
body
|
|
||||||
{
|
{
|
||||||
states_.reserve(32);
|
states_.reserve(32);
|
||||||
indents_.reserve(32);
|
indents_.reserve(32);
|
||||||
|
@ -224,19 +219,22 @@ struct Emitter
|
||||||
///Write a string to the file/stream.
|
///Write a string to the file/stream.
|
||||||
void writeString(const char[] str) @safe
|
void writeString(const char[] str) @safe
|
||||||
{
|
{
|
||||||
try final switch(encoding_)
|
try
|
||||||
{
|
{
|
||||||
case Encoding.UTF_8:
|
static if(is(CharType == char))
|
||||||
stream_.writeExact(str);
|
{
|
||||||
break;
|
copy(str, stream_);
|
||||||
case Encoding.UTF_16:
|
}
|
||||||
|
static if(is(CharType == wchar))
|
||||||
|
{
|
||||||
const buffer = to!wstring(str);
|
const buffer = to!wstring(str);
|
||||||
stream_.writeExact(buffer);
|
copy(buffer, stream_);
|
||||||
break;
|
}
|
||||||
case Encoding.UTF_32:
|
static if(is(CharType == dchar))
|
||||||
|
{
|
||||||
const buffer = to!dstring(str);
|
const buffer = to!dstring(str);
|
||||||
stream_.writeExact(buffer);
|
copy(buffer, stream_);
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -319,7 +317,6 @@ struct Emitter
|
||||||
enforce(eventTypeIs(EventID.StreamStart),
|
enforce(eventTypeIs(EventID.StreamStart),
|
||||||
new EmitterException("Expected YStreamStart, but got " ~ event_.idString));
|
new EmitterException("Expected YStreamStart, but got " ~ event_.idString));
|
||||||
|
|
||||||
encoding_ = event_.encoding;
|
|
||||||
writeStreamStart();
|
writeStreamStart();
|
||||||
nextExpected(&expectDocumentStart!(Yes.first));
|
nextExpected(&expectDocumentStart!(Yes.first));
|
||||||
}
|
}
|
||||||
|
@ -411,7 +408,6 @@ struct Emitter
|
||||||
writeIndicator("...", Yes.needWhitespace);
|
writeIndicator("...", Yes.needWhitespace);
|
||||||
writeIndent();
|
writeIndent();
|
||||||
}
|
}
|
||||||
stream_.flush();
|
|
||||||
nextExpected(&expectDocumentStart!(No.first));
|
nextExpected(&expectDocumentStart!(No.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,7 +745,7 @@ struct Emitter
|
||||||
//{
|
//{
|
||||||
// writeIndent();
|
// writeIndent();
|
||||||
//}
|
//}
|
||||||
auto writer = ScalarWriter(this, analysis_.scalar,
|
auto writer = ScalarWriter!(Range, CharType)(this, analysis_.scalar,
|
||||||
context_ != Context.MappingSimpleKey);
|
context_ != Context.MappingSimpleKey);
|
||||||
with(writer) final switch(style_)
|
with(writer) final switch(style_)
|
||||||
{
|
{
|
||||||
|
@ -1153,29 +1149,15 @@ struct Emitter
|
||||||
///Start the YAML stream (write the unicode byte order mark).
|
///Start the YAML stream (write the unicode byte order mark).
|
||||||
void writeStreamStart() @safe
|
void writeStreamStart() @safe
|
||||||
{
|
{
|
||||||
immutable(ubyte)[] bom;
|
|
||||||
//Write BOM (except for UTF-8)
|
//Write BOM (except for UTF-8)
|
||||||
final switch(encoding_)
|
static if(is(CharType == wchar) || is(CharType == dchar))
|
||||||
{
|
{
|
||||||
case Encoding.UTF_8:
|
stream_.put(cast(CharType)'\uFEFF');
|
||||||
break;
|
|
||||||
case Encoding.UTF_16:
|
|
||||||
bom = std.system.endian == Endian.littleEndian
|
|
||||||
? bomTable[BOM.utf16le].sequence
|
|
||||||
: bomTable[BOM.utf16be].sequence;
|
|
||||||
break;
|
|
||||||
case Encoding.UTF_32:
|
|
||||||
bom = std.system.endian == Endian.littleEndian
|
|
||||||
? bomTable[BOM.utf32le].sequence
|
|
||||||
: bomTable[BOM.utf32be].sequence;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(stream_.write(bom) == bom.length, new EmitterException("Unable to write to stream"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///End the YAML stream.
|
///End the YAML stream.
|
||||||
void writeStreamEnd() @safe {stream_.flush();}
|
void writeStreamEnd() @safe {}
|
||||||
|
|
||||||
///Write an indicator (e.g. ":", "[", ">", etc.).
|
///Write an indicator (e.g. ":", "[", ">", etc.).
|
||||||
void writeIndicator(const char[] indicator,
|
void writeIndicator(const char[] indicator,
|
||||||
|
@ -1270,7 +1252,7 @@ struct Emitter
|
||||||
private:
|
private:
|
||||||
|
|
||||||
///RAII struct used to write out scalar values.
|
///RAII struct used to write out scalar values.
|
||||||
struct ScalarWriter
|
struct ScalarWriter(Range, CharType)
|
||||||
{
|
{
|
||||||
invariant()
|
invariant()
|
||||||
{
|
{
|
||||||
|
@ -1279,14 +1261,14 @@ struct ScalarWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@disable int opCmp(ref Emitter);
|
@disable int opCmp(ref Emitter!(Range, CharType));
|
||||||
@disable bool opEquals(ref Emitter);
|
@disable bool opEquals(ref Emitter!(Range, CharType));
|
||||||
|
|
||||||
///Used as "null" UTF-32 character.
|
///Used as "null" UTF-32 character.
|
||||||
static immutable dcharNone = dchar.max;
|
static immutable dcharNone = dchar.max;
|
||||||
|
|
||||||
///Emitter used to emit the scalar.
|
///Emitter used to emit the scalar.
|
||||||
Emitter* emitter_;
|
Emitter!(Range, CharType)* emitter_;
|
||||||
|
|
||||||
///UTF-8 encoded text of the scalar to write.
|
///UTF-8 encoded text of the scalar to write.
|
||||||
string text_;
|
string text_;
|
||||||
|
@ -1307,7 +1289,7 @@ struct ScalarWriter
|
||||||
|
|
||||||
public:
|
public:
|
||||||
///Construct a ScalarWriter using emitter to output text.
|
///Construct a ScalarWriter using emitter to output text.
|
||||||
this(ref Emitter emitter, string text, const bool split = true) @trusted nothrow
|
this(ref Emitter!(Range, CharType) emitter, string text, const bool split = true) @trusted nothrow
|
||||||
{
|
{
|
||||||
emitter_ = &emitter;
|
emitter_ = &emitter;
|
||||||
text_ = text;
|
text_ = text;
|
||||||
|
@ -1502,7 +1484,7 @@ struct ScalarWriter
|
||||||
///Write text as plain scalar.
|
///Write text as plain scalar.
|
||||||
void writePlain() @safe
|
void writePlain() @safe
|
||||||
{
|
{
|
||||||
if(emitter_.context_ == Emitter.Context.Root){emitter_.openEnded_ = true;}
|
if(emitter_.context_ == Emitter!(Range, CharType).Context.Root){emitter_.openEnded_ = true;}
|
||||||
if(text_ == ""){return;}
|
if(text_ == ""){return;}
|
||||||
if(!emitter_.whitespace_)
|
if(!emitter_.whitespace_)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,6 @@ module dyaml.event;
|
||||||
import std.array;
|
import std.array;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
|
|
||||||
import dyaml.encoding;
|
|
||||||
import dyaml.exception;
|
import dyaml.exception;
|
||||||
import dyaml.reader;
|
import dyaml.reader;
|
||||||
import dyaml.tagdirective;
|
import dyaml.tagdirective;
|
||||||
|
@ -80,8 +79,6 @@ struct Event
|
||||||
*/
|
*/
|
||||||
bool explicitDocument;
|
bool explicitDocument;
|
||||||
}
|
}
|
||||||
///Encoding of the stream, if this is a StreamStart.
|
|
||||||
Encoding encoding;
|
|
||||||
///Collection style, if this is a SequenceStart or MappingStart.
|
///Collection style, if this is a SequenceStart or MappingStart.
|
||||||
CollectionStyle collectionStyle = CollectionStyle.Invalid;
|
CollectionStyle collectionStyle = CollectionStyle.Invalid;
|
||||||
|
|
||||||
|
@ -159,16 +156,14 @@ Event collectionStartEvent(EventID id)
|
||||||
*
|
*
|
||||||
* Params: start = Start position of the event in the file/stream.
|
* Params: start = Start position of the event in the file/stream.
|
||||||
* end = End position of the event in the file/stream.
|
* end = End position of the event in the file/stream.
|
||||||
* encoding = Encoding of the stream.
|
|
||||||
*/
|
*/
|
||||||
Event streamStartEvent(const Mark start, const Mark end, const Encoding encoding)
|
Event streamStartEvent(const Mark start, const Mark end)
|
||||||
pure @safe nothrow
|
pure @safe nothrow
|
||||||
{
|
{
|
||||||
Event result;
|
Event result;
|
||||||
result.startMark = start;
|
result.startMark = start;
|
||||||
result.endMark = end;
|
result.endMark = end;
|
||||||
result.id = EventID.StreamStart;
|
result.id = EventID.StreamStart;
|
||||||
result.encoding = encoding;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ struct Loader
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
throw new YAMLException("Unable to open %s for YAML loading: %s"
|
throw new YAMLException("Unable to open %s for YAML loading: %s"
|
||||||
.format(name_, e.msg));
|
.format(name_, e.msg), e.file, e.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2011,24 +2011,22 @@ struct Node
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.dumper;
|
import dyaml.dumper;
|
||||||
import dyaml.stream;
|
auto stream = new Appender!string();
|
||||||
auto stream = new YMemoryStream();
|
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
auto node = Node([1, 2, 3, 4, 5]);
|
||||||
node.setStyle(CollectionStyle.Block);
|
node.setStyle(CollectionStyle.Block);
|
||||||
|
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.dump(node);
|
dumper.dump(node);
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.dumper;
|
import dyaml.dumper;
|
||||||
import dyaml.stream;
|
auto stream = new Appender!string();
|
||||||
auto stream = new YMemoryStream();
|
|
||||||
auto node = Node(4);
|
auto node = Node(4);
|
||||||
node.setStyle(ScalarStyle.Literal);
|
node.setStyle(ScalarStyle.Literal);
|
||||||
|
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.dump(node);
|
dumper.dump(node);
|
||||||
}
|
}
|
||||||
@safe unittest
|
@safe unittest
|
||||||
|
@ -2039,12 +2037,11 @@ struct Node
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import dyaml.dumper;
|
import dyaml.dumper;
|
||||||
import dyaml.stream;
|
|
||||||
{
|
{
|
||||||
auto stream = new YMemoryStream();
|
auto stream = new Appender!string();
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
auto node = Node([1, 2, 3, 4, 5]);
|
||||||
node.setStyle(CollectionStyle.Block);
|
node.setStyle(CollectionStyle.Block);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = false;
|
dumper.explicitEnd = false;
|
||||||
dumper.explicitStart = false;
|
dumper.explicitStart = false;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
@ -2054,10 +2051,10 @@ struct Node
|
||||||
assert(stream.data[0] == '-');
|
assert(stream.data[0] == '-');
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto stream = new YMemoryStream();
|
auto stream = new Appender!string();
|
||||||
auto node = Node([1, 2, 3, 4, 5]);
|
auto node = Node([1, 2, 3, 4, 5]);
|
||||||
node.setStyle(CollectionStyle.Flow);
|
node.setStyle(CollectionStyle.Flow);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = false;
|
dumper.explicitEnd = false;
|
||||||
dumper.explicitStart = false;
|
dumper.explicitStart = false;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
@ -2067,10 +2064,10 @@ struct Node
|
||||||
assert(stream.data[0] == '[');
|
assert(stream.data[0] == '[');
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto stream = new YMemoryStream();
|
auto stream = new Appender!string();
|
||||||
auto node = Node(1);
|
auto node = Node(1);
|
||||||
node.setStyle(ScalarStyle.SingleQuoted);
|
node.setStyle(ScalarStyle.SingleQuoted);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = false;
|
dumper.explicitEnd = false;
|
||||||
dumper.explicitStart = false;
|
dumper.explicitStart = false;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
@ -2079,10 +2076,10 @@ struct Node
|
||||||
assert(stream.data == "!!int '1'\n");
|
assert(stream.data == "!!int '1'\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto stream = new YMemoryStream();
|
auto stream = new Appender!string();
|
||||||
auto node = Node(1);
|
auto node = Node(1);
|
||||||
node.setStyle(ScalarStyle.DoubleQuoted);
|
node.setStyle(ScalarStyle.DoubleQuoted);
|
||||||
auto dumper = Dumper(stream);
|
auto dumper = dumper(stream);
|
||||||
dumper.explicitEnd = false;
|
dumper.explicitEnd = false;
|
||||||
dumper.explicitStart = false;
|
dumper.explicitStart = false;
|
||||||
dumper.YAMLVersion = null;
|
dumper.YAMLVersion = null;
|
||||||
|
|
|
@ -256,7 +256,7 @@ final class Parser
|
||||||
{
|
{
|
||||||
const token = scanner_.getToken();
|
const token = scanner_.getToken();
|
||||||
state_ = &parseImplicitDocumentStart;
|
state_ = &parseImplicitDocumentStart;
|
||||||
return streamStartEvent(token.startMark, token.endMark, token.encoding);
|
return streamStartEvent(token.startMark, token.endMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse implicit document start, unless explicit detected: if so, parse explicit.
|
/// Parse implicit document start, unless explicit detected: if so, parse explicit.
|
||||||
|
|
|
@ -154,7 +154,7 @@ final class Representer
|
||||||
return representer.representScalar("!mystruct.tag", scalar);
|
return representer.representScalar("!mystruct.tag", scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -207,7 +207,7 @@ final class Representer
|
||||||
return representer.representScalar("!myclass.tag", scalar);
|
return representer.representScalar("!myclass.tag", scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyClass(&representMyClass);
|
representer.addRepresenter!MyClass(&representMyClass);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -263,7 +263,7 @@ final class Representer
|
||||||
return representer.representScalar("!mystruct.tag", scalar);
|
return representer.representScalar("!mystruct.tag", scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -339,7 +339,7 @@ final class Representer
|
||||||
CollectionStyle.Flow);
|
CollectionStyle.Flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -422,7 +422,7 @@ final class Representer
|
||||||
return representer.representMapping("!mystruct.tag", pairs);
|
return representer.representMapping("!mystruct.tag", pairs);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dumper = Dumper("example.yaml");
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -457,7 +457,7 @@ final class Representer
|
||||||
}
|
}
|
||||||
|
|
||||||
//Represent a node, serializing with specified Serializer.
|
//Represent a node, serializing with specified Serializer.
|
||||||
void represent(ref Serializer serializer, ref Node node) @safe
|
void represent(Range, CharType)(ref Serializer!(Range, CharType) serializer, ref Node node) @safe
|
||||||
{
|
{
|
||||||
auto data = representData(node);
|
auto data = representData(node);
|
||||||
serializer.serialize(data);
|
serializer.serialize(data);
|
||||||
|
@ -677,15 +677,13 @@ Node representMyClass(ref Node node, Representer representer) @safe
|
||||||
return representer.representScalar("!myclass.tag", scalar);
|
return representer.representScalar("!myclass.tag", scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
import dyaml.stream;
|
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
foreach(r; [&representMyStruct,
|
foreach(r; [&representMyStruct,
|
||||||
&representMyStructSeq,
|
&representMyStructSeq,
|
||||||
&representMyStructMap])
|
&representMyStructMap])
|
||||||
{
|
{
|
||||||
auto dumper = Dumper(new YMemoryStream());
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyStruct(r);
|
representer.addRepresenter!MyStruct(r);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
@ -695,7 +693,7 @@ import dyaml.stream;
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
auto dumper = Dumper(new YMemoryStream());
|
auto dumper = dumper(new Appender!string);
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!MyClass(&representMyClass);
|
representer.addRepresenter!MyClass(&representMyClass);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
|
|
|
@ -16,7 +16,6 @@ import std.format;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
|
||||||
import dyaml.emitter;
|
import dyaml.emitter;
|
||||||
import dyaml.encoding;
|
|
||||||
import dyaml.event;
|
import dyaml.event;
|
||||||
import dyaml.exception;
|
import dyaml.exception;
|
||||||
import dyaml.node;
|
import dyaml.node;
|
||||||
|
@ -28,11 +27,11 @@ import dyaml.token;
|
||||||
package:
|
package:
|
||||||
|
|
||||||
///Serializes represented YAML nodes, generating events which are then emitted by Emitter.
|
///Serializes represented YAML nodes, generating events which are then emitted by Emitter.
|
||||||
struct Serializer
|
struct Serializer(Range, CharType)
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
///Emitter to emit events produced.
|
///Emitter to emit events produced.
|
||||||
Emitter* emitter_;
|
Emitter!(Range, CharType)* emitter_;
|
||||||
///Resolver used to determine which tags are automaticaly resolvable.
|
///Resolver used to determine which tags are automaticaly resolvable.
|
||||||
Resolver resolver_;
|
Resolver resolver_;
|
||||||
|
|
||||||
|
@ -60,13 +59,12 @@ struct Serializer
|
||||||
*
|
*
|
||||||
* Params: emitter = Emitter to emit events produced.
|
* Params: emitter = Emitter to emit events produced.
|
||||||
* resolver = Resolver used to determine which tags are automaticaly resolvable.
|
* resolver = Resolver used to determine which tags are automaticaly resolvable.
|
||||||
* encoding = Character encoding to use.
|
|
||||||
* explicitStart = Do all document starts have to be specified explicitly?
|
* explicitStart = Do all document starts have to be specified explicitly?
|
||||||
* explicitEnd = Do all document ends have to be specified explicitly?
|
* explicitEnd = Do all document ends have to be specified explicitly?
|
||||||
* YAMLVersion = YAML version string.
|
* YAMLVersion = YAML version string.
|
||||||
* tagDirectives = Tag directives to emit.
|
* tagDirectives = Tag directives to emit.
|
||||||
*/
|
*/
|
||||||
this(Emitter* emitter, Resolver resolver, Encoding encoding,
|
this(Emitter!(Range, CharType)* emitter, Resolver resolver,
|
||||||
const Flag!"explicitStart" explicitStart,
|
const Flag!"explicitStart" explicitStart,
|
||||||
const Flag!"explicitEnd" explicitEnd, string YAMLVersion,
|
const Flag!"explicitEnd" explicitEnd, string YAMLVersion,
|
||||||
TagDirective[] tagDirectives) @safe
|
TagDirective[] tagDirectives) @safe
|
||||||
|
@ -78,7 +76,7 @@ struct Serializer
|
||||||
YAMLVersion_ = YAMLVersion;
|
YAMLVersion_ = YAMLVersion;
|
||||||
tagDirectives_ = tagDirectives;
|
tagDirectives_ = tagDirectives;
|
||||||
|
|
||||||
emitter_.emit(streamStartEvent(Mark(), Mark(), encoding));
|
emitter_.emit(streamStartEvent(Mark(), Mark()));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Destroy the Serializer.
|
///Destroy the Serializer.
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
module dyaml.stream;
|
|
||||||
|
|
||||||
interface YStream
|
|
||||||
{
|
|
||||||
void writeExact(const void* buffer, size_t size);
|
|
||||||
void writeExact(const void[] buffer) @safe;
|
|
||||||
size_t write(const(ubyte)[] buffer) @safe;
|
|
||||||
size_t write(const(char)[] str) @safe;
|
|
||||||
void flush() @safe;
|
|
||||||
@property bool writeable() @safe;
|
|
||||||
}
|
|
||||||
|
|
||||||
class YMemoryStream : YStream
|
|
||||||
{
|
|
||||||
ubyte[] data;
|
|
||||||
|
|
||||||
void writeExact(const void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
data ~= cast(ubyte[])buffer[0 .. size];
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeExact(const void[] buffer) @trusted
|
|
||||||
{
|
|
||||||
data ~= cast(ubyte[])buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const(ubyte)[] buffer) @safe
|
|
||||||
{
|
|
||||||
data ~= buffer;
|
|
||||||
return buffer.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const(char)[] str) @safe
|
|
||||||
{
|
|
||||||
return write(cast(const(ubyte)[])str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush() @safe {}
|
|
||||||
|
|
||||||
@property bool writeable() @safe { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
class YFile : YStream
|
|
||||||
{
|
|
||||||
static import std.stdio;
|
|
||||||
std.stdio.File file;
|
|
||||||
|
|
||||||
this(string fn) @safe
|
|
||||||
{
|
|
||||||
this.file = std.stdio.File(fn, "w");
|
|
||||||
}
|
|
||||||
|
|
||||||
this(std.stdio.File file) @safe
|
|
||||||
{
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@system unittest
|
|
||||||
{
|
|
||||||
import std.stdio : File;
|
|
||||||
auto stream = new YFile(File.tmpfile);
|
|
||||||
stream.write("Test writing to tmpFile through YFile stream\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeExact(const void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
this.file.rawWrite(cast(const) buffer[0 .. size]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeExact(const void[] buffer) @trusted
|
|
||||||
{
|
|
||||||
this.file.rawWrite(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const(ubyte)[] buffer) @trusted
|
|
||||||
{
|
|
||||||
this.file.rawWrite(buffer);
|
|
||||||
return buffer.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const(char)[] str) @trusted
|
|
||||||
{
|
|
||||||
return write(cast(ubyte[])str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush() @safe
|
|
||||||
{
|
|
||||||
this.file.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@property bool writeable() @safe { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
import dyaml.dumper, dyaml.loader, dyaml.node;
|
|
||||||
import std.file : readText, remove;
|
|
||||||
|
|
||||||
string test = "Hello World : [Hello, World]\n" ~
|
|
||||||
"Answer: 42";
|
|
||||||
//Read the input.
|
|
||||||
Node expected = Loader.fromString(test).load();
|
|
||||||
assert(expected["Hello World"][0] == "Hello");
|
|
||||||
assert(expected["Hello World"][1] == "World");
|
|
||||||
assert(expected["Answer"].as!int == 42);
|
|
||||||
|
|
||||||
//Dump the loaded document to output.yaml.
|
|
||||||
Dumper("output.yaml").dump(expected);
|
|
||||||
|
|
||||||
// Load the file and verify that it was saved correctly.
|
|
||||||
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);
|
|
||||||
assert(actual == expected);
|
|
||||||
|
|
||||||
// Clean up.
|
|
||||||
remove("output.yaml");
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest // #88, #89
|
|
||||||
{
|
|
||||||
import dyaml.dumper, dyaml.loader;
|
|
||||||
import std.file : remove, read;
|
|
||||||
|
|
||||||
enum fn = "output.yaml";
|
|
||||||
scope (exit) fn.remove;
|
|
||||||
|
|
||||||
auto dumper = Dumper(fn);
|
|
||||||
dumper.YAMLVersion = null; // supress directive
|
|
||||||
dumper.dump(Loader.fromString("Hello world").load);
|
|
||||||
|
|
||||||
assert (fn.read()[0..3] == "Hel");
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@ import std.file;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
|
||||||
import dyaml.stream;
|
|
||||||
import dyaml.dumper;
|
import dyaml.dumper;
|
||||||
import dyaml.event;
|
import dyaml.event;
|
||||||
import dyaml.test.common;
|
import dyaml.test.common;
|
||||||
|
@ -83,17 +82,17 @@ void testEmitterOnData(string dataFilename, string canonicalFilename) @safe
|
||||||
//Must exist due to Anchor, Tags reference counts.
|
//Must exist due to Anchor, Tags reference counts.
|
||||||
auto loader = Loader.fromFile(dataFilename);
|
auto loader = Loader.fromFile(dataFilename);
|
||||||
auto events = loader.parse();
|
auto events = loader.parse();
|
||||||
auto emitStream = new YMemoryStream;
|
auto emitStream = new Appender!string;
|
||||||
Dumper(emitStream).emit(events);
|
dumper(emitStream).emit(events);
|
||||||
|
|
||||||
static if(verbose)
|
static if(verbose)
|
||||||
{
|
{
|
||||||
writeln(dataFilename);
|
writeln(dataFilename);
|
||||||
writeln("ORIGINAL:\n", readText(dataFilename));
|
writeln("ORIGINAL:\n", readText(dataFilename));
|
||||||
writeln("OUTPUT:\n", cast(char[])emitStream.data);
|
writeln("OUTPUT:\n", emitStream.toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto loader2 = Loader.fromBuffer(emitStream.data);
|
auto loader2 = Loader.fromString(emitStream.data);
|
||||||
loader2.name = "TEST";
|
loader2.name = "TEST";
|
||||||
loader2.constructor = new Constructor;
|
loader2.constructor = new Constructor;
|
||||||
loader2.resolver = new Resolver;
|
loader2.resolver = new Resolver;
|
||||||
|
@ -113,16 +112,16 @@ void testEmitterOnCanonical(string canonicalFilename) @safe
|
||||||
auto events = loader.parse();
|
auto events = loader.parse();
|
||||||
foreach(canonical; [false, true])
|
foreach(canonical; [false, true])
|
||||||
{
|
{
|
||||||
auto emitStream = new YMemoryStream;
|
auto emitStream = new Appender!string;
|
||||||
auto dumper = Dumper(emitStream);
|
auto dumper = dumper(emitStream);
|
||||||
dumper.canonical = canonical;
|
dumper.canonical = canonical;
|
||||||
dumper.emit(events);
|
dumper.emit(events);
|
||||||
static if(verbose)
|
static if(verbose)
|
||||||
{
|
{
|
||||||
writeln("OUTPUT (canonical=", canonical, "):\n",
|
writeln("OUTPUT (canonical=", canonical, "):\n",
|
||||||
cast(char[])emitStream.data);
|
emitStream.toString);
|
||||||
}
|
}
|
||||||
auto loader2 = Loader.fromBuffer(emitStream.data);
|
auto loader2 = Loader.fromString(emitStream.data);
|
||||||
loader2.name = "TEST";
|
loader2.name = "TEST";
|
||||||
loader2.constructor = new Constructor;
|
loader2.constructor = new Constructor;
|
||||||
loader2.resolver = new Resolver;
|
loader2.resolver = new Resolver;
|
||||||
|
@ -172,15 +171,15 @@ void testEmitterStyles(string dataFilename, string canonicalFilename) @safe
|
||||||
}
|
}
|
||||||
styledEvents ~= event;
|
styledEvents ~= event;
|
||||||
}
|
}
|
||||||
auto emitStream = new YMemoryStream;
|
auto emitStream = new Appender!string;
|
||||||
Dumper(emitStream).emit(styledEvents);
|
dumper(emitStream).emit(styledEvents);
|
||||||
static if(verbose)
|
static if(verbose)
|
||||||
{
|
{
|
||||||
writeln("OUTPUT (", filename, ", ", to!string(flowStyle), ", ",
|
writeln("OUTPUT (", filename, ", ", to!string(flowStyle), ", ",
|
||||||
to!string(style), ")");
|
to!string(style), ")");
|
||||||
writeln(cast(char[])emitStream.data);
|
writeln(emitStream.toString);
|
||||||
}
|
}
|
||||||
auto loader2 = Loader.fromBuffer(emitStream.data);
|
auto loader2 = Loader.fromString(emitStream.data);
|
||||||
loader2.name = "TEST";
|
loader2.name = "TEST";
|
||||||
loader2.constructor = new Constructor;
|
loader2.constructor = new Constructor;
|
||||||
loader2.resolver = new Resolver;
|
loader2.resolver = new Resolver;
|
||||||
|
|
|
@ -15,7 +15,6 @@ import std.file;
|
||||||
import std.system;
|
import std.system;
|
||||||
|
|
||||||
import dyaml.test.common;
|
import dyaml.test.common;
|
||||||
import dyaml.stream;
|
|
||||||
|
|
||||||
/// Get an UTF-16 byte order mark.
|
/// Get an UTF-16 byte order mark.
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,9 +10,12 @@ module dyaml.test.representer;
|
||||||
version(unittest)
|
version(unittest)
|
||||||
{
|
{
|
||||||
|
|
||||||
import std.path;
|
import std.array;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
import std.meta;
|
||||||
|
import std.path;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
|
import std.utf;
|
||||||
|
|
||||||
import dyaml.test.common;
|
import dyaml.test.common;
|
||||||
import dyaml.test.constructor;
|
import dyaml.test.constructor;
|
||||||
|
@ -30,9 +33,9 @@ void testRepresenterTypes(string codeFilename) @safe
|
||||||
new Exception("Unimplemented representer test: " ~ baseName));
|
new Exception("Unimplemented representer test: " ~ baseName));
|
||||||
|
|
||||||
Node[] expectedNodes = expected[baseName];
|
Node[] expectedNodes = expected[baseName];
|
||||||
foreach(encoding; [Encoding.UTF_8, Encoding.UTF_16, Encoding.UTF_32])
|
foreach(encoding; AliasSeq!(char, wchar, dchar))
|
||||||
{
|
{
|
||||||
ubyte[] output;
|
immutable(encoding)[] output;
|
||||||
Node[] readNodes;
|
Node[] readNodes;
|
||||||
|
|
||||||
scope(failure)
|
scope(failure)
|
||||||
|
@ -49,23 +52,20 @@ void testRepresenterTypes(string codeFilename) @safe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import dyaml.stream;
|
auto emitStream = new Appender!(immutable(encoding)[]);
|
||||||
|
|
||||||
auto emitStream = new YMemoryStream;
|
|
||||||
auto representer = new Representer;
|
auto representer = new Representer;
|
||||||
representer.addRepresenter!TestClass(&representClass);
|
representer.addRepresenter!TestClass(&representClass);
|
||||||
representer.addRepresenter!TestStruct(&representStruct);
|
representer.addRepresenter!TestStruct(&representStruct);
|
||||||
auto dumper = Dumper(emitStream);
|
auto dumper = dumper(emitStream);
|
||||||
dumper.representer = representer;
|
dumper.representer = representer;
|
||||||
dumper.encoding = encoding;
|
dumper.dump!encoding(expectedNodes);
|
||||||
dumper.dump(expectedNodes);
|
|
||||||
|
|
||||||
output = emitStream.data;
|
output = emitStream.data;
|
||||||
auto constructor = new Constructor;
|
auto constructor = new Constructor;
|
||||||
constructor.addConstructorMapping("!tag1", &constructClass);
|
constructor.addConstructorMapping("!tag1", &constructClass);
|
||||||
constructor.addConstructorScalar("!tag2", &constructStruct);
|
constructor.addConstructorScalar("!tag2", &constructStruct);
|
||||||
|
|
||||||
auto loader = Loader.fromBuffer(emitStream.data);
|
auto loader = Loader.fromString(emitStream.data.toUTF8);
|
||||||
loader.name = "TEST";
|
loader.name = "TEST";
|
||||||
loader.constructor = constructor;
|
loader.constructor = constructor;
|
||||||
readNodes = loader.loadAll();
|
readNodes = loader.loadAll();
|
||||||
|
|
Loading…
Reference in a new issue