convert examples to doc'd unittests, fix some parameter errors, remove some redundancy
This commit is contained in:
parent
7b316fdffb
commit
9d35b773b4
|
@ -137,47 +137,6 @@ final class Constructor
|
|||
*
|
||||
* Params: tag = Tag for the function to handle.
|
||||
* ctor = Constructor function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* --------------------
|
||||
* import std.string;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* MyStruct constructMyStructScalar(ref Node node)
|
||||
* {
|
||||
* //Guaranteed to be string as we construct from scalar.
|
||||
* //!mystruct x:y:z
|
||||
* auto parts = node.as!string().split(":");
|
||||
* // 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]));
|
||||
* }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto loader = Loader("file.yaml");
|
||||
* auto constructor = new Constructor;
|
||||
* constructor.addConstructorScalar("!mystruct", &constructMyStructScalar);
|
||||
* loader.constructor = constructor;
|
||||
* Node node = loader.load();
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
void addConstructorScalar(T)(const string tag, T function(ref Node) ctor)
|
||||
{
|
||||
|
@ -185,49 +144,44 @@ final class Constructor
|
|||
auto deleg = addConstructor!T(t, ctor);
|
||||
(*delegates!string)[t] = deleg;
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
static struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static MyStruct constructMyStructScalar(ref Node node) @safe
|
||||
{
|
||||
//Guaranteed to be string as we construct from scalar.
|
||||
//!mystruct x:y:z
|
||||
auto parts = node.as!string().split(":");
|
||||
// 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]));
|
||||
}
|
||||
|
||||
auto loader = Loader.fromString("!mystruct 12:34:56".dup);
|
||||
auto constructor = new Constructor;
|
||||
constructor.addConstructorScalar("!mystruct", &constructMyStructScalar);
|
||||
loader.constructor = constructor;
|
||||
Node node = loader.load();
|
||||
assert(node.get!MyStruct == MyStruct(12, 34, 56));
|
||||
}
|
||||
|
||||
/** Add a constructor function from sequence.
|
||||
*
|
||||
* See_Also: addConstructorScalar
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* --------------------
|
||||
* import std.string;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* MyStruct constructMyStructSequence(ref Node node)
|
||||
* {
|
||||
* //node is guaranteed to be sequence.
|
||||
* //!mystruct [x, y, z]
|
||||
* return MyStruct(node[0].as!int, node[1].as!int, node[2].as!int);
|
||||
* }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto loader = Loader("file.yaml");
|
||||
* auto constructor = new Constructor;
|
||||
* constructor.addConstructorSequence("!mystruct", &constructMyStructSequence);
|
||||
* loader.constructor = constructor;
|
||||
* Node node = loader.load();
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
void addConstructorSequence(T)(const string tag, T function(ref Node) ctor)
|
||||
{
|
||||
|
@ -235,49 +189,40 @@ final class Constructor
|
|||
auto deleg = addConstructor!T(t, ctor);
|
||||
(*delegates!(Node[]))[t] = deleg;
|
||||
}
|
||||
///
|
||||
@safe unittest {
|
||||
static struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static MyStruct constructMyStructSequence(ref Node node) @safe
|
||||
{
|
||||
//node is guaranteed to be sequence.
|
||||
//!mystruct [x, y, z]
|
||||
return MyStruct(node[0].as!int, node[1].as!int, node[2].as!int);
|
||||
}
|
||||
auto loader = Loader.fromString("!mystruct [1,2,3]".dup);
|
||||
auto constructor = new Constructor;
|
||||
constructor.addConstructorSequence("!mystruct", &constructMyStructSequence);
|
||||
loader.constructor = constructor;
|
||||
Node node = loader.load();
|
||||
assert(node.get!MyStruct == MyStruct(1, 2, 3));
|
||||
}
|
||||
|
||||
/** Add a constructor function from a mapping.
|
||||
*
|
||||
* See_Also: addConstructorScalar
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* --------------------
|
||||
* import std.string;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* MyStruct constructMyStructMapping(ref Node node)
|
||||
* {
|
||||
* //node is guaranteed to be mapping.
|
||||
* //!mystruct {"x": x, "y": y, "z": z}
|
||||
* return MyStruct(node["x"].as!int, node["y"].as!int, node["z"].as!int);
|
||||
* }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto loader = Loader("file.yaml");
|
||||
* auto constructor = new Constructor;
|
||||
* constructor.addConstructorMapping("!mystruct", &constructMyStructMapping);
|
||||
* loader.constructor = constructor;
|
||||
* Node node = loader.load();
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
void addConstructorMapping(T)(const string tag, T function(ref Node) ctor)
|
||||
{
|
||||
|
@ -285,6 +230,36 @@ final class Constructor
|
|||
auto deleg = addConstructor!T(t, ctor);
|
||||
(*delegates!(Node.Pair[]))[t] = deleg;
|
||||
}
|
||||
///
|
||||
@safe unittest {
|
||||
static struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static MyStruct constructMyStructMapping(ref Node node) @safe
|
||||
{
|
||||
//node is guaranteed to be mapping.
|
||||
//!mystruct {"x": x, "y": y, "z": z}
|
||||
return MyStruct(node["x"].as!int, node["y"].as!int, node["z"].as!int);
|
||||
}
|
||||
auto loader = Loader.fromString(`!mystruct {"x": 11, "y": 22, "z": 33}`.dup);
|
||||
auto constructor = new Constructor;
|
||||
constructor.addConstructorMapping("!mystruct", &constructMyStructMapping);
|
||||
loader.constructor = constructor;
|
||||
Node node = loader.load();
|
||||
assert(node.get!MyStruct == MyStruct(11, 22, 33));
|
||||
}
|
||||
|
||||
package:
|
||||
/*
|
||||
|
|
|
@ -31,52 +31,10 @@ import dyaml.tagdirective;
|
|||
/**
|
||||
* Dumps YAML documents to files or streams.
|
||||
*
|
||||
* User specified Representer and/or Resolver can be used to support new
|
||||
* User specified Representer and/or Resolver can be used to support new
|
||||
* tags / data types.
|
||||
*
|
||||
* Setters are provided to affect output details (style, encoding, etc.).
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Write to a file:
|
||||
* --------------------
|
||||
* auto node = Node([1, 2, 3, 4, 5]);
|
||||
* Dumper("file.yaml").dump(node);
|
||||
* --------------------
|
||||
*
|
||||
* Write multiple YAML documents to a file:
|
||||
* --------------------
|
||||
* auto node1 = Node([1, 2, 3, 4, 5]);
|
||||
* auto node2 = Node("This document contains only one string");
|
||||
* Dumper("file.yaml").dump(node1, node2);
|
||||
*
|
||||
* //Or with an array:
|
||||
* //Dumper("file.yaml").dump([node1, node2]);
|
||||
*
|
||||
*
|
||||
* --------------------
|
||||
*
|
||||
* Write to memory:
|
||||
* --------------------
|
||||
* import std.stream;
|
||||
* auto stream = new YMemoryStream();
|
||||
* auto node = Node([1, 2, 3, 4, 5]);
|
||||
* Dumper(stream).dump(node);
|
||||
* --------------------
|
||||
*
|
||||
* Use a custom representer/resolver to support custom data types and/or implicit tags:
|
||||
* --------------------
|
||||
* auto node = Node([1, 2, 3, 4, 5]);
|
||||
* auto representer = new Representer();
|
||||
* auto resolver = new Resolver();
|
||||
*
|
||||
* //Add representer functions / resolver expressions here...
|
||||
*
|
||||
* auto dumper = Dumper("file.yaml");
|
||||
* dumper.representer = representer;
|
||||
* dumper.resolver = resolver;
|
||||
* dumper.dump(node);
|
||||
* --------------------
|
||||
*/
|
||||
struct Dumper
|
||||
{
|
||||
|
@ -271,21 +229,10 @@ struct Dumper
|
|||
*
|
||||
* Each prefix MUST not be empty.
|
||||
*
|
||||
* The "!!" handle is used for default YAML _tags with prefix
|
||||
* The "!!" handle is used for default YAML _tags with prefix
|
||||
* "tag:yaml.org,2002:". This can be overridden.
|
||||
*
|
||||
* Params: tags = Tag directives (keys are handles, values are prefixes).
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* Dumper dumper = Dumper("file.yaml");
|
||||
* string[string] directives;
|
||||
* directives["!short!"] = "tag:long.org,2011:";
|
||||
* //This will emit tags starting with "tag:long.org,2011"
|
||||
* //with a "!short!" prefix instead.
|
||||
* dumper.tagDirectives(directives);
|
||||
* dumper.dump(Node("foo"));
|
||||
* --------------------
|
||||
*/
|
||||
@property void tagDirectives(string[string] tags) pure @safe
|
||||
{
|
||||
|
@ -300,6 +247,17 @@ struct Dumper
|
|||
}
|
||||
tags_ = t;
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
Dumper dumper = Dumper("example.yaml");
|
||||
string[string] directives;
|
||||
directives["!short!"] = "tag:long.org,2011:";
|
||||
//This will emit tags starting with "tag:long.org,2011"
|
||||
//with a "!short!" prefix instead.
|
||||
dumper.tagDirectives(directives);
|
||||
dumper.dump(Node("foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump one or more YAML _documents to the file/stream.
|
||||
|
@ -357,3 +315,38 @@ struct Dumper
|
|||
}
|
||||
}
|
||||
}
|
||||
///Write to a file
|
||||
@safe unittest
|
||||
{
|
||||
auto node = Node([1, 2, 3, 4, 5]);
|
||||
Dumper("example.yaml").dump(node);
|
||||
}
|
||||
///Write multiple YAML documents to a file
|
||||
@safe unittest
|
||||
{
|
||||
auto node1 = Node([1, 2, 3, 4, 5]);
|
||||
auto node2 = Node("This document contains only one string");
|
||||
Dumper("example.yaml").dump(node1, node2);
|
||||
//Or with an array:
|
||||
Dumper("example.yaml").dump([node1, node2]);
|
||||
}
|
||||
///Write to memory
|
||||
@safe unittest
|
||||
{
|
||||
import dyaml.stream;
|
||||
auto stream = new YMemoryStream();
|
||||
auto node = Node([1, 2, 3, 4, 5]);
|
||||
Dumper(stream).dump(node);
|
||||
}
|
||||
///Use a custom representer/resolver to support custom data types and/or implicit tags
|
||||
@safe unittest
|
||||
{
|
||||
auto node = Node([1, 2, 3, 4, 5]);
|
||||
auto representer = new Representer();
|
||||
auto resolver = new Resolver();
|
||||
//Add representer functions / resolver expressions here...
|
||||
auto dumper = Dumper("example.yaml");
|
||||
dumper.representer = representer;
|
||||
dumper.resolver = resolver;
|
||||
dumper.dump(node);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ Event event(EventID id)(const Mark start, const Mark end, const string anchor =
|
|||
* anchor = Anchor of the sequence, if any.
|
||||
* tag = Tag of the sequence, if specified.
|
||||
* implicit = Should the tag be implicitly resolved?
|
||||
* style = Style to use when outputting document.
|
||||
*/
|
||||
Event collectionStartEvent(EventID id)
|
||||
(const Mark start, const Mark end, const string anchor, const string tag,
|
||||
|
|
|
@ -17,20 +17,6 @@ package:
|
|||
* Struct holding multiple named boolean values in a single byte.
|
||||
*
|
||||
* Can hold at most 8 values.
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* Flags!("empty", "multiline") flags;
|
||||
* assert(flags.empty == false && flags.multiline == false);
|
||||
* flags.multiline = true;
|
||||
* assert(flags.empty == false && flags.multiline == true);
|
||||
* flags.empty = true;
|
||||
* assert(flags.empty == true && flags.multiline == true);
|
||||
* flags.multiline = false;
|
||||
* assert(flags.empty == true && flags.multiline == false);
|
||||
* flags.empty = false;
|
||||
* assert(flags.empty == false && flags.multiline == false);
|
||||
* --------------------
|
||||
*/
|
||||
struct Flags(names ...) if(names.length <= 8)
|
||||
{
|
||||
|
@ -72,6 +58,7 @@ struct Flags(names ...) if(names.length <= 8)
|
|||
///Flag accessors.
|
||||
mixin(flags(names));
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
|
|
@ -23,22 +23,22 @@ import dyaml.style;
|
|||
* 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).
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* // Node node // loaded from a file
|
||||
* if(node.isScalar)
|
||||
* {
|
||||
* import std.stdio;
|
||||
* writeln(node.scalarStyleHack());
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
ScalarStyle scalarStyleHack(ref const(Node) node) @safe nothrow
|
||||
{
|
||||
assert(node.isScalar, "Trying to get scalar style of a non-scalar node");
|
||||
return node.scalarStyle;
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
import dyaml;
|
||||
Node node = Loader.fromString(`"42"`.dup).load(); // loaded from a file
|
||||
if(node.isScalar)
|
||||
{
|
||||
assert(node.scalarStyleHack() == ScalarStyle.DoubleQuoted);
|
||||
}
|
||||
}
|
||||
@safe unittest
|
||||
{
|
||||
writeln("D:YAML scalarStyleHack getter unittest");
|
||||
|
|
|
@ -28,74 +28,6 @@ import dyaml.token;
|
|||
*
|
||||
* User specified Constructor and/or Resolver can be used to support new
|
||||
* tags / data types.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Load single YAML document from a file:
|
||||
* --------------------
|
||||
* auto rootNode = Loader("file.yaml").load();
|
||||
* ...
|
||||
* --------------------
|
||||
*
|
||||
* Load all YAML documents from a file:
|
||||
* --------------------
|
||||
* auto nodes = Loader("file.yaml").loadAll();
|
||||
* ...
|
||||
* --------------------
|
||||
*
|
||||
* Iterate over YAML documents in a file, lazily loading them:
|
||||
* --------------------
|
||||
* auto loader = Loader("file.yaml");
|
||||
*
|
||||
* foreach(ref node; loader)
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* --------------------
|
||||
*
|
||||
* Load YAML from a string:
|
||||
* --------------------
|
||||
* char[] yaml_input = "red: '#ff0000'\n"
|
||||
* "green: '#00ff00'\n"
|
||||
* "blue: '#0000ff'".dup;
|
||||
*
|
||||
* auto colors = Loader.fromString(yaml_input).load();
|
||||
*
|
||||
* foreach(string color, string value; colors)
|
||||
* {
|
||||
* import std.stdio;
|
||||
* writeln(color, " is ", value, " in HTML/CSS");
|
||||
* }
|
||||
* --------------------
|
||||
*
|
||||
* Load a file into a buffer in memory and then load YAML from that buffer:
|
||||
* --------------------
|
||||
* try
|
||||
* {
|
||||
* import std.file;
|
||||
* void[] buffer = std.file.read("file.yaml");
|
||||
* auto yamlNode = Loader(buffer);
|
||||
*
|
||||
* // Read data from yamlNode here...
|
||||
* }
|
||||
* catch(FileException e)
|
||||
* {
|
||||
* writeln("Failed to read file 'file.yaml'");
|
||||
* }
|
||||
* --------------------
|
||||
*
|
||||
* Use a custom constructor/resolver to support custom data types and/or implicit tags:
|
||||
* --------------------
|
||||
* auto constructor = new Constructor();
|
||||
* auto resolver = new Resolver();
|
||||
*
|
||||
* // Add constructor functions / resolver expressions here...
|
||||
*
|
||||
* auto loader = Loader("file.yaml");
|
||||
* loader.constructor = constructor;
|
||||
* loader.resolver = resolver;
|
||||
* auto rootNode = loader.load(node);
|
||||
* --------------------
|
||||
*/
|
||||
struct Loader
|
||||
{
|
||||
|
@ -375,7 +307,48 @@ struct Loader
|
|||
if(constructor_ is null) { constructor_ = new Constructor(); }
|
||||
}
|
||||
}
|
||||
/// Load single YAML document from a file:
|
||||
@safe unittest
|
||||
{
|
||||
write("example.yaml", "Hello world!");
|
||||
auto rootNode = Loader("example.yaml").load();
|
||||
assert(rootNode == "Hello world!");
|
||||
}
|
||||
/// Load all YAML documents from a file:
|
||||
@safe unittest
|
||||
{
|
||||
import std.file : write;
|
||||
write("example.yaml",
|
||||
"---\n"~
|
||||
"Hello world!\n"~
|
||||
"...\n"~
|
||||
"---\n"~
|
||||
"Hello world 2!\n"~
|
||||
"...\n"
|
||||
);
|
||||
auto nodes = Loader("example.yaml").loadAll();
|
||||
assert(nodes.length == 2);
|
||||
}
|
||||
/// Iterate over YAML documents in a file, lazily loading them:
|
||||
@safe unittest
|
||||
{
|
||||
import std.file : write;
|
||||
write("example.yaml",
|
||||
"---\n"~
|
||||
"Hello world!\n"~
|
||||
"...\n"~
|
||||
"---\n"~
|
||||
"Hello world 2!\n"~
|
||||
"...\n"
|
||||
);
|
||||
auto loader = Loader("example.yaml");
|
||||
|
||||
foreach(ref node; loader)
|
||||
{
|
||||
//Do something
|
||||
}
|
||||
}
|
||||
/// Load YAML from a string:
|
||||
@safe unittest
|
||||
{
|
||||
char[] yaml_input = ("red: '#ff0000'\n" ~
|
||||
|
@ -390,3 +363,50 @@ struct Loader
|
|||
writeln(color, " is ", value, " in HTML/CSS");
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a file into a buffer in memory and then load YAML from that buffer:
|
||||
@safe unittest
|
||||
{
|
||||
import std.file : read, write;
|
||||
import std.stdio : writeln;
|
||||
// Create a yaml document
|
||||
write("example.yaml",
|
||||
"---\n"~
|
||||
"Hello world!\n"~
|
||||
"...\n"~
|
||||
"---\n"~
|
||||
"Hello world 2!\n"~
|
||||
"...\n"
|
||||
);
|
||||
try
|
||||
{
|
||||
void[] buffer = read("example.yaml");
|
||||
auto yamlNode = Loader(buffer);
|
||||
|
||||
// Read data from yamlNode here...
|
||||
}
|
||||
catch(FileException e)
|
||||
{
|
||||
writeln("Failed to read file 'example.yaml'");
|
||||
}
|
||||
}
|
||||
/// Use a custom constructor/resolver to support custom data types and/or implicit tags:
|
||||
@safe unittest
|
||||
{
|
||||
import std.file : write;
|
||||
// Create a yaml document
|
||||
write("example.yaml",
|
||||
"---\n"~
|
||||
"Hello world!\n"~
|
||||
"...\n"
|
||||
);
|
||||
auto constructor = new Constructor();
|
||||
auto resolver = new Resolver();
|
||||
|
||||
// Add constructor functions / resolver expressions here...
|
||||
|
||||
auto loader = Loader("example.yaml");
|
||||
loader.constructor = constructor;
|
||||
loader.resolver = resolver;
|
||||
auto rootNode = loader.load();
|
||||
}
|
||||
|
|
|
@ -311,13 +311,6 @@ struct Node
|
|||
* must be in full form, e.g. "tag:yaml.org,2002:set",
|
||||
* not a shortcut, like "!!set".
|
||||
*
|
||||
* Examples:
|
||||
* --------------------
|
||||
* // Will be emitted as a sequence (default for arrays)
|
||||
* auto seq = Node([1, 2, 3, 4, 5]);
|
||||
* // Will be emitted as a set (overriden tag)
|
||||
* auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
|
||||
* --------------------
|
||||
*/
|
||||
this(T)(T[] array, const string tag = null) @trusted
|
||||
if (!isSomeString!(T[]))
|
||||
|
@ -341,6 +334,14 @@ struct Node
|
|||
value_ = Value(nodes);
|
||||
}
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
// Will be emitted as a sequence (default for arrays)
|
||||
auto seq = Node([1, 2, 3, 4, 5]);
|
||||
// Will be emitted as a set (overriden tag)
|
||||
auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
|
||||
}
|
||||
@safe unittest
|
||||
{
|
||||
with(Node([1, 2, 3]))
|
||||
|
@ -350,10 +351,6 @@ struct Node
|
|||
assert(opIndex(2).as!int == 3);
|
||||
}
|
||||
|
||||
// Will be emitted as a sequence (default for arrays)
|
||||
auto seq = Node([1, 2, 3, 4, 5]);
|
||||
// Will be emitted as a set (overriden tag)
|
||||
auto set = Node([1, 2, 3, 4, 5], "tag:yaml.org,2002:set");
|
||||
}
|
||||
|
||||
/** Construct a node from an associative _array.
|
||||
|
@ -373,15 +370,6 @@ struct Node
|
|||
* in full form, e.g. "tag:yaml.org,2002:omap", not a
|
||||
* shortcut, like "!!omap".
|
||||
*
|
||||
* Examples:
|
||||
* --------------------
|
||||
* // Will be emitted as an unordered mapping (default for mappings)
|
||||
* auto map = Node([1 : "a", 2 : "b"]);
|
||||
* // Will be emitted as an ordered map (overriden tag)
|
||||
* auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
|
||||
* // Will be emitted as pairs (overriden tag)
|
||||
* auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
|
||||
* --------------------
|
||||
*/
|
||||
this(K, V)(V[K] array, const string tag = null) @trusted
|
||||
{
|
||||
|
@ -391,6 +379,16 @@ struct Node
|
|||
foreach(key, ref value; array){pairs ~= Pair(key, value);}
|
||||
value_ = Value(pairs);
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
// Will be emitted as an unordered mapping (default for mappings)
|
||||
auto map = Node([1 : "a", 2 : "b"]);
|
||||
// Will be emitted as an ordered map (overriden tag)
|
||||
auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
|
||||
// Will be emitted as pairs (overriden tag)
|
||||
auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
|
||||
}
|
||||
@safe unittest
|
||||
{
|
||||
int[string] aa;
|
||||
|
@ -403,12 +401,6 @@ struct Node
|
|||
assert(opIndex("2").as!int == 2);
|
||||
}
|
||||
|
||||
// Will be emitted as an unordered mapping (default for mappings)
|
||||
auto map = Node([1 : "a", 2 : "b"]);
|
||||
// Will be emitted as an ordered map (overriden tag)
|
||||
auto omap = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:omap");
|
||||
// Will be emitted as pairs (overriden tag)
|
||||
auto pairs = Node([1 : "a", 2 : "b"], "tag:yaml.org,2002:pairs");
|
||||
}
|
||||
|
||||
/** Construct a node from arrays of _keys and _values.
|
||||
|
@ -437,15 +429,6 @@ struct Node
|
|||
* in full form, e.g. "tag:yaml.org,2002:omap", not a
|
||||
* shortcut, like "!!omap".
|
||||
*
|
||||
* Examples:
|
||||
* --------------------
|
||||
* // Will be emitted as an unordered mapping (default for mappings)
|
||||
* auto map = Node([1, 2], ["a", "b"]);
|
||||
* // Will be emitted as an ordered map (overriden tag)
|
||||
* auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap");
|
||||
* // Will be emitted as pairs (overriden tag)
|
||||
* auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs");
|
||||
* --------------------
|
||||
*/
|
||||
this(K, V)(K[] keys, V[] values, const string tag = null) @trusted
|
||||
if(!(isSomeString!(K[]) || isSomeString!(V[])))
|
||||
|
@ -463,6 +446,16 @@ struct Node
|
|||
foreach(i; 0 .. keys.length){pairs ~= Pair(keys[i], values[i]);}
|
||||
value_ = Value(pairs);
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
// Will be emitted as an unordered mapping (default for mappings)
|
||||
auto map = Node([1, 2], ["a", "b"]);
|
||||
// Will be emitted as an ordered map (overridden tag)
|
||||
auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap");
|
||||
// Will be emitted as pairs (overriden tag)
|
||||
auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs");
|
||||
}
|
||||
@safe unittest
|
||||
{
|
||||
with(Node(["1", "2"], [1, 2]))
|
||||
|
@ -472,12 +465,6 @@ struct Node
|
|||
assert(opIndex("2").as!int == 2);
|
||||
}
|
||||
|
||||
// Will be emitted as an unordered mapping (default for mappings)
|
||||
auto map = Node([1, 2], ["a", "b"]);
|
||||
// Will be emitted as an ordered map (overriden tag)
|
||||
auto omap = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:omap");
|
||||
// Will be emitted as pairs (overriden tag)
|
||||
auto pairs = Node([1, 2], ["a", "b"], "tag:yaml.org,2002:pairs");
|
||||
}
|
||||
|
||||
/// Is this node valid (initialized)?
|
||||
|
@ -580,17 +567,6 @@ struct Node
|
|||
* by old versions of the program, which expect the node to be a scalar.
|
||||
* )
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Automatic type conversion:
|
||||
* --------------------
|
||||
* auto node = Node(42);
|
||||
*
|
||||
* assert(node.as!int == 42);
|
||||
* assert(node.as!string == "42");
|
||||
* assert(node.as!double == 42.0);
|
||||
* --------------------
|
||||
*
|
||||
* Returns: Value of the node as specified type.
|
||||
*
|
||||
* Throws: NodeException if unable to convert to specified type, or if
|
||||
|
@ -669,6 +645,15 @@ struct Node
|
|||
}
|
||||
assert(false, "This code should never be reached");
|
||||
}
|
||||
/// Automatic type conversion
|
||||
@safe unittest
|
||||
{
|
||||
auto node = Node(42);
|
||||
|
||||
assert(node.get!int == 42);
|
||||
assert(node.get!string == "42");
|
||||
assert(node.get!double == 42.0);
|
||||
}
|
||||
@safe unittest
|
||||
{
|
||||
assertThrown!NodeException(Node("42").get!int);
|
||||
|
@ -968,7 +953,9 @@ struct Node
|
|||
*
|
||||
* To set element at a null index, use YAMLNull for index.
|
||||
*
|
||||
* Params: index = Index of the value to set.
|
||||
* Params:
|
||||
* value = Value to assign.
|
||||
* index = Index of the value to set.
|
||||
*
|
||||
* 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.
|
||||
|
|
|
@ -363,17 +363,7 @@ auto decodeUTF8NoGC(Flag!"validated" validated)(const(char[]) str, ref size_t in
|
|||
else { return invalidUTF; }
|
||||
}
|
||||
|
||||
/// @nogc version of std.utf.decode() for char[], but assumes str is valid UTF-8.
|
||||
///
|
||||
/// The caller $(B must) handle ASCII (< 0x80) characters manually; this is asserted to
|
||||
/// force code using this function to be efficient.
|
||||
///
|
||||
/// Params:
|
||||
///
|
||||
/// str = Will decode the first code point from this string. Must be valid UTF-8,
|
||||
/// otherwise undefined behavior WILL occur.
|
||||
/// index = Index in str where the code point starts. Will be updated to point to the
|
||||
/// next code point.
|
||||
/// ditto
|
||||
alias decodeValidUTF8NoGC = decodeUTF8NoGC!(Yes.validated);
|
||||
|
||||
/// @nogc version of std.utf.encode() for char[].
|
||||
|
@ -451,18 +441,7 @@ auto encodeCharNoGC(Flag!"validated" validated)(ref char[4] buf, dchar c)
|
|||
}
|
||||
}
|
||||
|
||||
/// @nogc version of std.utf.encode() for char[], but assumes c is a valid UTF-32 char.
|
||||
///
|
||||
/// The caller $(B must) handle ASCII (< 0x80) characters manually; this is asserted to
|
||||
/// force code using this function to be efficient.
|
||||
///
|
||||
/// Params:
|
||||
///
|
||||
/// buf = Buffer to write the encoded result to.
|
||||
/// c = Character to encode. Must be valid UTF-32, otherwise undefined behavior
|
||||
/// $(D will) occur.
|
||||
///
|
||||
/// Returns: Number of bytes the encoded character takes up in buf.
|
||||
/// ditto
|
||||
alias encodeValidCharNoGC = encodeCharNoGC!(Yes.validated);
|
||||
|
||||
/// @nogc version of std.utf.isValidDchar
|
||||
|
|
|
@ -108,7 +108,8 @@ final class Representer
|
|||
* throw a $(D RepresenterException). See the example for more information.
|
||||
*
|
||||
*
|
||||
* Only one function may be specified for one data type. Default data
|
||||
*
|
||||
* Only one function may be specified for one data type. Default data
|
||||
* types already have representer functions unless disabled in the
|
||||
* $(D Representer) constructor.
|
||||
*
|
||||
|
@ -121,106 +122,6 @@ final class Representer
|
|||
* values - it is not const for compatibility reasons.
|
||||
*
|
||||
* Params: representer = Representer function to add.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Representing a simple struct:
|
||||
* --------------------
|
||||
* import std.string;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Node representMyStruct(ref Node node, Representer representer)
|
||||
* {
|
||||
* //The node is guaranteed to be MyStruct as we add representer for MyStruct.
|
||||
* auto value = node.as!MyStruct;
|
||||
* //Using custom scalar format, x:y:z.
|
||||
* auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
* //Representing as a scalar, with custom tag to specify this data type.
|
||||
* return representer.representScalar("!mystruct.tag", scalar);
|
||||
* }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto dumper = Dumper("file.yaml");
|
||||
* auto representer = new Representer;
|
||||
* representer.addRepresenter!MyStruct(&representMyStruct);
|
||||
* dumper.representer = representer;
|
||||
* dumper.dump(Node(MyStruct(1,2,3)));
|
||||
* }
|
||||
* --------------------
|
||||
*
|
||||
* Representing a class:
|
||||
* --------------------
|
||||
* import std.string;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* class MyClass
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* this(int x, int y, int z)
|
||||
* {
|
||||
* this.x = x;
|
||||
* this.y = y;
|
||||
* this.z = z;
|
||||
* }
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* override int opCmp(Object o)
|
||||
* {
|
||||
* MyClass s = cast(MyClass)o;
|
||||
* if(s is null){return -1;}
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* ///Useful for Node.as!string .
|
||||
* override string toString()
|
||||
* {
|
||||
* return format("MyClass(%s, %s, %s)", x, y, z);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* //Same as representMyStruct.
|
||||
* Node representMyClass(ref Node node, Representer representer)
|
||||
* {
|
||||
* //The node is guaranteed to be MyClass as we add representer for MyClass.
|
||||
* auto value = node.as!MyClass;
|
||||
* //Using custom scalar format, x:y:z.
|
||||
* auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
* //Representing as a scalar, with custom tag to specify this data type.
|
||||
* return representer.representScalar("!myclass.tag", scalar);
|
||||
* }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto dumper = Dumper("file.yaml");
|
||||
* auto representer = new Representer;
|
||||
* representer.addRepresenter!MyClass(&representMyClass);
|
||||
* dumper.representer = representer;
|
||||
* dumper.dump(Node(new MyClass(1,2,3)));
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
void addRepresenter(T)(Node function(ref Node, Representer) @safe representer)
|
||||
@safe pure
|
||||
|
@ -230,6 +131,96 @@ final class Representer
|
|||
" already specified. Can't specify another one");
|
||||
representers_[typeid(T)] = representer;
|
||||
}
|
||||
/// Representing a simple struct:
|
||||
unittest {
|
||||
import std.string;
|
||||
|
||||
import dyaml;
|
||||
|
||||
struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Node representMyStruct(ref Node node, Representer representer) @safe
|
||||
{
|
||||
//The node is guaranteed to be MyStruct as we add representer for MyStruct.
|
||||
auto value = node.as!MyStruct;
|
||||
//Using custom scalar format, x:y:z.
|
||||
auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
//Representing as a scalar, with custom tag to specify this data type.
|
||||
return representer.representScalar("!mystruct.tag", scalar);
|
||||
}
|
||||
|
||||
auto dumper = Dumper("example.yaml");
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||
dumper.representer = representer;
|
||||
dumper.dump(Node(MyStruct(1,2,3)));
|
||||
}
|
||||
/// Representing a class:
|
||||
unittest {
|
||||
import std.string;
|
||||
|
||||
import dyaml;
|
||||
|
||||
class MyClass
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
this(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
override int opCmp(Object o)
|
||||
{
|
||||
MyClass s = cast(MyClass)o;
|
||||
if(s is null){return -1;}
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///Useful for Node.as!string .
|
||||
override string toString()
|
||||
{
|
||||
return format("MyClass(%s, %s, %s)", x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
//Same as representMyStruct.
|
||||
static Node representMyClass(ref Node node, Representer representer) @safe
|
||||
{
|
||||
//The node is guaranteed to be MyClass as we add representer for MyClass.
|
||||
auto value = node.as!MyClass;
|
||||
//Using custom scalar format, x:y:z.
|
||||
auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
//Representing as a scalar, with custom tag to specify this data type.
|
||||
return representer.representScalar("!myclass.tag", scalar);
|
||||
}
|
||||
|
||||
auto dumper = Dumper("example.yaml");
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!MyClass(&representMyClass);
|
||||
dumper.representer = representer;
|
||||
dumper.dump(Node(new MyClass(1,2,3)));
|
||||
}
|
||||
|
||||
//If profiling shows a bottleneck on tag construction in these 3 methods,
|
||||
//we'll need to take Tag directly and have string based wrappers for
|
||||
|
@ -246,31 +237,6 @@ final class Representer
|
|||
* If the node was loaded before, previous _style will always be used.
|
||||
*
|
||||
* Returns: The represented node.
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Node representMyStruct(ref Node node, Representer representer)
|
||||
* {
|
||||
* auto value = node.as!MyStruct;
|
||||
* auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
* return representer.representScalar("!mystruct.tag", scalar);
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
Node representScalar(string tag, string scalar,
|
||||
ScalarStyle style = ScalarStyle.Invalid) @trusted
|
||||
|
@ -279,6 +245,37 @@ final class Representer
|
|||
return Node.rawNode(Node.Value(scalar), Mark(), tag, style,
|
||||
CollectionStyle.Invalid);
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Node representMyStruct(ref Node node, Representer representer)
|
||||
{
|
||||
auto value = node.as!MyStruct;
|
||||
auto scalar = format("%s:%s:%s", value.x, value.y, value.z);
|
||||
return representer.representScalar("!mystruct.tag", scalar);
|
||||
}
|
||||
|
||||
auto dumper = Dumper("example.yaml");
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||
dumper.representer = representer;
|
||||
dumper.dump(Node(MyStruct(1,2,3)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent a _sequence with specified _tag, representing children first.
|
||||
|
@ -293,33 +290,6 @@ final class Representer
|
|||
* Returns: The represented node.
|
||||
*
|
||||
* Throws: $(D RepresenterException) if a child could not be represented.
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Node representMyStruct(ref Node node, Representer representer)
|
||||
* {
|
||||
* auto value = node.as!MyStruct;
|
||||
* auto nodes = [Node(value.x), Node(value.y), Node(value.z)];
|
||||
* //use flow style
|
||||
* return representer.representSequence("!mystruct.tag", nodes,
|
||||
* CollectionStyle.Flow);
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
Node representSequence(string tag, Node[] sequence,
|
||||
CollectionStyle style = CollectionStyle.Invalid) @trusted
|
||||
|
@ -341,14 +311,46 @@ final class Representer
|
|||
|
||||
if(style == CollectionStyle.Invalid)
|
||||
{
|
||||
style = defaultCollectionStyle_ != CollectionStyle.Invalid
|
||||
style = defaultCollectionStyle_ != CollectionStyle.Invalid
|
||||
? defaultCollectionStyle_
|
||||
: bestStyle;
|
||||
}
|
||||
return Node.rawNode(Node.Value(value), Mark(), tag,
|
||||
ScalarStyle.Invalid, style);
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Node representMyStruct(ref Node node, Representer representer)
|
||||
{
|
||||
auto value = node.as!MyStruct;
|
||||
auto nodes = [Node(value.x), Node(value.y), Node(value.z)];
|
||||
//use flow style
|
||||
return representer.representSequence("!mystruct.tag", nodes,
|
||||
CollectionStyle.Flow);
|
||||
}
|
||||
|
||||
auto dumper = Dumper("example.yaml");
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||
dumper.representer = representer;
|
||||
dumper.dump(Node(MyStruct(1,2,3)));
|
||||
}
|
||||
/**
|
||||
* Represent a mapping with specified _tag, representing children first.
|
||||
*
|
||||
|
@ -362,33 +364,6 @@ final class Representer
|
|||
* Returns: The represented node.
|
||||
*
|
||||
* Throws: $(D RepresenterException) if a child could not be represented.
|
||||
*
|
||||
* Example:
|
||||
* --------------------
|
||||
* struct MyStruct
|
||||
* {
|
||||
* int x, y, z;
|
||||
*
|
||||
* //Any D:YAML type must have a custom opCmp operator.
|
||||
* //This is used for ordering in mappings.
|
||||
* const int opCmp(ref const MyStruct s)
|
||||
* {
|
||||
* if(x != s.x){return x - s.x;}
|
||||
* if(y != s.y){return y - s.y;}
|
||||
* if(z != s.z){return z - s.z;}
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Node representMyStruct(ref Node node, Representer representer)
|
||||
* {
|
||||
* auto value = node.as!MyStruct;
|
||||
* auto pairs = [Node.Pair("x", value.x),
|
||||
* Node.Pair("y", value.y),
|
||||
* Node.Pair("z", value.z)];
|
||||
* return representer.representMapping("!mystruct.tag", pairs);
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
Node representMapping(string tag, Node.Pair[] pairs,
|
||||
CollectionStyle style = CollectionStyle.Invalid) @trusted
|
||||
|
@ -425,6 +400,39 @@ final class Representer
|
|||
return Node.rawNode(Node.Value(value), Mark(), tag,
|
||||
ScalarStyle.Invalid, style);
|
||||
}
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
struct MyStruct
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
//Any D:YAML type must have a custom opCmp operator.
|
||||
//This is used for ordering in mappings.
|
||||
const int opCmp(ref const MyStruct s)
|
||||
{
|
||||
if(x != s.x){return x - s.x;}
|
||||
if(y != s.y){return y - s.y;}
|
||||
if(z != s.z){return z - s.z;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Node representMyStruct(ref Node node, Representer representer)
|
||||
{
|
||||
auto value = node.as!MyStruct;
|
||||
auto pairs = [Node.Pair("x", value.x),
|
||||
Node.Pair("y", value.y),
|
||||
Node.Pair("z", value.z)];
|
||||
return representer.representMapping("!mystruct.tag", pairs);
|
||||
}
|
||||
|
||||
auto dumper = Dumper("example.yaml");
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!MyStruct(&representMyStruct);
|
||||
dumper.representer = representer;
|
||||
dumper.dump(Node(MyStruct(1,2,3)));
|
||||
}
|
||||
|
||||
package:
|
||||
//Represent a node based on its type, and return the represented result.
|
||||
|
|
|
@ -92,28 +92,6 @@ final class Resolver
|
|||
* regexp = Regular expression the scalar must match to have this _tag.
|
||||
* first = String of possible starting characters of the scalar.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* Resolve scalars starting with 'A' to !_tag :
|
||||
* --------------------
|
||||
* import std.regex;
|
||||
*
|
||||
* import dyaml.all;
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* auto loader = Loader("file.txt");
|
||||
* auto resolver = new Resolver();
|
||||
* resolver.addImplicitResolver("!tag", std.regex.regex("A.*"), "A");
|
||||
* loader.resolver = resolver;
|
||||
*
|
||||
* //Note that we have no constructor from tag "!tag", so we can't
|
||||
* //actually load anything that resolves to this tag.
|
||||
* //See Constructor API documentation and tutorial for more information.
|
||||
*
|
||||
* auto node = loader.load();
|
||||
* }
|
||||
* --------------------
|
||||
*/
|
||||
void addImplicitResolver(string tag, Regex!char regexp, string first)
|
||||
pure @safe
|
||||
|
@ -127,6 +105,24 @@ final class Resolver
|
|||
yamlImplicitResolvers_[c] ~= tuple(tag, regexp);
|
||||
}
|
||||
}
|
||||
/// Resolve scalars starting with 'A' to !_tag
|
||||
unittest {
|
||||
import std.regex;
|
||||
|
||||
import dyaml;
|
||||
|
||||
|
||||
auto loader = Loader("example.yaml");
|
||||
auto resolver = new Resolver();
|
||||
resolver.addImplicitResolver("!tag", regex("A.*"), "A");
|
||||
loader.resolver = resolver;
|
||||
|
||||
//Note that we have no constructor from tag "!tag", so we can't
|
||||
//actually load anything that resolves to this tag.
|
||||
//See Constructor API documentation and tutorial for more information.
|
||||
|
||||
//auto node = loader.load();
|
||||
}
|
||||
|
||||
package:
|
||||
/*
|
||||
|
|
|
@ -103,6 +103,7 @@ static assert(Token.sizeof <= 32, "Token has unexpected size");
|
|||
/// end = End position of the token.
|
||||
/// value = Value of the token.
|
||||
/// directive = Directive type (YAML or TAG in YAML 1.1).
|
||||
/// nameEnd = Position of the end of the name
|
||||
Token directiveToken(const Mark start, const Mark end, char[] value,
|
||||
DirectiveType directive, const uint nameEnd) @safe pure nothrow @nogc
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue