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