diff --git a/source/dyaml/dumper.d b/source/dyaml/dumper.d index 530f2e4..a955b3b 100644 --- a/source/dyaml/dumper.d +++ b/source/dyaml/dumper.d @@ -140,12 +140,11 @@ struct Dumper * Throws: YAMLException on error (e.g. invalid nodes, * unable to write to file/stream). */ - void dump(Range)(Range range, Node[] documents ...) - if (isOutputRange!(Range, char)) + void dump(scope void delegate(scope const char[]) @safe range, Node[] documents ...) @safe { try { - auto emitter = new Emitter!Range(range, canonical, indent_, textWidth, lineBreak); + auto emitter = new Emitter(range, canonical, indent_, textWidth, lineBreak); auto serializer = Serializer(resolver, explicitStart ? Yes.explicitStart : No.explicitStart, explicitEnd ? Yes.explicitEnd : No.explicitEnd, YAMLVersion, tags_); serializer.startStream(emitter); @@ -162,6 +161,14 @@ struct Dumper ~ name ~ " : " ~ e.msg, e.file, e.line); } } + void dump(Range)(auto ref Range range, Node[] documents ...) + { + import std.algorithm.mutation : copy; + void dg(scope const char[] str) { + copy(str, range); + } + dump(&dg, documents); + } } ///Write to a file @safe unittest diff --git a/source/dyaml/emitter.d b/source/dyaml/emitter.d index 04bb649..5a58e9a 100644 --- a/source/dyaml/emitter.d +++ b/source/dyaml/emitter.d @@ -65,7 +65,7 @@ private alias isFlowIndicator = among!(',', '?', '[', ']', '{', '}'); private alias isSpace = among!('\0', '\n', '\r', '\u0085', '\u2028', '\u2029', ' ', '\t'); //Emits YAML events into a file/stream. -struct Emitter(Range) if (isOutputRange!(Range, char)) +struct Emitter { private: ///Default tag handle shortcuts and replacements. @@ -73,7 +73,7 @@ struct Emitter(Range) if (isOutputRange!(Range, char)) [TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")]; ///Stream to write to. - Range stream_; + void delegate(scope const char[]) @safe writeString; /// Type used for upcoming emitter steps alias EmitterFunction = void function(scope typeof(this)*) @safe; @@ -159,12 +159,12 @@ struct Emitter(Range) if (isOutputRange!(Range, char)) * indent = Indentation width. * lineBreak = Line break character/s. */ - this(Range stream, const bool canonical, const int indent, const int width, + this(typeof(writeString) stream, const bool canonical, const int indent, const int width, const LineBreak lineBreak) @safe { states_.reserve(32); indents_.reserve(32); - stream_ = stream; + writeString = stream; canonical_ = canonical; nextExpected!"expectStreamStart"(); @@ -214,12 +214,6 @@ struct Emitter(Range) if (isOutputRange!(Range, char)) return result; } - ///Write a string to the file/stream. - void writeString(const scope char[] str) @safe - { - copy(str, stream_); - } - ///In some cases, we wait for a few next events before emitting. bool needMoreEvents() @safe nothrow { @@ -713,7 +707,7 @@ struct Emitter(Range) if (isOutputRange!(Range, char)) //{ // writeIndent(); //} - auto writer = ScalarWriter!Range(&this, analysis_.scalar, + auto writer = ScalarWriter(&this, analysis_.scalar, context_ != Context.mappingSimpleKey); final switch(style_) { @@ -1251,7 +1245,7 @@ struct Emitter(Range) if (isOutputRange!(Range, char)) private: ///RAII struct used to write out scalar values. -struct ScalarWriter(Range) +struct ScalarWriter { invariant() { @@ -1264,7 +1258,7 @@ struct ScalarWriter(Range) static immutable dcharNone = dchar.max; ///Emitter used to emit the scalar. - Emitter!Range* emitter_; + Emitter* emitter_; ///UTF-8 encoded text of the scalar to write. string text_; @@ -1283,9 +1277,9 @@ struct ScalarWriter(Range) ///Start and end character of the text range we're currently working with. long startChar_, endChar_; - public: + public scope: ///Construct a ScalarWriter using emitter to output text. - this(Emitter!Range* emitter, string text, const bool split = true) @safe nothrow + this(return Emitter* emitter, string text, const bool split = true) @safe nothrow { emitter_ = emitter; text_ = text; @@ -1480,7 +1474,7 @@ struct ScalarWriter(Range) ///Write text as plain scalar. void writePlain() @safe { - if(emitter_.context_ == Emitter!Range.Context.root){emitter_.openEnded_ = true;} + if(emitter_.context_ == Emitter.Context.root){emitter_.openEnded_ = true;} if(text_ == ""){return;} if(!emitter_.whitespace_) { @@ -1555,7 +1549,7 @@ struct ScalarWriter(Range) } ///Determine hints (indicators) for block scalar. - size_t determineBlockHints(char[] hints, uint bestIndent) const pure @safe + size_t determineBlockHints(scope char[] hints, uint bestIndent) const pure @safe { size_t hintsIdx; if(text_.length == 0) diff --git a/source/dyaml/test/suitehelpers.d b/source/dyaml/test/suitehelpers.d index c62ca01..a941417 100644 --- a/source/dyaml/test/suitehelpers.d +++ b/source/dyaml/test/suitehelpers.d @@ -87,8 +87,8 @@ bool testImplicitResolver(string name, string data, string detectData, out strin // Try to emit an event range. Event[] emitTestCommon(string name, Event[] events, bool canonical) @safe { - auto emitStream = new Appender!string(); - auto emitter = Emitter!(typeof(emitStream))(emitStream, canonical, 2, 80, LineBreak.unix); + Appender!string emitStream; + auto emitter = Emitter(&emitStream.put!(const char[]), canonical, 2, 80, LineBreak.unix); foreach (event; events) { emitter.emit(event);