diff --git a/source/dyaml/emitter.d b/source/dyaml/emitter.d index 04de005..4e753da 100644 --- a/source/dyaml/emitter.d +++ b/source/dyaml/emitter.d @@ -332,7 +332,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType)) } ///Expect nothing, throwing if we still have something. - void expectNothing() const @safe + void expectNothing() @safe { throw new EmitterException("Expected nothing, but got " ~ event_.idString); } diff --git a/source/dyaml/node.d b/source/dyaml/node.d index ca2d04a..a82c109 100644 --- a/source/dyaml/node.d +++ b/source/dyaml/node.d @@ -1216,70 +1216,51 @@ struct Node * Throws: NodeException if the node is not a sequence or an * element could not be converted to specified type. */ - template opApply(T) + int opApply(D)(D dg) if (isDelegate!D && (Parameters!D.length == 1)) { - int opApplyImpl(DG)(DG dg) - { - enforce(isSequence, - new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node", - startMark_)); + enforce(isSequence, + new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node", + startMark_)); - int result; - foreach(ref node; get!(Node[])) - { - static if(is(Unqual!T == Node)) - { - result = dg(node); - } - else - { - T temp = node.as!T; - result = dg(temp); - } - if(result){break;} - } - return result; - } - // Ugly workaround due to issues with inout and delegate params - int opApplyImpl(DG)(DG dg) const + int result; + foreach(ref node; get!(Node[])) { - enforce(isSequence, - new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node", - startMark_)); + static if(is(Unqual!(Parameters!D[0]) == Node)) + { + result = dg(node); + } + else + { + Parameters!D[0] temp = node.as!(Parameters!D[0]); + result = dg(temp); + } + if(result){break;} + } + return result; + } + /// ditto + int opApply(D)(D dg) const if (isDelegate!D && (Parameters!D.length == 1)) + { + enforce(isSequence, + new NodeException("Trying to sequence-foreach over a " ~ nodeTypeString ~ " node", + startMark_)); - int result; - foreach(ref node; get!(Node[])) + int result; + foreach(ref node; get!(Node[])) + { + static if(is(Unqual!(Parameters!D[0]) == Node)) { - static if(is(Unqual!T == Node)) - { - result = dg(node); - } - else - { - T temp = node.as!T; - result = dg(temp); - } - if(result){break;} + result = dg(node); } - return result; + else + { + Parameters!D[0] temp = node.as!(Parameters!D[0]); + result = dg(temp); + } + if(result){break;} } - int opApply(scope int delegate(ref T) @system dg) - { - return opApplyImpl(dg); - } - int opApply(scope int delegate(ref T) @safe dg) - { - return opApplyImpl(dg); - } - int opApply(scope int delegate(ref const T) @system dg) const - { - return opApplyImpl(dg); - } - int opApply(scope int delegate(ref const T) @safe dg) const - { - return opApplyImpl(dg); - } - } + return result; + } @safe unittest { Node n1 = Node(11); @@ -1287,8 +1268,9 @@ struct Node Node n3 = Node(13); Node n4 = Node(14); Node narray = Node([n1, n2, n3, n4]); + const cNArray = narray; - int[] array, array2; + int[] array, array2, array3; foreach(int value; narray) { array ~= value; @@ -1297,8 +1279,13 @@ struct Node { array2 ~= node.as!int; } + foreach (const Node node; cNArray) + { + array3 ~= node.as!int; + } assert(array == [11, 12, 13, 14]); assert(array2 == [11, 12, 13, 14]); + assert(array3 == [11, 12, 13, 14]); } @safe unittest { @@ -1325,6 +1312,13 @@ struct Node i++; } } + @safe unittest + { + auto node = Node(["a":1, "b":2, "c":3]); + const cNode = node; + assertThrown({foreach (Node n; node) {}}()); + assertThrown({foreach (const Node n; cNode) {}}()); + } /** Foreach over a mapping, getting each key/value as K/V. * @@ -1334,94 +1328,79 @@ struct Node * Throws: NodeException if the node is not a mapping or an * element could not be converted to specified type. */ - template opApply(K, V) - { - int opApplyImpl(DG)(DG dg) - { - enforce(isMapping, - new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node", - startMark_)); + int opApply(DG)(DG dg) if (isDelegate!DG && (Parameters!DG.length == 2)) + { + alias K = Parameters!DG[0]; + alias V = Parameters!DG[1]; + enforce(isMapping, + new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node", + startMark_)); - int result; - foreach(ref pair; get!(Node.Pair[])) + int result; + foreach(ref pair; get!(Node.Pair[])) + { + static if(is(Unqual!K == Node) && is(Unqual!V == Node)) { - static if(is(Unqual!K == Node) && is(Unqual!V == Node)) - { - result = dg(pair.key, pair.value); - } - else static if(is(Unqual!K == Node)) - { - V tempValue = pair.value.as!V; - result = dg(pair.key, tempValue); - } - else static if(is(Unqual!V == Node)) - { - K tempKey = pair.key.as!K; - result = dg(tempKey, pair.value); - } - else - { - K tempKey = pair.key.as!K; - V tempValue = pair.value.as!V; - result = dg(tempKey, tempValue); - } - - if(result){break;} + result = dg(pair.key, pair.value); } - return result; - } - // Ugly workaround due to issues with inout and delegate params - int opApplyImpl(DG)(DG dg) const - { - enforce(isMapping, - new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node", - startMark_)); - - int result; - foreach(ref pair; get!(Node.Pair[])) + else static if(is(Unqual!K == Node)) { - static if(is(Unqual!K == Node) && is(Unqual!V == Node)) - { - result = dg(pair.key, pair.value); - } - else static if(is(Unqual!K == Node)) - { - V tempValue = pair.value.as!V; - result = dg(pair.key, tempValue); - } - else static if(is(Unqual!V == Node)) - { - K tempKey = pair.key.as!K; - result = dg(tempKey, pair.value); - } - else - { - K tempKey = pair.key.as!K; - V tempValue = pair.value.as!V; - result = dg(tempKey, tempValue); - } - - if(result){break;} + V tempValue = pair.value.as!V; + result = dg(pair.key, tempValue); } - return result; + else static if(is(Unqual!V == Node)) + { + K tempKey = pair.key.as!K; + result = dg(tempKey, pair.value); + } + else + { + K tempKey = pair.key.as!K; + V tempValue = pair.value.as!V; + result = dg(tempKey, tempValue); + } + + if(result){break;} } - int opApply(scope int delegate(ref K, ref V) @system dg) + return result; + } + /// ditto + int opApply(DG)(DG dg) const if (isDelegate!DG && (Parameters!DG.length == 2)) + { + alias K = Parameters!DG[0]; + alias V = Parameters!DG[1]; + enforce(isMapping, + new NodeException("Trying to mapping-foreach over a " ~ nodeTypeString ~ " node", + startMark_)); + + int result; + foreach(ref pair; get!(Node.Pair[])) { - return opApplyImpl(dg); + static if(is(Unqual!K == Node) && is(Unqual!V == Node)) + { + result = dg(pair.key, pair.value); + } + else static if(is(Unqual!K == Node)) + { + V tempValue = pair.value.as!V; + result = dg(pair.key, tempValue); + } + else static if(is(Unqual!V == Node)) + { + K tempKey = pair.key.as!K; + result = dg(tempKey, pair.value); + } + else + { + K tempKey = pair.key.as!K; + V tempValue = pair.value.as!V; + result = dg(tempKey, tempValue); + } + + if(result){break;} } - int opApply(scope int delegate(ref K, ref V) @safe dg) - { - return opApplyImpl(dg); - } - int opApply(scope int delegate(ref const K, ref const V) @system dg) const - { - return opApplyImpl(dg); - } - int opApply(scope int delegate(ref const K, ref const V) @safe dg) const - { - return opApplyImpl(dg); - } - } + return result; + } @safe unittest { Node n1 = Node(cast(long)11); @@ -1466,6 +1445,19 @@ struct Node default: assert(false); } } + const nmap3 = nmap2; + + foreach(const Node key, const Node value; nmap3) + { + switch(key.as!string) + { + case "11": assert(value.as!int == 5 ); break; + case "12": assert(value.as!bool == true ); break; + case "13": assert(value.as!float == 1.0 ); break; + case "14": assert(value.as!string == "yarly"); break; + default: assert(false); + } + } } @safe unittest { @@ -1486,6 +1478,13 @@ struct Node assert(elem == testStrs[i]); } } + @safe unittest + { + auto node = Node(["a", "b", "c"]); + const cNode = node; + assertThrown({foreach (Node a, Node b; node) {}}()); + assertThrown({foreach (const Node a, const Node b; cNode) {}}()); + } /** Add an element to a sequence. * diff --git a/source/dyaml/reader.d b/source/dyaml/reader.d index 1fb09d7..221438a 100644 --- a/source/dyaml/reader.d +++ b/source/dyaml/reader.d @@ -526,7 +526,7 @@ public: /// end of the slice being built, the slice is extended (trivial operation). /// /// See_Also: begin - void write(char[] str) @safe pure nothrow @nogc + void write(scope char[] str) @safe pure nothrow @nogc { assert(inProgress, "write called without begin"); assert(end_ <= reader_.bufferOffset_,