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