Reverted doc style due to DDoc issues.
This commit is contained in:
parent
fdf4cecddb
commit
0f017646fc
|
@ -51,19 +51,20 @@ package class ConstructorException : YAMLException
|
||||||
|
|
||||||
private alias ConstructorException Error;
|
private alias ConstructorException Error;
|
||||||
|
|
||||||
/// Constructs YAML values.
|
/** Constructs YAML values.
|
||||||
///
|
*
|
||||||
/// Each YAML scalar, sequence or mapping has a tag specifying its data type.
|
* Each YAML scalar, sequence or mapping has a tag specifying its data type.
|
||||||
/// Constructor uses user-specifyable functions to create a node of desired
|
* Constructor uses user-specifyable functions to create a node of desired
|
||||||
/// data type from a scalar, sequence or mapping.
|
* data type from a scalar, sequence or mapping.
|
||||||
///
|
*
|
||||||
///
|
*
|
||||||
/// Each of these functions is associated with a tag, and can process either
|
* Each of these functions is associated with a tag, and can process either
|
||||||
/// a scalar, a sequence, or a mapping. The constructor passes each value to
|
* a scalar, a sequence, or a mapping. The constructor passes each value to
|
||||||
/// the function with corresponding tag, which then returns the resulting value
|
* the function with corresponding tag, which then returns the resulting value
|
||||||
/// that can be stored in a node.
|
* that can be stored in a node.
|
||||||
///
|
*
|
||||||
/// If a tag is detected with no known constructor function, it is considered an error.
|
* If a tag is detected with no known constructor function, it is considered an error.
|
||||||
|
*/
|
||||||
final class Constructor
|
final class Constructor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -116,72 +117,73 @@ final class Constructor
|
||||||
fromMapping_ = null;
|
fromMapping_ = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a constructor function from scalar.
|
/** Add a constructor function from scalar.
|
||||||
///
|
*
|
||||||
/// The function must take a reference to $(D Node) to construct from.
|
* The function must take a reference to $(D Node) to construct from.
|
||||||
/// The node contains a string for scalars, $(Node[]) for sequences and
|
* The node contains a string for scalars, $(D Node[]) for sequences and
|
||||||
/// $(Node.Pair[]) for mappings.
|
* $(D Node.Pair[]) for mappings.
|
||||||
///
|
*
|
||||||
/// Any exception thrown by this function will be caught by D:YAML and
|
* Any exception thrown by this function will be caught by D:YAML and
|
||||||
/// its message will be added to a $(YAMLException) that will also tell
|
* its message will be added to a $(D YAMLException) that will also tell
|
||||||
/// the user which type failed to construct, and position in the file.
|
* the user which type failed to construct, and position in the file.
|
||||||
///
|
*
|
||||||
///
|
*
|
||||||
/// The value returned by this function will be stored in the resulting node.
|
* The value returned by this function will be stored in the resulting node.
|
||||||
///
|
*
|
||||||
/// Only one constructor function can be set for one tag.
|
* Only one constructor function can be set for one tag.
|
||||||
///
|
*
|
||||||
///
|
*
|
||||||
/// Structs and classes must implement the $(D opCmp()) operator for D:YAML
|
* Structs and classes must implement the $(D opCmp()) operator for D:YAML
|
||||||
/// support. The signature of the operator that must be implemented
|
* support. The signature of the operator that must be implemented
|
||||||
/// is $(D const int opCmp(ref const MyStruct s)) for structs where
|
* is $(D const int opCmp(ref const MyStruct s)) for structs where
|
||||||
/// $(I MyStruct) is the struct type, and $(D int opCmp(Object o)) for
|
* $(I MyStruct) is the struct type, and $(D int opCmp(Object o)) for
|
||||||
/// classes. Note that the class $(D opCmp()) should not alter the compared
|
* classes. Note that the class $(D opCmp()) should not alter the compared
|
||||||
/// values - it is not const for compatibility reasons.
|
* values - it is not const for compatibility reasons.
|
||||||
///
|
*
|
||||||
/// Params: tag = Tag for the function to handle.
|
* Params: tag = Tag for the function to handle.
|
||||||
/// ctor = Constructor function.
|
* ctor = Constructor function.
|
||||||
///
|
*
|
||||||
/// Example:
|
* Example:
|
||||||
///
|
*
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// import std.string;
|
* import std.string;
|
||||||
///
|
*
|
||||||
/// import dyaml.all;
|
* import dyaml.all;
|
||||||
///
|
*
|
||||||
/// struct MyStruct
|
* struct MyStruct
|
||||||
/// {
|
* {
|
||||||
/// int x, y, z;
|
* int x, y, z;
|
||||||
///
|
*
|
||||||
/// //Any D:YAML type must have a custom opCmp operator.
|
* //Any D:YAML type must have a custom opCmp operator.
|
||||||
/// //This is used for ordering in mappings.
|
* //This is used for ordering in mappings.
|
||||||
/// const int opCmp(ref const MyStruct s)
|
* const int opCmp(ref const MyStruct s)
|
||||||
/// {
|
* {
|
||||||
/// if(x != s.x){return x - s.x;}
|
* if(x != s.x){return x - s.x;}
|
||||||
/// if(y != s.y){return y - s.y;}
|
* if(y != s.y){return y - s.y;}
|
||||||
/// if(z != s.z){return z - s.z;}
|
* if(z != s.z){return z - s.z;}
|
||||||
/// return 0;
|
* return 0;
|
||||||
/// }
|
* }
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// MyStruct constructMyStructScalar(ref Node node)
|
* MyStruct constructMyStructScalar(ref Node node)
|
||||||
/// {
|
* {
|
||||||
/// //Guaranteed to be string as we construct from scalar.
|
* //Guaranteed to be string as we construct from scalar.
|
||||||
/// //!mystruct x:y:z
|
* //!mystruct x:y:z
|
||||||
/// auto parts = node.as!string().split(":");
|
* auto parts = node.as!string().split(":");
|
||||||
/// // If this throws, the D:YAML will handle it and throw a YAMLException.
|
* // If this throws, the D:YAML will handle it and throw a YAMLException.
|
||||||
/// return MyStruct(to!int(parts[0]), to!int(parts[1]), to!int(parts[2]));
|
* return MyStruct(to!int(parts[0]), to!int(parts[1]), to!int(parts[2]));
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// void main()
|
* void main()
|
||||||
/// {
|
* {
|
||||||
/// auto loader = Loader("file.yaml");
|
* auto loader = Loader("file.yaml");
|
||||||
/// auto constructor = new Constructor;
|
* auto constructor = new Constructor;
|
||||||
/// constructor.addConstructorScalar("!mystruct", &constructMyStructScalar);
|
* constructor.addConstructorScalar("!mystruct", &constructMyStructScalar);
|
||||||
/// loader.constructor = constructor;
|
* loader.constructor = constructor;
|
||||||
/// Node node = loader.load();
|
* Node node = loader.load();
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
|
*/
|
||||||
void addConstructorScalar(T)(const string tag, T function(ref Node) ctor)
|
void addConstructorScalar(T)(const string tag, T function(ref Node) ctor)
|
||||||
@safe nothrow
|
@safe nothrow
|
||||||
{
|
{
|
||||||
|
@ -190,48 +192,49 @@ final class Constructor
|
||||||
(*delegates!string)[t] = deleg;
|
(*delegates!string)[t] = deleg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a constructor function from sequence.
|
/** Add a constructor function from sequence.
|
||||||
///
|
*
|
||||||
/// See_Also: addConstructorScalar
|
* See_Also: addConstructorScalar
|
||||||
///
|
*
|
||||||
/// Example:
|
* Example:
|
||||||
///
|
*
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// import std.string;
|
* import std.string;
|
||||||
///
|
*
|
||||||
/// import dyaml.all;
|
* import dyaml.all;
|
||||||
///
|
*
|
||||||
/// struct MyStruct
|
* struct MyStruct
|
||||||
/// {
|
* {
|
||||||
/// int x, y, z;
|
* int x, y, z;
|
||||||
///
|
*
|
||||||
/// //Any D:YAML type must have a custom opCmp operator.
|
* //Any D:YAML type must have a custom opCmp operator.
|
||||||
/// //This is used for ordering in mappings.
|
* //This is used for ordering in mappings.
|
||||||
/// const int opCmp(ref const MyStruct s)
|
* const int opCmp(ref const MyStruct s)
|
||||||
/// {
|
* {
|
||||||
/// if(x != s.x){return x - s.x;}
|
* if(x != s.x){return x - s.x;}
|
||||||
/// if(y != s.y){return y - s.y;}
|
* if(y != s.y){return y - s.y;}
|
||||||
/// if(z != s.z){return z - s.z;}
|
* if(z != s.z){return z - s.z;}
|
||||||
/// return 0;
|
* return 0;
|
||||||
/// }
|
* }
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// MyStruct constructMyStructSequence(ref Node node)
|
* MyStruct constructMyStructSequence(ref Node node)
|
||||||
/// {
|
* {
|
||||||
/// //node is guaranteed to be sequence.
|
* //node is guaranteed to be sequence.
|
||||||
/// //!mystruct [x, y, z]
|
* //!mystruct [x, y, z]
|
||||||
/// return MyStruct(node[0].as!int, node[1].as!int, node[2].as!int);
|
* return MyStruct(node[0].as!int, node[1].as!int, node[2].as!int);
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// void main()
|
* void main()
|
||||||
/// {
|
* {
|
||||||
/// auto loader = Loader("file.yaml");
|
* auto loader = Loader("file.yaml");
|
||||||
/// auto constructor = new Constructor;
|
* auto constructor = new Constructor;
|
||||||
/// constructor.addConstructorSequence("!mystruct", &constructMyStructSequence);
|
* constructor.addConstructorSequence("!mystruct", &constructMyStructSequence);
|
||||||
/// loader.constructor = constructor;
|
* loader.constructor = constructor;
|
||||||
/// Node node = loader.load();
|
* Node node = loader.load();
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
|
*/
|
||||||
void addConstructorSequence(T)(const string tag, T function(ref Node) ctor)
|
void addConstructorSequence(T)(const string tag, T function(ref Node) ctor)
|
||||||
@safe nothrow
|
@safe nothrow
|
||||||
{
|
{
|
||||||
|
@ -240,48 +243,49 @@ final class Constructor
|
||||||
(*delegates!(Node[]))[t] = deleg;
|
(*delegates!(Node[]))[t] = deleg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a constructor function from a mapping.
|
/** Add a constructor function from a mapping.
|
||||||
///
|
*
|
||||||
/// See_Also: addConstructorScalar
|
* See_Also: addConstructorScalar
|
||||||
///
|
*
|
||||||
/// Example:
|
* Example:
|
||||||
///
|
*
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// import std.string;
|
* import std.string;
|
||||||
///
|
*
|
||||||
/// import dyaml.all;
|
* import dyaml.all;
|
||||||
///
|
*
|
||||||
/// struct MyStruct
|
* struct MyStruct
|
||||||
/// {
|
* {
|
||||||
/// int x, y, z;
|
* int x, y, z;
|
||||||
///
|
*
|
||||||
/// //Any D:YAML type must have a custom opCmp operator.
|
* //Any D:YAML type must have a custom opCmp operator.
|
||||||
/// //This is used for ordering in mappings.
|
* //This is used for ordering in mappings.
|
||||||
/// const int opCmp(ref const MyStruct s)
|
* const int opCmp(ref const MyStruct s)
|
||||||
/// {
|
* {
|
||||||
/// if(x != s.x){return x - s.x;}
|
* if(x != s.x){return x - s.x;}
|
||||||
/// if(y != s.y){return y - s.y;}
|
* if(y != s.y){return y - s.y;}
|
||||||
/// if(z != s.z){return z - s.z;}
|
* if(z != s.z){return z - s.z;}
|
||||||
/// return 0;
|
* return 0;
|
||||||
/// }
|
* }
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// MyStruct constructMyStructMapping(ref Node node)
|
* MyStruct constructMyStructMapping(ref Node node)
|
||||||
/// {
|
* {
|
||||||
/// //node is guaranteed to be mapping.
|
* //node is guaranteed to be mapping.
|
||||||
/// //!mystruct {"x": x, "y": y, "z": z}
|
* //!mystruct {"x": x, "y": y, "z": z}
|
||||||
/// return MyStruct(node["x"].as!int, node["y"].as!int, node["z"].as!int);
|
* return MyStruct(node["x"].as!int, node["y"].as!int, node["z"].as!int);
|
||||||
/// }
|
* }
|
||||||
///
|
*
|
||||||
/// void main()
|
* void main()
|
||||||
/// {
|
* {
|
||||||
/// auto loader = Loader("file.yaml");
|
* auto loader = Loader("file.yaml");
|
||||||
/// auto constructor = new Constructor;
|
* auto constructor = new Constructor;
|
||||||
/// constructor.addConstructorMapping("!mystruct", &constructMyStructMapping);
|
* constructor.addConstructorMapping("!mystruct", &constructMyStructMapping);
|
||||||
/// loader.constructor = constructor;
|
* loader.constructor = constructor;
|
||||||
/// Node node = loader.load();
|
* Node node = loader.load();
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
|
*/
|
||||||
void addConstructorMapping(T)(const string tag, T function(ref Node) ctor)
|
void addConstructorMapping(T)(const string tag, T function(ref Node) ctor)
|
||||||
@safe nothrow
|
@safe nothrow
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
|
||||||
/// Functionality that may be sometimes needed but allows unsafe or unstandard
|
/// Functionality that may sometimes be needed but allows unsafe or unstandard behavior, and should only be used in specific cases.
|
||||||
/// behavior, and should only be used in specific cases.
|
|
||||||
module dyaml.hacks;
|
module dyaml.hacks;
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,25 +14,26 @@ import dyaml.node;
|
||||||
import dyaml.style;
|
import dyaml.style;
|
||||||
|
|
||||||
|
|
||||||
/// Get the scalar style a YAML node had in the file it was loaded from.
|
/** Get the scalar style a node had in the file it was loaded from.
|
||||||
///
|
*
|
||||||
/// This is only useful for nodes loaded from files.
|
* This is only useful for nodes loaded from files.
|
||||||
///
|
*
|
||||||
/// This is a "hack" because a YAML application is supposed to be unaware of styles
|
* This is a "hack" because a YAML application is supposed to be unaware of styles
|
||||||
/// used in YAML styles, i.e. treating different styles differently is unstandard.
|
* used in YAML styles, i.e. treating different styles differently is unstandard.
|
||||||
/// However, determining style may be useful in some cases, e.g. YAML utilities.
|
* However, determining style may be useful in some cases, e.g. YAML utilities.
|
||||||
///
|
*
|
||||||
/// May only be called on scalar nodes (nodes where node.isScalar() == true).
|
* May only be called on scalar nodes (nodes where node.isScalar() == true).
|
||||||
///
|
*
|
||||||
/// Example:
|
* Example:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// // Node node // loaded from a file
|
* // Node node // loaded from a file
|
||||||
/// if(node.isScalar)
|
* if(node.isScalar)
|
||||||
/// {
|
* {
|
||||||
/// import std.stdio;
|
* import std.stdio;
|
||||||
/// writeln(node.scalarStyleHack());
|
* writeln(node.scalarStyleHack());
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
|
*/
|
||||||
ScalarStyle scalarStyleHack(ref const(Node) node) @safe nothrow
|
ScalarStyle scalarStyleHack(ref const(Node) node) @safe nothrow
|
||||||
{
|
{
|
||||||
assert(node.isScalar, "Trying to get scalar style of a non-scalar node");
|
assert(node.isScalar, "Trying to get scalar style of a non-scalar node");
|
||||||
|
@ -64,7 +64,7 @@ unittest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Set the scalar style a YAML node had in the file it was loaded from.
|
/// Set the scalar style node should have when written to a file.
|
||||||
///
|
///
|
||||||
/// Setting the style might be useful when generating YAML or reformatting existing
|
/// Setting the style might be useful when generating YAML or reformatting existing
|
||||||
/// files.
|
/// files.
|
||||||
|
@ -84,7 +84,7 @@ unittest
|
||||||
assert(node.scalarStyleHack() == ScalarStyle.DoubleQuoted);
|
assert(node.scalarStyleHack() == ScalarStyle.DoubleQuoted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the scalar style a YAML node had in the file it was loaded from.
|
/// Set the collection style node should have when written to a file.
|
||||||
///
|
///
|
||||||
/// Setting the style might be useful when generating YAML or reformatting existing
|
/// Setting the style might be useful when generating YAML or reformatting existing
|
||||||
/// files.
|
/// files.
|
||||||
|
|
|
@ -24,78 +24,79 @@ import dyaml.scanner;
|
||||||
import dyaml.token;
|
import dyaml.token;
|
||||||
|
|
||||||
|
|
||||||
/// Loads YAML documents from files or streams.
|
/** Loads YAML documents from files or streams.
|
||||||
///
|
*
|
||||||
/// User specified Constructor and/or Resolver can be used to support new
|
* User specified Constructor and/or Resolver can be used to support new
|
||||||
/// tags / data types.
|
* tags / data types.
|
||||||
///
|
*
|
||||||
/// Examples:
|
* Examples:
|
||||||
///
|
*
|
||||||
/// Load single YAML document from a file:
|
* Load single YAML document from a file:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// auto rootNode = Loader("file.yaml").load();
|
* auto rootNode = Loader("file.yaml").load();
|
||||||
/// ...
|
* ...
|
||||||
/// --------------------
|
* --------------------
|
||||||
///
|
*
|
||||||
/// Load all YAML documents from a file:
|
* Load all YAML documents from a file:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// auto nodes = Loader("file.yaml").loadAll();
|
* auto nodes = Loader("file.yaml").loadAll();
|
||||||
/// ...
|
* ...
|
||||||
/// --------------------
|
* --------------------
|
||||||
///
|
*
|
||||||
/// Iterate over YAML documents in a file, lazily loading them:
|
* Iterate over YAML documents in a file, lazily loading them:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// auto loader = Loader("file.yaml");
|
* auto loader = Loader("file.yaml");
|
||||||
///
|
*
|
||||||
/// foreach(ref node; loader)
|
* foreach(ref node; loader)
|
||||||
/// {
|
* {
|
||||||
/// ...
|
* ...
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
///
|
*
|
||||||
/// Load YAML from a string:
|
* Load YAML from a string:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// char[] yaml_input = "red: '#ff0000'\n"
|
* char[] yaml_input = "red: '#ff0000'\n"
|
||||||
/// "green: '#00ff00'\n"
|
* "green: '#00ff00'\n"
|
||||||
/// "blue: '#0000ff'".dup;
|
* "blue: '#0000ff'".dup;
|
||||||
///
|
*
|
||||||
/// auto colors = Loader.fromString(yaml_input).load();
|
* auto colors = Loader.fromString(yaml_input).load();
|
||||||
///
|
*
|
||||||
/// foreach(string color, string value; colors)
|
* foreach(string color, string value; colors)
|
||||||
/// {
|
* {
|
||||||
/// import std.stdio;
|
* import std.stdio;
|
||||||
/// writeln(color, " is ", value, " in HTML/CSS");
|
* writeln(color, " is ", value, " in HTML/CSS");
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
///
|
*
|
||||||
/// Load a file into a buffer in memory and then load YAML from that buffer:
|
* Load a file into a buffer in memory and then load YAML from that buffer:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// try
|
* try
|
||||||
/// {
|
* {
|
||||||
/// import std.file;
|
* import std.file;
|
||||||
/// void[] buffer = std.file.read("file.yaml");
|
* void[] buffer = std.file.read("file.yaml");
|
||||||
/// auto yamlNode = Loader(buffer);
|
* auto yamlNode = Loader(buffer);
|
||||||
///
|
*
|
||||||
/// // Read data from yamlNode here...
|
* // Read data from yamlNode here...
|
||||||
/// }
|
* }
|
||||||
/// catch(FileException e)
|
* catch(FileException e)
|
||||||
/// {
|
* {
|
||||||
/// writeln("Failed to read file 'file.yaml'");
|
* writeln("Failed to read file 'file.yaml'");
|
||||||
/// }
|
* }
|
||||||
/// --------------------
|
* --------------------
|
||||||
///
|
*
|
||||||
/// Use a custom constructor/resolver to support custom data types and/or implicit tags:
|
* Use a custom constructor/resolver to support custom data types and/or implicit tags:
|
||||||
/// --------------------
|
* --------------------
|
||||||
/// auto constructor = new Constructor();
|
* auto constructor = new Constructor();
|
||||||
/// auto resolver = new Resolver();
|
* auto resolver = new Resolver();
|
||||||
///
|
*
|
||||||
/// // Add constructor functions / resolver expressions here...
|
* // Add constructor functions / resolver expressions here...
|
||||||
///
|
*
|
||||||
/// auto loader = Loader("file.yaml");
|
* auto loader = Loader("file.yaml");
|
||||||
/// loader.constructor = constructor;
|
* loader.constructor = constructor;
|
||||||
/// loader.resolver = resolver;
|
* loader.resolver = resolver;
|
||||||
/// auto rootNode = loader.load(node);
|
* auto rootNode = loader.load(node);
|
||||||
/// --------------------
|
* --------------------
|
||||||
|
*/
|
||||||
struct Loader
|
struct Loader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -119,11 +120,12 @@ struct Loader
|
||||||
@disable int opCmp(ref Loader);
|
@disable int opCmp(ref Loader);
|
||||||
@disable bool opEquals(ref Loader);
|
@disable bool opEquals(ref Loader);
|
||||||
|
|
||||||
/// Construct a Loader to load YAML from a file.
|
/** Construct a Loader to load YAML from a file.
|
||||||
///
|
*
|
||||||
/// Params: filename = Name of the file to load from.
|
* Params: filename = Name of the file to load from.
|
||||||
///
|
*
|
||||||
/// Throws: YAMLException if the file could not be opened or read.
|
* Throws: YAMLException if the file could not be opened or read.
|
||||||
|
*/
|
||||||
this(string filename) @trusted
|
this(string filename) @trusted
|
||||||
{
|
{
|
||||||
name_ = filename;
|
name_ = filename;
|
||||||
|
@ -144,17 +146,18 @@ struct Loader
|
||||||
return Loader(cast(ubyte[])data.dup);
|
return Loader(cast(ubyte[])data.dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a Loader to load YAML from a string (char []).
|
/** Construct a Loader to load YAML from a string (char []).
|
||||||
///
|
*
|
||||||
/// Params: data = String to load YAML from. $(B will) be overwritten during
|
* Params: data = String to load YAML from. $(B will) be overwritten during
|
||||||
/// parsing as D:YAML reuses memory. Use data.dup if you don't
|
* parsing as D:YAML reuses memory. Use data.dup if you don't
|
||||||
/// want to modify the original string.
|
* want to modify the original string.
|
||||||
///
|
*
|
||||||
/// Returns: Loader loading YAML from given string.
|
* Returns: Loader loading YAML from given string.
|
||||||
///
|
*
|
||||||
/// Throws:
|
* Throws:
|
||||||
///
|
*
|
||||||
/// YAMLException if data could not be read (e.g. a decoding error)
|
* YAMLException if data could not be read (e.g. a decoding error)
|
||||||
|
*/
|
||||||
static Loader fromString(char[] data) @safe
|
static Loader fromString(char[] data) @safe
|
||||||
{
|
{
|
||||||
return Loader(cast(ubyte[])data);
|
return Loader(cast(ubyte[])data);
|
||||||
|
@ -186,19 +189,21 @@ struct Loader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a Loader to load YAML from a buffer.
|
/** Construct a Loader to load YAML from a buffer.
|
||||||
///
|
*
|
||||||
/// Params: yamlData = Buffer with YAML data to load. This may be e.g. a file
|
* Params: yamlData = Buffer with YAML data to load. This may be e.g. a file
|
||||||
/// loaded to memory or a string with YAML data. Note that
|
* loaded to memory or a string with YAML data. Note that
|
||||||
/// buffer $(B will) be overwritten, as D:YAML minimizes
|
* buffer $(B will) be overwritten, as D:YAML minimizes
|
||||||
/// memory allocations by reusing the input _buffer.
|
* memory allocations by reusing the input _buffer.
|
||||||
///
|
*
|
||||||
/// D:YAML looks for byte-order-makrs YAML files encoded in UTF-16/UTF-32
|
*
|
||||||
/// (and sometimes UTF-8) use to specify the encoding and endianness, so it
|
* Note that D:YAML looks for byte-order-marks YAML files encoded in
|
||||||
/// should be enough to load an entire file to a buffer and pass it to D:YAML,
|
* UTF-16/UTF-32 (and sometimes UTF-8) use to specify the encoding and
|
||||||
/// regardless of Unicode encoding.
|
* endianness, so it should be enough to load an entire file to a buffer and
|
||||||
///
|
* pass it to D:YAML, regardless of Unicode encoding.
|
||||||
/// Throws: YAMLException if yamlData contains data illegal in YAML.
|
*
|
||||||
|
* Throws: YAMLException if yamlData contains data illegal in YAML.
|
||||||
|
*/
|
||||||
this(void[] yamlData) @safe
|
this(void[] yamlData) @safe
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -242,16 +247,17 @@ struct Loader
|
||||||
constructor_ = constructor;
|
constructor_ = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load single YAML document.
|
/** Load single YAML document.
|
||||||
///
|
*
|
||||||
/// If none or more than one YAML document is found, this throws a YAMLException.
|
* If none or more than one YAML document is found, this throws a YAMLException.
|
||||||
///
|
*
|
||||||
/// This can only be called once; this is enforced by contract.
|
* This can only be called once; this is enforced by contract.
|
||||||
///
|
*
|
||||||
/// Returns: Root node of the document.
|
* Returns: Root node of the document.
|
||||||
///
|
*
|
||||||
/// Throws: YAMLException if there wasn't exactly one document
|
* Throws: YAMLException if there wasn't exactly one document
|
||||||
/// or on a YAML parsing error.
|
* or on a YAML parsing error.
|
||||||
|
*/
|
||||||
Node load() @safe
|
Node load() @safe
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -273,17 +279,18 @@ struct Loader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load all YAML documents.
|
/** Load all YAML documents.
|
||||||
///
|
*
|
||||||
/// This is just a shortcut that iterates over all documents and returns them
|
* This is just a shortcut that iterates over all documents and returns them
|
||||||
/// all at once. Calling loadAll after iterating over the node or vice versa
|
* all at once. Calling loadAll after iterating over the node or vice versa
|
||||||
/// will not return any documents, as they have all been parsed already.
|
* will not return any documents, as they have all been parsed already.
|
||||||
///
|
*
|
||||||
/// This can only be called once; this is enforced by contract.
|
* This can only be called once; this is enforced by contract.
|
||||||
///
|
*
|
||||||
/// Returns: Array of root nodes of all documents in the file/stream.
|
* Returns: Array of root nodes of all documents in the file/stream.
|
||||||
///
|
*
|
||||||
/// Throws: YAMLException on a parsing error.
|
* Throws: YAMLException on a parsing error.
|
||||||
|
*/
|
||||||
Node[] loadAll() @trusted
|
Node[] loadAll() @trusted
|
||||||
{
|
{
|
||||||
Node[] nodes;
|
Node[] nodes;
|
||||||
|
@ -295,13 +302,14 @@ struct Loader
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Foreach over YAML documents.
|
/** Foreach over YAML documents.
|
||||||
///
|
*
|
||||||
/// Parses documents lazily, when they are needed.
|
* Parses documents lazily, when they are needed.
|
||||||
///
|
*
|
||||||
/// Foreach over a Loader can only be used once; this is enforced by contract.
|
* Foreach over a Loader can only be used once; this is enforced by contract.
|
||||||
///
|
*
|
||||||
/// Throws: YAMLException on a parsing error.
|
* Throws: YAMLException on a parsing error.
|
||||||
|
*/
|
||||||
int opApply(int delegate(ref Node) dg) @trusted
|
int opApply(int delegate(ref Node) dg) @trusted
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,11 +178,12 @@ private struct Pair
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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:
|
||||||
|
@ -220,25 +221,26 @@ 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))
|
||||||
{
|
{
|
||||||
|
@ -272,30 +274,31 @@ 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[]))
|
||||||
{
|
{
|
||||||
|
@ -333,32 +336,33 @@ 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);
|
||||||
|
@ -387,41 +391,42 @@ 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
|
||||||
|
@ -494,32 +499,25 @@ 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 compares 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, gets a value of type T from the node and tests
|
||||||
/// 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:
|
* Params: rhs = Variable to test equality with.
|
||||||
/// --------------------
|
*
|
||||||
/// auto node = Node(42);
|
* Returns: true if equal, false otherwise.
|
||||||
///
|
*/
|
||||||
/// assert(node == 42);
|
|
||||||
/// assert(node != "42");
|
|
||||||
/// assert(node != "43");
|
|
||||||
/// --------------------
|
|
||||||
///
|
|
||||||
/// Params: rhs = Variable to test equality with.
|
|
||||||
///
|
|
||||||
/// 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);
|
||||||
}
|
}
|
||||||
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto node = Node(42);
|
auto node = Node(42);
|
||||||
|
@ -535,48 +533,49 @@ 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))
|
||||||
{
|
{
|
||||||
|
@ -711,13 +710,14 @@ 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;}
|
||||||
|
@ -726,24 +726,25 @@ 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. containsKey() can be used to determine if a mapping
|
||||||
/// has a specific key.
|
* 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)
|
||||||
|
@ -807,36 +808,31 @@ 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.
|
* Params: rhs = Item to look for. Use YAMLNull to check for a null value.
|
||||||
///
|
*
|
||||||
/// 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 mapping contains specified key.
|
||||||
///
|
*
|
||||||
/// If the node is a mapping, check if it has a key
|
* Params: rhs = Key to look for. Use YAMLNull to check for a null key.
|
||||||
/// that matches specified key.
|
*
|
||||||
///
|
* Returns: true if rhs was found, false otherwise.
|
||||||
/// To check for a null key, use YAMLNull for rhs.
|
*
|
||||||
///
|
* Throws: NodeException if the node is not a mapping.
|
||||||
/// Params: rhs = Item to look for.
|
*/
|
||||||
///
|
|
||||||
/// Returns: true if rhs was found, false otherwise.
|
|
||||||
///
|
|
||||||
/// 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);
|
||||||
|
@ -921,26 +917,27 @@ 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())
|
||||||
|
@ -1005,13 +1002,14 @@ 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,
|
||||||
|
@ -1060,13 +1058,14 @@ 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,
|
||||||
|
@ -1152,19 +1151,20 @@ 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(),
|
||||||
|
@ -1186,20 +1186,21 @@ 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(),
|
||||||
|
@ -1221,20 +1222,22 @@ 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) @system
|
||||||
|
if (op == "in")
|
||||||
{
|
{
|
||||||
enforce(isMapping, new Error("Trying to use 'in' on a " ~
|
enforce(isMapping, new Error("Trying to use 'in' on a " ~
|
||||||
nodeTypeString ~ " node", startMark_));
|
nodeTypeString ~ " node", startMark_));
|
||||||
|
@ -1262,17 +1265,18 @@ 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);
|
||||||
|
@ -1303,23 +1307,24 @@ 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);
|
||||||
|
@ -1355,26 +1360,15 @@ struct Node
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute hash of the node.
|
// Compute hash of the node.
|
||||||
hash_t toHash() const nothrow @safe
|
hash_t toHash() @safe nothrow const
|
||||||
{
|
{
|
||||||
// Hack to allow const nothrow @safe.
|
const tagHash = tag_.isNull ? 0 : tag_.toHash();
|
||||||
// Should be rewritten once std.variant is fixed.
|
// Variant toHash is not const at the moment, so we need to const-cast.
|
||||||
hash_t unsafeHash() nothrow @trusted
|
return tagHash + value_.toHash();
|
||||||
{
|
}
|
||||||
const tagHash = tag_.isNull ? 0 : tag_.toHash();
|
unittest
|
||||||
// Variant toHash is not nothrow at the moment, so we need to catch
|
{
|
||||||
// an exception that is never thrown.
|
writeln("Node(42).toHash(): ", Node(42).toHash());
|
||||||
try
|
|
||||||
{
|
|
||||||
// Variant toHash is not const at the moment, so we need to const-cast.
|
|
||||||
return tagHash + (cast(Value)value_).toHash();
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
assert(false, "Unexpected exception caught");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return unsafeHash();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
package:
|
package:
|
||||||
|
|
Loading…
Reference in a new issue