1 /* Supporting different types and containers.
2  * Copyright (C) 2017  Marko Semet
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 module structuresd.utils;
18 
19 private
20 {
21 	import std.algorithm.comparison;
22 	import std.meta;
23 }
24 
25 /**
26  * Check two function have same enough signature to convert T2 to T1. Result type is a bool.
27  * @tparam T1 Base function
28  * @tparam T2 Function to check
29  */
30 public enum bool isSameFunction(alias T1, alias T2) = is(typeof(&T1) : typeof(&T2));
31 
32 /**
33  * Check function from two different containers to be equal. Result type is a boolean.
34  * BASE_T have to contain a member with the name NAME
35  * @tparam BASE_T base type
36  * @tparam TYPE_T container to check
37  * @tparam NAME name of the member
38  */
39 template isSameContainerFunction(BASE_T, TYPE_T, string NAME)
40 {
41 	static assert(__traits(hasMember, BASE_T, NAME));
42 	public enum bool isSameContainerFunction = __traits(hasMember, TYPE_T, NAME) && isSameFunction!(__traits(getMember, BASE_T, NAME), __traits(getMember, TYPE_T, NAME));
43 }
44 
45 /**
46  * Checks if an member has an attribute.
47  * @tparam ATTRIBUTE The attribute to check if exits.
48  * @tparam MEMBER The member to check.
49  */
50 public template hasAttribute(ATTRIBUTE, alias MEMBER)
51 {
52 	enum bool hasAttribute = Filter!(_hasAttribute!ATTRIBUTE, __traits(getAttributes, MEMBER)).length > 0;
53 }
54 private template _hasAttribute(ATTRIBUTE)
55 {
56 	enum bool _hasAttribute(MEMBER) = is(ATTRIBUTE == MEMBER);
57 }
58 
59 /**
60  * List all members with matching credentials.
61  * @tparam CHECKER The checker function
62  * @tparam TYPE The type to search in.
63  */
64 public template membersWith(alias CHECKER, TYPE)
65 {
66 	alias membersWith = Filter!(_membersWith!(CHECKER, TYPE), __traits(allMembers, TYPE));
67 }
68 private template _membersWith(alias CHECKER, TYPE)
69 {
70 	alias _membersWith(alias T) = CHECKER!(__traits(getMember, TYPE, T));
71 }
72 
73 /**
74  * Returns array type
75  * @tparam T The array to unpack
76  */
77 public template arrayType(alias T = A[], A)
78 {
79 	alias arrayType = A;
80 }
81 
82 /**
83  * Returns the minimum.
84  * @tparam T Parameters of the function
85  * @return Type from the first parameter
86  */
87 pragma(inline, true)
88 public T[0] min(T...)(T data) if(T.length > 0)
89 {
90 	T[0] result = data[0];
91 	static foreach(i; data[1..$])
92 	{
93 		result = result < i ? result : i;
94 	}
95 	return result;
96 }
97 
98 /**
99  * Returns the maximum.
100  * @tparam T Parameters of the function
101  * @return Type from the first parameter
102  */
103 pragma(inline, true)
104 public T[0] max(T...)(T data)
105 {
106 	T[0] result = data[0];
107 	static foreach(i; data)
108 	{
109 		result = result > i ? result : i;
110 	}
111 	return result;
112 }