Added ranges-iterators to the Node struct.
Added methods: sequence, mapping (iterates over pairs), mappingKeys, mappingValues.
This commit is contained in:
parent
860eab9be5
commit
2b6c417006
|
@ -1041,6 +1041,198 @@ struct Node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return a range object iterating over a sequence, getting each
|
||||||
|
* element as T.
|
||||||
|
*
|
||||||
|
* If T is Node, simply iterate over the nodes in the sequence.
|
||||||
|
* Otherwise, convert each node to T during iteration.
|
||||||
|
*
|
||||||
|
* Throws: NodeException if the node is not a sequence or an element
|
||||||
|
* could not be converted to specified type.
|
||||||
|
*/
|
||||||
|
auto sequence(T = Node)() @trusted
|
||||||
|
{
|
||||||
|
enforce(isSequence,
|
||||||
|
new Error("Trying to 'sequence'-iterate over a " ~ nodeTypeString ~ " node",
|
||||||
|
startMark_));
|
||||||
|
struct Range
|
||||||
|
{
|
||||||
|
Node[] subnodes;
|
||||||
|
size_t position;
|
||||||
|
|
||||||
|
this(Node[] nodes)
|
||||||
|
{
|
||||||
|
subnodes = nodes;
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input range functionality. */
|
||||||
|
bool empty() { return position >= subnodes.length; }
|
||||||
|
void popFront() { position++; }
|
||||||
|
T front()
|
||||||
|
{
|
||||||
|
static if (is(Unqual!T == Node))
|
||||||
|
return subnodes[position];
|
||||||
|
else
|
||||||
|
return subnodes[position].as!T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forward range functionality. */
|
||||||
|
Range save() { return this; }
|
||||||
|
|
||||||
|
/* Bidirectional range functionality. */
|
||||||
|
void popBack() { subnodes = subnodes[0 .. $ - 1]; }
|
||||||
|
T back()
|
||||||
|
{
|
||||||
|
static if (is(Unqual!T == Node))
|
||||||
|
return subnodes[$ - 1];
|
||||||
|
else
|
||||||
|
return subnodes[$ - 1].as!T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Random-access range functionality. */
|
||||||
|
T opIndex(size_t index)
|
||||||
|
{
|
||||||
|
static if (is(Unqual!T == Node))
|
||||||
|
return subnodes[index];
|
||||||
|
else
|
||||||
|
return subnodes[index].as!T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Range(get!(Node[]));
|
||||||
|
}
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
writeln("D:YAML Node sequence unittest");
|
||||||
|
|
||||||
|
Node n1 = Node([1, 2, 3, 4]);
|
||||||
|
int[int] array;
|
||||||
|
Node n2 = Node(array);
|
||||||
|
|
||||||
|
auto r = n1.sequence!int.map!(x => x * 10);
|
||||||
|
assert(r.equal([10, 20, 30, 40]));
|
||||||
|
|
||||||
|
assertThrown(n2.sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return a range object iterating over mapping's pairs.
|
||||||
|
*
|
||||||
|
* Throws: NodeException if the node is not a mapping.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
auto mapping() @trusted
|
||||||
|
{
|
||||||
|
enforce(isMapping,
|
||||||
|
new Error("Trying to 'mapping'-iterate over a "
|
||||||
|
~ nodeTypeString ~ " node", startMark_));
|
||||||
|
struct Range
|
||||||
|
{
|
||||||
|
Node.Pair[] pairs;
|
||||||
|
size_t position;
|
||||||
|
|
||||||
|
this(Node.Pair[] pairs)
|
||||||
|
{
|
||||||
|
this.pairs = pairs;
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input range functionality. */
|
||||||
|
bool empty() { return position >= pairs.length; }
|
||||||
|
void popFront() { position++; }
|
||||||
|
Pair front() { return pairs[position]; }
|
||||||
|
|
||||||
|
/* Forward range functionality. */
|
||||||
|
Range save() { return this; }
|
||||||
|
|
||||||
|
/* Bidirectional range functionality. */
|
||||||
|
void popBack() { pairs = pairs[0 .. $ - 1]; }
|
||||||
|
Pair back() { return pairs[$ - 1]; }
|
||||||
|
|
||||||
|
/* Random-access range functionality. */
|
||||||
|
Pair opIndex(size_t index) { return pairs[index]; }
|
||||||
|
}
|
||||||
|
return Range(get!(Node.Pair[]));
|
||||||
|
}
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
writeln("D:YAML Node mapping unittest");
|
||||||
|
|
||||||
|
int[int] array;
|
||||||
|
Node n = Node(array);
|
||||||
|
n[1] = "foo";
|
||||||
|
n[2] = "bar";
|
||||||
|
n[3] = "baz";
|
||||||
|
|
||||||
|
string[int] test;
|
||||||
|
foreach (pair; n.mapping)
|
||||||
|
test[pair.key.as!int] = pair.value.as!string;
|
||||||
|
|
||||||
|
assert(test[1] == "foo");
|
||||||
|
assert(test[2] == "bar");
|
||||||
|
assert(test[3] == "baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return a range object iterating over mapping's keys.
|
||||||
|
*
|
||||||
|
* If K is Node, simply iterate over the keys in the mapping.
|
||||||
|
* Otherwise, convert each key to T during iteration.
|
||||||
|
*
|
||||||
|
* Throws: NodeException if the nodes is not a mapping or an element
|
||||||
|
* could not be converted to specified type.
|
||||||
|
*/
|
||||||
|
auto mappingKeys(K = Node)() @trusted
|
||||||
|
{
|
||||||
|
enforce(isMapping,
|
||||||
|
new Error("Trying to 'mappingKeys'-iterate over a "
|
||||||
|
~ nodeTypeString ~ " node", startMark_));
|
||||||
|
static if (is(Unqual!K == Node))
|
||||||
|
return mapping.map!(pair => pair.key);
|
||||||
|
else
|
||||||
|
return mapping.map!(pair => pair.key.as!K);
|
||||||
|
}
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
writeln("D:YAML Node mappingKeys unittest");
|
||||||
|
|
||||||
|
int[int] array;
|
||||||
|
Node m1 = Node(array);
|
||||||
|
m1["foo"] = 2;
|
||||||
|
m1["bar"] = 3;
|
||||||
|
|
||||||
|
assert(m1.mappingKeys.equal(["foo", "bar"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return a range object iterating over mapping's values.
|
||||||
|
*
|
||||||
|
* If V is Node, simply iterate over the values in the mapping.
|
||||||
|
* Otherwise, convert each key to V during iteration.
|
||||||
|
*
|
||||||
|
* Throws: NodeException if the nodes is not a mapping or an element
|
||||||
|
* could not be converted to specified type.
|
||||||
|
*/
|
||||||
|
auto mappingValues(V = Node)() @trusted
|
||||||
|
{
|
||||||
|
enforce(isMapping,
|
||||||
|
new Error("Trying to 'mappingValues'-iterate over a "
|
||||||
|
~ nodeTypeString ~ " node", startMark_));
|
||||||
|
static if (is(Unqual!V == Node))
|
||||||
|
return mapping.map!(pair => pair.value);
|
||||||
|
else
|
||||||
|
return mapping.map!(pair => pair.value.as!V);
|
||||||
|
}
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
writeln("D:YAML Node mappingValues unittest");
|
||||||
|
|
||||||
|
int[int] array;
|
||||||
|
Node m1 = Node(array);
|
||||||
|
m1["foo"] = 2;
|
||||||
|
m1["bar"] = 3;
|
||||||
|
|
||||||
|
assert(m1.mappingValues.equal([2, 3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Foreach over a sequence, getting each element as T.
|
/** Foreach over a sequence, getting each element as T.
|
||||||
*
|
*
|
||||||
* If T is Node, simply iterate over the nodes in the sequence.
|
* If T is Node, simply iterate over the nodes in the sequence.
|
||||||
|
|
Loading…
Reference in a new issue