1 /**
2 * This module is contains utility templates and functions used by the other
3 * modules in  $(CALIB_ABSTRACT).
4 *
5 * Take a look the various modules in $(CALIB_ABSTRACT) for usage examples.
6 */
7 
8 module caLib_abstract.util;
9 
10 import std..string : replace, split;
11 import std.algorithm.searching : canFind;
12 
13 
14 
15 /**
16 * return `true` if `T` has an `alias` named `CellStateType`. `False` if not
17 */
18 template hasCellStateType(T)
19 {
20 	enum hasCellStateType =
21 		is(T.CellStateType) &&
22 		is(T.init.CellStateType);
23 }
24 
25 ///
26 unittest
27 {
28 	struct Foo {
29 		alias CellStateType = void;
30 	}
31 
32 	static assert( hasCellStateType!Foo);
33 	static assert(!hasCellStateType!string);
34 }
35 
36 
37 
38 /**
39 * Return true all of the given arguments are types that can be impliciltly
40 * converted to one-another
41 *
42 * It is unclear if it behaves the way it should in all cases and should
43 * not be used .
44 */
45 deprecated template isCellStateTypesCompatible(T...)
46 {
47 	static assert(T.length != 0);
48 
49 	static if(T.length == 1)
50 	{
51 		enum isCellStateTypesCompatible = true;
52 	}
53 	else
54 	{
55 		enum isCellStateTypesCompatible =
56 			__traits(compiles, (() {
57 						static assert(is(T[0] : T[1]));
58 					})() ) &&
59 			isDimensionsCompatible!(T[1..$]);
60 	}
61 }
62 
63 ///
64 unittest
65 {
66 	static assert( isCellStateTypesCompatible!(int));
67 	static assert( isCellStateTypesCompatible!(int, uint));
68 	static assert(!isCellStateTypesCompatible!(int, string));
69 }
70 
71 
72 
73 /**
74 * return `true` if `T` has an `alias` named `DisplayValueType`. `False` if not
75 */
76 template hasDisplayValueType(T)
77 {
78 	enum hasDisplayValueType =
79 		is(T.DisplayValueType) &&
80 		is(T.init.DisplayValueType);
81 }
82 
83 ///
84 unittest
85 {
86 	struct Foo {
87 		alias DisplayValueType = uint;
88 	}
89 
90 	static assert( hasDisplayValueType!Foo);
91 	static assert(!hasDisplayValueType!string);
92 }
93 
94 
95 
96 /**
97 * Return true all of the given arguments are types that can be impliciltly
98 * converted to one-another
99 *
100 * It is unclear if it behaves the way it should in all cases and should
101 * not be used .
102 */
103 deprecated template isDisplayValueTypesCompatible(T...)
104 {
105 	static assert(T.length != 0);
106 
107 	static if(T.length == 1)
108 	{
109 		enum isCellStateTypesCompatible = true;
110 	}
111 	else
112 	{
113 		enum isCellStateTypesCompatible =
114 			__traits(compiles, (() {
115 						static assert(is(T[0] : T[1]));
116 					})() ) &&
117 			isDimensionsCompatible!(T[1..$]);
118 	}
119 }
120 
121 ///
122 unittest
123 {
124 	static assert( isCellStateTypesCompatible!(int));
125 	static assert( isCellStateTypesCompatible!(int, uint));
126 	static assert(!isCellStateTypesCompatible!(int, string));
127 }
128 
129 
130 
131 /**
132 * return `true` if `T` has an `enum uint` named `Dimension`. `False` if not
133 */
134 template hasDimension(T)
135 {
136 	enum hasDimension =
137 		is(typeof(T.Dimension) : int) &&
138 		is(typeof(T.init.Dimension) : int);
139 }
140 
141 ///
142 unittest
143 {
144 	struct Foo {
145 		static immutable int Dimension = 0;
146 	}
147 
148 	static assert( hasDimension!Foo);
149 	static assert(!hasDimension!int);
150 }
151 
152 
153 
154 /**
155 * Return true all of the given arguments are types that can be impliciltly
156 * converted to one-another
157 *
158 * It is unclear if it behaves the way it should in all cases and should
159 * not be used .
160 */
161 deprecated template isDimensionsCompatible(T...)
162 {
163 	static assert(T.length != 0);
164 
165 	static if(T.length == 1)
166 	{
167 		enum isDimensionsCompatible = true;
168 	}
169 	else
170 	{
171 		enum isDimensionsCompatible =
172 			__traits(compiles, (() {
173 						static assert(T[0] == T[1]);
174 					})() ) &&
175 			isDimensionsCompatible!(T[1..$]);
176 			
177 	}
178 }
179 
180 ///
181 unittest
182 {
183 	static assert( isDimensionsCompatible!(0));
184 	static assert( isDimensionsCompatible!(0, 0u));
185 	static assert( isDimensionsCompatible!(0, 0u, byte(0)));
186 	static assert(!isDimensionsCompatible!(0, 0.1f));
187 }
188 
189 
190 
191 /**
192 * return `true` if `T` has an `alias` named `NeighbourhoodType`. `False` if not
193 *
194 * return `true` if `T` has an `alias` named `NeighbourhoodType`. `False` if not.
195 * $(B Note) that `NeighbourhoodType` need not actually be a neighbourhood.
196 * It can be any type
197 */
198 template hasNeighbourhoodType(T)
199 {
200 	enum hasNeighbourhoodType =
201 		is(T.NeighbourhoodType) &&
202 		is(T.init.NeighbourhoodType);
203 }
204 
205 ///
206 unittest
207 {
208 	struct Foo {
209 		alias NeighbourhoodType = char; //car is is not a neighbourhood
210 	}
211 
212 	static assert( hasNeighbourhoodType!Foo); //but this return true anyways
213 	static assert(!hasNeighbourhoodType!int);
214 }
215 
216 
217 
218 ///
219 template formatBehaviour(string behaviour)
220 {
221 	immutable string[] formatBehaviour =
222 	(string behaviour){
223 		behaviour = behaviour.replace(" ", "");
224 
225 		string[] behaviourList = behaviour.split("-");
226 
227 		if(behaviourList.length == 1 && !behaviourList[0].canFind(","))
228 			return behaviourList;
229 		else if(behaviourList.length == 2)
230 			return behaviourList[0] ~ behaviourList[1].split(",");
231 		else
232 			return null;
233 	}(behaviour);
234 }