1 module econf; 2 3 import std.stdio; 4 import std.conv : to; 5 import std.string; 6 import std.array; 7 import std.file : readText; 8 import std.uni : isNumber; 9 import std.conv : parse; 10 public import econf.tokens; 11 public import econf.extra; 12 13 enum EType { 14 Str, 15 Int, 16 Float, 17 Hex, 18 19 StrArr, 20 IntArr, 21 FloatArr, 22 HexArr, 23 24 Obj 25 } 26 27 class EConf { 28 private string f; 29 EToken[int] toks_asnum; 30 private string[string] toks; 31 private EToken[string] toks_at_string; 32 private int currtok=0; 33 34 private void addTok(string str) { 35 this.toks_asnum[currtok]=new EToken(str); 36 this.currtok+=1; 37 } 38 39 private void toksToObject() { 40 int j=0; 41 while(j<toks_asnum.length) { 42 this.toks[this.toks_asnum[j].getString()]= 43 this.toks_asnum[j+1].getString(); 44 this.toks_at_string[this.toks_asnum[j].getString()]= 45 this.toks_asnum[j+1]; 46 j+=2; 47 } 48 } 49 50 this(string f) { 51 int i=0; 52 while(i<this.f.length) { 53 if(this.f[i]==' '||this.f[i]=='\t'||this.f[i]=='\n') {i+=1; continue;} 54 else if(this.f[i]=='#') { 55 if(this.f.indexOf("\n")==-1) { 56 break; 57 } 58 else { 59 i=to!int(this.f.indexOf("\n")+1); 60 continue; 61 } 62 } 63 else { 64 if(this.f[i]=='\"') { 65 // STRING 66 string temp_str="\""; 67 for(int j=i+1; j<this.f.length; j++) { 68 if(this.f[j]=='\"') { 69 temp_str~="\""; 70 i=j+1; 71 j=to!int(this.f.length+1); 72 } 73 else { 74 temp_str~=this.f[j]; 75 } 76 } 77 addTok(temp_str.strip()); 78 temp_str=""; 79 } 80 else { 81 // FLOAT, INTEGER OR IDENTIFIER 82 if(isNumber(this.f[i])) { 83 // FLOAT OR INTEGER 84 string temp_num=""~this.f[i]; 85 for(int j=i+1; j<this.f.length; j++) { 86 if(this.f[j]==' ' 87 ||this.f[j]=='\"' 88 ||this.f[j]=='[' 89 ||this.f[j]==']' 90 ||this.f[j]=='{' 91 ||this.f[j]=='}' 92 ||this.f[j]=='\t' 93 ||this.f[j]=='\n') { 94 i=j; 95 j=to!int(this.f.length+1); 96 } 97 else { 98 temp_num~=this.f[j]; 99 if(j+1==this.f.length) { 100 i=j+1; 101 } 102 } 103 } 104 addTok(temp_num.strip()); 105 temp_num=""; 106 } 107 else if(this.f[i]!='['&&this.f[i]!=']' 108 &&this.f[i]!='{'&&this.f[i]!='}'){ 109 // IDENTIFIER 110 string temp_i=""; 111 for(int j=i; j<this.f.length; j++) { 112 if(this.f[j]==' ' 113 ||this.f[j]=='\"' 114 ||this.f[j]=='[' 115 ||this.f[j]==']' 116 ||this.f[j]=='{' 117 ||this.f[j]=='}' 118 ||isNumber(this.f[j]) 119 ||this.f[j]=='\t' 120 ||this.f[j]=='\n') { 121 i=j; 122 j=to!int(this.f.length+1); 123 } 124 else { 125 temp_i~=this.f[j]; 126 if(j+1==this.f.length) { 127 i=j+1; 128 } 129 } 130 } 131 if(temp_i.strip()!="") addTok(temp_i.strip()); 132 temp_i=""; 133 } 134 else { 135 // START_ARRAY or END_ARRAY or START_OBJECT or END_OBJECT 136 addTok(""~this.f[i]); 137 i+=1; 138 } 139 } 140 } 141 } 142 this.toks_asnum=EConfInitArrays(this.toks_asnum); 143 this.toks_asnum=EConfInitObjects(this.toks_asnum); 144 toksToObject(); 145 } 146 147 template get(string name) { 148 string Str() { 149 if(name in this.toks) { 150 return this.toks[name][1..$-1]; 151 } 152 else { 153 throw new StringException("Error: undefined token \""~ 154 name~"\"!"); 155 } 156 } 157 string[int] StrArr() { 158 if(name in this.toks) { 159 EToken[int] chs=this.toks_at_string[name].childs; 160 string[int] arr; 161 for(int i=0; i<chs.length; i++) { 162 arr[i]=chs[i].getString()[1..$-1]; 163 } 164 return arr; 165 } 166 else { 167 throw new StringException("Error: undefined token \""~ 168 name~"\"!"); 169 } 170 } 171 int Int() { 172 if(name in this.toks) { 173 return to!int(this.toks[name]); 174 } 175 else { 176 throw new StringException("Error: undefined token \""~ 177 name~"\"!"); 178 } 179 } 180 float Float() { 181 if(name in this.toks) { 182 return to!float(this.toks[name]); 183 } 184 else { 185 throw new StringException("Error: undefined token \""~ 186 name~"\"!"); 187 } 188 } 189 int[int] IntArr() { 190 if(name in this.toks) { 191 EToken[int] chs=this.toks_at_string[name].childs; 192 int[int] arr; 193 for(int i=0; i<chs.length; i++) { 194 arr[i]=to!int(chs[i].getString()); 195 } 196 return arr; 197 } 198 else { 199 throw new StringException("Error: undefined token \""~ 200 name~"\"!"); 201 } 202 } 203 float[int] FloatArr() { 204 if(name in this.toks) { 205 EToken[int] chs=this.toks_at_string[name].childs; 206 float[int] arr; 207 for(int i=0; i<chs.length; i++) { 208 arr[i]=to!float(chs[i].getString()); 209 } 210 return arr; 211 } 212 else { 213 throw new StringException("Error: undefined token \""~ 214 name~"\"!"); 215 } 216 } 217 int Hex() { 218 if(name in this.toks) { 219 return to!int(this.toks[name][2..$],16); 220 } 221 else { 222 throw new StringException("Error: undefined token \""~ 223 name~"\"!"); 224 } 225 } 226 int[int] HexArr() { 227 if(name in this.toks) { 228 EToken[int] chs=this.toks_at_string[name].childs; 229 int[int] arr; 230 for(int i=0; i<chs.length; i++) { 231 arr[i]=to!int(chs[i].getString(),16); 232 } 233 return arr; 234 } 235 else { 236 throw new StringException("Error: undefined token \""~ 237 name~"\"!"); 238 } 239 } 240 EToken[string] Obj() { 241 if(name in this.toks) { 242 EToken[int] chs=this.toks_at_string[name].childs; 243 EToken[string] arr; 244 int i=0; 245 while(i<chs.length) { 246 arr[chs[i].getString()]=chs[i+1]; 247 i+=2; 248 } 249 return arr; 250 } 251 else { 252 throw new StringException("Error: undefined token \""~ 253 name~"\"!"); 254 } 255 } 256 } 257 template put(T) { 258 T put(string name, T value) { 259 T a; 260 string b; 261 if(typeid(a)==typeid(b)) { 262 this.toks[name]="\""~value~"\""; 263 } 264 else { 265 this.toks[name]=to!string(value); 266 } 267 } 268 } 269 string toksToString() { 270 string all_toks=""; 271 int j=0; 272 while(j<this.toks_asnum.length) { 273 all_toks~=this.toks_asnum[j].getString() 274 ~" "~this.toks_asnum[j+1].getString()~"\n"; 275 j+=2; 276 } 277 return all_toks.strip(); 278 } 279 }