1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.core.typeinfo;
13 
14 import std.algorithm;
15 import std.traits;
16 import std.meta;
17 
18 enum QTypeInfoFlags {
19     Q_COMPLEX_TYPE = 0,
20     Q_PRIMITIVE_TYPE = 0x1,
21     Q_STATIC_TYPE = 0,
22     Q_MOVABLE_TYPE = 0x2,               // ### Qt6: merge movable and relocatable once QList no longer depends on it
23     Q_DUMMY_TYPE = 0x4,
24     Q_RELOCATABLE_TYPE = 0x8
25 };
26 /*static foreach(name; __traits(allMembers, QTypeInfoFlags))
27 {
28     mixin("enum " + name + " = QTypeInfoFlags." + name + ";");
29 }*/
30 enum Q_MOVABLE_TYPE = QTypeInfoFlags.Q_MOVABLE_TYPE;
31 enum Q_PRIMITIVE_TYPE = QTypeInfoFlags.Q_PRIMITIVE_TYPE;
32 enum Q_RELOCATABLE_TYPE = QTypeInfoFlags.Q_RELOCATABLE_TYPE;
33 
34 template is_integral(T)
35 {
36     enum is_integral = isIntegral!T || isBoolean!T || isSomeChar!T;
37 }
38 
39 template qIsTrivial(T)
40 {
41     enum qIsTrivial = is(T==enum) || is_integral!T;
42 }
43 
44 template qIsRelocatable(T)
45 {
46     enum qIsRelocatable = is(T==enum) || is_integral!T;
47 }
48 
49 template QTypeInfo(T)
50 {
51     static if(is(T == R*, R) || is(T == class))
52     {
53         enum isRelocatable = true;
54         enum isComplex = false;
55     }
56     else static if(is(T == int) || is(T == uint) || is(T == double))
57     {
58         enum isRelocatable = true;
59         enum isComplex = false;
60     }
61     else static if(is(T == void))
62     {
63         enum isRelocatable = false;
64         enum isComplex = false;
65     }
66     else static if(is(T == enum))
67     {
68         enum isRelocatable = true;
69         enum isComplex = false;
70     }
71     else static if(fullyQualifiedName!T.startsWith("qt.core.pair.pair!"))
72     {
73         enum isRelocatable = QTypeInfo!(T.first_type).isRelocatable && QTypeInfo!(T.second_type).isRelocatable;
74         enum isComplex = QTypeInfo!(T.first_type).isComplex || QTypeInfo!(T.second_type).isComplex;
75     }
76     else static if(fullyQualifiedName!T.startsWith("qt.core.list.QList!") || fullyQualifiedName!T.startsWith("qt.core.vector.QVector!"))
77     {
78         enum isRelocatable = true;
79         enum isComplex = true;
80     }
81     else static if(fullyQualifiedName!T.startsWith("qt.core.flags.QFlags!"))
82     {
83         enum isRelocatable = true;
84         enum isComplex = false;
85     }
86     else static if(qIsTrivial!T)
87     {
88         enum isRelocatable = qIsRelocatable!T;
89         enum isComplex = !qIsTrivial!T;
90     }
91     else static if(getUDAs!(T, QTypeInfoFlags).length)
92     {
93         enum combinedFlags = (){
94             QTypeInfoFlags r;
95             foreach(flag; getUDAs!(T, QTypeInfoFlags))
96             {
97                 r |= flag;
98             }
99             return r;
100         }();
101         enum isComplex = (combinedFlags & Q_PRIMITIVE_TYPE) == 0 && !qIsTrivial!T;
102         enum isRelocatable = !isComplex || ((combinedFlags) & Q_RELOCATABLE_TYPE) || qIsRelocatable!T;
103     }
104     else
105     {
106         enum isRelocatable = qIsRelocatable!T;
107         enum isComplex = !qIsTrivial!T;
108     }
109     enum isLarge = T.sizeof > (void*).sizeof;
110     enum isIntegral = is_integral!T;
111     enum isPointer = is(T == X*, X);
112 
113     //pragma(msg, T.stringof, " ", isRelocatable, isComplex, isLarge);
114 }
115 alias QTypeInfoQuery = QTypeInfo;