From efd3e403c77ba5c742f56fef30ae023b8990494c Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:00:40 -0300 Subject: [PATCH 1/6] use Appender for stacks --- source/dyaml/emitter.d | 22 +++++++++++----------- source/dyaml/parser.d | 38 +++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/source/dyaml/emitter.d b/source/dyaml/emitter.d index 10e739d..34bc28b 100644 --- a/source/dyaml/emitter.d +++ b/source/dyaml/emitter.d @@ -82,7 +82,7 @@ struct Emitter Encoding encoding_ = Encoding.UTF_8; ///Stack of states. - Array!(void function() @safe) states_; + Appender!(void function() @safe[]) states_; ///Current state. //WARNING! DO NOT CALL DIRECTLY! Use callNext() instead! void function() @safe state_; @@ -93,7 +93,7 @@ struct Emitter Event event_; ///Stack of previous indentation levels. - Array!int indents_; + Appender!(int[]) indents_; ///Current indentation level. int indent_ = -1; @@ -197,12 +197,12 @@ struct Emitter private: ///Pop and return the newest state in states_. - void function() @safe popState() @trusted + void function() @safe popState() @safe { - enforce(states_.length > 0, + enforce(states_.data.length > 0, new YAMLException("Emitter: Need to pop a state but there are no states left")); - const result = states_.back; - states_.length = states_.length - 1; + const result = states_.data[$-1]; + states_.shrinkTo(states_.data.length - 1); return result; } @@ -212,13 +212,13 @@ struct Emitter } ///Pop and return the newest indent in indents_. - int popIndent() @trusted + int popIndent() @safe { - enforce(indents_.length > 0, + enforce(indents_.data.length > 0, new YAMLException("Emitter: Need to pop an indent level but there" ~ " are no indent levels left")); - const result = indents_.back; - indents_.length = indents_.length - 1; + const result = indents_.data[$-1]; + indents_.shrinkTo(indents_.data.length - 1); return result; } @@ -287,7 +287,7 @@ struct Emitter } ///Increase indentation level. - void increaseIndent(const Flag!"flow" flow = No.flow, const bool indentless = false) @trusted + void increaseIndent(const Flag!"flow" flow = No.flow, const bool indentless = false) @safe { indents_ ~= indent_; if(indent_ == -1) diff --git a/source/dyaml/parser.d b/source/dyaml/parser.d index cde978a..00b8d3e 100644 --- a/source/dyaml/parser.d +++ b/source/dyaml/parser.d @@ -125,16 +125,16 @@ final class Parser TagDirective[] tagDirectives_; ///Stack of states. - Array!(Event delegate() @safe) states_; + Appender!(Event delegate() @safe[]) states_; ///Stack of marks used to keep track of extents of e.g. YAML collections. - Array!Mark marks_; + Appender!(Mark[]) marks_; ///Current state. Event delegate() @safe state_; public: ///Construct a Parser using specified Scanner. - this(Scanner scanner) @trusted + this(Scanner scanner) @safe { state_ = &parseStreamStart; scanner_ = scanner; @@ -216,32 +216,32 @@ final class Parser private: ///Pop and return the newest state in states_. - Event delegate() @safe popState() @trusted + Event delegate() @safe popState() @safe { - enforce(states_.length > 0, + enforce(states_.data.length > 0, new YAMLException("Parser: Need to pop state but no states left to pop")); - const result = states_.back; - states_.length = states_.length - 1; + const result = states_.data.back; + states_.shrinkTo(states_.data.length - 1); return result; } ///Pop and return the newest mark in marks_. - Mark popMark() @trusted + Mark popMark() @safe { - enforce(marks_.length > 0, + enforce(marks_.data.length > 0, new YAMLException("Parser: Need to pop mark but no marks left to pop")); - const result = marks_.back; - marks_.length = marks_.length - 1; + const result = marks_.data.back; + marks_.shrinkTo(marks_.data.length - 1); return result; } /// Push a state on the stack - void pushState(Event delegate() @safe state) @trusted + void pushState(Event delegate() @safe state) @safe { states_ ~= state; } /// Push a mark on the stack - void pushMark(Mark mark) @trusted + void pushMark(Mark mark) @safe { marks_ ~= mark; } @@ -304,8 +304,8 @@ final class Parser { //Parse the end of the stream. const token = scanner_.getToken(); - assert(states_.length == 0); - assert(marks_.length == 0); + assert(states_.data.length == 0); + assert(marks_.data.length == 0); state_ = null; return streamEndEvent(token.startMark, token.endMark); } @@ -671,7 +671,7 @@ final class Parser if(!scanner_.checkToken(TokenID.BlockEnd)) { const token = scanner_.peekToken(); - throw new ParserException("While parsing a block collection", marks_.back, + throw new ParserException("While parsing a block collection", marks_.data.back, "expected block end, but found " ~ token.idString, token.startMark); } @@ -736,7 +736,7 @@ final class Parser if(!scanner_.checkToken(TokenID.BlockEnd)) { const token = scanner_.peekToken(); - throw new ParserException("While parsing a block mapping", marks_.back, + throw new ParserException("While parsing a block mapping", marks_.data.back, "expected block end, but found: " ~ token.idString, token.startMark); } @@ -797,7 +797,7 @@ final class Parser else { const token = scanner_.peekToken(); - throw new ParserException("While parsing a flow sequence", marks_.back, + throw new ParserException("While parsing a flow sequence", marks_.data.back, "expected ',' or ']', but got: " ~ token.idString, token.startMark); } @@ -905,7 +905,7 @@ final class Parser else { const token = scanner_.peekToken(); - throw new ParserException("While parsing a flow mapping", marks_.back, + throw new ParserException("While parsing a flow mapping", marks_.data.back, "expected ',' or '}', but got: " ~ token.idString, token.startMark); } From 5172f8b932f84bf58e685910f330d00cec7c90ca Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:04:48 -0300 Subject: [PATCH 2/6] eliminate an unnecessary heap allocation --- source/dyaml/dumper.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dyaml/dumper.d b/source/dyaml/dumper.d index e829633..f518c0e 100644 --- a/source/dyaml/dumper.d +++ b/source/dyaml/dumper.d @@ -270,7 +270,7 @@ struct Dumper { try { - auto emitter = new Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); + auto emitter = Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); foreach(ref event; events) { emitter.emit(event); From ccaa7749bbc2458bc4d8acc6ed7e5829171253e8 Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:10:19 -0300 Subject: [PATCH 3/6] use copies of Emitter instead of passing pointers around --- source/dyaml/dumper.d | 2 +- source/dyaml/queue.d | 2 -- source/dyaml/serializer.d | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/source/dyaml/dumper.d b/source/dyaml/dumper.d index f518c0e..15a47c5 100644 --- a/source/dyaml/dumper.d +++ b/source/dyaml/dumper.d @@ -243,7 +243,7 @@ struct Dumper { try { - auto emitter = new Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); + auto emitter = Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); auto serializer = Serializer(emitter, resolver_, encoding_, explicitStart_, explicitEnd_, YAMLVersion_, tags_); foreach(ref document; documents) diff --git a/source/dyaml/queue.d b/source/dyaml/queue.d index 3f090d0..32069ac 100644 --- a/source/dyaml/queue.d +++ b/source/dyaml/queue.d @@ -95,8 +95,6 @@ public: @disable bool opEquals(ref Queue); @disable int opCmp(ref Queue); - @disable this(this); - ~this() @safe nothrow @nogc { freeStock(); diff --git a/source/dyaml/serializer.d b/source/dyaml/serializer.d index bb10390..a108008 100644 --- a/source/dyaml/serializer.d +++ b/source/dyaml/serializer.d @@ -32,7 +32,7 @@ struct Serializer { private: ///Emitter to emit events produced. - Emitter* emitter_; + Emitter emitter_; ///Resolver used to determine which tags are automaticaly resolvable. Resolver resolver_; @@ -66,7 +66,7 @@ struct Serializer * YAMLVersion = YAML version string. * tagDirectives = Tag directives to emit. */ - this(Emitter* emitter, Resolver resolver, Encoding encoding, + this(Emitter emitter, Resolver resolver, Encoding encoding, const Flag!"explicitStart" explicitStart, const Flag!"explicitEnd" explicitEnd, string YAMLVersion, TagDirective[] tagDirectives) @safe From 590f0cfece6d9dfeada56e58893e9f3ff3e1767c Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:18:09 -0300 Subject: [PATCH 4/6] replace dyaml.scanner's Array with an Appender --- source/dyaml/scanner.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/dyaml/scanner.d b/source/dyaml/scanner.d index b8ae410..58d3efe 100644 --- a/source/dyaml/scanner.d +++ b/source/dyaml/scanner.d @@ -131,7 +131,7 @@ final class Scanner /// Current indentation level. int indent_ = -1; /// Past indentation levels. Used as a stack. - Array!int indents_; + Appender!(int[]) indents_; /// Processed tokens not yet emitted. Used as a queue. Queue!Token tokens_; @@ -440,9 +440,9 @@ final class Scanner // In block context, we may need to issue the BLOCK-END tokens. while(indent_ > column) { - indent_ = indents_.back; - assert(indents_.length); - indents_.length = indents_.length - 1; + indent_ = indents_.data.back; + assert(indents_.data.length); + indents_.shrinkTo(indents_.data.length - 1); tokens_.push(blockEndToken(reader_.mark, reader_.mark)); } } From 118fc291e962e3bc3405b3990d066f6988c10722 Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:18:31 -0300 Subject: [PATCH 5/6] remove obsolete std.container imports --- source/dyaml/emitter.d | 1 - source/dyaml/parser.d | 1 - source/dyaml/scanner.d | 1 - 3 files changed, 3 deletions(-) diff --git a/source/dyaml/emitter.d b/source/dyaml/emitter.d index 34bc28b..e8e0df6 100644 --- a/source/dyaml/emitter.d +++ b/source/dyaml/emitter.d @@ -13,7 +13,6 @@ module dyaml.emitter; import std.algorithm; import std.array; import std.ascii; -import std.container; import std.conv; import std.encoding; import std.exception; diff --git a/source/dyaml/parser.d b/source/dyaml/parser.d index 00b8d3e..d7c03d5 100644 --- a/source/dyaml/parser.d +++ b/source/dyaml/parser.d @@ -13,7 +13,6 @@ module dyaml.parser; import std.algorithm; import std.array; -import std.container; import std.conv; import std.exception; import std.typecons; diff --git a/source/dyaml/scanner.d b/source/dyaml/scanner.d index 58d3efe..f4fa176 100644 --- a/source/dyaml/scanner.d +++ b/source/dyaml/scanner.d @@ -13,7 +13,6 @@ import core.stdc.string; import std.algorithm; import std.array; -import std.container; import std.conv; import std.ascii : isAlphaNum, isDigit, isHexDigit; import std.exception; From 9eb6f314ec60cd849c31c4d403fecc4f2f0a41c2 Mon Sep 17 00:00:00 2001 From: Cameron Ross Date: Sat, 16 Jun 2018 02:20:30 -0300 Subject: [PATCH 6/6] revert emitter copying --- source/dyaml/dumper.d | 2 +- source/dyaml/queue.d | 2 ++ source/dyaml/serializer.d | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/dyaml/dumper.d b/source/dyaml/dumper.d index 15a47c5..f518c0e 100644 --- a/source/dyaml/dumper.d +++ b/source/dyaml/dumper.d @@ -243,7 +243,7 @@ struct Dumper { try { - auto emitter = Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); + auto emitter = new Emitter(stream_, canonical_, indent_, textWidth_, lineBreak_); auto serializer = Serializer(emitter, resolver_, encoding_, explicitStart_, explicitEnd_, YAMLVersion_, tags_); foreach(ref document; documents) diff --git a/source/dyaml/queue.d b/source/dyaml/queue.d index 32069ac..3f090d0 100644 --- a/source/dyaml/queue.d +++ b/source/dyaml/queue.d @@ -95,6 +95,8 @@ public: @disable bool opEquals(ref Queue); @disable int opCmp(ref Queue); + @disable this(this); + ~this() @safe nothrow @nogc { freeStock(); diff --git a/source/dyaml/serializer.d b/source/dyaml/serializer.d index a108008..bb10390 100644 --- a/source/dyaml/serializer.d +++ b/source/dyaml/serializer.d @@ -32,7 +32,7 @@ struct Serializer { private: ///Emitter to emit events produced. - Emitter emitter_; + Emitter* emitter_; ///Resolver used to determine which tags are automaticaly resolvable. Resolver resolver_; @@ -66,7 +66,7 @@ struct Serializer * YAMLVersion = YAML version string. * tagDirectives = Tag directives to emit. */ - this(Emitter emitter, Resolver resolver, Encoding encoding, + this(Emitter* emitter, Resolver resolver, Encoding encoding, const Flag!"explicitStart" explicitStart, const Flag!"explicitEnd" explicitEnd, string YAMLVersion, TagDirective[] tagDirectives) @safe