convert Resolver to struct (#229)

convert Resolver to struct
merged-on-behalf-of: Basile-z <Basile-z@users.noreply.github.com>
This commit is contained in:
Cameron Ross 2019-02-05 05:30:48 -03:30 committed by The Dlang Bot
parent fff8cead76
commit 8de1a45922
8 changed files with 72 additions and 92 deletions

View file

@ -12,12 +12,10 @@ int main(string[] args)
try
{
auto resolver = new Resolver;
resolver.addImplicitResolver("!color", regex("[0-9a-fA-F]{6}"),
"0123456789abcdefABCDEF");
auto loader = Loader.fromFile("input.yaml");
loader.resolver = resolver;
loader.resolver.addImplicitResolver("!color", regex("[0-9a-fA-F]{6}"),
"0123456789abcdefABCDEF");
auto root = loader.load();

View file

@ -101,7 +101,7 @@ void main(string[] args) //@safe
{
// Instead of constructing a resolver/constructor with each Loader,
// construct them once to remove noise when profiling.
auto resolver = new Resolver();
auto resolver = Resolver.withDefaultResolvers;
auto constructTime = stopWatch.peek();
@ -122,7 +122,7 @@ void main(string[] args) //@safe
return;
}
loader.resolver = resolver;
loader.resolver = resolver;
nodes = loader.array;
}
void runDumpBenchmark() @safe

View file

@ -79,7 +79,6 @@ struct Composer
pure @safe nothrow ~this()
{
parser_ = null;
resolver_ = null;
anchors_.destroy();
anchors_ = null;
}

View file

@ -99,7 +99,7 @@ struct Dumper(Range)
*/
this(Range stream) @safe
{
resolver_ = new Resolver();
resolver_ = Resolver.withDefaultResolvers;
stream_ = stream;
}
@ -110,9 +110,9 @@ struct Dumper(Range)
}
///Specify custom Resolver to use.
@property void resolver(Resolver resolver) @safe
auto ref resolver() @safe
{
resolver_ = resolver;
return resolver_;
}
///Write scalars in _canonical form?
@ -290,10 +290,10 @@ struct Dumper(Range)
///Use a custom resolver to support custom data types and/or implicit tags
@safe unittest
{
import std.regex : regex;
auto node = Node([1, 2, 3, 4, 5]);
auto resolver = new Resolver();
auto dumper = dumper(new Appender!string());
dumper.resolver = resolver;
dumper.resolver.addImplicitResolver("!tag", regex("A.*"), "A");
dumper.dump(node);
}
/// Set default scalar style

View file

