Node struct enlarged to 40 bytes. There is no significant
slowdown and a slight memory usage increase. Fixed a potential bug in Reader. Tag is now implemented as a zero-terminated string, removing the need for global state. Node opIndex now returns a reference.
This commit is contained in:
parent
6eda5d9d4a
commit
c787531497
2
cdc.d
2
cdc.d
|
@ -226,7 +226,7 @@ void main(string[] args)
|
||||||
case "all": build("debug", "release", "unittest"); break;
|
case "all": build("debug", "release", "unittest"); break;
|
||||||
default:
|
default:
|
||||||
writeln("unknown build target: ", target);
|
writeln("unknown build target: ", target);
|
||||||
writeln("available targets: 'debug', 'release', 'all'");
|
writeln("available targets: 'debug', 'release', 'profile', 'all'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -669,9 +669,9 @@ unittest
|
||||||
Node[] pairs;
|
Node[] pairs;
|
||||||
foreach(long i; 0 .. length)
|
foreach(long i; 0 .. length)
|
||||||
{
|
{
|
||||||
auto pair = (i % 2) ? Pair(Node.rawNode(Node.Value(to!string(i))), Node.rawNode(Node.Value(i)))
|
auto pair = (i % 2) ? Pair(to!string(i), i)
|
||||||
: Pair(Node.rawNode(Node.Value(i)), Node.rawNode(Node.Value(to!string(i))));
|
: Pair(i, to!string(i));
|
||||||
pairs ~= Node.rawNode(Node.Value([pair]));
|
pairs ~= Node([pair]);
|
||||||
}
|
}
|
||||||
return pairs;
|
return pairs;
|
||||||
}
|
}
|
||||||
|
@ -681,8 +681,8 @@ unittest
|
||||||
Node[] pairs;
|
Node[] pairs;
|
||||||
foreach(long i; 0 .. length)
|
foreach(long i; 0 .. length)
|
||||||
{
|
{
|
||||||
auto pair = Pair(Node.rawNode(Node.Value(to!string(i))), Node.rawNode(Node.Value(i)));
|
auto pair = Pair(to!string(i), i);
|
||||||
pairs ~= Node.rawNode(Node.Value([pair]));
|
pairs ~= Node([pair]);
|
||||||
}
|
}
|
||||||
return pairs;
|
return pairs;
|
||||||
}
|
}
|
||||||
|
@ -736,7 +736,7 @@ unittest
|
||||||
Node.Pair[] pairs;
|
Node.Pair[] pairs;
|
||||||
foreach(long i; 0 .. length)
|
foreach(long i; 0 .. length)
|
||||||
{
|
{
|
||||||
pairs ~= Node.Pair(Node.rawNode(Node.Value(to!string(i))), Node.rawNode(Node.Value(YAMLNull())));
|
pairs ~= Node.Pair(to!string(i), YAMLNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
return pairs;
|
return pairs;
|
||||||
|
|
|
@ -632,7 +632,7 @@ struct Node
|
||||||
* non-integral index is used with a sequence or the node is
|
* non-integral index is used with a sequence or the node is
|
||||||
* not a collection.
|
* not a collection.
|
||||||
*/
|
*/
|
||||||
Node opIndex(T)(T index)
|
ref Node opIndex(T)(T index)
|
||||||
{
|
{
|
||||||
if(isSequence)
|
if(isSequence)
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,7 +126,8 @@ final class Reader
|
||||||
}
|
}
|
||||||
available_ = stream_.available;
|
available_ = stream_.available;
|
||||||
|
|
||||||
bufferReserve(256);
|
auto ptr = cast(dchar*)core.stdc.stdlib.malloc(dchar.sizeof * 256);
|
||||||
|
bufferAllocated_ = ptr[0 .. 256];
|
||||||
}
|
}
|
||||||
|
|
||||||
///Destroy the Reader.
|
///Destroy the Reader.
|
||||||
|
|
|
@ -146,22 +146,16 @@ struct Serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors_[node] = Anchor(null);
|
anchors_[node] = Anchor(null);
|
||||||
if(node.isSequence)
|
if(node.isSequence) foreach(ref Node item; node)
|
||||||
{
|
|
||||||
foreach(ref Node item; node)
|
|
||||||
{
|
{
|
||||||
anchorNode(item);
|
anchorNode(item);
|
||||||
}
|
}
|
||||||
}
|
else if(node.isMapping) foreach(ref Node key, ref Node value; node)
|
||||||
else if(node.isMapping)
|
|
||||||
{
|
|
||||||
foreach(ref Node key, ref Node value; node)
|
|
||||||
{
|
{
|
||||||
anchorNode(key);
|
anchorNode(key);
|
||||||
anchorNode(value);
|
anchorNode(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
///Generate and return a new anchor.
|
///Generate and return a new anchor.
|
||||||
Anchor generateAnchor()
|
Anchor generateAnchor()
|
||||||
|
@ -205,7 +199,7 @@ struct Serializer
|
||||||
}
|
}
|
||||||
if(node.isSequence)
|
if(node.isSequence)
|
||||||
{
|
{
|
||||||
auto defaultTag = resolver_.defaultSequenceTag;
|
const defaultTag = resolver_.defaultSequenceTag;
|
||||||
bool implicit = node.tag_ == defaultTag;
|
bool implicit = node.tag_ == defaultTag;
|
||||||
emitter_.emit(sequenceStartEvent(Mark(), Mark(), aliased, node.tag_,
|
emitter_.emit(sequenceStartEvent(Mark(), Mark(), aliased, node.tag_,
|
||||||
implicit, CollectionStyle.Invalid));
|
implicit, CollectionStyle.Invalid));
|
||||||
|
|
|
@ -33,9 +33,7 @@ template SharedObject(T, MixedIn)
|
||||||
*
|
*
|
||||||
* When this reaches zero, objects_ are cleared. This is not
|
* When this reaches zero, objects_ are cleared. This is not
|
||||||
* the number of shared objects, but rather of objects using this kind
|
* the number of shared objects, but rather of objects using this kind
|
||||||
* of shared object. This is used e.g. with Anchor, but not with Tag
|
* of shared object.
|
||||||
* - tags can be stored by the user in Nodes so there is no way to know
|
|
||||||
* when there are no Tags anymore.
|
|
||||||
*/
|
*/
|
||||||
int referenceCount_ = 0;
|
int referenceCount_ = 0;
|
||||||
|
|
||||||
|
@ -124,7 +122,7 @@ template SharedObject(T, MixedIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
///Is this object null (invalid)?
|
///Is this object null (invalid)?
|
||||||
bool isNull() const {return index_ == uint.max;}
|
@property bool isNull() const {return index_ == uint.max;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///Add a new object, checking if identical object already exists.
|
///Add a new object, checking if identical object already exists.
|
||||||
|
|
49
dyaml/tag.d
49
dyaml/tag.d
|
@ -7,24 +7,63 @@
|
||||||
///YAML tag.
|
///YAML tag.
|
||||||
module dyaml.tag;
|
module dyaml.tag;
|
||||||
|
|
||||||
import dyaml.sharedobject;
|
|
||||||
|
import core.stdc.string;
|
||||||
|
|
||||||
|
|
||||||
///YAML tag (data type) struct. Encapsulates a tag to save memory and speed-up comparison.
|
///YAML tag (data type) struct. Encapsulates a tag to save memory and speed-up comparison.
|
||||||
struct Tag
|
struct Tag
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
mixin SharedObject!(string, Tag);
|
///Zero terminated tag string.
|
||||||
|
immutable(char)* tag_ = null;
|
||||||
|
|
||||||
|
public:
|
||||||
///Construct a tag from a string representation.
|
///Construct a tag from a string representation.
|
||||||
this(string tag)
|
this(string tag)
|
||||||
{
|
{
|
||||||
if(tag is null || tag == "")
|
if(tag is null || tag == "")
|
||||||
{
|
{
|
||||||
index_ = uint.max;
|
tag_ = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(tag);
|
tag_ = (tag ~ '\0').ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Get the tag string.
|
||||||
|
@property string get() const
|
||||||
|
in{assert(!isNull());}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return cast(string)tag_[0 .. strlen(tag_)];
|
||||||
|
}
|
||||||
|
|
||||||
|
///Test for equality with another tag.
|
||||||
|
bool opEquals(const ref Tag tag) const
|
||||||
|
{
|
||||||
|
return isNull ? tag.isNull :
|
||||||
|
tag.isNull ? false : (0 == strcmp(tag_, tag.tag_));
|
||||||
|
}
|
||||||
|
|
||||||
|
///Compute a hash.
|
||||||
|
hash_t toHash() const
|
||||||
|
in{assert(!isNull);}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
static type = typeid(string);
|
||||||
|
auto str = get();
|
||||||
|
return type.getHash(&str);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Compare with another tag.
|
||||||
|
int opCmp(const ref Tag tag) const
|
||||||
|
in{assert(!isNull && !tag.isNull);}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return strcmp(tag_, tag.tag_);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Is this tag null (invalid)?
|
||||||
|
@property bool isNull() const {return tag_ is null;}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue