Merge Node constructors (#146)
Merge Node constructors merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
parent
28a61180bf
commit
5757869e9a
|
@ -203,14 +203,6 @@ struct Node
|
||||||
static assert(Value.sizeof <= 24, "Unexpected YAML value size");
|
static assert(Value.sizeof <= 24, "Unexpected YAML value size");
|
||||||
static assert(Node.sizeof <= 56, "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.
|
|
||||||
//
|
|
||||||
// TODO
|
|
||||||
// Eventually we should simplify this and make all Node constructors except from
|
|
||||||
// user values nothrow (and think even about those user values). 2014-08-28
|
|
||||||
enum scalarCtorNothrow(T) =
|
|
||||||
(is(Unqual!T == string) || isIntegral!T || isFloatingPoint!T) || is(Unqual!T == bool) ||
|
|
||||||
(Value.allowed!T && (!is(Unqual!T == Value) && !isSomeString!T && !isArray!T && !isAssociativeArray!T));
|
|
||||||
public:
|
public:
|
||||||
/** Construct a Node from a value.
|
/** Construct a Node from a value.
|
||||||
*
|
*
|
||||||
|
@ -219,6 +211,12 @@ struct Node
|
||||||
* more efficiently. To create a node representing a null value,
|
* more efficiently. To create a node representing a null value,
|
||||||
* construct it from YAMLNull.
|
* construct it from YAMLNull.
|
||||||
*
|
*
|
||||||
|
* If value is a node, its value will be copied directly. The tag and
|
||||||
|
* other information attached to the original node will be discarded.
|
||||||
|
*
|
||||||
|
* If value is an array of nodes or pairs, it is stored directly.
|
||||||
|
* Otherwise, every value in the array is converted to a node, and
|
||||||
|
* those nodes are stored.
|
||||||
*
|
*
|
||||||
* Note that to emit any non-default types you store
|
* Note that to emit any non-default types you store
|
||||||
* in a node, you need a Representer to represent them in YAML -
|
* in a node, you need a Representer to represent them in YAML -
|
||||||
|
@ -233,39 +231,127 @@ struct Node
|
||||||
* a shortcut, like "!!int".
|
* a shortcut, like "!!int".
|
||||||
*/
|
*/
|
||||||
this(T)(T value, const string tag = null)
|
this(T)(T value, const string tag = null)
|
||||||
if(!scalarCtorNothrow!T && (!isArray!T && !isAssociativeArray!T))
|
|
||||||
{
|
{
|
||||||
tag_ = tag;
|
tag_ = tag;
|
||||||
|
|
||||||
// No copyconstruction.
|
//Unlike with assignment, we're just copying the value.
|
||||||
static assert(!is(Unqual!T == Node));
|
static if (is(Unqual!T == Node))
|
||||||
|
{
|
||||||
enum unexpectedType = "Unexpected type in the non-nothrow YAML node constructor";
|
setValue(value.value_);
|
||||||
static if(isSomeString!T) { setValue(value.to!string); }
|
}
|
||||||
else static if(is(Unqual!T == Value)) { setValue(value); }
|
else static if(isSomeString!T)
|
||||||
else static if(Value.allowed!T) { static assert(false, unexpectedType); }
|
{
|
||||||
|
setValue(value.to!string);
|
||||||
|
}
|
||||||
|
else static if(is(Unqual!T == bool))
|
||||||
|
{
|
||||||
|
setValue(cast(bool)value);
|
||||||
|
}
|
||||||
|
else static if(isIntegral!T)
|
||||||
|
{
|
||||||
|
setValue(cast(long)value);
|
||||||
|
}
|
||||||
|
else static if(isFloatingPoint!T)
|
||||||
|
{
|
||||||
|
setValue(cast(real)value);
|
||||||
|
}
|
||||||
|
else static if (isArray!T)
|
||||||
|
{
|
||||||
|
alias ElementT = Unqual!(ElementType!T);
|
||||||
|
// Construction from raw node or pair array.
|
||||||
|
static if(is(ElementT == Node) || is(ElementT == Node.Pair))
|
||||||
|
{
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
// Need to handle byte buffers separately.
|
||||||
|
else static if(is(ElementT == byte) || is(ElementT == ubyte))
|
||||||
|
{
|
||||||
|
setValue(cast(ubyte[]) value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Node[] nodes;
|
||||||
|
foreach(ref v; value)
|
||||||
|
{
|
||||||
|
nodes ~= Node(v);
|
||||||
|
}
|
||||||
|
setValue(nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else static if (isAssociativeArray!T)
|
||||||
|
{
|
||||||
|
Node.Pair[] pairs;
|
||||||
|
foreach(k, ref v; value)
|
||||||
|
{
|
||||||
|
pairs ~= Pair(k, v);
|
||||||
|
}
|
||||||
|
setValue(pairs);
|
||||||
|
}
|
||||||
// User defined type.
|
// User defined type.
|
||||||
else { setValue(value); }
|
else
|
||||||
|
{
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Ditto.
|
/// Construct a scalar node
|
||||||
// Overload for types where we can make this nothrow.
|
@safe unittest
|
||||||
this(T)(T value, const string tag = null)
|
|
||||||
if(scalarCtorNothrow!T)
|
|
||||||
{
|
{
|
||||||
tag_ = tag;
|
// Integer
|
||||||
// We can easily store ints, floats, strings.
|
{
|
||||||
static if(isIntegral!T) { setValue(cast(long)value); }
|
auto node = Node(5);
|
||||||
else static if(is(Unqual!T==bool)){ setValue(cast(bool)value); }
|
}
|
||||||
else static if(isFloatingPoint!T) { setValue(cast(real)value); }
|
// String
|
||||||
// User defined type or plain string.
|
{
|
||||||
else { setValue(value);}
|
auto node = Node("Hello world!");
|
||||||
|
}
|
||||||
|
// Floating point
|
||||||
|
{
|
||||||
|
auto node = Node(5.0f);
|
||||||
|
}
|
||||||
|
// Boolean
|
||||||
|
{
|
||||||
|
auto node = Node(true);
|
||||||
|
}
|
||||||
|
// Time
|
||||||
|
{
|
||||||
|
auto node = Node(SysTime(DateTime(2005, 06, 15, 20, 00, 00), UTC()));
|
||||||
|
}
|
||||||
|
// Integer, dumped as a string
|
||||||
|
{
|
||||||
|
auto node = Node(5, "tag:yaml.org,2002:str");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Construct a sequence node
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
// Will be emitted as a sequence (default for arrays)
|
||||||
|
{
|
||||||
|
auto seq = Node([1, 2, 3, 4, 5]);
|
||||||
|
}
|
||||||
|
// Will be emitted as a set (overridden tag)
|
||||||
|
{
|
||||||
|
auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
|
||||||
|
}
|
||||||
|
// Can also store arrays of arrays
|
||||||
|
{
|
||||||
|
auto node = Node([[1,2], [3,4]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Construct a mapping node
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
// Will be emitted as an unordered mapping (default for mappings)
|
||||||
|
auto map = Node([1 : "a", 2 : "b"]);
|
||||||
|
// Will be emitted as an ordered map (overridden tag)
|
||||||
|
auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
|
||||||
|
// Will be emitted as pairs (overridden tag)
|
||||||
|
auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
|
||||||
}
|
}
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto node = Node(42);
|
auto node = Node(42);
|
||||||
assert(node.isScalar && !node.isSequence &&
|
assert(node.isScalar && !node.isSequence && !node.isMapping && !node.isUserType);
|
||||||
!node.isMapping && !node.isUserType);
|
|
||||||
assert(node.as!int == 42 && node.as!float == 42.0f && node.as!string == "42");
|
assert(node.as!int == 42 && node.as!float == 42.0f && node.as!string == "42");
|
||||||
assert(!node.isUserType);
|
assert(!node.isUserType);
|
||||||
}
|
}
|
||||||
|
@ -279,55 +365,6 @@ struct Node
|
||||||
assert(node.as!string == "string");
|
assert(node.as!string == "string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a node from an _array.
|
|
||||||
*
|
|
||||||
* If _array is an _array of nodes or pairs, it is stored directly.
|
|
||||||
* Otherwise, every value in the array is converted to a node, and
|
|
||||||
* those nodes are stored.
|
|
||||||
*
|
|
||||||
* Params: array = Values to store in the node.
|
|
||||||
* tag = Overrides tag of the node when emitted, regardless
|
|
||||||
* of tag determined by Representer. Representer uses
|
|
||||||
* this to determine YAML data type when a D data type
|
|
||||||
* maps to multiple different YAML data types.
|
|
||||||
* This is used to differentiate between YAML sequences
|
|
||||||
* ("!!seq") and sets ("!!set"), which both are
|
|
||||||
* internally represented as an array_ of nodes. Tag
|
|
||||||
* must be in full form, e.g. "tag:yaml.org,2002:set",
|
|
||||||
* not a shortcut, like "!!set".
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
this(T)(T[] array, const string tag = null)
|
|
||||||
if (!isSomeString!(T[]))
|
|
||||||
{
|
|
||||||
tag_ = tag;
|
|
||||||
|
|
||||||
// Construction from raw node or pair array.
|
|
||||||
static if(is(Unqual!T == Node) || is(Unqual!T == Node.Pair))
|
|
||||||
{
|
|
||||||
setValue(array);
|
|
||||||
}
|
|
||||||
// Need to handle byte buffers separately.
|
|
||||||
else static if(is(Unqual!T == byte) || is(Unqual!T == ubyte))
|
|
||||||
{
|
|
||||||
setValue(cast(ubyte[]) array);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Node[] nodes;
|
|
||||||
foreach(ref value; array){nodes ~= Node(value);}
|
|
||||||
setValue(nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
///
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
// Will be emitted as a sequence (default for arrays)
|
|
||||||
auto seq = Node([1, 2, 3, 4, 5]);
|
|
||||||
// Will be emitted as a set (overriden tag)
|
|
||||||
auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
|
|
||||||
}
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
with(Node([1, 2, 3]))
|
with(Node([1, 2, 3]))
|
||||||
|
@ -338,43 +375,6 @@ struct Node
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a node from an associative _array.
|
|
||||||
*
|
|
||||||
* If keys and/or values of _array are nodes, they stored directly.
|
|
||||||
* Otherwise they are converted to nodes and then stored.
|
|
||||||
*
|
|
||||||
* Params: array = Values to store in the node.
|
|
||||||
* tag = Overrides tag of the node when emitted, regardless
|
|
||||||
* of tag determined by Representer. Representer uses
|
|
||||||
* this to determine YAML data type when a D data type
|
|
||||||
* maps to multiple different YAML data types.
|
|
||||||
* This is used to differentiate between YAML unordered
|
|
||||||
* mappings ("!!map"), ordered mappings ("!!omap"), and
|
|
||||||
* pairs ("!!pairs") which are all internally
|
|
||||||
* represented as an _array of node pairs. Tag must be
|
|
||||||
* in full form, e.g. "tag:yaml.org,2002:omap", not a
|
|
||||||
* shortcut, like "!!omap".
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
this(K, V)(V[K] array, const string tag = null)
|
|
||||||
{
|
|
||||||
tag_ = tag;
|
|
||||||
|
|
||||||
Node.Pair[] pairs;
|
|
||||||
foreach(key, ref value; array){pairs ~= Pair(key, value);}
|
|
||||||
setValue(pairs);
|
|
||||||
}
|
|
||||||
///
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
// Will be emitted as an unordered mapping (default for mappings)
|
|
||||||
auto map = Node([1 : "a", 2 : "b"]);
|
|
||||||
// Will be emitted as an ordered map (overriden tag)
|
|
||||||
auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
|
|
||||||
// Will be emitted as pairs (overriden tag)
|
|
||||||
auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
|
|
||||||
}
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
int[string] aa;
|
int[string] aa;
|
||||||
|
@ -386,7 +386,12 @@ struct Node
|
||||||
assert(length == 2);
|
assert(length == 2);
|
||||||
assert(opIndex("2").as!int == 2);
|
assert(opIndex("2").as!int == 2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto node = Node(Node(4, "tag:yaml.org,2002:str"));
|
||||||
|
assert(node == 4);
|
||||||
|
assert(node.tag_ == "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a node from arrays of _keys and _values.
|
/** Construct a node from arrays of _keys and _values.
|
||||||
|
|
Loading…
Reference in a new issue