cosmetix
[xreader.git] / xiniz.d
blob8d1de77ff308de079e4176755957dbf019042508
1 /* Written by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module xiniz /*is aliced*/;
19 import iv.strex;
20 import iv.vfs;
23 void xiniParse(A...) (VFile fl, A args) {
24 import std.traits;
25 char[] line, linebuf;
26 scope(exit) line.destroy;
27 bool eof = false;
28 while (!eof) {
29 line = null;
30 auto sz = line.length;
31 for (;;) {
32 char ch = void;
33 if (fl.rawRead((&ch)[0..1]).length == 0) { eof = true; break; }
34 if (ch == '\n') break;
35 if (sz >= linebuf.length) {
36 if (sz > 1024*1024) throw new Exception("line too long");
37 line = null;
38 linebuf.assumeSafeAppend;
39 linebuf.length = sz+1024;
41 linebuf.ptr[sz++] = ch;
43 if (sz == 0) continue;
44 line = linebuf[0..sz];
45 while (line.length && line[0] <= ' ') line = line[1..$];
46 while (line.length && line[$-1] <= ' ') line = line[0..$-1];
47 if (line.length == 0 || line[0] == '#' || line[0] == ';') continue;
48 uint eqp = 0;
49 while (eqp < line.length && line.ptr[eqp] != '=') ++eqp;
50 if (eqp >= line.length) continue;
51 auto name = line[0..eqp];
52 auto value = line[eqp+1..$];
53 while (name.length && name[0] <= ' ') name = name[1..$];
54 while (name.length && name[$-1] <= ' ') name = name[0..$-1];
55 while (value.length && value[0] <= ' ') value = value[1..$];
56 while (value.length && value[$-1] <= ' ') value = value[0..$-1];
57 //{ import std.stdio; writeln(name.quote, "=", value.quote); }
58 bool found = false;
59 foreach (immutable idx, immutable TA; A) {
60 //pragma(msg, idx, " : ", A[idx]);
61 static if (idx%2 == 0) {
62 static if (is(TA == string)) {
63 if (args[idx] == name) {
64 found = true;
65 static if (isCallable!(A[idx+1])) {
66 args[idx+1](name, value);
67 } else static if (is(A[idx+1] : T*, T)) {
68 import std.conv : to;
69 static if (is(T == ubyte) || is(T == ushort) || is(T == uint) || is(T == ulong)) {
70 if (value.length > 2 && value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
71 *(args[idx+1]) = to!T(value[2..$], 16);
72 } else {
73 *(args[idx+1]) = to!T(value);
75 } else {
76 *(args[idx+1]) = to!T(value);
78 //{ import std.stdio; writeln("TA: ", args[idx].quote); }
79 } else {
80 static assert(0, "argument for value should be delegate or pointer");
82 } else if (args[idx].length == name.length+1 && args[idx][0] == '?' && args[idx][1..$] == name) {
83 // this should be bool -- "i've seen her" flag
84 static if (isCallable!(A[idx+1])) {
85 } else static if (is(A[idx+1] : T*, T)) {
86 import std.conv : to;
87 //pragma(msg, "b: ", T);
88 *(args[idx+1]) = to!T(true);
89 } else {
90 static assert(0, "argument for checked should be var");
96 // call "unknown key" callback
97 static if (A.length%2 && isCallable!(A[$-1])) {
98 if (!found) args[$-1](name, value);
105 void main () {
106 int sec = -1, par = -1, word = -1;
107 bool wasSec = false;
108 xiniParse(VFile("z00.rc"),
109 "section", &sec,
110 "?section", &wasSec,
111 "paragraph", &par,
112 "word", &word,
113 "boo", (const(char)[] name, const(char)[] value) { import std.stdio; writeln("<", name, ">=<", value, ">"); },
115 import std.stdio;
116 writeln("sec=", sec);
117 writeln("par=", par);
118 writeln("word=", word);
119 writeln("wasSec=", wasSec);