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