@ -149,6 +149,7 @@ struct Loader
/// Ditto
private this(ubyte[] yamlData) @safe
{
resolver_ = Resolver.withDefaultResolvers;
try
{
reader_ = new Reader(yamlData);
@ -170,9 +171,9 @@ struct Loader
}
/// Specify custom Resolver to use.
void resolver(Resolver resolver) pure @safe nothrow @nogc
auto ref resolver() pure @safe nothrow @nogc
{
resolver_ = resolver;
return resolver_;
}
/** Load single YAML document.
@ -221,7 +222,6 @@ struct Loader
static Composer composer;
if (!rangeInitialized)
{
lazyInitConstructorResolver();
composer = Composer(parser_, resolver_);
rangeInitialized = true;
}
@ -290,13 +290,6 @@ struct Loader
{
return parser_;
}
// Construct default constructor/resolver if the user has not yet specified
// their own.
void lazyInitConstructorResolver() @safe
{
if(resolver_ is null) { resolver_ = new Resolver(); }
}
}
/// Load single YAML document from a file:
@safe unittest
@ -394,7 +387,7 @@ struct Loader
writeln("Failed to read file 'example.yaml'");
}
}
/// Use a custom constructor/resolver to support custom data types and/or implicit tags:
/// Use a custom resolver to support custom data types and/or implicit tags:
@safe unittest
{
import std.file : write;
@ -404,11 +397,11 @@ struct Loader
"Hello world!\n"~
"...\n"
);
auto resolver = new Resolver();
// Add constructor functions / resolver expressions here...
auto loader = Loader.fromFile("example.yaml");
loader.resolver = resolver;
// Add resolver expressions here...
// loader.resolver.addImplicitResolver(...);
auto rootNode = loader.load();
}

View file

@ -24,12 +24,53 @@ import dyaml.node;
import dyaml.exception;
static Tuple!(string, "tag", Regex!char, "regexp", string, "chars")[] regexes;
static this() @safe {
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:bool",
regex(r"^(?:yes|Yes|YES|no|No|NO|true|True|TRUE" ~
"|false|False|FALSE|on|On|ON|off|Off|OFF)$"),
"yYnNtTfFoO");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:float",
regex(r"^(?:[-+]?([0-9][0-9_]*)\\.[0-9_]*" ~
"(?:[eE][-+][0-9]+)?|[-+]?(?:[0-9][0-9_]" ~
"*)?\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?" ~
"[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]" ~
"*|[-+]?\\.(?:inf|Inf|INF)|\\." ~
"(?:nan|NaN|NAN))$"),
"-+0123456789.");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:int",
regex(r"^(?:[-+]?0b[0-1_]+" ~
"|[-+]?0[0-7_]+" ~
"|[-+]?(?:0|[1-9][0-9_]*)" ~
"|[-+]?0x[0-9a-fA-F_]+" ~
"|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),
"-+0123456789");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:merge", regex(r"^<<$"), "<");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:null",
regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:timestamp",
regex(r"^[0-9][0-9][0-9][0-9]-[0-9][0-9]-" ~
"[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9]" ~
"[0-9]?-[0-9][0-9]?[Tt]|[ \t]+[0-9]" ~
"[0-9]?:[0-9][0-9]:[0-9][0-9]" ~
"(?:\\.[0-9]*)?(?:[ \t]*Z|[-+][0-9]" ~
"[0-9]?(?::[0-9][0-9])?)?$"),
"0123456789");
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:value", regex(r"^=$"), "=");
//The following resolver is only for documentation purposes. It cannot work
//because plain scalars cannot start with '!', '&', or '*'.
regexes ~= tuple!("tag", "regexp", "chars")("tag:yaml.org,2002:yaml", regex(r"^(?:!|&|\*)$"), "!&*");
}
/**
* Resolves YAML tags (data types).
*
* Can be used to implicitly resolve custom data types of scalar values.
*/
final class Resolver
struct Resolver
{
private:
// Default tag to use for scalars.
@ -47,24 +88,21 @@ final class Resolver
*/
Tuple!(string, Regex!char)[][dchar] yamlImplicitResolvers_;
package:
static auto withDefaultResolvers() @safe
{
Resolver resolver;
foreach(pair; regexes)
{
resolver.addImplicitResolver(pair.tag, pair.regexp, pair.chars);
}
return resolver;
}
public:
@disable bool opEquals(ref Resolver);
@disable int opCmp(ref Resolver);
/**
* Construct a Resolver.
*
* If you don't want to implicitly resolve default YAML tags/data types,
* you can use defaultImplicitResolvers to disable default resolvers.
*
* Params: defaultImplicitResolvers = Use default YAML implicit resolvers?
*/
this(Flag!"useDefaultImplicitResolvers" defaultImplicitResolvers = Yes.useDefaultImplicitResolvers)
@safe
{
if(defaultImplicitResolvers){addImplicitResolvers();}
}
/**
* Add an implicit scalar resolver.
*
@ -105,9 +143,7 @@ final class Resolver
write("example.yaml", "A");
auto loader = Loader.fromFile("example.yaml");
auto resolver = new Resolver();
resolver.addImplicitResolver("!tag", regex("A.*"), "A");
loader.resolver = resolver;
loader.resolver.addImplicitResolver("!tag", regex("A.*"), "A");
auto node = loader.load();
assert(node.tag == "!tag");
@ -169,7 +205,7 @@ final class Resolver
}
@safe unittest
{
auto resolver = new Resolver();
auto resolver = Resolver.withDefaultResolvers;
bool tagMatch(string tag, string[] values) @safe
{
@ -215,46 +251,4 @@ final class Resolver
///Returns: Default mapping tag.
@property string defaultMappingTag() const pure @safe nothrow {return defaultMappingTag_;}
private:
// Add default implicit resolvers.
void addImplicitResolvers() @safe
{
addImplicitResolver("tag:yaml.org,2002:bool",
regex(r"^(?:yes|Yes|YES|no|No|NO|true|True|TRUE" ~
"|false|False|FALSE|on|On|ON|off|Off|OFF)$"),
"yYnNtTfFoO");
addImplicitResolver("tag:yaml.org,2002:float",
regex(r"^(?:[-+]?([0-9][0-9_]*)\\.[0-9_]*" ~
"(?:[eE][-+][0-9]+)?|[-+]?(?:[0-9][0-9_]" ~
"*)?\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?" ~
"[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]" ~
"*|[-+]?\\.(?:inf|Inf|INF)|\\." ~
"(?:nan|NaN|NAN))$"),
"-+0123456789.");
addImplicitResolver("tag:yaml.org,2002:int",
regex(r"^(?:[-+]?0b[0-1_]+" ~
"|[-+]?0[0-7_]+" ~
"|[-+]?(?:0|[1-9][0-9_]*)" ~
"|[-+]?0x[0-9a-fA-F_]+" ~
"|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),
"-+0123456789");
addImplicitResolver("tag:yaml.org,2002:merge", regex(r"^<<$"), "<");
addImplicitResolver("tag:yaml.org,2002:null",
regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0");
addImplicitResolver("tag:yaml.org,2002:timestamp",
regex(r"^[0-9][0-9][0-9][0-9]-[0-9][0-9]-" ~
"[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9]" ~
"[0-9]?-[0-9][0-9]?[Tt]|[ \t]+[0-9]" ~
"[0-9]?:[0-9][0-9]:[0-9][0-9]" ~
"(?:\\.[0-9]*)?(?:[ \t]*Z|[-+][0-9]" ~
"[0-9]?(?::[0-9][0-9])?)?$"),
"0123456789");
addImplicitResolver("tag:yaml.org,2002:value", regex(r"^=$"), "=");
//The following resolver is only for documentation purposes. It cannot work
//because plain scalars cannot start with '!', '&', or '*'.
addImplicitResolver("tag:yaml.org,2002:yaml", regex(r"^(?:!|&|\*)$"), "!&*");
}
}

View file

@ -935,7 +935,6 @@ void testConstructor(string dataFilename, string codeDummy) @safe
new Exception("Unimplemented constructor test: " ~ base));
auto loader = Loader.fromFile(dataFilename);
loader.resolver = new Resolver;
Node[] exp = expected[base];

View file

@ -90,7 +90,6 @@ void testEmitterOnData(string dataFilename, string canonicalFilename) @safe
auto loader2 = Loader.fromString(emitStream.data);
loader2.name = "TEST";
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}
@ -118,7 +117,6 @@ void testEmitterOnCanonical(string canonicalFilename) @safe
}
auto loader2 = Loader.fromString(emitStream.data);
loader2.name = "TEST";
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}
@ -175,7 +173,6 @@ void testEmitterStyles(string dataFilename, string canonicalFilename) @safe
}
auto loader2 = Loader.fromString(emitStream.data);
loader2.name = "TEST";
loader2.resolver = new Resolver;
auto newEvents = loader2.parse();
assert(compareEvents(events, newEvents));
}