1 module dast.config;
2 
3 import tame.data.yaml,
4 std.traits : isNumeric;
5 
6 version (Have_ctfepp)
7 	private enum PP = true;
8 else
9 	private enum PP = false;
10 
11 public import tame.data.yaml : Node;
12 
13 Node readyml(string content, bool preprocess = PP) {
14 	if (preprocess) {
15 		static if (PP) {
16 			import ctfepp;
17 
18 			auto file = PPFile(content);
19 			executePPParser(file);
20 			auto edata = EvaluateData(file);
21 			static foreach (s; [
22 				"Windows", "Win32", "Win64", "linux", "OSX", "iOS", "TVOS",
23 				"VisionOS",
24 				"Posix", "Android", "Emscripten", "PlayStation",
25 				"PlayStation4",
26 				"Cygwin", "MinGW", "X86", "X86_64", "ARM", "AArch64",
27 				"LittleEndian", "BigEndian", "D_SIMD", "D_AVX", "D_AVX2"
28 			]) {
29 				mixin("version(", s, `) edata.defineValues[s] = "1";`);
30 			}
31 			executeEvaulator(edata);
32 			content = edata.output;
33 		} else
34 			throw new Exception("Preprocess is not supported");
35 	}
36 	return loadyml(content);
37 }
38 
39 Exception readcfgEnv(alias s)(string path = null, bool preprocess = PP) {
40 	import std.array;
41 	import std.conv : to;
42 	import dast.util;
43 	import tame.io.file;
44 
45 	Node root;
46 	try {
47 		root = Node(string[string].init);
48 		if (path.length) {
49 			auto buf = uninitializedArray!(ubyte[])(getSize(path));
50 			auto file = File(path);
51 			if (!file.isOpen)
52 				return new Exception("Open file failed: " ~ path);
53 			scope (exit)
54 				file.close();
55 			file.read(buf);
56 			if (file.error)
57 				return new Exception("Read file failed: " ~ path);
58 			root = readyml(cast(string)buf, preprocess);
59 		}
60 
61 		foreach (i, ref f; s.tupleof) {
62 			enum key = KeyName!(s.tupleof[i]);
63 			auto var = getEnv!key;
64 			if (var) {
65 				alias T = typeof(f);
66 				static if (is(T : string))
67 					f = var;
68 				else static if (is(T : bool))
69 					f = var == "1";
70 				else static if (isNumeric!T)
71 					f = var.to!T;
72 				else
73 					static assert(0, "Unsupported type: " ~ T.stringof);
74 			} else if (key in root)
75 				f = root[key].as!(T);
76 		}
77 	} catch (Exception e)
78 		return e;
79 	return null;
80 }
81 
82 void readcfg(alias s, S)(S path = null, bool preprocess = PP) {
83 	import std.file : read;
84 	import dast.util;
85 
86 	Node root = Node(string[string].init);
87 	if (path.length)
88 		root = readyml(cast(string)read(path), preprocess);
89 
90 	foreach (i, ref f; s.tupleof) {
91 		enum key = KeyName!(s.tupleof[i]);
92 		if (key in root)
93 			f = root[key].as!(typeof(f));
94 	}
95 }