1 module variantconfig;
2 
3 import std.string : lineSplitter, split, strip, indexOf;
4 import std.stdio : File, writeln;
5 import std.file : exists, readText;
6 import std.algorithm : sort, find;
7 import std.traits : isNumeric;
8 import std.path : isValidFilename;
9 
10 public import std.variant;
11 
12 struct VariantConfig
13 {
14 private:
15 	void load(immutable string fileName) @safe
16 	{
17 		string text;
18 
19 		if(fileName.indexOf("=") == -1)
20 		{
21 			if(exists(fileName))
22 			{
23 				text = readText(fileName);
24 			}
25 		}
26 		else
27 		{
28 			text = fileName;
29 		}
30 
31 		processText(text);
32 	}
33 
34 	void save() @trusted
35 	{
36 		auto configfile = File(fileName_, "w+");
37 
38 		foreach(key; sort(values_.keys))
39 		{
40 			configfile.writeln(key, separator_, values_[key]);
41 		}
42 	}
43 
44 	void processText(immutable string text) @safe
45 	{
46 		auto lines = text.lineSplitter();
47 
48 		foreach(line; lines)
49 		{
50 			auto fields = split(strip(line), separator_);
51 
52 			if(fields.length == 2)
53 			{
54 				values_[fields[0]] = fields[1];
55 			}
56 		}
57 	}
58 public:
59 	this(immutable string fileName) @safe
60 	{
61 		fileName_ = fileName;
62 		load(fileName);
63 	}
64 
65 	~this() @safe
66 	{
67 		save();
68 	}
69 
70 	bool hasValue(immutable string key) pure @safe
71 	{
72 		if(key in values_)
73 		{
74 			return true;
75 		}
76 		return false;
77 	}
78 
79 	Variant getValue(immutable string key) @safe
80 	{
81 		return values_.get(key, Variant(0));
82 	}
83 
84 	Variant getValue(immutable string key, Variant defval) @safe
85 	{
86 		return values_.get(key, Variant(defval));
87 	}
88 
89 	void setValue(immutable string key, Variant value) @safe
90 	{
91 		values_[key] = value;
92 	}
93 
94 	bool remove(immutable string key) pure @safe
95 	{
96 		return values_.remove(key);
97 	}
98 
99 	Variant opIndex(immutable string key) @safe
100 	{
101 		return getValue(key);
102 	}
103 
104 	void opIndexAssign(T)(T value, immutable string key) @safe
105 	{
106 		setValue(key, Variant(value));
107 	}
108 
109 private:
110 	immutable char separator_ = '=';
111 	Variant[string] values_;
112 	immutable string fileName_; // Only used for saving
113 }
114 
115 int toInt(Variant value) @safe
116 {
117 	return value.coerce!(int);
118 }
119 
120 long toLong(Variant value) @safe
121 {
122 	return value.coerce!(long);
123 }
124 
125 bool toBool(Variant value) @safe
126 {
127 	return value.coerce!(bool);
128 }
129 
130 double toDouble(Variant value) @safe
131 {
132 	return value.coerce!(double);
133 }
134 
135 real toReal(Variant value) @safe
136 {
137 	return value.coerce!(real);
138 }
139 
140 string toStr(Variant value) @safe // NOTE: Must be named toStr instead of toString or D buildin will override.
141 {
142 	if(value == 0)
143 	{
144 		return "";
145 	}
146 	return value.coerce!(string);
147 }
148