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 }