1 module Engine.util;
2 
3 import std.range;
4 import std.parallelism;
5 
6 package extern (C) Object _d_newclass (in ClassInfo info);
7 
8 T copy(T:Object) (T value)
9 {
10 	if (value is null)
11 		return null;
12 	auto size = value.classinfo.init.length;	
13 	Object v = cast(Object) ( (cast(void*)value) [0..size].dup.ptr );
14 	v.__monitor = null;
15 	return cast (T)v;
16 }
17 
18 T copy2(T:Object) (T value)
19 {
20 	if (value is null)
21 		return null;
22 	void *c = cast(void*)_d_newclass (value.classinfo);
23 	size_t size = value.classinfo.init.length;
24 	c[0..size] = (cast (void *) value)[0..size];
25 	(cast(Object)c).__monitor = null;
26 	return cast (T)c;
27 }
28 
29 
30 package Object newInstance (in ClassInfo classInfo)
31 {
32 	return _d_newclass(classInfo);
33 }
34 
35 template remove(ArrTy, IntTy) {
36 	static assert(is(IntTy : int));
37 	void remove(ArrTy arr, IntTy ix) {
38 		arr[ix] = arr[$-1];
39 		arr.length = arr.length - 1;
40 	}
41 }
42 
43 public import std.traits : isPointer;
44 
45 template baseType(T : T*) {
46 	static if (!is(baseType!T == T)) {
47 		alias baseType = baseType!T;
48 	} else {
49 		alias baseType = T;
50 	}
51 }
52 
53 template baseType(T) {
54 	alias baseType = T;
55 }
56 
57 template pointerType(T) {
58 	alias Tp = baseType!T;
59 	static if (is(Tp == class) || is (Tp == interface)) {
60 		alias pointerType = Tp;
61 	}
62 	else { 
63 		alias pointerType = Tp*;
64 	}
65 }   
66 
67 unittest {
68 	class A {
69 
70 	}
71 	struct B {
72 
73 	}
74 	interface C {
75 
76 	}
77 	assert(is(baseType!A == A));
78 	assert(is(baseType!(A*) == A));
79 	assert(is(baseType!(A**) == A));
80 	assert(is(baseType!(A***) == A));
81 	
82 	assert(is(baseType!B == B));
83 	assert(is(baseType!(B*) == B));
84 	assert(is(baseType!(B**) == B));
85 	assert(is(baseType!(B***) == B));
86 
87 	assert(is(baseType!C == C));
88 	assert(is(baseType!(C*) == C));
89 	assert(is(baseType!(C**) == C));
90 	assert(is(baseType!(C***) == C));
91 
92 	assert(is(pointerType!A == A));
93 	assert(is(pointerType!(A*) == A));
94 	assert(is(pointerType!(A**) == A));
95 	assert(is(pointerType!(A***) == A));
96 
97 	assert(is(pointerType!B == B*));
98 	assert(is(pointerType!(B*) == B*));
99 	assert(is(pointerType!(B**) == B*));
100 	assert(is(pointerType!(B***) == B*));
101 
102 	assert(is(pointerType!C == C));
103 	assert(is(pointerType!(C*) == C));
104 	assert(is(pointerType!(C**) == C));
105 	assert(is(pointerType!(C***) == C));
106 }
107 
108 void parallelRange(int works, T, R)(T t, R range) {
109 	typeof(scopedTask(t,range))[works] tasks;
110 	int m = range.length/(tasks.length+1);
111 	for (int i=0;i<tasks.length;i++) {
112 		tasks[i] = scopedTask(t,range[i*m..(i+1)*m]);
113 		taskPool.put(tasks[i]);
114 	}
115 	t(range[(tasks.length)*m..range.length]);
116 }
117 
118 struct ConstArray(T) {
119 	package T[] array;
120 
121 	this(T[] array) {
122 		this.array = array;
123 	}
124 
125 	@property length() { return array.length; }
126 
127 	T opIndex(size_t i) {
128 		return array[i];
129 	}
130 
131 	auto opSlice(size_t x, size_t y) {
132 		return typeof(this)(array[x..y]);
133 	}	
134 
135 	@property front() { return array.front; }
136 	@property back() { return array.back; }
137 	@property empty() const {return array.empty;}
138 	void popFront() {assert(!empty); array.popFront();}
139 	void popBack() {assert(!empty); array.popBack();}
140 	@property typeof(this) save() {return typeof(this)(array);}
141 	
142 	static assert(isForwardRange!(typeof(this)));
143 	static assert(hasLength!(typeof(this)));
144 	static assert(isRandomAccessRange!(typeof(this)));
145 }