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 }