1 module jive.internal;
2 
3 /**
4  * For internal use in the other modules of jive.
5  */
6 
7 import core.exception : onOutOfMemoryError;
8 import core.memory : GC;
9 import std.functional : binaryFun;
10 //import std.typecons;
11 //import std.typetuple;
12 import std.traits : hasIndirections;
13 
14 private extern(C)
15 {
16 	// TODO: switch to core.memory.pureMalloc/pureFree when https://github.com/dlang/druntime/pull/1836 is resolved
17 	void* malloc(size_t) @system pure @nogc nothrow;
18 	void free(void*) @system pure @nogc nothrow;
19 }
20 
21 /**
22  * Wrappers around malloc/free that
23  *  - cast to appropriate type
24  *  - call GC.addRange/removeRange when neccessary
25  */
26 T* jiveMalloc(T)(size_t n) @trusted /*pure*/ @nogc nothrow
27 {
28 	if(n == 0)
29 		return null;
30 	auto ptr = cast(T*)malloc(T.sizeof * n);
31 	if(ptr is null)
32 		onOutOfMemoryError();
33 	static if(hasIndirections!T)
34 		GC.addRange(ptr, T.sizeof * n);
35 	return ptr;
36 }
37 
38 void jiveFree(T)(T* ptr) @trusted /*pure*/ @nogc nothrow
39 {
40 	if(ptr is null)
41 		return;
42 	static if(hasIndirections!T)
43 		GC.removeRange(ptr);
44 	free(ptr);
45 }
46 
47 /**
48  *  Workaround to make somewhat nice out-of-bounds errors in @nogc code.
49  *  TODO: remove when DIP1008 is implemented which should make a simple
50  *        'throw new RangeError(file, line)' work even in @nogc code.
51  */
52 template boundsCheckMsg(string file, int line)
53 {
54 	import std.format : format;
55 	static immutable string boundsCheckMsg = format("Array out-of-bounds at %s(%s)", file, line);
56 }
57 
58 version(D_NoBoundsChecks)
59 	enum boundsChecks = false;
60 else
61 	enum boundsChecks = true;
62 
63 template PredicateHelper(alias p, V)
64 {
65 	static if(__traits(compiles, binaryFun!p(V.init, V.init)))
66 	{
67 		enum dynamicPred = false;
68 		alias pred = binaryFun!p;
69 	}
70 	else static if(__traits(compiles, p.init(V.init, V.init)))
71 	{
72 		enum dynamicPred = true;
73 		p pred;
74 	}
75 	else
76 	{
77 		enum dynamicPred = false; // for better error messasge
78 
79 		static assert(false, "invalid predicate: "~p.stringof);
80 	}
81 }
82 
83 size_t roundToPowerOfTwo(size_t x) pure
84 {
85 	size_t y = 1;
86 	while(y < x)
87 		y *= 2;
88 	return y;
89 }