remove zerostring (#94)

remove zerostring
merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
Cameron Ross 2018-02-28 23:20:43 -04:00 committed by The Dlang Bot
parent 72995df864
commit 683335aa3e
15 changed files with 105 additions and 231 deletions

View file

@ -10,7 +10,6 @@ src_dir = include_directories('source/')
pkgc = import('pkgconfig') pkgc = import('pkgconfig')
dyaml_src = [ dyaml_src = [
'source/dyaml/anchor.d',
'source/dyaml/composer.d', 'source/dyaml/composer.d',
'source/dyaml/constructor.d', 'source/dyaml/constructor.d',
'source/dyaml/dumper.d', 'source/dyaml/dumper.d',
@ -36,7 +35,6 @@ dyaml_src = [
'source/dyaml/serializer.d', 'source/dyaml/serializer.d',
'source/dyaml/stream.d', 'source/dyaml/stream.d',
'source/dyaml/style.d', 'source/dyaml/style.d',
'source/dyaml/tag.d',
'source/dyaml/tagdirective.d', 'source/dyaml/tagdirective.d',
'source/dyaml/test/common.d', 'source/dyaml/test/common.d',
'source/dyaml/test/compare.d', 'source/dyaml/test/compare.d',
@ -49,8 +47,7 @@ dyaml_src = [
'source/dyaml/test/resolver.d', 'source/dyaml/test/resolver.d',
'source/dyaml/test/tokens.d', 'source/dyaml/test/tokens.d',
'source/dyaml/token.d', 'source/dyaml/token.d',
'source/dyaml/unused.d', 'source/dyaml/unused.d'
'source/dyaml/zerostring.d'
] ]
install_subdir('source/dyaml', install_dir: 'include/d/yaml/') install_subdir('source/dyaml', install_dir: 'include/d/yaml/')

View file

@ -1,13 +0,0 @@
// Copyright Ferdinand Majerech 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
///YAML anchor.
module dyaml.anchor;
import dyaml.zerostring;
///YAML anchor (reference) struct. Encapsulates an anchor to save memory.
alias ZeroString!"Anchor" Anchor;

View file

@ -17,7 +17,6 @@ import std.conv;
import std.exception; import std.exception;
import std.typecons; import std.typecons;
import dyaml.anchor;
import dyaml.constructor; import dyaml.constructor;
import dyaml.event; import dyaml.event;
import dyaml.exception; import dyaml.exception;
@ -48,7 +47,7 @@ final class Composer
///Constructor constructing YAML values. ///Constructor constructing YAML values.
Constructor constructor_; Constructor constructor_;
///Nodes associated with anchors. Used by YAML aliases. ///Nodes associated with anchors. Used by YAML aliases.
Node[Anchor] anchors_; Node[string] anchors_;
///Used to reduce allocations when creating pair arrays. ///Used to reduce allocations when creating pair arrays.
/// ///
@ -182,14 +181,14 @@ final class Composer
immutable event = parser_.getEvent(); immutable event = parser_.getEvent();
const anchor = event.anchor; const anchor = event.anchor;
enforce((anchor in anchors_) !is null, enforce((anchor in anchors_) !is null,
new ComposerException("Found undefined alias: " ~ anchor.get, new ComposerException("Found undefined alias: " ~ anchor,
event.startMark)); event.startMark));
//If the node referenced by the anchor is uninitialized, //If the node referenced by the anchor is uninitialized,
//it's not finished, i.e. we're currently composing it //it's not finished, i.e. we're currently composing it
//and trying to use it recursively here. //and trying to use it recursively here.
enforce(anchors_[anchor] != Node(), enforce(anchors_[anchor] != Node(),
new ComposerException("Found recursive alias: " ~ anchor.get, new ComposerException("Found recursive alias: " ~ anchor,
event.startMark)); event.startMark));
return anchors_[anchor]; return anchors_[anchor];
@ -197,16 +196,16 @@ final class Composer
immutable event = parser_.peekEvent(); immutable event = parser_.peekEvent();
const anchor = event.anchor; const anchor = event.anchor;
if(!anchor.isNull() && (anchor in anchors_) !is null) if((anchor !is null) && (anchor in anchors_) !is null)
{ {
throw new ComposerException("Found duplicate anchor: " ~ anchor.get, throw new ComposerException("Found duplicate anchor: " ~ anchor,
event.startMark); event.startMark);
} }
Node result; Node result;
//Associate the anchor, if any, with an uninitialized node. //Associate the anchor, if any, with an uninitialized node.
//used to detect duplicate and recursive anchors. //used to detect duplicate and recursive anchors.
if(!anchor.isNull()) if(anchor !is null)
{ {
anchors_[anchor] = Node(); anchors_[anchor] = Node();
} }
@ -225,7 +224,7 @@ final class Composer
} }
else{assert(false, "This code should never be reached");} else{assert(false, "This code should never be reached");}
if(!anchor.isNull()) if(anchor !is null)
{ {
anchors_[anchor] = result; anchors_[anchor] = result;
} }

View file

@ -27,7 +27,6 @@ import std.utf;
import dyaml.node; import dyaml.node;
import dyaml.exception; import dyaml.exception;
import dyaml.tag;
import dyaml.style; import dyaml.style;
@ -67,11 +66,11 @@ final class Constructor
{ {
private: private:
// Constructor functions from scalars. // Constructor functions from scalars.
Node.Value delegate(ref Node)[Tag] fromScalar_; Node.Value delegate(ref Node)[string] fromScalar_;
// Constructor functions from sequences. // Constructor functions from sequences.
Node.Value delegate(ref Node)[Tag] fromSequence_; Node.Value delegate(ref Node)[string] fromSequence_;
// Constructor functions from mappings. // Constructor functions from mappings.
Node.Value delegate(ref Node)[Tag] fromMapping_; Node.Value delegate(ref Node)[string] fromMapping_;
public: public:
/// Construct a Constructor. /// Construct a Constructor.
@ -185,7 +184,7 @@ final class Constructor
void addConstructorScalar(T)(const string tag, T function(ref Node) ctor) void addConstructorScalar(T)(const string tag, T function(ref Node) ctor)
@safe nothrow @safe nothrow
{ {
const t = Tag(tag); const t = tag;
auto deleg = addConstructor!T(t, ctor); auto deleg = addConstructor!T(t, ctor);
(*delegates!string)[t] = deleg; (*delegates!string)[t] = deleg;
} }
@ -236,7 +235,7 @@ final class Constructor
void addConstructorSequence(T)(const string tag, T function(ref Node) ctor) void addConstructorSequence(T)(const string tag, T function(ref Node) ctor)
@safe nothrow @safe nothrow
{ {
const t = Tag(tag); const t = tag;
auto deleg = addConstructor!T(t, ctor); auto deleg = addConstructor!T(t, ctor);
(*delegates!(Node[]))[t] = deleg; (*delegates!(Node[]))[t] = deleg;
} }
@ -287,7 +286,7 @@ final class Constructor
void addConstructorMapping(T)(const string tag, T function(ref Node) ctor) void addConstructorMapping(T)(const string tag, T function(ref Node) ctor)
@safe nothrow @safe nothrow
{ {
const t = Tag(tag); const t = tag;
auto deleg = addConstructor!T(t, ctor); auto deleg = addConstructor!T(t, ctor);
(*delegates!(Node.Pair[]))[t] = deleg; (*delegates!(Node.Pair[]))[t] = deleg;
} }
@ -304,7 +303,7 @@ final class Constructor
* *
* Returns: Constructed node. * Returns: Constructed node.
*/ */
Node node(T, U)(const Mark start, const Mark end, const Tag tag, Node node(T, U)(const Mark start, const Mark end, const string tag,
T value, U style) @trusted T value, U style) @trusted
if((is(T : string) || is(T == Node[]) || is(T == Node.Pair[])) && if((is(T : string) || is(T == Node[]) || is(T == Node.Pair[])) &&
(is(U : CollectionStyle) || is(U : ScalarStyle))) (is(U : CollectionStyle) || is(U : ScalarStyle)))
@ -315,7 +314,7 @@ final class Constructor
"ERROR"; "ERROR";
enforce((tag in *delegates!T) !is null, enforce((tag in *delegates!T) !is null,
new Error("No constructor function from " ~ type ~ new Error("No constructor function from " ~ type ~
" for tag " ~ tag.get(), start, end)); " for tag " ~ tag, start, end));
Node node = Node(value); Node node = Node(value);
try try
@ -346,13 +345,13 @@ final class Constructor
* Params: tag = Tag for the function to handle. * Params: tag = Tag for the function to handle.
* ctor = Constructor function. * ctor = Constructor function.
*/ */
auto addConstructor(T)(const Tag tag, T function(ref Node) ctor) auto addConstructor(T)(const string tag, T function(ref Node) ctor)
@safe nothrow @safe nothrow
{ {
assert((tag in fromScalar_) is null && assert((tag in fromScalar_) is null &&
(tag in fromSequence_) is null && (tag in fromSequence_) is null &&
(tag in fromMapping_) is null, (tag in fromMapping_) is null,
"Constructor function for tag " ~ tag.get ~ " is already " ~ "Constructor function for tag " ~ tag ~ " is already " ~
"specified. Can't specify another one."); "specified. Can't specify another one.");

View file

@ -16,7 +16,6 @@ module dyaml.dumper;
import std.typecons; import std.typecons;
import dyaml.stream; import dyaml.stream;
import dyaml.anchor;
import dyaml.emitter; import dyaml.emitter;
import dyaml.encoding; import dyaml.encoding;
import dyaml.event; import dyaml.event;

View file

@ -24,7 +24,6 @@ import std.typecons;
import std.utf; import std.utf;
import dyaml.stream; import dyaml.stream;
import dyaml.anchor;
import dyaml.encoding; import dyaml.encoding;
import dyaml.escapes; import dyaml.escapes;
import dyaml.event; import dyaml.event;
@ -34,7 +33,6 @@ import dyaml.flags;
import dyaml.linebreak; import dyaml.linebreak;
import dyaml.queue; import dyaml.queue;
import dyaml.style; import dyaml.style;
import dyaml.tag;
import dyaml.tagdirective; import dyaml.tagdirective;
@ -500,7 +498,7 @@ struct Emitter
///Handle an alias. ///Handle an alias.
void expectAlias() @trusted void expectAlias() @trusted
{ {
enforce(!event_.anchor.isNull(), new Error("Anchor is not specified for alias")); enforce(event_.anchor !is null, new Error("Anchor is not specified for alias"));
processAnchor("*"); processAnchor("*");
state_ = popState(); state_ = popState();
} }
@ -707,8 +705,8 @@ struct Emitter
} }
const event = events_.peek(); const event = events_.peek();
const emptyScalar = event.id == EventID.Scalar && event.anchor.isNull() && const emptyScalar = event.id == EventID.Scalar && (event.anchor is null) &&
event.tag.isNull() && event.implicit && event.value == ""; (event.tag is null) && event.implicit && event.value == "";
return emptyScalar; return emptyScalar;
} }
@ -722,7 +720,7 @@ struct Emitter
id == EventID.SequenceStart; id == EventID.SequenceStart;
if((id == EventID.Alias || scalar || collectionStart) if((id == EventID.Alias || scalar || collectionStart)
&& !event_.anchor.isNull()) && (event_.anchor !is null))
{ {
if(preparedAnchor_ is null) if(preparedAnchor_ is null)
{ {
@ -731,7 +729,7 @@ struct Emitter
length += preparedAnchor_.length; length += preparedAnchor_.length;
} }
if((scalar || collectionStart) && !event_.tag.isNull()) if((scalar || collectionStart) && (event_.tag !is null))
{ {
if(preparedTag_ is null){preparedTag_ = prepareTag(event_.tag);} if(preparedTag_ is null){preparedTag_ = prepareTag(event_.tag);}
length += preparedTag_.length; length += preparedTag_.length;
@ -784,7 +782,7 @@ struct Emitter
///Process and write an anchor/alias. ///Process and write an anchor/alias.
void processAnchor(const string indicator) @trusted void processAnchor(const string indicator) @trusted
{ {
if(event_.anchor.isNull()) if(event_.anchor is null)
{ {
preparedAnchor_ = null; preparedAnchor_ = null;
return; return;
@ -804,30 +802,30 @@ struct Emitter
///Process and write a tag. ///Process and write a tag.
void processTag() @trusted void processTag() @trusted
{ {
Tag tag = event_.tag; string tag = event_.tag;
if(event_.id == EventID.Scalar) if(event_.id == EventID.Scalar)
{ {
if(style_ == ScalarStyle.Invalid){style_ = chooseScalarStyle();} if(style_ == ScalarStyle.Invalid){style_ = chooseScalarStyle();}
if((!canonical_ || tag.isNull()) && if((!canonical_ || (tag is null)) &&
(style_ == ScalarStyle.Plain ? event_.implicit : event_.implicit_2)) (style_ == ScalarStyle.Plain ? event_.implicit : event_.implicit_2))
{ {
preparedTag_ = null; preparedTag_ = null;
return; return;
} }
if(event_.implicit && tag.isNull()) if(event_.implicit && (tag is null))
{ {
tag = Tag("!"); tag = "!";
preparedTag_ = null; preparedTag_ = null;
} }
} }
else if((!canonical_ || tag.isNull()) && event_.implicit) else if((!canonical_ || (tag is null)) && event_.implicit)
{ {
preparedTag_ = null; preparedTag_ = null;
return; return;
} }
enforce(!tag.isNull(), new Error("Tag is not specified")); enforce(tag !is null, new Error("Tag is not specified"));
if(preparedTag_ is null){preparedTag_ = prepareTag(tag);} if(preparedTag_ is null){preparedTag_ = prepareTag(tag);}
if(preparedTag_ !is null && preparedTag_ != "") if(preparedTag_ !is null && preparedTag_ != "")
{ {
@ -946,11 +944,11 @@ struct Emitter
} }
///Prepare tag for output. ///Prepare tag for output.
string prepareTag(in Tag tag) @trusted string prepareTag(in string tag) @trusted
{ {
enforce(!tag.isNull(), new Error("Tag must not be empty")); enforce(tag !is null, new Error("Tag must not be empty"));
string tagString = tag.get; string tagString = tag;
if(tagString == "!"){return tagString;} if(tagString == "!"){return tagString;}
string handle = null; string handle = null;
string suffix = tagString; string suffix = tagString;
@ -993,11 +991,11 @@ struct Emitter
} }
///Prepare anchor for output. ///Prepare anchor for output.
static string prepareAnchor(const Anchor anchor) @trusted static string prepareAnchor(const string anchor) @trusted
{ {
enforce(!anchor.isNull() && anchor.get != "", enforce(anchor != "",
new Error("Anchor must not be empty")); new Error("Anchor must not be empty"));
const str = anchor.get; const str = anchor;
foreach(const dchar c; str) foreach(const dchar c; str)
{ {
enforce(isAlphaNum(c) || "-_"d.canFind(c), enforce(isAlphaNum(c) || "-_"d.canFind(c),

View file

@ -14,11 +14,9 @@ import std.array;
import std.conv; import std.conv;
import std.typecons; import std.typecons;
import dyaml.anchor;
import dyaml.encoding; import dyaml.encoding;
import dyaml.exception; import dyaml.exception;
import dyaml.reader; import dyaml.reader;
import dyaml.tag;
import dyaml.tagdirective; import dyaml.tagdirective;
import dyaml.style; import dyaml.style;
@ -60,9 +58,9 @@ struct Event
struct struct
{ {
///Anchor of the event, if any. ///Anchor of the event, if any.
Anchor anchor; string anchor;
///Tag of the event, if any. ///Tag of the event, if any.
Tag tag; string tag;
} }
///Tag directives, if this is a DocumentStart. ///Tag directives, if this is a DocumentStart.
//TagDirectives tagDirectives; //TagDirectives tagDirectives;
@ -96,7 +94,7 @@ struct Event
///Get string representation of the token ID. ///Get string representation of the token ID.
@property string idString() const @system {return to!string(id);} @property string idString() const @system {return to!string(id);}
static assert(Event.sizeof <= 48, "Event struct larger than expected"); static assert(Event.sizeof <= 64, "Event struct larger than expected");
} }
/** /**
@ -106,7 +104,7 @@ struct Event
* end = End position of the event in the file/stream. * end = End position of the event in the file/stream.
* anchor = Anchor, if this is an alias event. * anchor = Anchor, if this is an alias event.
*/ */
Event event(EventID id)(const Mark start, const Mark end, const Anchor anchor = Anchor()) Event event(EventID id)(const Mark start, const Mark end, const string anchor = null)
pure @trusted nothrow pure @trusted nothrow
{ {
Event result; Event result;
@ -127,7 +125,7 @@ Event event(EventID id)(const Mark start, const Mark end, const Anchor anchor =
* implicit = Should the tag be implicitly resolved? * implicit = Should the tag be implicitly resolved?
*/ */
Event collectionStartEvent(EventID id) Event collectionStartEvent(EventID id)
(const Mark start, const Mark end, const Anchor anchor, const Tag tag, (const Mark start, const Mark end, const string anchor, const string tag,
const bool implicit, const CollectionStyle style) pure @trusted nothrow const bool implicit, const CollectionStyle style) pure @trusted nothrow
{ {
static assert(id == EventID.SequenceStart || id == EventID.SequenceEnd || static assert(id == EventID.SequenceStart || id == EventID.SequenceEnd ||
@ -219,7 +217,7 @@ Event documentEndEvent(const Mark start, const Mark end, const bool explicit) pu
/// implicit = Should the tag be implicitly resolved? /// implicit = Should the tag be implicitly resolved?
/// value = String value of the scalar. /// value = String value of the scalar.
/// style = Scalar style. /// style = Scalar style.
Event scalarEvent(const Mark start, const Mark end, const Anchor anchor, const Tag tag, Event scalarEvent(const Mark start, const Mark end, const string anchor, const string tag,
const Tuple!(bool, bool) implicit, const string value, const Tuple!(bool, bool) implicit, const string value,
const ScalarStyle style = ScalarStyle.Invalid) @safe pure nothrow @nogc const ScalarStyle style = ScalarStyle.Invalid) @safe pure nothrow @nogc
{ {

View file

@ -25,8 +25,6 @@ import std.variant;
import dyaml.event; import dyaml.event;
import dyaml.exception; import dyaml.exception;
import dyaml.style; import dyaml.style;
import dyaml.tag;
/// Exception thrown at node related errors. /// Exception thrown at node related errors.
class NodeException : YAMLException class NodeException : YAMLException
@ -212,14 +210,14 @@ struct Node
package: package:
// Tag of the node. // Tag of the node.
Tag tag_; string tag_;
// Node scalar style. Used to remember style this node was loaded with. // Node scalar style. Used to remember style this node was loaded with.
ScalarStyle scalarStyle = ScalarStyle.Invalid; ScalarStyle scalarStyle = ScalarStyle.Invalid;
// Node collection style. Used to remember style this node was loaded with. // Node collection style. Used to remember style this node was loaded with.
CollectionStyle collectionStyle = CollectionStyle.Invalid; CollectionStyle collectionStyle = CollectionStyle.Invalid;
static assert(Value.sizeof <= 24, "Unexpected YAML value size"); static assert(Value.sizeof <= 24, "Unexpected YAML value size");
static assert(Node.sizeof <= 48, "Unexpected YAML node size"); static assert(Node.sizeof <= 56, "Unexpected YAML node size");
// If scalarCtorNothrow!T is true, scalar node ctor from T can be nothrow. // If scalarCtorNothrow!T is true, scalar node ctor from T can be nothrow.
// //
@ -253,7 +251,7 @@ struct Node
this(T)(T value, const string tag = null) @trusted this(T)(T value, const string tag = null) @trusted
if(!scalarCtorNothrow!T && (!isArray!T && !isAssociativeArray!T)) if(!scalarCtorNothrow!T && (!isArray!T && !isAssociativeArray!T))
{ {
tag_ = Tag(tag); tag_ = tag;
// No copyconstruction. // No copyconstruction.
static assert(!is(Unqual!T == Node)); static assert(!is(Unqual!T == Node));
@ -270,7 +268,7 @@ struct Node
this(T)(T value, const string tag = null) @trusted pure nothrow this(T)(T value, const string tag = null) @trusted pure nothrow
if(scalarCtorNothrow!T) if(scalarCtorNothrow!T)
{ {
tag_ = Tag(tag); tag_ = tag;
// We can easily store ints, floats, strings. // We can easily store ints, floats, strings.
static if(isIntegral!T) { value_ = Value(cast(long)value); } static if(isIntegral!T) { value_ = Value(cast(long)value); }
else static if(is(Unqual!T==bool)){ value_ = Value(cast(bool)value); } else static if(is(Unqual!T==bool)){ value_ = Value(cast(bool)value); }
@ -326,7 +324,7 @@ struct Node
this(T)(T[] array, const string tag = null) @trusted this(T)(T[] array, const string tag = null) @trusted
if (!isSomeString!(T[])) if (!isSomeString!(T[]))
{ {
tag_ = Tag(tag); tag_ = tag;
// Construction from raw node or pair array. // Construction from raw node or pair array.
static if(is(Unqual!T == Node) || is(Unqual!T == Node.Pair)) static if(is(Unqual!T == Node) || is(Unqual!T == Node.Pair))
@ -389,7 +387,7 @@ struct Node
*/ */
this(K, V)(V[K] array, const string tag = null) @trusted this(K, V)(V[K] array, const string tag = null) @trusted
{ {
tag_ = Tag(tag); tag_ = tag;
Node.Pair[] pairs; Node.Pair[] pairs;
foreach(key, ref value; array){pairs ~= Pair(key, value);} foreach(key, ref value; array){pairs ~= Pair(key, value);}
@ -461,7 +459,7 @@ struct Node
} }
body body
{ {
tag_ = Tag(tag); tag_ = tag;
Node.Pair[] pairs; Node.Pair[] pairs;
foreach(i; 0 .. keys.length){pairs ~= Pair(keys[i], values[i]);} foreach(i; 0 .. keys.length){pairs ~= Pair(keys[i], values[i]);}
@ -521,7 +519,7 @@ struct Node
} }
/// Return tag of the node. /// Return tag of the node.
@property string tag() const @safe nothrow {return tag_.get;} @property string tag() const @safe nothrow {return tag_;}
/** Equality test. /** Equality test.
* *
@ -1634,9 +1632,9 @@ struct Node
} }
// Compute hash of the node. // Compute hash of the node.
hash_t toHash() @safe nothrow const hash_t toHash() nothrow const
{ {
const tagHash = tag_.isNull ? 0 : tag_.toHash(); const tagHash = (tag_ is null) ? 0 : tag_.hashOf();
// Variant toHash is not const at the moment, so we need to const-cast. // Variant toHash is not const at the moment, so we need to const-cast.
return tagHash + value_.toHash(); return tagHash + value_.toHash();
} }
@ -1655,7 +1653,7 @@ struct Node
// collectionStyle = Collection style of the node. // collectionStyle = Collection style of the node.
// //
// Returns: Constructed node. // Returns: Constructed node.
static Node rawNode(Value value, const Mark startMark, const Tag tag, static Node rawNode(Value value, const Mark startMark, const string tag,
const ScalarStyle scalarStyle, const ScalarStyle scalarStyle,
const CollectionStyle collectionStyle) @trusted const CollectionStyle collectionStyle) @trusted
{ {
@ -1739,8 +1737,8 @@ struct Node
// Compare tags - if equal or both null, we need to compare further. // Compare tags - if equal or both null, we need to compare further.
static if(useTag) static if(useTag)
{ {
const tagCmp = tag_.isNull ? rhs.tag_.isNull ? 0 : -1 const tagCmp = (tag_ is null) ? (rhs.tag_ is null) ? 0 : -1
: rhs.tag_.isNull ? 1 : tag_.opCmp(rhs.tag_); : (rhs.tag_ is null) ? 1 : std.algorithm.comparison.cmp(tag_, rhs.tag_);
if(tagCmp != 0){return tagCmp;} if(tagCmp != 0){return tagCmp;}
} }

View file

@ -18,13 +18,11 @@ import std.conv;
import std.exception; import std.exception;
import std.typecons; import std.typecons;
import dyaml.anchor;
import dyaml.event; import dyaml.event;
import dyaml.exception; import dyaml.exception;
import dyaml.scanner; import dyaml.scanner;
import dyaml.style; import dyaml.style;
import dyaml.token; import dyaml.token;
import dyaml.tag;
import dyaml.tagdirective; import dyaml.tagdirective;
@ -423,7 +421,7 @@ final class Parser
const token = scanner_.getToken(); const token = scanner_.getToken();
state_ = popState(); state_ = popState();
return aliasEvent(token.startMark, token.endMark, return aliasEvent(token.startMark, token.endMark,
Anchor(cast(string)token.value)); cast(string)token.value);
} }
string anchor = null; string anchor = null;
@ -467,8 +465,8 @@ final class Parser
{ {
state_ = &parseIndentlessSequenceEntry; state_ = &parseIndentlessSequenceEntry;
return sequenceStartEvent return sequenceStartEvent
(startMark, scanner_.peekToken().endMark, Anchor(anchor), (startMark, scanner_.peekToken().endMark, anchor,
Tag(tag), implicit, CollectionStyle.Block); tag, implicit, CollectionStyle.Block);
} }
if(scanner_.checkToken(TokenID.Scalar)) if(scanner_.checkToken(TokenID.Scalar))
@ -481,7 +479,7 @@ final class Parser
implicit = (token.style == ScalarStyle.Plain && tag is null) || tag == "!"; implicit = (token.style == ScalarStyle.Plain && tag is null) || tag == "!";
bool implicit_2 = (!implicit) && tag is null; bool implicit_2 = (!implicit) && tag is null;
state_ = popState(); state_ = popState();
return scalarEvent(startMark, token.endMark, Anchor(anchor), Tag(tag), return scalarEvent(startMark, token.endMark, anchor, tag,
tuple(implicit, implicit_2), value, token.style); tuple(implicit, implicit_2), value, token.style);
} }
@ -489,7 +487,7 @@ final class Parser
{ {
endMark = scanner_.peekToken().endMark; endMark = scanner_.peekToken().endMark;
state_ = &parseFlowSequenceEntry!(Yes.first); state_ = &parseFlowSequenceEntry!(Yes.first);
return sequenceStartEvent(startMark, endMark, Anchor(anchor), Tag(tag), return sequenceStartEvent(startMark, endMark, anchor, tag,
implicit, CollectionStyle.Flow); implicit, CollectionStyle.Flow);
} }
@ -497,7 +495,7 @@ final class Parser
{ {
endMark = scanner_.peekToken().endMark; endMark = scanner_.peekToken().endMark;
state_ = &parseFlowMappingKey!(Yes.first); state_ = &parseFlowMappingKey!(Yes.first);
return mappingStartEvent(startMark, endMark, Anchor(anchor), Tag(tag), return mappingStartEvent(startMark, endMark, anchor, tag,
implicit, CollectionStyle.Flow); implicit, CollectionStyle.Flow);
} }
@ -505,7 +503,7 @@ final class Parser
{ {
endMark = scanner_.peekToken().endMark; endMark = scanner_.peekToken().endMark;
state_ = &parseBlockSequenceEntry!(Yes.first); state_ = &parseBlockSequenceEntry!(Yes.first);
return sequenceStartEvent(startMark, endMark, Anchor(anchor), Tag(tag), return sequenceStartEvent(startMark, endMark, anchor, tag,
implicit, CollectionStyle.Block); implicit, CollectionStyle.Block);
} }
@ -513,11 +511,11 @@ final class Parser
{ {
endMark = scanner_.peekToken().endMark; endMark = scanner_.peekToken().endMark;
state_ = &parseBlockMappingKey!(Yes.first); state_ = &parseBlockMappingKey!(Yes.first);
return mappingStartEvent(startMark, endMark, Anchor(anchor), Tag(tag), return mappingStartEvent(startMark, endMark, anchor, tag,
implicit, CollectionStyle.Block); implicit, CollectionStyle.Block);
} }
if(anchor != null || tag !is null) if(anchor !is null || tag !is null)
{ {
state_ = popState(); state_ = popState();
@ -525,7 +523,7 @@ final class Parser
//but the second bool is never used after that - so we don't use it. //but the second bool is never used after that - so we don't use it.
//Empty scalars are allowed even if a tag or an anchor is specified. //Empty scalars are allowed even if a tag or an anchor is specified.
return scalarEvent(startMark, endMark, Anchor(anchor), Tag(tag), return scalarEvent(startMark, endMark, anchor, tag,
tuple(implicit, false) , ""); tuple(implicit, false) , "");
} }
@ -815,7 +813,7 @@ final class Parser
const token = scanner_.peekToken(); const token = scanner_.peekToken();
state_ = &parseFlowSequenceEntryMappingKey; state_ = &parseFlowSequenceEntryMappingKey;
return mappingStartEvent(token.startMark, token.endMark, return mappingStartEvent(token.startMark, token.endMark,
Anchor(), Tag(), true, CollectionStyle.Flow); null, null, true, CollectionStyle.Flow);
} }
else if(!scanner_.checkToken(TokenID.FlowSequenceEnd)) else if(!scanner_.checkToken(TokenID.FlowSequenceEnd))
{ {
@ -952,6 +950,6 @@ final class Parser
///Return an empty scalar. ///Return an empty scalar.
Event processEmptyScalar(const Mark mark) @safe pure nothrow const @nogc Event processEmptyScalar(const Mark mark) @safe pure nothrow const @nogc
{ {
return scalarEvent(mark, mark, Anchor(), Tag(), tuple(true, false), ""); return scalarEvent(mark, mark, null, null, tuple(true, false), "");
} }
} }

View file

@ -29,7 +29,6 @@ import dyaml.exception;
import dyaml.node; import dyaml.node;
import dyaml.serializer; import dyaml.serializer;
import dyaml.style; import dyaml.style;
import dyaml.tag;
///Exception thrown on Representer errors. ///Exception thrown on Representer errors.
@ -277,7 +276,7 @@ final class Representer
ScalarStyle style = ScalarStyle.Invalid) @trusted ScalarStyle style = ScalarStyle.Invalid) @trusted
{ {
if(style == ScalarStyle.Invalid){style = defaultScalarStyle_;} if(style == ScalarStyle.Invalid){style = defaultScalarStyle_;}
return Node.rawNode(Node.Value(scalar), Mark(), Tag(tag), style, return Node.rawNode(Node.Value(scalar), Mark(), tag, style,
CollectionStyle.Invalid); CollectionStyle.Invalid);
} }
@ -346,7 +345,7 @@ final class Representer
? defaultCollectionStyle_ ? defaultCollectionStyle_
: bestStyle; : bestStyle;
} }
return Node.rawNode(Node.Value(value), Mark(), Tag(tag), return Node.rawNode(Node.Value(value), Mark(), tag,
ScalarStyle.Invalid, style); ScalarStyle.Invalid, style);
} }
@ -423,7 +422,7 @@ final class Representer
? defaultCollectionStyle_ ? defaultCollectionStyle_
: bestStyle; : bestStyle;
} }
return Node.rawNode(Node.Value(value), Mark(), Tag(tag), return Node.rawNode(Node.Value(value), Mark(), tag,
ScalarStyle.Invalid, style); ScalarStyle.Invalid, style);
} }
@ -440,7 +439,7 @@ final class Representer
Node result = representers_[type](data, this); Node result = representers_[type](data, this);
//Override tag if specified. //Override tag if specified.
if(!data.tag_.isNull()){result.tag_ = data.tag_;} if(data.tag_ !is null){result.tag_ = data.tag_;}
//Remember style if this was loaded before. //Remember style if this was loaded before.
if(data.scalarStyle != ScalarStyle.Invalid) if(data.scalarStyle != ScalarStyle.Invalid)
@ -527,7 +526,7 @@ Node representSysTime(ref Node node, Representer representer) @system
Node representNodes(ref Node node, Representer representer) @safe Node representNodes(ref Node node, Representer representer) @safe
{ {
auto nodes = node.as!(Node[]); auto nodes = node.as!(Node[]);
if(node.tag_ == Tag("tag:yaml.org,2002:set")) if(node.tag_ == "tag:yaml.org,2002:set")
{ {
///YAML sets are mapping with null values. ///YAML sets are mapping with null values.
Node.Pair[] pairs; Node.Pair[] pairs;
@ -537,7 +536,7 @@ Node representNodes(ref Node node, Representer representer) @safe
{ {
pairs[idx] = Node.Pair(key, representNull(dummy, representer)); pairs[idx] = Node.Pair(key, representNull(dummy, representer));
} }
return representer.representMapping(node.tag_.get, pairs); return representer.representMapping(node.tag_, pairs);
} }
else else
{ {
@ -574,15 +573,15 @@ Node representPairs(ref Node node, Representer representer) @system
return nodes; return nodes;
} }
if(node.tag_ == Tag("tag:yaml.org,2002:omap")) if(node.tag_ == "tag:yaml.org,2002:omap")
{ {
enforce(!hasDuplicates(pairs), enforce(!hasDuplicates(pairs),
new RepresenterException("Duplicate entry in an ordered map")); new RepresenterException("Duplicate entry in an ordered map"));
return representer.representSequence(node.tag_.get, mapToSequence(pairs)); return representer.representSequence(node.tag_, mapToSequence(pairs));
} }
else if(node.tag_ == Tag("tag:yaml.org,2002:pairs")) else if(node.tag_ == "tag:yaml.org,2002:pairs")
{ {
return representer.representSequence(node.tag_.get, mapToSequence(pairs)); return representer.representSequence(node.tag_, mapToSequence(pairs));
} }
else else
{ {

View file

@ -23,7 +23,6 @@ import std.utf;
import dyaml.node; import dyaml.node;
import dyaml.exception; import dyaml.exception;
import dyaml.tag;
/** /**
@ -35,11 +34,11 @@ final class Resolver
{ {
private: private:
// Default tag to use for scalars. // Default tag to use for scalars.
Tag defaultScalarTag_; string defaultScalarTag_;
// Default tag to use for sequences. // Default tag to use for sequences.
Tag defaultSequenceTag_; string defaultSequenceTag_;
// Default tag to use for mappings. // Default tag to use for mappings.
Tag defaultMappingTag_; string defaultMappingTag_;
/* /*
* Arrays of scalar resolver tuples indexed by starting character of a scalar. * Arrays of scalar resolver tuples indexed by starting character of a scalar.
@ -47,7 +46,7 @@ final class Resolver
* Each tuple stores regular expression the scalar must match, * Each tuple stores regular expression the scalar must match,
* and tag to assign to it if it matches. * and tag to assign to it if it matches.
*/ */
Tuple!(Tag, Regex!char)[][dchar] yamlImplicitResolvers_; Tuple!(string, Regex!char)[][dchar] yamlImplicitResolvers_;
public: public:
@disable bool opEquals(ref Resolver); @disable bool opEquals(ref Resolver);
@ -64,9 +63,9 @@ final class Resolver
this(Flag!"useDefaultImplicitResolvers" defaultImplicitResolvers = Yes.useDefaultImplicitResolvers) this(Flag!"useDefaultImplicitResolvers" defaultImplicitResolvers = Yes.useDefaultImplicitResolvers)
@safe @safe
{ {
defaultScalarTag_ = Tag("tag:yaml.org,2002:str"); defaultScalarTag_ = "tag:yaml.org,2002:str";
defaultSequenceTag_ = Tag("tag:yaml.org,2002:seq"); defaultSequenceTag_ = "tag:yaml.org,2002:seq";
defaultMappingTag_ = Tag("tag:yaml.org,2002:map"); defaultMappingTag_ = "tag:yaml.org,2002:map";
if(defaultImplicitResolvers){addImplicitResolvers();} if(defaultImplicitResolvers){addImplicitResolvers();}
} }
@ -125,7 +124,7 @@ final class Resolver
{ {
yamlImplicitResolvers_[c] = []; yamlImplicitResolvers_[c] = [];
} }
yamlImplicitResolvers_[c] ~= tuple(Tag(tag), regexp); yamlImplicitResolvers_[c] ~= tuple(tag, regexp);
} }
} }
@ -143,10 +142,10 @@ final class Resolver
* *
* Returns: Resolved tag. * Returns: Resolved tag.
*/ */
Tag resolve(const NodeID kind, const Tag tag, const string value, string resolve(const NodeID kind, const string tag, const string value,
const bool implicit) @safe const bool implicit) @safe
{ {
if(!tag.isNull() && tag.get() != "!"){return tag;} if((tag !is null) && tag != "!"){return tag;}
if(kind == NodeID.Scalar) if(kind == NodeID.Scalar)
{ {
@ -178,10 +177,10 @@ final class Resolver
bool tagMatch(string tag, string[] values) bool tagMatch(string tag, string[] values)
{ {
Tag expected = Tag(tag); string expected = tag;
foreach(value; values) foreach(value; values)
{ {
Tag resolved = resolver.resolve(NodeID.Scalar, Tag(), value, true); string resolved = resolver.resolve(NodeID.Scalar, null, value, true);
if(expected != resolved) if(expected != resolved)
{ {
return false; return false;
@ -213,13 +212,13 @@ final class Resolver
} }
///Return default scalar tag. ///Return default scalar tag.
@property Tag defaultScalarTag() const pure @safe nothrow {return defaultScalarTag_;} @property string defaultScalarTag() const pure @safe nothrow {return defaultScalarTag_;}
///Return default sequence tag. ///Return default sequence tag.
@property Tag defaultSequenceTag() const pure @safe nothrow {return defaultSequenceTag_;} @property string defaultSequenceTag() const pure @safe nothrow {return defaultSequenceTag_;}
///Return default mapping tag. ///Return default mapping tag.
@property Tag defaultMappingTag() const pure @safe nothrow {return defaultMappingTag_;} @property string defaultMappingTag() const pure @safe nothrow {return defaultMappingTag_;}
private: private:
// Add default implicit resolvers. // Add default implicit resolvers.

View file

@ -15,14 +15,12 @@ import std.array;
import std.format; import std.format;
import std.typecons; import std.typecons;
import dyaml.anchor;
import dyaml.emitter; import dyaml.emitter;
import dyaml.encoding; import dyaml.encoding;
import dyaml.event; import dyaml.event;
import dyaml.exception; import dyaml.exception;
import dyaml.node; import dyaml.node;
import dyaml.resolver; import dyaml.resolver;
import dyaml.tag;
import dyaml.tagdirective; import dyaml.tagdirective;
import dyaml.token; import dyaml.token;
@ -50,7 +48,7 @@ struct Serializer
//TODO Use something with more deterministic memory usage. //TODO Use something with more deterministic memory usage.
///Nodes with assigned anchors. ///Nodes with assigned anchors.
Anchor[Node] anchors_; string[Node] anchors_;
///Nodes with assigned anchors that are already serialized. ///Nodes with assigned anchors that are already serialized.
bool[Node] serializedNodes_; bool[Node] serializedNodes_;
///ID of the last anchor generated. ///ID of the last anchor generated.
@ -105,7 +103,7 @@ struct Serializer
emitter_.emit(documentEndEvent(Mark(), Mark(), explicitEnd_)); emitter_.emit(documentEndEvent(Mark(), Mark(), explicitEnd_));
serializedNodes_.destroy(); serializedNodes_.destroy();
anchors_.destroy(); anchors_.destroy();
Anchor[Node] emptyAnchors; string[Node] emptyAnchors;
anchors_ = emptyAnchors; anchors_ = emptyAnchors;
lastAnchorID_ = 0; lastAnchorID_ = 0;
} }
@ -139,14 +137,14 @@ struct Serializer
if((node in anchors_) !is null) if((node in anchors_) !is null)
{ {
if(anchors_[node].isNull()) if(anchors_[node] is null)
{ {
anchors_[node] = generateAnchor(); anchors_[node] = generateAnchor();
} }
return; return;
} }
anchors_[node] = Anchor(null); anchors_[node] = null;
if(node.isSequence) foreach(ref Node item; node) if(node.isSequence) foreach(ref Node item; node)
{ {
anchorNode(item); anchorNode(item);
@ -159,12 +157,12 @@ struct Serializer
} }
///Generate and return a new anchor. ///Generate and return a new anchor.
Anchor generateAnchor() @trusted string generateAnchor() @trusted
{ {
++lastAnchorID_; ++lastAnchorID_;
auto appender = appender!string(); auto appender = appender!string();
formattedWrite(appender, "id%03d", lastAnchorID_); formattedWrite(appender, "id%03d", lastAnchorID_);
return Anchor(appender.data); return appender.data;
} }
///Serialize a node and all its subnodes. ///Serialize a node and all its subnodes.
@ -173,7 +171,7 @@ struct Serializer
//If the node has an anchor, emit an anchor (as aliasEvent) on the //If the node has an anchor, emit an anchor (as aliasEvent) on the
//first occurrence, save it in serializedNodes_, and emit an alias //first occurrence, save it in serializedNodes_, and emit an alias
//if it reappears. //if it reappears.
Anchor aliased = Anchor(null); string aliased = null;
if(anchorable(node) && (node in anchors_) !is null) if(anchorable(node) && (node in anchors_) !is null)
{ {
aliased = anchors_[node]; aliased = anchors_[node];
@ -189,8 +187,8 @@ struct Serializer
{ {
assert(node.isType!string, "Scalar node type must be string before serialized"); assert(node.isType!string, "Scalar node type must be string before serialized");
auto value = node.as!string; auto value = node.as!string;
const detectedTag = resolver_.resolve(NodeID.Scalar, Tag(null), value, true); const detectedTag = resolver_.resolve(NodeID.Scalar, null, value, true);
const defaultTag = resolver_.resolve(NodeID.Scalar, Tag(null), value, false); const defaultTag = resolver_.resolve(NodeID.Scalar, null, value, false);
bool isDetected = node.tag_ == detectedTag; bool isDetected = node.tag_ == detectedTag;
bool isDefault = node.tag_ == defaultTag; bool isDefault = node.tag_ == defaultTag;

View file

@ -1,13 +0,0 @@
// Copyright Ferdinand Majerech 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
///YAML tag.
module dyaml.tag;
import dyaml.zerostring;
///YAML tag (data type) struct. Encapsulates a tag to save memory and speed up comparison.
alias ZeroString!"Tag" Tag;

View file

@ -16,7 +16,6 @@ import std.path;
import std.string; import std.string;
import std.typecons; import std.typecons;
import dyaml.tag;
import dyaml.test.common; import dyaml.test.common;

View file

@ -1,81 +0,0 @@
// Copyright Ferdinand Majerech 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
///Zero terminated string.
module dyaml.zerostring;
import core.stdc.string;
/**
* Zero terminated string used to decrease data structure size.
*
* TypeName is used to differentiate types (better than simple alias).
*/
struct ZeroString(string TypeName)
{
private:
///Zero terminated string.
immutable(char)* str_ = null;
public:
@disable int opCmp(ref ZeroString);
///Construct a string.
this(const string str) pure nothrow @trusted
{
if(str is null || str == "")
{
str_ = null;
return;
}
str_ = &(str ~ '\0')[0];
}
///Get the string.
@property string get() const nothrow @trusted
in{assert(!isNull());}
body
{
return cast(string)str_[0 .. strlen(str_)];
}
///Test for equality with another string.
bool opEquals(const ZeroString str) const nothrow @trusted
{
return isNull ? str.isNull :
str.isNull ? false : (0 == strcmp(str_, str.str_));
}
///Compute a hash.
hash_t toHash() const nothrow @safe
in{assert(!isNull);}
body
{
auto str = get();
return getHash(str);
}
///Compare with another string.
int opCmp(const ref ZeroString str) const nothrow @trusted
in{assert(!isNull && !str.isNull);}
body
{
return strcmp(str_, str.str_);
}
///Is this string null (invalid)?
@property bool isNull() pure const nothrow @safe {return str_ is null;}
private:
///Hack to allow toHash to be @safe.
//
//To remove this hack, need a typeid(string).getHash() replacement that does not take a pointer.
hash_t getHash(ref string str) const nothrow @trusted
{
return typeid(string).getHash(&str);
}
}