From efda0746d891b363107c37fc60472742ca361c61 Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Fri, 3 Mar 2023 06:00:12 +1300 Subject: [PATCH] Improve the build times of dyaml.node --- source/dyaml/node.d | 64 +++++++++++++++++++++++++++++++++++++-- source/dyaml/resolver.d | 67 ++++++++++++++++++++--------------------- 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/source/dyaml/node.d b/source/dyaml/node.d index 4c3c5eb..1a67498 100644 --- a/source/dyaml/node.d +++ b/source/dyaml/node.d @@ -2477,7 +2477,28 @@ struct Node return this.value_.tryMatch!( (inout bool v) @safe => v.to!TType, (inout long v) @safe => v.to!TType, - (inout Node[] v) @trusted => v.to!TType, + (inout Node[] v) @trusted + { + static if (is(TType == string)) + { + auto sink = appender!string(); + sink ~= "["; + + foreach(i, ref node; v) + { + if (i > 0) + sink ~= ", "; + node.toString(sink); + } + + sink ~= "]"; + return sink.data; + } + else + { + return v.to!TType; + } + }, (inout ubyte[] v) @safe => v.to!TType, (inout string v) @safe => v.to!TType, (inout Node.Pair[] v) @trusted => v.to!TType, @@ -2510,17 +2531,54 @@ struct Node this.value_.match!( (const bool v) => formattedWrite(sink, v ? "true" : "false"), (const long v) => formattedWrite(sink, "%s", v), - (const Node[] v) => formattedWrite(sink, "[%(%s, %)]", v), + (scope const Node[] v) @trusted + { + sink ~= "["; + + foreach(i, ref node; v) + { + if (i > 0) + sink ~= ", "; + node.toString(sink); + } + + sink ~= "]"; + return 0; + }, (const ubyte[] v) => formattedWrite(sink, "%s", v), (const string v) => formattedWrite(sink, `"%s"`, v), (const Node.Pair[] v) => formattedWrite(sink, "{%(%s, %)}", v), - (const SysTime v) => formattedWrite(sink, "%s", v), + (const SysTime v) + { + v.toString(sink); + return 0; + }, (const YAMLNull v) => formattedWrite(sink, "%s", v), (const YAMLMerge v) => formattedWrite(sink, "%s", v), (const real v) => formattedWrite(sink, "%s", v), (const YAMLInvalid v) => formattedWrite(sink, "%s", v), ); } + + @safe unittest + { + import std.array : appender; + auto output = appender!string(); + auto seq1 = Node([1, 2, 3, 4, 5]); + + seq1.toString(output); + assert(output.data.length > 0); + } + + @safe unittest + { + import std.array : appender; + auto output = appender!string(); + auto node = Node(SysTime(DateTime(2005, 6, 15, 20, 0, 0), UTC())); + + node.toString(output); + assert(output.data.length > 0); + } } package: diff --git a/source/dyaml/resolver.d b/source/dyaml/resolver.d index 16d8419..9f50f41 100644 --- a/source/dyaml/resolver.d +++ b/source/dyaml/resolver.d @@ -27,43 +27,42 @@ import dyaml.exception; /// Type of `regexes` private alias RegexType = Tuple!(string, "tag", const Regex!char, "regexp", string, "chars"); -private immutable RegexType[] regexes = [ - RegexType("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"), - RegexType("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."), - RegexType("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"), - RegexType("tag:yaml.org,2002:merge", regex(r"^<<$"), "<"), - RegexType("tag:yaml.org,2002:null", - regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0"), - RegexType("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"), - RegexType("tag:yaml.org,2002:value", regex(r"^=$"), "="), +// build this at runtime, to prevent build time costs +private __gshared immutable RegexType[] regexes; + +shared static this() { + __gshared string forceRT; + RegexType[] regexArray; + Regex!char toBuild; + + toBuild = regex(r"^(?:yes|Yes|YES|no|No|NO|true|True|TRUE" ~ "|false|False|FALSE|on|On|ON|off|Off|OFF)$" ~ forceRT); + regexArray ~= RegexType("tag:yaml.org,2002:bool", toBuild, "yYnNtTfFoO"); + + toBuild = 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))$" ~ forceRT); + regexArray ~= RegexType("tag:yaml.org,2002:float", toBuild, "-+0123456789."); + + toBuild = 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])+)$" ~ forceRT); + regexArray ~= RegexType("tag:yaml.org,2002:int", toBuild, "-+0123456789"); + + toBuild = regex(r"^<<$" ~ forceRT); + regexArray ~= RegexType("tag:yaml.org,2002:merge", toBuild, "<"); + + toBuild = regex(r"^$|^(?:~|null|Null|NULL)$" ~ forceRT); + regexArray ~= RegexType("tag:yaml.org,2002:null", toBuild, "~nN\0"); + + toBuild = 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])?)?$"); + regexArray ~= RegexType("tag:yaml.org,2002:timestamp", toBuild, "0123456789"); + + toBuild = regex(r"^=$"); + regexArray ~= RegexType("tag:yaml.org,2002:value", toBuild, "="); //The following resolver is only for documentation purposes. It cannot work //because plain scalars cannot start with '!', '&', or '*'. - RegexType("tag:yaml.org,2002:yaml", regex(r"^(?:!|&|\*)$"), "!&*"), -]; + toBuild = regex(r"^(?:!|&|\*)$"); + regexArray ~= RegexType("tag:yaml.org,2002:yaml", toBuild, "!&*"); + + regexes = cast(immutable)regexArray; +} /** * Resolves YAML tags (data types).