Doc style change in node.d

This commit is contained in:
Ferdinand Majerech 2014-07-19 01:58:24 +02:00
parent 7ae4de4776
commit 28979baa6c

View file

@ -4,10 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
/** /// Node of a YAML document. Used to read YAML data once it's loaded,
* Node of a YAML document. Used to read YAML data once it's loaded, /// and to prepare data to emit.
* and to prepare data to emit.
*/
module dyaml.node; module dyaml.node;
@ -34,12 +32,10 @@ import dyaml.tag;
class NodeException : YAMLException class NodeException : YAMLException
{ {
package: package:
/* // Construct a NodeException.
* Construct a NodeException. //
* // Params: msg = Error message.
* Params: msg = Error message. // start = Start position of the node.
* start = Start position of the node.
*/
this(string msg, Mark start, string file = __FILE__, int line = __LINE__) this(string msg, Mark start, string file = __FILE__, int line = __LINE__)
@safe @safe
{ {
@ -121,13 +117,11 @@ package class YAMLContainer(T) if (!Node.allowed!T): YAMLObject
this(T value) @trusted {value_ = value;} this(T value) @trusted {value_ = value;}
} }
/** /// YAML node.
* YAML node. ///
* /// This is a pseudo-dynamic type that can store any YAML value, including a
* This is a pseudo-dynamic type that can store any YAML value, including a /// sequence or mapping of nodes. You can get data from a Node directly or
* sequence or mapping of nodes. You can get data from a Node directly or /// iterate over it if it's a collection.
* iterate over it if it's a collection.
*/
struct Node struct Node
{ {
public: public:
@ -170,12 +164,10 @@ struct Node
} }
private: private:
/* // Comparison with another Pair.
* Comparison with another Pair. //
* // useTag determines whether or not we consider node tags
* useTag determines whether or not we consider node tags // in the comparison.
* in the comparison.
*/
int cmp(Flag!"useTag" useTag)(ref const(Pair) rhs) const @safe int cmp(Flag!"useTag" useTag)(ref const(Pair) rhs) const @safe
{ {
const keyCmp = key.cmp!useTag(rhs.key); const keyCmp = key.cmp!useTag(rhs.key);
@ -226,27 +218,25 @@ struct Node
static assert(Node.sizeof <= 48, "Unexpected YAML node size"); static assert(Node.sizeof <= 48, "Unexpected YAML node size");
public: public:
/** /// Construct a Node from a value.
* Construct a Node from a value. ///
* /// Any type except for Node can be stored in a Node, but default YAML
* Any type except for Node can be stored in a Node, but default YAML /// types (integers, floats, strings, timestamps, etc.) will be stored
* types (integers, floats, strings, timestamps, etc.) will be stored /// 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. ///
* ///
* /// 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 - /// otherwise emitting will fail.
* otherwise emitting will fail. ///
* /// Params: value = Value to store in the node.
* Params: value = Value to store in the node. /// tag = Overrides tag of the node when emitted, regardless
* tag = Overrides tag of the node when emitted, regardless /// of tag determined by Representer. Representer uses
* of tag determined by Representer. Representer uses /// this to determine YAML data type when a D data type
* this to determine YAML data type when a D data type /// maps to multiple different YAML data types. Tag must
* maps to multiple different YAML data types. Tag must /// be in full form, e.g. "tag:yaml.org,2002:int", not
* be in full form, e.g. "tag:yaml.org,2002:int", not /// a shortcut, like "!!int".
* a shortcut, like "!!int".
*/
this(T)(T value, const string tag = null) @trusted this(T)(T value, const string tag = null) @trusted
if (isSomeString!T || (!isArray!T && !isAssociativeArray!T)) if (isSomeString!T || (!isArray!T && !isAssociativeArray!T))
{ {
@ -280,32 +270,30 @@ struct Node
} }
} }
/** /// Construct a node from an _array.
* Construct a node from an _array. ///
* /// If _array is an _array of nodes or pairs, it is stored directly.
* 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
* Otherwise, every value in the array is converted to a node, and /// those nodes are stored.
* those nodes are stored. ///
* /// Params: array = Values to store in the node.
* Params: array = Values to store in the node. /// tag = Overrides tag of the node when emitted, regardless
* tag = Overrides tag of the node when emitted, regardless /// of tag determined by Representer. Representer uses
* of tag determined by Representer. Representer uses /// this to determine YAML data type when a D data type
* this to determine YAML data type when a D data type /// maps to multiple different YAML data types.
* maps to multiple different YAML data types. /// This is used to differentiate between YAML sequences
* This is used to differentiate between YAML sequences /// ("!!seq") and sets ("!!set"), which both are
* ("!!seq") and sets ("!!set"), which both are /// internally represented as an array_ of nodes. Tag
* internally represented as an array_ of nodes. Tag /// must be in full form, e.g. "tag:yaml.org,2002:set",
* must be in full form, e.g. "tag:yaml.org,2002:set", /// not a shortcut, like "!!set".
* not a shortcut, like "!!set". ///
* /// Examples:
* Examples: /// --------------------
* -------------------- /// // Will be emitted as a sequence (default for arrays)
* //Will be emitted as a sequence (default for arrays) /// auto seq = Node([1, 2, 3, 4, 5]);
* auto seq = Node([1, 2, 3, 4, 5]); /// // Will be emitted as a set (overriden tag)
* //Will be emitted as a set (overriden tag) /// auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
* auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set"); /// --------------------
* --------------------
*/
this(T)(T[] array, const string tag = null) @safe this(T)(T[] array, const string tag = null) @safe
if (!isSomeString!(T[])) if (!isSomeString!(T[]))
{ {
@ -343,34 +331,32 @@ struct Node
auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set"); auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
} }
/** /// Construct a node from an associative _array.
* Construct a node from an associative _array. ///
* /// If keys and/or values of _array are nodes, they stored directly.
* If keys and/or values of _array are nodes, they stored directly. /// Otherwise they are converted to nodes and then stored.
* Otherwise they are converted to nodes and then stored. ///
* /// Params: array = Values to store in the node.
* Params: array = Values to store in the node. /// tag = Overrides tag of the node when emitted, regardless
* tag = Overrides tag of the node when emitted, regardless /// of tag determined by Representer. Representer uses
* of tag determined by Representer. Representer uses /// this to determine YAML data type when a D data type
* this to determine YAML data type when a D data type /// maps to multiple different YAML data types.
* maps to multiple different YAML data types. /// This is used to differentiate between YAML unordered
* This is used to differentiate between YAML unordered /// mappings ("!!map"), ordered mappings ("!!omap"), and
* mappings ("!!map"), ordered mappings ("!!omap"), and /// pairs ("!!pairs") which are all internally
* pairs ("!!pairs") which are all internally /// represented as an _array of node pairs. Tag must be
* represented as an _array of node pairs. Tag must be /// in full form, e.g. "tag:yaml.org,2002:omap", not a
* in full form, e.g. "tag:yaml.org,2002:omap", not a /// shortcut, like "!!omap".
* shortcut, like "!!omap". ///
* /// Examples:
* Examples: /// --------------------
* -------------------- /// // Will be emitted as an unordered mapping (default for mappings)
* //Will be emitted as an unordered mapping (default for mappings) /// auto map = Node([1 : "a", 2 : "b"]);
* auto map = Node([1 : "a", 2 : "b"]); /// // Will be emitted as an ordered map (overriden tag)
* //Will be emitted as an ordered map (overriden tag) /// auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
* auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap"); /// // Will be emitted as pairs (overriden tag)
* //Will be emitted as pairs (overriden tag) /// auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
* auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs"); /// --------------------
* --------------------
*/
this(K, V)(V[K] array, const string tag = null) @safe this(K, V)(V[K] array, const string tag = null) @safe
{ {
tag_ = Tag(tag); tag_ = Tag(tag);
@ -399,43 +385,41 @@ struct Node
auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs"); auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
} }
/** /// Construct a node from arrays of _keys and _values.
* Construct a node from arrays of _keys and _values. ///
* /// Constructs a mapping node with key-value pairs from
* Constructs a mapping node with key-value pairs from /// _keys and _values, keeping their order. Useful when order
* _keys and _values, keeping their order. Useful when order /// is important (ordered maps, pairs).
* is important (ordered maps, pairs). ///
* ///
* /// keys and values must have equal length.
* keys and values must have equal length. ///
* ///
* /// If _keys and/or _values are nodes, they are stored directly/
* If _keys and/or _values are nodes, they are stored directly/ /// Otherwise they are converted to nodes and then stored.
* Otherwise they are converted to nodes and then stored. ///
* /// Params: keys = Keys of the mapping, from first to last pair.
* Params: keys = Keys of the mapping, from first to last pair. /// values = Values of the mapping, from first to last pair.
* values = Values of the mapping, from first to last pair. /// tag = Overrides tag of the node when emitted, regardless
* tag = Overrides tag of the node when emitted, regardless /// of tag determined by Representer. Representer uses
* of tag determined by Representer. Representer uses /// this to determine YAML data type when a D data type
* this to determine YAML data type when a D data type /// maps to multiple different YAML data types.
* maps to multiple different YAML data types. /// This is used to differentiate between YAML unordered
* This is used to differentiate between YAML unordered /// mappings ("!!map"), ordered mappings ("!!omap"), and
* mappings ("!!map"), ordered mappings ("!!omap"), and /// pairs ("!!pairs") which are all internally
* pairs ("!!pairs") which are all internally /// represented as an array of node pairs. Tag must be
* represented as an array of node pairs. Tag must be /// in full form, e.g. "tag:yaml.org,2002:omap", not a
* in full form, e.g. "tag:yaml.org,2002:omap", not a /// shortcut, like "!!omap".
* shortcut, like "!!omap". ///
* /// Examples:
* Examples: /// --------------------
* -------------------- /// // Will be emitted as an unordered mapping (default for mappings)
* //Will be emitted as an unordered mapping (default for mappings) /// auto map = Node([1, 2], ["a", "b"]);
* auto map = Node([1, 2], ["a", "b"]); /// // Will be emitted as an ordered map (overriden tag)
* //Will be emitted as an ordered map (overriden tag) /// auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap");
* auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap"); /// // Will be emitted as pairs (overriden tag)
* //Will be emitted as pairs (overriden tag) /// auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs");
* auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs"); /// --------------------
* --------------------
*/
this(K, V)(K[] keys, V[] values, const string tag = null) @safe this(K, V)(K[] keys, V[] values, const string tag = null) @safe
if(!(isSomeString!(K[]) || isSomeString!(V[]))) if(!(isSomeString!(K[]) || isSomeString!(V[])))
in in
@ -508,30 +492,28 @@ struct Node
/// Return tag of the node. /// Return tag of the node.
@property string tag() const @safe nothrow {return tag_.get;} @property string tag() const @safe nothrow {return tag_.get;}
/** /// Equality test.
* Equality test. ///
* /// If T is Node, recursively compare all subnodes.
* If T is Node, recursively compare all subnodes. /// This might be quite expensive if testing entire documents.
* This might be quite expensive if testing entire documents. ///
* /// If T is not Node, get a value if type T from the node and test
* If T is not Node, get a value if type T from the node and test /// equality with that.
* equality with that. ///
* /// To test equality with a null YAML value, use YAMLNull.
* To test equality with a null YAML value, use YAMLNull. ///
* /// Examples:
* Examples: /// --------------------
* -------------------- /// auto node = Node(42);
* auto node = Node(42); ///
* /// assert(node == 42);
* assert(node == 42); /// assert(node != "42");
* assert(node != "42"); /// assert(node != "43");
* assert(node != "43"); /// --------------------
* -------------------- ///
* /// Params: rhs = Variable to test equality with.
* Params: rhs = Variable to test equality with. ///
* /// Returns: true if equal, false otherwise.
* Returns: true if equal, false otherwise.
*/
bool opEquals(T)(const auto ref T rhs) const @safe bool opEquals(T)(const auto ref T rhs) const @safe
{ {
return equals!(Yes.useTag)(rhs); return equals!(Yes.useTag)(rhs);
@ -551,50 +533,48 @@ struct Node
/// Shortcut for get(). /// Shortcut for get().
alias get as; alias get as;
/** /// Get the value of the node as specified type.
* Get the value of the node as specified type. ///
* /// If the specifed type does not match type in the node,
* If the specifed type does not match type in the node, /// conversion is attempted. The stringConversion template
* conversion is attempted. The stringConversion template /// parameter can be used to disable conversion from non-string
* parameter can be used to disable conversion from non-string /// types to strings.
* types to strings. ///
* /// Numeric values are range checked, throwing if out of range of
* Numeric values are range checked, throwing if out of range of /// requested type.
* requested type. ///
* /// Timestamps are stored as std.datetime.SysTime.
* Timestamps are stored as std.datetime.SysTime. /// Binary values are decoded and stored as ubyte[].
* Binary values are decoded and stored as ubyte[]. ///
* /// To get a null value, use get!YAMLNull . This is to
* To get a null value, use get!YAMLNull . This is to /// prevent getting null values for types such as strings or classes.
* prevent getting null values for types such as strings or classes. ///
* /// $(BR)$(B Mapping default values:)
* $(BR)$(B Mapping default values:) ///
* /// $(PBR
* $(PBR /// The '=' key can be used to denote the default value of a mapping.
* The '=' key can be used to denote the default value of a mapping. /// This can be used when a node is scalar in early versions of a program,
* This can be used when a node is scalar in early versions of a program, /// but is replaced by a mapping later. Even if the node is a mapping, the
* but is replaced by a mapping later. Even if the node is a mapping, the /// get method can be used as if it was a scalar if it has a default value.
* get method can be used as if it was a scalar if it has a default value. /// This way, new YAML files where the node is a mapping can still be read
* This way, new YAML files where the node is a mapping can still be read /// by old versions of the program, which expect the node to be a scalar.
* by old versions of the program, which expect the node to be a scalar. /// )
* ) ///
* /// Examples:
* Examples: ///
* /// Automatic type conversion:
* Automatic type conversion: /// --------------------
* -------------------- /// auto node = Node(42);
* auto node = Node(42); ///
* /// assert(node.as!int == 42);
* assert(node.as!int == 42); /// assert(node.as!string == "42");
* assert(node.as!string == "42"); /// assert(node.as!double == 42.0);
* assert(node.as!double == 42.0); /// --------------------
* -------------------- ///
* /// Returns: Value of the node as specified type.
* Returns: Value of the node as specified type. ///
* /// Throws: NodeException if unable to convert to specified type, or if
* Throws: NodeException if unable to convert to specified type, or if /// the value is out of range of requested type.
* the value is out of range of requested type.
*/
@property T get(T, Flag!"stringConversion" stringConversion = Yes.stringConversion)() @property T get(T, Flag!"stringConversion" stringConversion = Yes.stringConversion)()
@trusted if(!is(T == const)) @trusted if(!is(T == const))
{ {
@ -729,15 +709,13 @@ struct Node
} }
} }
/** /// If this is a collection, return its _length.
* If this is a collection, return its _length. ///
* /// Otherwise, throw NodeException.
* Otherwise, throw NodeException. ///
* /// Returns: Number of elements in a sequence or key-value pairs in a mapping.
* Returns: Number of elements in a sequence or key-value pairs in a mapping. ///
* /// Throws: NodeException if this is not a sequence nor a mapping.
* Throws: NodeException if this is not a sequence nor a mapping.
*/
@property size_t length() const @safe @property size_t length() const @safe
{ {
if(isSequence) {return value_.get!(const Node[]).length;} if(isSequence) {return value_.get!(const Node[]).length;}
@ -746,25 +724,24 @@ struct Node
startMark_); startMark_);
} }
/** /// Get the element at specified index.
* Get the element at specified index. ///
* /// If the node is a sequence, index must be integral.
* If the node is a sequence, index must be integral. ///
* ///
* /// If the node is a mapping, return the value corresponding to the first
* If the node is a mapping, return the value corresponding to the first /// key equal to index. containsKey() can be used to determine if a mapping
* key equal to index. /// has a specific key.
* ///
* To get element at a null index, use YAMLNull for index. /// To get element at a null index, use YAMLNull for index.
* ///
* Params: index = Index to use. /// Params: index = Index to use.
* ///
* Returns: Value corresponding to the index. /// Returns: Value corresponding to the index.
* ///
* Throws: NodeException if the index could not be found, /// Throws: NodeException if the index could not be found,
* 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.
*/
ref Node opIndex(T)(T index) @trusted ref Node opIndex(T)(T index) @trusted
{ {
if(isSequence) if(isSequence)
@ -789,10 +766,10 @@ struct Node
} }
throw new Error("Trying to index a " ~ nodeTypeString ~ " node", startMark_); throw new Error("Trying to index a " ~ nodeTypeString ~ " node", startMark_);
} }
///
unittest unittest
{ {
writeln("D:YAML Node opIndex unittest"); writeln("D:YAML Node opIndex unittest");
alias Node.Value Value; alias Node.Value Value;
alias Node.Pair Pair; alias Node.Pair Pair;
Node n1 = Node(cast(long)11); Node n1 = Node(cast(long)11);
@ -824,40 +801,36 @@ struct Node
assertThrown!NodeException(nmap[14]); assertThrown!NodeException(nmap[14]);
} }
/** /// Determine if a collection contains specified value.
* Determine if a collection contains specified value. ///
* /// If the node is a sequence, check if it contains the specified value.
* If the node is a sequence, check if it contains the specified value. /// If it's a mapping, check if it has a value that matches specified value.
* If it's a mapping, check if it has a value that matches specified value. ///
* /// To check for a null value, use YAMLNull for rhs.
* To check for a null value, use YAMLNull for rhs. ///
* /// Params: rhs = Item to look for.
* Params: rhs = Item to look for. ///
* /// Returns: true if rhs was found, false otherwise.
* Returns: true if rhs was found, false otherwise. ///
* /// Throws: NodeException if the node is not a collection.
* Throws: NodeException if the node is not a collection.
*/
bool contains(T)(T rhs) const @safe bool contains(T)(T rhs) const @safe
{ {
return contains_!(T, No.key, "contains")(rhs); return contains_!(T, No.key, "contains")(rhs);
} }
/** /// Determine if a collection contains specified key.
* Determine if a collection contains specified key. ///
* /// If the node is a mapping, check if it has a key
* If the node is a mapping, check if it has a key /// that matches specified key.
* that matches specified key. ///
* /// To check for a null key, use YAMLNull for rhs.
* To check for a null key, use YAMLNull for rhs. ///
* /// Params: rhs = Item to look for.
* Params: rhs = Item to look for. ///
* /// Returns: true if rhs was found, false otherwise.
* Returns: true if rhs was found, false otherwise. ///
* /// Throws: NodeException if the node is not a mapping.
* Throws: NodeException if the node is not a mapping.
*/
bool containsKey(T)(T rhs) const @safe bool containsKey(T)(T rhs) const @safe
{ {
return contains_!(T, Yes.key, "containsKey")(rhs); return contains_!(T, Yes.key, "containsKey")(rhs);
@ -942,28 +915,26 @@ struct Node
"Node.opAssign() doesn't produce an equivalent copy"); "Node.opAssign() doesn't produce an equivalent copy");
} }
/** /// Set element at specified index in a collection.
* Set element at specified index in a collection. ///
* /// This method can only be called on collection nodes.
* This method can only be called on collection nodes. ///
* /// If the node is a sequence, index must be integral.
* If the node is a sequence, index must be integral. ///
* /// If the node is a mapping, sets the _value corresponding to the first
* If the node is a mapping, sets the _value corresponding to the first /// key matching index (including conversion, so e.g. "42" matches 42).
* key matching index (including conversion, so e.g. "42" matches 42). ///
* /// If the node is a mapping and no key matches index, a new key-value
* If the node is a mapping and no key matches index, a new key-value /// pair is added to the mapping. In sequences the index must be in
* pair is added to the mapping. In sequences the index must be in /// range. This ensures behavior siilar to D arrays and associative
* range. This ensures behavior siilar to D arrays and associative /// arrays.
* arrays. ///
* /// To set element at a null index, use YAMLNull for index.
* To set element at a null index, use YAMLNull for index. ///
* /// Params: index = Index of the value to set.
* Params: index = Index of the value to set. ///
* /// Throws: NodeException if the node is not a collection, index is out
* Throws: NodeException if the node is not a collection, index is out /// of range or if a non-integral index is used on a sequence node.
* of range or if a non-integral index is used on a sequence node.
*/
void opIndexAssign(K, V)(V value, K index) @safe void opIndexAssign(K, V)(V value, K index) @safe
{ {
if(isSequence()) if(isSequence())
@ -1028,15 +999,13 @@ struct Node
} }
} }
/** /// 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. /// Otherwise, convert each node to T during iteration.
* Otherwise, convert each node to T during iteration. ///
* /// Throws: NodeException if the node is not a sequence or an
* Throws: NodeException if the node is not a sequence or an /// element could not be converted to specified type.
* element could not be converted to specified type.
*/
int opApply(T)(int delegate(ref T) dg) @trusted int opApply(T)(int delegate(ref T) dg) @trusted
{ {
enforce(isSequence, enforce(isSequence,
@ -1085,15 +1054,13 @@ struct Node
assert(array2 == [11, 12, 13, 14]); assert(array2 == [11, 12, 13, 14]);
} }
/** /// Foreach over a mapping, getting each key/value as K/V.
* Foreach over a mapping, getting each key/value as K/V. ///
* /// If the K and/or V is Node, simply iterate over the nodes in the mapping.
* If the K and/or V is Node, simply iterate over the nodes in the mapping. /// Otherwise, convert each key/value to T during iteration.
* Otherwise, convert each key/value to T during iteration. ///
* /// Throws: NodeException if the node is not a mapping or an
* Throws: NodeException if the node is not a mapping or an /// element could not be converted to specified type.
* element could not be converted to specified type.
*/
int opApply(K, V)(int delegate(ref K, ref V) dg) @trusted int opApply(K, V)(int delegate(ref K, ref V) dg) @trusted
{ {
enforce(isMapping, enforce(isMapping,
@ -1179,21 +1146,19 @@ struct Node
} }
} }
/** /// Add an element to a sequence.
* Add an element to a sequence. ///
* /// This method can only be called on sequence nodes.
* This method can only be called on sequence nodes. ///
* /// If value is a node, it is copied to the sequence directly. Otherwise
* If value is a node, it is copied to the sequence directly. Otherwise /// value is converted to a node and then stored in the sequence.
* value is converted to a node and then stored in the sequence. ///
* /// $(P When emitting, all values in the sequence will be emitted. When
* $(P When emitting, all values in the sequence will be emitted. When /// using the !!set tag, the user needs to ensure that all elements in
* using the !!set tag, the user needs to ensure that all elements in /// the sequence are unique, otherwise $(B invalid) YAML code will be
* the sequence are unique, otherwise $(B invalid) YAML code will be /// emitted.)
* emitted.) ///
* /// Params: value = Value to _add to the sequence.
* Params: value = Value to _add to the sequence.
*/
void add(T)(T value) @safe void add(T)(T value) @safe
{ {
enforce(isSequence(), enforce(isSequence(),
@ -1215,22 +1180,20 @@ struct Node
} }
} }
/** /// Add a key-value pair to a mapping.
* Add a key-value pair to a mapping. ///
* /// This method can only be called on mapping nodes.
* This method can only be called on mapping nodes. ///
* /// If key and/or value is a node, it is copied to the mapping directly.
* If key and/or value is a node, it is copied to the mapping directly. /// Otherwise it is converted to a node and then stored in the mapping.
* Otherwise it is converted to a node and then stored in the mapping. ///
* /// $(P It is possible for the same key to be present more than once in a
* $(P It is possible for the same key to be present more than once in a /// mapping. When emitting, all key-value pairs will be emitted.
* mapping. When emitting, all key-value pairs will be emitted. /// This is useful with the "!!pairs" tag, but will result in
* This is useful with the "!!pairs" tag, but will result in /// $(B invalid) YAML with "!!map" and "!!omap" tags.)
* $(B invalid) YAML with "!!map" and "!!omap" tags.) ///
* /// Params: key = Key to _add.
* Params: key = Key to _add. /// value = Value to _add.
* value = Value to _add.
*/
void add(K, V)(K key, V value) @safe void add(K, V)(K key, V value) @safe
{ {
enforce(isMapping(), enforce(isMapping(),
@ -1252,21 +1215,19 @@ struct Node
} }
} }
/** /// Determine whether a key is in a mapping, and access its value.
* Determine whether a key is in a mapping, and access its value. ///
* /// This method can only be called on mapping nodes.
* This method can only be called on mapping nodes. ///
* /// Params: key = Key to search for.
* Params: key = Key to search for. ///
* /// Returns: A pointer to the value (as a Node) corresponding to key,
* Returns: A pointer to the value (as a Node) corresponding to key, /// or null if not found.
* or null if not found. ///
* /// Note: Any modification to the node can invalidate the returned
* Note: Any modification to the node can invalidate the returned /// pointer.
* pointer. ///
* /// See_Also: contains
* See_Also: contains
*/
Node* opBinaryRight(string op, K)(K key) @trusted if (op == "in") Node* opBinaryRight(string op, K)(K key) @trusted if (op == "in")
{ {
enforce(isMapping, new Error("Trying to use 'in' on a " ~ enforce(isMapping, new Error("Trying to use 'in' on a " ~
@ -1295,19 +1256,17 @@ struct Node
assert(mapping["foo"] == Node("newfoo")); assert(mapping["foo"] == Node("newfoo"));
} }
/** /// Remove first (if any) occurence of a value in a collection.
* Remove first (if any) occurence of a value in a collection. ///
* /// This method can only be called on collection nodes.
* This method can only be called on collection nodes. ///
* /// If the node is a sequence, the first node matching value is removed.
* If the node is a sequence, the first node matching value is removed. /// If the node is a mapping, the first key-value pair where _value
* If the node is a mapping, the first key-value pair where _value /// matches specified value is removed.
* matches specified value is removed. ///
* /// Params: rhs = Value to _remove.
* Params: rhs = Value to _remove. ///
* /// Throws: NodeException if the node is not a collection.
* Throws: NodeException if the node is not a collection.
*/
void remove(T)(T rhs) @trusted void remove(T)(T rhs) @trusted
{ {
remove_!(T, No.key, "remove")(rhs); remove_!(T, No.key, "remove")(rhs);
@ -1338,25 +1297,23 @@ struct Node
} }
} }
/** /// Remove element at the specified index of a collection.
* Remove element at the specified index of a collection. ///
* /// This method can only be called on collection nodes.
* This method can only be called on collection nodes. ///
* /// If the node is a sequence, index must be integral.
* If the node is a sequence, index must be integral. ///
* /// If the node is a mapping, remove the first key-value pair where
* If the node is a mapping, remove the first key-value pair where /// key matches index.
* key matches index. ///
* /// If the node is a mapping and no key matches index, nothing is removed
* If the node is a mapping and no key matches index, nothing is removed /// and no exception is thrown. This ensures behavior siilar to D arrays
* and no exception is thrown. This ensures behavior siilar to D arrays /// and associative arrays.
* and associative arrays. ///
* /// Params: index = Index to remove at.
* Params: index = Index to remove at. ///
* /// Throws: NodeException if the node is not a collection, index is out
* Throws: NodeException if the node is not a collection, index is out /// of range or if a non-integral index is used on a sequence node.
* of range or if a non-integral index is used on a sequence node.
*/
void removeAt(T)(T index) @trusted void removeAt(T)(T index) @trusted
{ {
remove_!(T, Yes.key, "removeAt")(index); remove_!(T, Yes.key, "removeAt")(index);
@ -1415,17 +1372,15 @@ struct Node
} }
package: package:
/* // Construct a node from raw data.
* Construct a node from raw data. //
* // Params: value = Value of the node.
* Params: value = Value of the node. // startMark = Start position of the node in file.
* startMark = Start position of the node in file. // tag = Tag of the node.
* tag = Tag of the node. // scalarStyle = Scalar style of the node.
* scalarStyle = Scalar style of the node. // collectionStyle = Collection style of the node.
* collectionStyle = Collection style of the node. //
* // Returns: Constructed node.
* Returns: Constructed node.
*/
static Node rawNode(Value value, const Mark startMark, const Tag tag, static Node rawNode(Value value, const Mark startMark, const Tag tag,
const ScalarStyle scalarStyle, const ScalarStyle scalarStyle,
const CollectionStyle collectionStyle) @safe const CollectionStyle collectionStyle) @safe
@ -1468,11 +1423,9 @@ struct Node
else static assert(false, "Unknown value type. Is value() in sync with allowed()?"); else static assert(false, "Unknown value type. Is value() in sync with allowed()?");
} }
/* // Equality test with any value.
* Equality test with any value. //
* // 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(Flag!"useTag" useTag, T)(ref T rhs) const @safe bool equals(Flag!"useTag" useTag, T)(ref T rhs) const @safe
{ {
static if(is(Unqual!T == Node)) static if(is(Unqual!T == Node))
@ -1498,13 +1451,11 @@ struct Node
} }
} }
/* // Comparison with another node.
* Comparison with another node. //
* // Used for ordering in mappings and for opEquals.
* Used for ordering in mappings and for opEquals. //
* // useTag determines whether or not to consider tags in the comparison.
* useTag determines whether or not to consider tags in the comparison.
*/
int cmp(Flag!"useTag" useTag)(const ref Node rhs) const @trusted int cmp(Flag!"useTag" useTag)(const ref Node rhs) const @trusted
{ {
// Compare tags - if equal or both null, we need to compare further. // Compare tags - if equal or both null, we need to compare further.
@ -1611,13 +1562,11 @@ struct Node
assert(false, "Unknown type of node for comparison : " ~ type.toString()); assert(false, "Unknown type of node for comparison : " ~ type.toString());
} }
/* // Get a string representation of the node tree. Used for debugging.
* Get a string representation of the node tree. Used for debugging. //
* // Params: level = Level of the node in the tree.
* Params: level = Level of the node in the tree. //
* // Returns: String representing the node tree.
* Returns: String representing the node tree.
*/
@property string debugString(uint level = 0) @trusted @property string debugString(uint level = 0) @trusted
{ {
string indent; string indent;
@ -1660,11 +1609,9 @@ struct Node
return (cast(nothrowType)&value_.type)(); return (cast(nothrowType)&value_.type)();
} }
/* // Determine if the value stored by the node is of specified type.
* Determine if the value stored by the node is of specified type. //
* // This only works for default YAML types, not for user defined types.
* This only works for default YAML types, not for user defined types.
*/
@property bool isType(T)() const @safe nothrow @property bool isType(T)() const @safe nothrow
{ {
return this.type is typeid(Unqual!T); return this.type is typeid(Unqual!T);
@ -1850,15 +1797,13 @@ struct Node
} }
package: package:
/* // Merge a pair into an array of pairs based on merge rules in the YAML spec.
* Merge a pair into an array of pairs based on merge rules in the YAML spec. //
* // The new pair will only be added if there is not already a pair
* The new pair will only be added if there is not already a pair // with the same key.
* with the same key. //
* // Params: pairs = Appender managing the array of pairs to merge into.
* Params: pairs = Appender managing the array of pairs to merge into. // toMerge = Pair to merge.
* toMerge = Pair to merge.
*/
void merge(ref Appender!(Node.Pair[], Node.Pair) pairs, ref Node.Pair toMerge) @trusted void merge(ref Appender!(Node.Pair[], Node.Pair) pairs, ref Node.Pair toMerge) @trusted
{ {
foreach(ref pair; pairs.data) foreach(ref pair; pairs.data)
@ -1868,15 +1813,13 @@ void merge(ref Appender!(Node.Pair[], Node.Pair) pairs, ref Node.Pair toMerge) @
pairs.put(toMerge); pairs.put(toMerge);
} }
/* // Merge pairs into an array of pairs based on merge rules in the YAML spec.
* Merge pairs into an array of pairs based on merge rules in the YAML spec. //
* // Any new pair will only be added if there is not already a pair
* Any new pair will only be added if there is not already a pair // with the same key.
* with the same key. //
* // Params: pairs = Appender managing the array of pairs to merge into.
* Params: pairs = Appender managing the array of pairs to merge into. // toMerge = Pairs to merge.
* toMerge = Pairs to merge.
*/
void merge(ref Appender!(Node.Pair[], Node.Pair) pairs, Node.Pair[] toMerge) @trusted void merge(ref Appender!(Node.Pair[], Node.Pair) pairs, Node.Pair[] toMerge) @trusted
{ {
bool eq(ref Node.Pair a, ref Node.Pair b){return a.key == b.key;} bool eq(ref Node.Pair a, ref Node.Pair b){return a.key == b.key;}