Updated Node for much more constness (unfortunately, quite some
code duplication as well). No longer need a custom Variant.
This commit is contained in:
parent
508696584e
commit
8208e817de
|
@ -29,7 +29,7 @@ links = ../index.html Documentation home
|
||||||
# Source files or patterns to ignore. Supports regexp syntax.
|
# Source files or patterns to ignore. Supports regexp syntax.
|
||||||
# E.g; To ignore main.d and all source files in the test/ directory,
|
# E.g; To ignore main.d and all source files in the test/ directory,
|
||||||
# you would use: "main.d test/*"
|
# you would use: "main.d test/*"
|
||||||
ignore = test/*, examples/*, docsrc/*, autoddoc/*, yaml.d, unittest.d, cdc.d, dyaml/composer.d, dyaml/event.d, dyaml/parser.d, dyaml/reader.d, dyaml/scanner.d, dyaml/token.d, dyaml/util.d, dyaml/anchor.d, dyaml/emitter.d, dyaml/flags.d, dyaml/serializer.d, dyaml/sharedobject.d, dyaml/tag.d, dyaml/tagdirectives.d, dyaml/queue.d, dyaml/escapes.d, dyaml/fastcharsearch.d, dyaml/std/variant.d
|
ignore = test/*, examples/*, docsrc/*, autoddoc/*, yaml.d, unittest.d, cdc.d, dyaml/composer.d, dyaml/event.d, dyaml/parser.d, dyaml/reader.d, dyaml/scanner.d, dyaml/token.d, dyaml/util.d, dyaml/anchor.d, dyaml/emitter.d, dyaml/flags.d, dyaml/serializer.d, dyaml/sharedobject.d, dyaml/tag.d, dyaml/tagdirectives.d, dyaml/queue.d, dyaml/escapes.d, dyaml/fastcharsearch.d
|
||||||
|
|
||||||
[DDOC]
|
[DDOC]
|
||||||
# Command to use to generate the documentation.
|
# Command to use to generate the documentation.
|
||||||
|
|
Binary file not shown.
|
@ -52,6 +52,12 @@
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Null YAML type. Used in nodes with null values.</p>
|
<dd><p>Null YAML type. Used in nodes with null values.</p>
|
||||||
|
|
||||||
|
<dl><dt class="d_decl">const string <a name="toString"></a><span class="ddoc_psymbol">toString</span>();
|
||||||
|
</dt>
|
||||||
|
<dd><p>Used for string conversion.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">struct <a name="Node"></a><span class="ddoc_psymbol">Node</span>;
|
<dt class="d_decl">struct <a name="Node"></a><span class="ddoc_psymbol">Node</span>;
|
||||||
</dt>
|
</dt>
|
||||||
|
@ -80,7 +86,7 @@
|
||||||
<dd><p>Construct a Pair from two values. Will be converted to Nodes if needed.</p>
|
<dd><p>Construct a Pair from two values. Will be converted to Nodes if needed.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">bool <a name="equals"></a><span class="ddoc_psymbol">equals</span>(ref Pair <b>rhs</b>);
|
<dt class="d_decl">const bool <a name="opEquals"></a><span class="ddoc_psymbol">opEquals</span>(ref const Pair <b>rhs</b>);
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Equality test with another Pair.</p>
|
<dd><p>Equality test with another Pair.</p>
|
||||||
|
|
||||||
|
@ -263,7 +269,7 @@
|
||||||
<dd><p>Return <a name="tag"></a><span class="ddoc_psymbol">tag</span> of the node.</p>
|
<dd><p>Return <a name="tag"></a><span class="ddoc_psymbol">tag</span> of the node.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">bool <a name="opEquals"></a><span class="ddoc_psymbol">opEquals</span>(T)(ref T <b>rhs</b>);
|
<dt class="d_decl">const bool <a name="opEquals"></a><span class="ddoc_psymbol">opEquals</span>(T)(ref const T <b>rhs</b>);
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Equality test.
|
<dd><p>Equality test.
|
||||||
</p>
|
</p>
|
||||||
|
@ -337,7 +343,7 @@
|
||||||
the value is out of range of requested type.</div>
|
the value is out of range of requested type.</div>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">@property size_t <a name="length"></a><span class="ddoc_psymbol">length</span>();
|
<dt class="d_decl">const @property size_t <a name="length"></a><span class="ddoc_psymbol">length</span>();
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>If this is a collection, return its length.
|
<dd><p>If this is a collection, return its length.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -138,7 +138,7 @@ struct appears in Phobos.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -368,7 +368,7 @@ directory of the D:YAML package.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -237,7 +237,7 @@ example in the <tt class="docutils literal"><span class="pre">example/getting_st
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -330,7 +330,7 @@ Some of these might change in the future (especially !!map and !!set).</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 29, 2011.
|
Last updated on Oct 30, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
294
dyaml/node.d
294
dyaml/node.d
|
@ -16,11 +16,12 @@ import std.conv;
|
||||||
import std.datetime;
|
import std.datetime;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
import std.math;
|
import std.math;
|
||||||
|
import std.range;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import dyaml.std.variant;
|
import std.variant;
|
||||||
|
|
||||||
import dyaml.event;
|
import dyaml.event;
|
||||||
import dyaml.exception;
|
import dyaml.exception;
|
||||||
|
@ -73,7 +74,7 @@ package abstract class YAMLObject
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///Test for equality with another YAMLObject.
|
///Test for equality with another YAMLObject.
|
||||||
bool equals(YAMLObject rhs) {assert(false);}
|
bool equals(const YAMLObject rhs) const {assert(false);}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stores a user defined YAML data type.
|
//Stores a user defined YAML data type.
|
||||||
|
@ -102,10 +103,10 @@ package class YAMLContainer(T) if (!Node.Value.allowed!T): YAMLObject
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//Test for equality with another YAMLObject.
|
//Test for equality with another YAMLObject.
|
||||||
override bool equals(YAMLObject rhs)
|
override bool equals(const YAMLObject rhs) const
|
||||||
{
|
{
|
||||||
if(rhs.type !is typeid(T)){return false;}
|
if(rhs.type !is typeid(T)){return false;}
|
||||||
return cast(T)value_ == (cast(YAMLContainer)rhs).value_;
|
return cast(T)value_ == (cast(const YAMLContainer)rhs).value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -134,7 +135,6 @@ struct Node
|
||||||
Node value;
|
Node value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@disable bool opEquals(ref Pair);
|
|
||||||
@disable int opCmp(ref Pair);
|
@disable int opCmp(ref Pair);
|
||||||
|
|
||||||
///Construct a Pair from two values. Will be converted to Nodes if needed.
|
///Construct a Pair from two values. Will be converted to Nodes if needed.
|
||||||
|
@ -147,10 +147,10 @@ struct Node
|
||||||
}
|
}
|
||||||
|
|
||||||
///Equality test with another Pair.
|
///Equality test with another Pair.
|
||||||
bool equals(ref Pair rhs)
|
bool opEquals(const ref Pair rhs) const
|
||||||
{
|
{
|
||||||
return equals_!true(rhs);
|
return equals!true(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
|
@ -159,10 +159,10 @@ struct Node
|
||||||
* useTag determines whether or not we consider node tags
|
* useTag determines whether or not we consider node tags
|
||||||
* in the test.
|
* in the test.
|
||||||
*/
|
*/
|
||||||
bool equals_(bool useTag)(ref Pair rhs)
|
bool equals(bool useTag)(ref const(Pair) rhs) const
|
||||||
{
|
{
|
||||||
return key.equals!(Node, useTag)(rhs.key) &&
|
return key.equals!(useTag)(rhs.key) &&
|
||||||
value.equals!(Node, useTag)(rhs.value);
|
value.equals!(useTag)(rhs.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +188,6 @@ struct Node
|
||||||
public:
|
public:
|
||||||
@disable int opCmp(ref Node);
|
@disable int opCmp(ref Node);
|
||||||
|
|
||||||
@disable bool opEquals(T)(ref T) const if(is(T == const));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Node from a value.
|
* Construct a Node from a value.
|
||||||
*
|
*
|
||||||
|
@ -468,9 +466,9 @@ struct Node
|
||||||
*
|
*
|
||||||
* Returns: true if equal, false otherwise.
|
* Returns: true if equal, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool opEquals(T)(ref T rhs) if(!is(T == const))
|
bool opEquals(T)(const ref T rhs) const
|
||||||
{
|
{
|
||||||
return equals!(T, true)(rhs);
|
return equals!true(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Shortcut for get().
|
///Shortcut for get().
|
||||||
|
@ -517,37 +515,23 @@ struct Node
|
||||||
*/
|
*/
|
||||||
@property T get(T)() if(!is(T == const))
|
@property T get(T)() if(!is(T == const))
|
||||||
{
|
{
|
||||||
if(isType!T)
|
if(isType!T){return value_.get!T;}
|
||||||
{
|
|
||||||
return value_.get!T;
|
|
||||||
}
|
|
||||||
|
|
||||||
static if(!Value.allowed!T)
|
///Must go before others, as even string/int/etc could be stored in a YAMLObject.
|
||||||
|
static if(!Value.allowed!T) if(isUserType)
|
||||||
{
|
{
|
||||||
///Must go before others, as even string/int/etc could be stored in a YAMLObject.
|
auto object = as!YAMLObject;
|
||||||
if(isUserType)
|
if(object.type is typeid(T))
|
||||||
{
|
{
|
||||||
auto object = as!YAMLObject;
|
return (cast(YAMLContainer!T)object).value_;
|
||||||
if(object.type is typeid(T))
|
|
||||||
{
|
|
||||||
return (cast(YAMLContainer!T)object).value_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
throw new Error("Node has unexpected type: " ~ object.type.toString ~
|
||||||
|
". Expected: " ~ typeid(T).toString, startMark_);
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we're getting from a mapping and we're not getting Node.Pair[],
|
//If we're getting from a mapping and we're not getting Node.Pair[],
|
||||||
//we're getting the default value.
|
//we're getting the default value.
|
||||||
if(isMapping)
|
if(isMapping){return this["="].as!T;}
|
||||||
{
|
|
||||||
return this["="].as!T;
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwUnexpectedType()
|
|
||||||
{
|
|
||||||
//Can't get the value.
|
|
||||||
throw new Error("Node has unexpected type: " ~ type.toString ~
|
|
||||||
". Expected: " ~ typeid(T).toString, startMark_);
|
|
||||||
}
|
|
||||||
|
|
||||||
static if(isSomeString!T)
|
static if(isSomeString!T)
|
||||||
{
|
{
|
||||||
|
@ -561,46 +545,79 @@ struct Node
|
||||||
throw new Error("Unable to convert node value to string", startMark_);
|
throw new Error("Unable to convert node value to string", startMark_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else static if(isFloatingPoint!T)
|
else
|
||||||
{
|
{
|
||||||
///Can convert int to float.
|
static if(isFloatingPoint!T)
|
||||||
if(isInt())
|
|
||||||
{
|
{
|
||||||
return to!T(value_.get!long);
|
///Can convert int to float.
|
||||||
|
if(isInt()) {return to!T(value_.get!(const long));}
|
||||||
|
else if(isFloat()){return to!T(value_.get!(const real));}
|
||||||
}
|
}
|
||||||
else if(isFloat())
|
else static if(isIntegral!T) if(isInt())
|
||||||
{
|
|
||||||
return to!T(value_.get!real);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throwUnexpectedType();
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else static if(isIntegral!T)
|
|
||||||
{
|
|
||||||
if(isInt())
|
|
||||||
{
|
{
|
||||||
const temp = value_.get!long;
|
const temp = value_.get!(const long);
|
||||||
if(temp < T.min || temp > T.max)
|
enforce(temp >= T.min && temp <= T.max,
|
||||||
{
|
new Error("Integer value of type " ~ typeid(T).toString ~
|
||||||
throw new Error("Integer value out of range of type " ~
|
" out of range. Value: " ~ to!string(temp), startMark_));
|
||||||
typeid(T).toString ~ "Value: " ~ to!string(temp),
|
|
||||||
startMark_);
|
|
||||||
}
|
|
||||||
return to!T(temp);
|
return to!T(temp);
|
||||||
}
|
}
|
||||||
else
|
throw new Error("Node has unexpected type: " ~ type.toString ~
|
||||||
|
". Expected: " ~ typeid(T).toString, startMark_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Const version of get.
|
||||||
|
@property T get(T)() const if(is(T == const))
|
||||||
|
{
|
||||||
|
if(isType!T){return value_.get!T;}
|
||||||
|
|
||||||
|
///Must go before others, as even string/int/etc could be stored in a YAMLObject.
|
||||||
|
static if(!Value.allowed!T) if(isUserType)
|
||||||
|
{
|
||||||
|
auto object = as!(const YAMLObject);
|
||||||
|
if(object.type is typeid(T))
|
||||||
{
|
{
|
||||||
throwUnexpectedType();
|
return (cast(const YAMLContainer!T)object).value_;
|
||||||
assert(false);
|
}
|
||||||
|
throw new Error("Node has unexpected type: " ~ object.type.toString ~
|
||||||
|
". Expected: " ~ typeid(T).toString, startMark_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we're getting from a mapping and we're not getting Node.Pair[],
|
||||||
|
//we're getting the default value.
|
||||||
|
if(isMapping){return indexConst("=").as!T;}
|
||||||
|
|
||||||
|
static if(isSomeString!T)
|
||||||
|
{
|
||||||
|
//Try to convert to string.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//NOTE: We are casting away const here
|
||||||
|
return (cast(Value)value_).coerce!T();
|
||||||
|
}
|
||||||
|
catch(VariantException e)
|
||||||
|
{
|
||||||
|
throw new Error("Unable to convert node value to string", startMark_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwUnexpectedType();
|
static if(isFloatingPoint!T)
|
||||||
assert(false);
|
{
|
||||||
|
///Can convert int to float.
|
||||||
|
if(isInt()) {return to!T(value_.get!(const long));}
|
||||||
|
else if(isFloat()){return to!T(value_.get!(const real));}
|
||||||
|
}
|
||||||
|
else static if(isIntegral!T) if(isInt())
|
||||||
|
{
|
||||||
|
const temp = value_.get!(const long);
|
||||||
|
enforce(temp >= T.min && temp <= T.max,
|
||||||
|
new Error("Integer value of type " ~ typeid(T).toString ~
|
||||||
|
" out of range. Value: " ~ to!string(temp), startMark_));
|
||||||
|
return to!T(temp);
|
||||||
|
}
|
||||||
|
throw new Error("Node has unexpected type: " ~ type.toString ~
|
||||||
|
". Expected: " ~ typeid(T).toString, startMark_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,13 +660,19 @@ struct Node
|
||||||
if(isSequence)
|
if(isSequence)
|
||||||
{
|
{
|
||||||
checkSequenceIndex(index);
|
checkSequenceIndex(index);
|
||||||
static if(isIntegral!T){return value_.get!(Node[])[index];}
|
static if(isIntegral!T)
|
||||||
|
{
|
||||||
|
return cast(Node)value_.get!(Node[])[index];
|
||||||
|
}
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
else if(isMapping)
|
else if(isMapping)
|
||||||
{
|
{
|
||||||
auto idx = findPair(index);
|
auto idx = findPair(index);
|
||||||
if(idx >= 0){return as!(Pair[])[idx].value;}
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
return cast(Node)value_.get!(Pair[])[idx].value;
|
||||||
|
}
|
||||||
|
|
||||||
string msg = "Mapping index not found" ~ (isSomeString!T ? ": " ~ to!string(index) : "");
|
string msg = "Mapping index not found" ~ (isSomeString!T ? ": " ~ to!string(index) : "");
|
||||||
throw new Error(msg, startMark_);
|
throw new Error(msg, startMark_);
|
||||||
|
@ -1141,7 +1164,7 @@ struct Node
|
||||||
*
|
*
|
||||||
* useTag determines whether or not to consider tags in node-node comparisons.
|
* useTag determines whether or not to consider tags in node-node comparisons.
|
||||||
*/
|
*/
|
||||||
bool equals(T, bool useTag)(ref T rhs)
|
bool equals(bool useTag, T)(ref T rhs) const
|
||||||
{
|
{
|
||||||
static if(is(Unqual!T == Node))
|
static if(is(Unqual!T == Node))
|
||||||
{
|
{
|
||||||
|
@ -1155,55 +1178,50 @@ struct Node
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(isSequence)
|
|
||||||
|
static bool compareCollection(T)(const ref Node lhs, const ref Node rhs)
|
||||||
{
|
{
|
||||||
auto seq1 = as!(Node[]);
|
const c1 = lhs.value_.get!(const T);
|
||||||
auto seq2 = rhs.as!(Node[]);
|
const c2 = rhs.value_.get!(const T);
|
||||||
if(seq1 is seq2){return true;}
|
if(c1 is c2){return true;}
|
||||||
if(seq1.length != seq2.length){return false;}
|
if(c1.length != c2.length){return false;}
|
||||||
foreach(node; 0 .. seq1.length)
|
foreach(ref i1, ref i2; lockstep(c1, c2))
|
||||||
{
|
{
|
||||||
if(!seq1[node].equals!(T, useTag)(seq2[node])){return false;}
|
if(!i1.equals!useTag(i2)){return false;}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(isMapping)
|
|
||||||
|
static bool compare(T)(const ref Node lhs, const ref Node rhs)
|
||||||
{
|
{
|
||||||
auto map1 = as!(Node.Pair[]);
|
return lhs.value_.get!(const T) == rhs.value_.get!(const T);
|
||||||
auto map2 = rhs.as!(Node.Pair[]);
|
|
||||||
if(map1 is map2){return true;}
|
|
||||||
if(map1.length != map2.length){return false;}
|
|
||||||
foreach(pair; 0 .. map1.length)
|
|
||||||
{
|
|
||||||
if(!map1[pair].equals_!useTag(map2[pair])){return false;}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if(isScalar)
|
|
||||||
|
if(isSequence) {return compareCollection!(Node[])(this, rhs);}
|
||||||
|
else if(isMapping){return compareCollection!(Pair[])(this, rhs);}
|
||||||
|
else if(isString) {return compare!string(this, rhs);}
|
||||||
|
else if(isInt) {return compare!long(this, rhs);}
|
||||||
|
else if(isBool) {return compare!bool(this, rhs);}
|
||||||
|
else if(isBinary) {return compare!(ubyte[])(this, rhs);}
|
||||||
|
else if(isNull) {return true;}
|
||||||
|
else if(isFloat)
|
||||||
{
|
{
|
||||||
if(isUserType)
|
const r1 = value_.get!(const real);
|
||||||
{
|
const r2 = rhs.value_.get!(const real);
|
||||||
if(!rhs.isUserType){return false;}
|
return isNaN(r1) ? isNaN(r2)
|
||||||
return get!YAMLObject.equals(rhs.as!YAMLObject);
|
: (r1 <= r2 + real.epsilon && r1 >= r2 - real.epsilon);
|
||||||
}
|
|
||||||
if(isFloat)
|
|
||||||
{
|
|
||||||
if(!rhs.isFloat){return false;}
|
|
||||||
real r1 = get!real;
|
|
||||||
real r2 = rhs.get!real;
|
|
||||||
bool equals(real r1, real r2)
|
|
||||||
{
|
|
||||||
return r1 <= r2 + real.epsilon && r1 >= r2 - real.epsilon;
|
|
||||||
}
|
|
||||||
if(isNaN(r1)){return isNaN(r2);}
|
|
||||||
return equals(r1, r2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value_ == rhs.value_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(false, "Unknown kind of node");
|
else if(isTime)
|
||||||
|
{
|
||||||
|
const t1 = value_.get!(const SysTime);
|
||||||
|
const t2 = rhs.value_.get!(const SysTime);
|
||||||
|
return t1 == t2;
|
||||||
|
}
|
||||||
|
else if(isUserType)
|
||||||
|
{
|
||||||
|
return value_.get!(const YAMLObject).equals(rhs.value_.get!(const YAMLObject));
|
||||||
|
}
|
||||||
|
assert(false, "Unknown kind of node (equality comparison) : " ~ type.toString);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1265,15 +1283,27 @@ struct Node
|
||||||
@property bool isType(T)() const {return value_.type is typeid(Unqual!T);}
|
@property bool isType(T)() const {return value_.type is typeid(Unqual!T);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Is the value an integer of some kind?
|
//Is the value a bool?
|
||||||
|
alias isType!bool isBool;
|
||||||
|
|
||||||
|
//Is the value a raw binary buffer?
|
||||||
|
alias isType!(ubyte[]) isBinary;
|
||||||
|
|
||||||
|
//Is the value an integer?
|
||||||
alias isType!long isInt;
|
alias isType!long isInt;
|
||||||
|
|
||||||
//Is the value a floating point number of some kind?
|
//Is the value a floating point number?
|
||||||
alias isType!real isFloat;
|
alias isType!real isFloat;
|
||||||
|
|
||||||
//Is the value a string of some kind?
|
//Is the value a string?
|
||||||
alias isType!string isString;
|
alias isType!string isString;
|
||||||
|
|
||||||
|
//Is the value a timestamp?
|
||||||
|
alias isType!SysTime isTime;
|
||||||
|
|
||||||
|
//Is the value a null value?
|
||||||
|
alias isType!YAMLNull isNull;
|
||||||
|
|
||||||
//Does given node have the same type as this node?
|
//Does given node have the same type as this node?
|
||||||
bool hasEqualType(const ref Node node) const
|
bool hasEqualType(const ref Node node) const
|
||||||
{
|
{
|
||||||
|
@ -1293,11 +1323,11 @@ struct Node
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get index of pair with key (or value, if value is true) matching index.
|
//Get index of pair with key (or value, if value is true) matching index.
|
||||||
long findPair(T, bool value = false)(const ref T index)
|
long findPair(T, bool value = false)(const ref T index) const
|
||||||
{
|
{
|
||||||
auto pairs = as!(Node.Pair[])();
|
const pairs = value_.get!(const Pair[])();
|
||||||
Node* node;
|
const(Node)* node;
|
||||||
foreach(idx, ref pair; pairs)
|
foreach(idx, ref const(Pair) pair; pairs)
|
||||||
{
|
{
|
||||||
static if(value){node = &pair.value;}
|
static if(value){node = &pair.value;}
|
||||||
else{node = &pair.key;}
|
else{node = &pair.key;}
|
||||||
|
@ -1317,7 +1347,7 @@ struct Node
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try if(node.as!T == index){return idx;}
|
try if(node.as!(const T) == index){return idx;}
|
||||||
catch(NodeException e)
|
catch(NodeException e)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -1341,6 +1371,32 @@ struct Node
|
||||||
startMark_));
|
startMark_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Const version of opIndex.
|
||||||
|
ref const(Node) indexConst(T)(T index) const
|
||||||
|
{
|
||||||
|
if(isSequence)
|
||||||
|
{
|
||||||
|
checkSequenceIndex(index);
|
||||||
|
static if(isIntegral!T)
|
||||||
|
{
|
||||||
|
return value_.get!(const Node[])[index];
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
else if(isMapping)
|
||||||
|
{
|
||||||
|
auto idx = findPair(index);
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
return value_.get!(const Pair[])[idx].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string msg = "Mapping index not found" ~ (isSomeString!T ? ": " ~ to!string(index) : "");
|
||||||
|
throw new Error(msg, startMark_);
|
||||||
|
}
|
||||||
|
throw new Error("Trying to index node that does not support indexing", startMark_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
package:
|
package:
|
||||||
|
|
1493
dyaml/std/variant.d
1493
dyaml/std/variant.d
File diff suppressed because it is too large
Load diff
|
@ -403,7 +403,7 @@ void testConstructor(bool verbose, string dataFilename, string codeDummy)
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
foreach(node; loader)
|
foreach(node; loader)
|
||||||
{
|
{
|
||||||
if(!node.equals!(Node, false)(exp[i]))
|
if(!node.equals!false(exp[i]))
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,7 @@ void testRepresenterTypes(bool verbose, string codeFilename)
|
||||||
assert(expectedNodes.length == readNodes.length);
|
assert(expectedNodes.length == readNodes.length);
|
||||||
foreach(n; 0 .. expectedNodes.length)
|
foreach(n; 0 .. expectedNodes.length)
|
||||||
{
|
{
|
||||||
assert(expectedNodes[n].equals!(Node, false)(readNodes[n]));
|
assert(expectedNodes[n].equals!false(readNodes[n]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue