1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module dextool.plugin.mutate.backend.utility; 11 12 import core.time : Duration; 13 import std.algorithm : filter; 14 15 import dextool.type : Path, AbsolutePath; 16 import dextool.from; 17 18 public import dextool.plugin.mutate.backend.type; 19 public import dextool.plugin.mutate.backend.mutation_type; 20 public import dextool.clang_extensions : OpKind; 21 public import dextool.plugin.mutate.backend.interface_ : Blob; 22 23 @safe: 24 25 Path trustedRelativePath(string p, AbsolutePath root) @trusted { 26 import std.path : relativePath; 27 28 return relativePath(p, root).Path; 29 } 30 31 /** 32 * trusted: void[] is perfectly representable as ubyte[] accoding to the specification. 33 */ 34 Checksum checksum(const(ubyte)[] a) { 35 import dextool.hash : makeMurmur3; 36 37 return makeMurmur3(a); 38 } 39 40 /// Package the values to a checksum. 41 Checksum checksum(T)(const(T[2]) a) if (T.sizeof == 8) { 42 return Checksum(cast(ulong) a[0], cast(ulong) a[1]); 43 } 44 45 /// Package the values to a checksum. 46 Checksum checksum(T)(const T a, const T b) if (T.sizeof == 8) { 47 return Checksum(cast(ulong) a, cast(ulong) b); 48 } 49 50 /// Sleep for a random time that is min_ + rnd(0, span msecs) 51 void rndSleep(Duration min_, int span) nothrow @trusted { 52 import core.thread : Thread; 53 import core.time : dur; 54 import std.random : uniform; 55 56 auto t_span = () { 57 try { 58 return uniform(0, span).dur!"msecs"; 59 } catch (Exception e) { 60 } 61 return span.dur!"msecs"; 62 }(); 63 64 Thread.sleep(min_ + t_span); 65 } 66 67 /** Returns: the file content as an array of tokens. 68 * 69 * This is a bit slow, I think. Optimize by reducing the created strings. 70 * trusted: none of the unsafe accessed data escape this function. 71 */ 72 auto tokenize(ref from!"cpptooling.analyzer.clang.context".ClangContext ctx, Path file) @trusted { 73 import std.array : appender; 74 import clang.Index; 75 import clang.TranslationUnit; 76 77 auto tu = ctx.makeTranslationUnit(file); 78 79 auto toks = appender!(Token[])(); 80 foreach (ref t; tu.cursor.tokens) { 81 auto ext = t.extent; 82 auto start = ext.start; 83 auto end = ext.end; 84 toks.put(Token(t.kind, Offset(start.offset, end.offset), 85 SourceLoc(start.line, start.column), SourceLoc(end.line, end.column), t.spelling)); 86 } 87 88 return toks.data; 89 } 90 91 struct TokenRange { 92 private { 93 Token[] tokens; 94 } 95 96 Token front() @safe pure nothrow { 97 assert(!empty, "Can't get front of an empty range"); 98 return tokens[0]; 99 } 100 101 void popFront() @safe pure nothrow { 102 assert(!empty, "Can't pop front of an empty range"); 103 tokens = tokens[1 .. $]; 104 } 105 106 bool empty() @safe pure nothrow const @nogc { 107 return tokens.length == 0; 108 } 109 }