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 	private 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 	EToken[int] getList() {return this.toks_asnum;}
137 
138 	template get(string name) {
139 		string Str() {
140 			if(name in this.toks) {
141 				return this.toks[name][1..$-1];
142 			}
143 			else {
144 				throw new StringException("Error: undefined token \""~
145 				    name~"\"!");
146 			}
147 		}
148 		string[int] StrArr() {
149 			if(name in this.toks) {
150 				EToken[int] chs=this.toks_at_string[name].childs;
151 				string[int] arr;
152 				for(int i=0; i<chs.length; i++) {
153 					arr[i]=chs[i].getString()[1..$-1];
154 				}
155 				return arr;
156 			}
157 			else {
158 				throw new StringException("Error: undefined token \""~
159 				    name~"\"!");
160 			}
161 		}
162 		int Int() {
163 			if(name in this.toks) {
164 				return to!int(this.toks[name]);
165 			}
166 			else {
167 				throw new StringException("Error: undefined token \""~
168 				    name~"\"!");
169 			}
170 		}
171 		float Float() {
172 			if(name in this.toks) {
173 				return to!float(this.toks[name]);
174 			}
175 			else {
176 				throw new StringException("Error: undefined token \""~
177 				    name~"\"!");
178 			}
179 		}
180         int[int] IntArr() {
181             if(name in this.toks) {
182 				EToken[int] chs=this.toks_at_string[name].childs;
183 				int[int] arr;
184 				for(int i=0; i<chs.length; i++) {
185 					arr[i]=to!int(chs[i].getString());
186 				}
187 				return arr;
188 			}
189 			else {
190 				throw new StringException("Error: undefined token \""~
191 				    name~"\"!");
192 			}
193         }
194         float[int] FloatArr() {
195             if(name in this.toks) {
196 				EToken[int] chs=this.toks_at_string[name].childs;
197 				float[int] arr;
198 				for(int i=0; i<chs.length; i++) {
199 					arr[i]=to!float(chs[i].getString());
200 				}
201 				return arr;
202 			}
203 			else {
204 				throw new StringException("Error: undefined token \""~
205 				    name~"\"!");
206 			}
207         }
208         int Hex() {
209             if(name in this.toks) {
210 				return to!int(this.toks[name][2..$],16);
211 			}
212 			else {
213 				throw new StringException("Error: undefined token \""~
214 				    name~"\"!");
215 			}
216         }
217         int[int] HexArr() {
218             if(name in this.toks) {
219 				EToken[int] chs=this.toks_at_string[name].childs;
220 				int[int] arr;
221 				for(int i=0; i<chs.length; i++) {
222 					arr[i]=to!int(chs[i].getString(),16);
223 				}
224 				return arr;
225 			}
226 			else {
227 				throw new StringException("Error: undefined token \""~
228 				    name~"\"!");
229 			}
230         }
231         EToken[string] Obj() {
232             if(name in this.toks) {
233 				EToken[int] chs=this.toks_at_string[name].childs;
234 				EToken[string] arr;
235 				int i=0;
236                 while(i<chs.length) {
237                     arr[chs[i].getString()]=chs[i+1];
238                     i+=2;
239                 }
240 				return arr;
241 			}
242 			else {
243 				throw new StringException("Error: undefined token \""~
244 				    name~"\"!");
245 			}
246         }
247 	}
248 	template put(T) {
249 		T put(string name, T value) {
250 			T a;
251 			string b;
252 			if(typeid(a)==typeid(b)) {
253 				this.toks[name]="\""~value~"\"";
254 			}
255 			else {
256 				this.toks[name]=to!string(value);
257 			}
258 		}
259 	}
260 	string toksToString() {
261 		string all_toks="";
262 		int j=0;
263 		while(j<this.toks_asnum.length) {
264 			all_toks~=this.toks_asnum[j].getString()
265 			~" "~this.toks_asnum[j+1].getString()~"\n";
266 			j+=2;
267 		}
268 		return all_toks.strip();
269 	}
270 }