aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2021-02-19 17:10:51 -0500
committerRalph Amissah <ralph.amissah@gmail.com>2021-02-24 16:46:47 -0500
commit02ca32ae0a5bc290918d2b2a3288e385b9cc6b11 (patch)
tree06379785e8a0165a7deb981c2eba362894820634 /src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
parentbuild from static source-tree pre fetch depends (diff)
external & build dependences in src tree
- external & build dependences boost licensed - ext_depends (external depends) - D-YAML - tinyendian - d2sqlite3 - imageformats - build_depends - dub2nix
Diffstat (limited to 'src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d')
-rw-r--r--src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d b/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
new file mode 100644
index 0000000..b970c31
--- /dev/null
+++ b/src/ext_depends/D-YAML/examples/yaml_gen/yaml_gen.d
@@ -0,0 +1,316 @@
+
+///Random YAML generator. Used to generate benchmarking inputs.
+
+import std.algorithm;
+import std.conv;
+import std.datetime;
+import std.math;
+import std.random;
+import std.stdio;
+import std.string;
+import dyaml;
+
+
+Node config;
+Node function(bool)[string] generators;
+auto typesScalar = ["string", "int", "float", "bool", "timestamp", "binary"];
+auto typesScalarKey = ["string", "int", "float", "timestamp"];
+auto typesCollection = ["map","omap", "pairs", "seq", "set"];
+ulong minNodesDocument;
+ulong totalNodes;
+
+static this()
+{
+ generators["string"] = &genString;
+ generators["int"] = &genInt;
+ generators["float"] = &genFloat;
+ generators["bool"] = &genBool;
+ generators["timestamp"] = &genTimestamp;
+ generators["binary"] = &genBinary;
+ generators["map"] = &genMap;
+ generators["omap"] = &genOmap;
+ generators["pairs"] = &genPairs;
+ generators["seq"] = &genSeq;
+ generators["set"] = &genSet;
+}
+
+real randomNormalized(const string distribution = "linear")
+{
+ auto generator = Random(unpredictableSeed());
+ const r = uniform!"[]"(0.0L, 1.0L, generator);
+ switch(distribution)
+ {
+ case "linear":
+ return r;
+ case "quadratic":
+ return r * r;
+ case "cubic":
+ return r * r * r;
+ default:
+ writeln("Unknown random distribution: ", distribution,
+ ", falling back to linear");
+ return randomNormalized("linear");
+ }
+}
+
+long randomLong(const long min, const long max, const string distribution = "linear")
+{
+ return min + cast(long)round((max - min) * randomNormalized(distribution));
+}
+
+real randomReal(const real min, const real max, const string distribution = "linear")
+{
+ return min + (max - min) * randomNormalized(distribution);
+}
+
+dchar randomChar(const dstring chars)
+{
+ return chars[randomLong(0, chars.length - 1)];
+}
+
+string randomType(string[] types)
+{
+ auto probabilities = new uint[types.length];
+ foreach(index, type; types)
+ {
+ probabilities[index] = config[type]["probability"].as!uint;
+ }
+ return types[dice(probabilities)];
+}
+
+Node genString(bool root = false)
+{
+ auto range = config["string"]["range"];
+
+ auto alphabet = config["string"]["alphabet"].as!dstring;
+
+ const chars = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ dchar[] result = new dchar[chars];
+ result[0] = randomChar(alphabet);
+ foreach(i; 1 .. chars)
+ {
+ result[i] = randomChar(alphabet);
+ }
+
+ return Node(result.to!string);
+}
+
+Node genInt(bool root = false)
+{
+ auto range = config["int"]["range"];
+
+ const result = randomLong(range["min"].as!int, range["max"].as!int,
+ range["dist"].as!string);
+
+ return Node(result);
+}
+
+Node genFloat(bool root = false)
+{
+ auto range = config["float"]["range"];
+
+ const result = randomReal(range["min"].as!real, range["max"].as!real,
+ range["dist"].as!string);
+
+ return Node(result);
+}
+
+Node genBool(bool root = false)
+{
+ return Node([true, false][randomLong(0, 1)]);
+}
+
+Node genTimestamp(bool root = false)
+{
+ auto range = config["timestamp"]["range"];
+
+ auto hnsecs = randomLong(range["min"].as!ulong, range["max"].as!ulong,
+ range["dist"].as!string);
+
+ if(randomNormalized() <= config["timestamp"]["round-chance"].as!real)
+ {
+ hnsecs -= hnsecs % 10000000;
+ }
+
+ return Node(SysTime(hnsecs));
+}
+
+Node genBinary(bool root = false)
+{
+ auto range = config["binary"]["range"];
+
+ const bytes = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ ubyte[] result = new ubyte[bytes];
+ foreach(i; 0 .. bytes)
+ {
+ result[i] = cast(ubyte)randomLong(0, 255);
+ }
+
+ return Node(result);
+}
+
+Node nodes(const bool root, Node range, const string tag, const bool set = false)
+{
+ auto types = config["collection-keys"].as!bool ? typesCollection : [];
+ types ~= (set ? typesScalarKey : typesScalar);
+
+ Node[] nodes;
+ if(root)
+ {
+ while(!(totalNodes >= minNodesDocument))
+ {
+ nodes.assumeSafeAppend;
+ nodes ~= generateNode(randomType(types));
+ }
+ }
+ else
+ {
+ const elems = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ nodes = new Node[elems];
+ foreach(i; 0 .. elems)
+ {
+ nodes[i] = generateNode(randomType(types));
+ }
+ }
+
+ return Node(nodes, tag);
+}
+
+Node genSeq(bool root = false)
+{
+ return nodes(root, config["seq"]["range"], "tag:yaml.org,2002:seq");
+}
+
+Node genSet(bool root = false)
+{
+ return nodes(root, config["seq"]["range"], "tag:yaml.org,2002:set", true);
+}
+
+Node pairs(bool root, bool complex, Node range, string tag)
+{
+ Node[] keys, values;
+
+ if(root)
+ {
+ while(!(totalNodes >= minNodesDocument))
+ {
+ const key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ // Maps can't contain duplicate keys
+ if(tag.endsWith("map") && keys.canFind(key)) { continue; }
+ keys.assumeSafeAppend;
+ values.assumeSafeAppend;
+ keys ~= key;
+ values ~= generateNode(randomType(typesScalar ~ typesCollection));
+ }
+ }
+ else
+ {
+ const pairs = randomLong(range["min"].as!uint, range["max"].as!uint,
+ range["dist"].as!string);
+
+ keys = new Node[pairs];
+ values = new Node[pairs];
+ outer: foreach(i; 0 .. pairs)
+ {
+ auto key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ // Maps can't contain duplicate keys
+ while(tag.endsWith("map") && keys[0 .. i].canFind(key))
+ {
+ key = generateNode(randomType(typesScalarKey ~ (complex ? typesCollection : [])));
+ }
+ keys[i] = key;
+ values[i] = generateNode(randomType(typesScalar ~ typesCollection));
+ }
+ }
+
+ return Node(keys, values, tag);
+}
+
+Node genMap(bool root = false)
+{
+ Node range = config["map"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:map");
+}
+
+Node genOmap(bool root = false)
+{
+ Node range = config["omap"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:omap");
+}
+
+Node genPairs(bool root = false)
+{
+ Node range = config["pairs"]["range"];
+ const complex = config["complex-keys"].as!bool;
+
+ return pairs(root, complex, range, "tag:yaml.org,2002:pairs");
+}
+
+Node generateNode(const string type, bool root = false)
+{
+ ++totalNodes;
+ return generators[type](root);
+}
+
+Node[] generate(const string configFileName)
+{
+ config = Loader.fromFile(configFileName).load();
+
+ minNodesDocument = config["min-nodes-per-document"].as!long;
+
+ Node[] result;
+ foreach(i; 0 .. config["documents"].as!uint)
+ {
+ result ~= generateNode(config["root-type"].as!string, true);
+ totalNodes = 0;
+ }
+
+ return result;
+}
+
+
+void main(string[] args)
+{
+ //Help message.
+ if(args.length == 1)
+ {
+ writeln("Usage: yaml_gen FILE [CONFIG_FILE]\n");
+ writeln("Generates a random YAML file and writes it to FILE.");
+ writeln("If provided, CONFIG_FILE overrides the default config file.");
+ return;
+ }
+
+ string configFile = args.length >= 3 ? args[2] : "config.yaml";
+
+ try
+ {
+ //Generate and dump the nodes.
+ Node[] generated = generate(configFile);
+
+ auto dumper = dumper();
+ auto encoding = config["encoding"];
+
+ dumper.indent = config["indent"].as!uint;
+ dumper.textWidth = config["text-width"].as!uint;
+ switch(encoding.as!string)
+ {
+ case "utf-16": dumper.dump!wchar(File(args[1], "w").lockingTextWriter, generated); break;
+ case "utf-32": dumper.dump!dchar(File(args[1], "w").lockingTextWriter, generated); break;
+ default: dumper.dump!char(File(args[1], "w").lockingTextWriter, generated); break;
+ }
+ }
+ catch(YAMLException e)
+ {
+ writeln("ERROR: ", e.msg);
+ }
+}