1 
2 module ddparser.util;
3 
4 import core.stdc.string;
5 public import core.stdc.stdint;
6 
7 import std.ascii;
8 import std.string;
9 import std.stdio;
10 import std.json;
11 import std.traits;
12 import std.conv;
13 import ddparser.serialize;
14 
15 enum INITIAL_SET_SIZE_INDEX =       2;
16 
17 enum INITIAL_VEC_SHIFT =    3;
18 enum INITIAL_VEC_SIZE = (1 << INITIAL_VEC_SHIFT);
19 enum INTEGRAL_VEC_SIZE =    3;
20 enum INTEGRAL_STACK_SIZE =  8;
21 
22 enum SET_MAX_SEQUENTIAL =   5;
23 
24 bool IS_BIT_SET(T, V)(T _v, V _s) { return cast(bool)(_v[_s / 8] & 1 << (_s % 8)); }
25 void SET_BIT(T, V)(ref T _v, V _s) { _v[_s / 8] |= (1 << (_s % 8)); }
26 
27 int d_verbose_level = 0;
28 int d_debug_level = 0;
29 int test_level = 0;
30 int d_rdebug_grammar_level = 0;
31 
32 void trace(string file = __FILE__, int line = __LINE__, Args...)(Args args)
33 {
34     if (0)
35     {
36         if (__ctfe)
37         {
38             __ctfeWrite(file, ":", line);
39             if (args.length)
40             {
41                 __ctfeWrite(": ", args);
42             }
43             __ctfeWrite("\n");
44         }
45         else
46         {
47             stderr.write(file, ":", line);
48             if (args.length)
49             {
50                 stderr.write(":", args);
51             }
52             stderr.writeln();
53         }
54     }
55 }
56 
57 struct Vec(T)
58 {
59     uint n;
60     uint i;
61     T *v;
62     T[INTEGRAL_VEC_SIZE] e;
63     uint isIterating;
64 
65     void clear()
66     {
67         assert(isIterating == 0);
68         n = 0;
69         v = null;
70     }
71 
72     @property size_t length() const
73     {
74         return n;
75     }
76 
77     void add(T _i) @trusted
78     {
79         assert(isIterating == 0);
80 
81         if (__ctfe)
82         {
83             v = (v[0 .. n] ~ _i).ptr;
84             return;
85         }
86 
87         if (!v) {
88             v = e.ptr;
89             e[n] = _i;
90             n++;
91             return;
92         } else if (v == e.ptr) {
93             if ((n < INTEGRAL_VEC_SIZE)) {
94                 v[n++] = (_i);
95                 return;
96             }
97         } else if (n & (INITIAL_VEC_SIZE - 1)) {
98             v[n++] = (_i);
99             return;
100         }
101         vec_add_internal(_i);
102     }
103 
104     @property inout(T)[] array() inout
105     {
106         return v[0 .. n];
107     }
108 
109     ref inout(T) opIndex(size_t index) inout @trusted
110     {
111         assert(index < n, "Index out of bounds: " ~ index.to!string());
112         return v[index];
113     }
114 
115     void opOpAssign(string s: "~")(T v)
116     {
117         add(v);
118     }
119 
120     int opApply(scope int delegate(ref T) operations)
121     {
122         isIterating++;
123         int res = 0;
124         for(int i = 0; i < n; ++i)
125         {
126             res = operations(v[i]);
127             if (res) break;
128         }
129         isIterating--;
130         return res;
131     }
132 
133     int opApplyReverse(scope int delegate(ref T) operations)
134     {
135         isIterating++;
136         int res = 0;
137         for(int i = n - 1; i >= 0; --i)
138         {
139             res = operations(v[i]);
140             if (res) break;
141         }
142         isIterating--;
143         return res;
144     }
145 
146 
147     private void vec_add_internal(T elem) {
148         assert(isIterating == 0);
149         if (!n) {
150             v = e.ptr;
151         } else if (v == e.ptr) {
152             v = cast(T*)MALLOC(INITIAL_VEC_SIZE * T.sizeof);
153             memcpy(v, e.ptr, n * T.sizeof);
154         } else {
155             if ((n & (INITIAL_VEC_SIZE - 1)) == 0) {
156                 int l = n, nl = (1 + INITIAL_VEC_SHIFT);
157                 l = l >> INITIAL_VEC_SHIFT;
158                 while (!(l&1)) { l = l >> 1; nl++; }
159                 l = l >> 1;
160                 if (!n || !l) {
161                     nl = 1 << nl;
162                     v = cast(T*)REALLOC(v, nl * T.sizeof);
163                 }
164             }
165         }
166         v[n] = elem;
167         n++;
168     }
169 
170     JSONValue customSerialize(Serializer s)
171     {
172         auto arr = v[0 .. n];
173         return s.serializeValue(arr);
174     }
175 
176     void customDeserialize(Serializer s, in JSONValue j)
177     {
178         auto arr = j.array;
179         foreach(i; arr)
180         {
181             T t;
182             s.deserializeValue(t, i);
183             add(t);
184         }
185     }
186 }
187 
188 struct Set(T, alias HashFunc, alias CompareFunc)
189 {
190     alias THash = ReturnType!HashFunc;
191     T[][THash] data;
192     T add(Args...)(T t, ref bool changed, Args args)
193     {
194         assert(isValidValue(t));
195 
196         auto h = HashFunc(t, args);
197         auto arr = h in data;
198         if (arr)
199         {
200             foreach(i; *arr)
201             {
202                 static if (is (ReturnType!CompareFunc == bool))
203                 {
204                     if (CompareFunc(i, t, args))
205                     {
206                         changed = false;
207                         return i;
208                     }
209                 }
210                 else
211                 {
212                     if (CompareFunc(i, t, args) == 0)
213                     {
214                         changed = false;
215                         return i;
216                     }
217                 }
218             }
219             *arr ~= t;
220         }
221         else
222         {
223             data[h] = [t];
224         }
225         changed = true;
226         return t;
227     }
228 
229     T add(Args...)(T t, Args args)
230     {
231         bool changed;
232         return add(t, changed, args);
233     }
234 
235     int opApply(scope int delegate(ref T v) d)
236     {
237         int result = 0;
238         foreach(k, v; data)
239         {
240             foreach(t; v)
241             {
242                 result = d(t);
243                 if (result) return result;
244             }
245         }
246         return result;
247     }
248 
249     bool unionSet(Other)(ref Other other)
250     {
251         bool changed = false;
252         foreach(i; other) if (isValidValue(i))
253         {
254             bool ch;
255             add(i, ch);
256             if (ch) changed = true;
257         }
258         return changed;
259     }
260 
261     void toVec(ref Vec!T result)
262     {
263         foreach(i; this) result ~= i;
264     }
265 
266     @property bool isEmpty() const
267     {
268         return data.length == 0;
269     }
270 
271     bool isValidValue(in T v)
272     {
273         static if (isPointer!T)
274             return v != null;
275         else
276             return true;
277     }
278 
279     void clear()
280     {
281         data = null;
282     }
283 }
284 
285 V _simpleHashFunc(V)(V v)
286 {
287     return v;
288 }
289 
290 bool _simpleCompareFunc(V)(in V a, in V b)
291 {
292     return a == b;
293 }
294 
295 alias SimpleSet(T) = Set!(T, _simpleHashFunc!T, _simpleCompareFunc!T);
296 
297 alias PointerSet(T) = SimpleSet!(T*);
298 
299 
300 
301 unittest
302 {
303     SimpleSet!(int) intSet;
304     intSet.add(5);
305     intSet.add(6);
306     intSet.add(5);
307 
308     Vec!int vec;
309     intSet.toVec(vec);
310 
311     assert((vec[0] == 5 && vec[1] == 6) || (vec[0] == 6 && vec[1] == 5));
312 }
313 
314 unittest
315 {
316     Vec!int v;
317     v ~= 5;
318     assert(v.length == 1);
319     v ~= 6;
320     assert(v.length == 2);
321     assert(v[0] == 5);
322     assert(v[1] == 6);
323 }
324 
325 void vec_add(T, U)(T _v, U _i) @safe if (isPointer!T)
326 {
327     _v.add(_i);
328 }
329 
330 struct Stack(_x)
331 {
332     _x *start;
333     _x *end;
334     _x *cur;
335     _x[INTEGRAL_STACK_SIZE] initial;
336 
337     void push(_x v)
338     {
339         if (cur == end )
340             stack_push_internal(v);
341         else
342         {
343             *cur = v;
344             cur++;
345         }
346     }
347 
348     @property bool isEmpty()
349     {
350         return cur == start;
351     }
352 
353     void stack_push_internal(_x elem)
354     {
355         auto n = cur - start;
356         if (start == initial.ptr) {
357             cur = cast(_x*)MALLOC(n * 2 * _x.sizeof);
358             memcpy(cur, start, n * _x.sizeof);
359         } else
360             cur = cast(_x*)REALLOC(start, n * 2 * _x.sizeof);
361         end = start = cur;
362         cur += n;
363         end += n * 2;
364         *cur++ = elem;
365     }
366 }
367 
368 alias uint8 = ubyte;
369 alias uint16 = ushort;
370 alias uint32 = uint;
371 alias uint64 = ulong;
372 
373 
374 void vec_clear(T)(T vec) if (isPointer!T && !isArray!(typeof(*vec)))
375 {
376     vec.clear();
377 }
378 
379 alias vec_free = vec_clear;
380 bool is_stack_empty(T)(T _s)
381 {
382     return _s.isEmpty;
383 }
384 
385 void stack_push(T, U)(T _s, U _x)
386 {
387     _s.push(_x);
388 }
389 
390 auto stack_head(T)(T _s)
391 {
392     return _s.cur[-1];
393 }
394 
395 auto stack_pop(T)(T _s)
396 {
397     return (*--((_s).cur));
398 }
399 
400 int stack_depth(T)(T _s) @safe
401 {
402     return cast(int)(_s.cur - _s.start);
403 }
404 
405 void stack_clear(T)(T _s)
406 {
407     _s.start = _s.cur = _s.end = _s.initial.ptr;
408     _s.end += INTEGRAL_STACK_SIZE;
409 }
410 
411 alias stack_free = stack_clear;
412 
413 immutable uint[] d_prime2 = [
414   1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191,
415   16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
416   4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
417   268435399, 536870909
418 ];
419 
420 void* MALLOC(size_t s)
421 {
422     import core.memory;
423     return GC.calloc(s);
424 }
425 
426 void* REALLOC(void* p, size_t s)
427 {
428     import core.memory;
429     return GC.realloc(p, s);
430 }
431 
432 void FREE(void* p) @safe
433 {
434 
435 }
436 
437 string dup_code(const char *str, const char *end)
438 {
439     if (0)
440     {
441     writeln("/+ g.r.final_code.code = dup_code(");
442     writeln("q{");
443     auto s = str[0 .. end - str].strip();
444     //assert(s.startsWith("TRACE("));
445     //assert(s.endsWith(")"));
446     if (s.startsWith("TRACE("))
447         s = s["TRACE(".length .. $ - 1];
448     writeln(s);
449     writeln("});");
450     writeln("+/");
451     }
452     return dup_str(str, end);
453 }
454 
455 import core.memory;
456 
457 string
458 d_dup_pathname_str(const(char)*s) {
459     const(char)*e = s;
460     if (!s)
461         return dup_str("", null);
462     if (*e == '"') {
463         e++; while (*e && *e != '"') e++;
464         return dup_str(s + 1, e);
465     } else
466         return dup_str(s, s+strlen(s));
467 }
468 
469 string
470 dup_str(const char *s, const char *e) {
471   int l = cast(int)(e ? e-s : strlen(s));
472   return s[0 .. l].idup;
473 }
474 
475 uint strhashl(const(char)[] s)
476 {
477     uint h = 0, g;
478     foreach(char c; s)
479     {
480         h = (h << 4) + cast(ubyte)c;
481         if ((g = h & 0xf0000000) != 0)
482             h = (h ^ (g >> 24)) ^ g;
483     }
484     return h;
485 }
486 
487 string readContentsOfFile(string path)
488 {
489     byte[] outbuf;
490     foreach(chunk; File(path).byChunk(4096)) outbuf ~= chunk;
491     return cast(string)outbuf;
492 }
493 
494 void d_fail(Args...)(Args args) @trusted
495 {
496     write("error: ");
497     writefln(args);
498     assert(false);
499 }
500 
501 void d_warn(Args...)(Args args) @trusted
502 {
503     write("warning: ");
504     writefln(args);
505 }
506 
507 string escape_string(const(char)[] s, bool singleQuote = false) @safe
508 {
509     auto result = appender!string();
510     result.reserve(s.length * 4);
511     foreach(c; s)
512     {
513         switch(c)
514         {
515             case '\b': result ~= "\\b"; break;
516             case '\f': result ~= "\\f"; break;
517             case '\n': result ~= "\\n"; break;
518             case '\r': result ~= "\\r"; break;
519             case '\t': result ~= "\\t"; break;
520             case '\v': result ~= "\\v"; break;
521             case '\a': result ~= "\\a"; break;
522             case '\\': result ~= "\\\\"; break;
523             case '\"':
524                 if (!singleQuote) result ~= '\\';
525                 result ~= c;
526                 break;
527             case '\'':
528                 if (singleQuote) result ~= '\\';
529                 result ~= c;
530                 break;
531             default:
532                 if (isPrintable(c))
533                     result ~= c;
534                 else
535                     formattedWrite(result, "\\x%X", cast(uint)c);
536         }
537     }
538 
539     return result.data;
540 }
541 
542 string escape_string_single_quote(const(char)[] s) @safe
543 {
544     return escape_string(s, true);
545 }
546 
547 void d_free(void *x) { }
548 
549 import std.format;
550 import std.algorithm;
551 import std.array;
552 
553 void delegate(string s) logFunc;
554 
555 void log(Args...)(Args args)
556 {
557     writeln(args);
558 }
559 
560 void logf(Args...)(Args args)
561 {
562     auto writer = appender!string();
563     formattedWrite(writer, args);
564     if (logFunc) logFunc(writer.data);
565     else write(writer.data);
566 }
567