1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2022 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QTYPES_H |
6 | #define QTYPES_H |
7 | |
8 | #include <QtCore/qprocessordetection.h> |
9 | #include <QtCore/qtconfigmacros.h> |
10 | #include <QtCore/qassert.h> |
11 | |
12 | #ifdef __cplusplus |
13 | # include <cstddef> |
14 | # include <cstdint> |
15 | #else |
16 | # include <assert.h> |
17 | #endif |
18 | |
19 | #if 0 |
20 | #pragma qt_class(QtTypes) |
21 | #pragma qt_class(QIntegerForSize) |
22 | #pragma qt_sync_stop_processing |
23 | #endif |
24 | |
25 | /* |
26 | Useful type definitions for Qt |
27 | */ |
28 | typedef unsigned char uchar; |
29 | typedef unsigned short ushort; |
30 | typedef unsigned int uint; |
31 | typedef unsigned long ulong; |
32 | |
33 | QT_BEGIN_NAMESPACE |
34 | |
35 | /* |
36 | Size-dependent types (architecture-dependent byte order) |
37 | |
38 | Make sure to update QMetaType when changing these typedefs |
39 | */ |
40 | |
41 | typedef signed char qint8; /* 8 bit signed */ |
42 | typedef unsigned char quint8; /* 8 bit unsigned */ |
43 | typedef short qint16; /* 16 bit signed */ |
44 | typedef unsigned short quint16; /* 16 bit unsigned */ |
45 | typedef int qint32; /* 32 bit signed */ |
46 | typedef unsigned int quint32; /* 32 bit unsigned */ |
47 | // Unlike LL / ULL in C++, for historical reasons, we force the |
48 | // result to be of the requested type. |
49 | #ifdef __cplusplus |
50 | # define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */ |
51 | # define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */ |
52 | #else |
53 | # define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */ |
54 | # define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */ |
55 | #endif |
56 | typedef long long qint64; /* 64 bit signed */ |
57 | typedef unsigned long long quint64; /* 64 bit unsigned */ |
58 | |
59 | typedef qint64 qlonglong; |
60 | typedef quint64 qulonglong; |
61 | |
62 | #if defined(__SIZEOF_INT128__) && !defined(QT_NO_INT128) |
63 | # define QT_SUPPORTS_INT128 __SIZEOF_INT128__ |
64 | #else |
65 | # undef QT_SUPPORTS_INT128 |
66 | #endif |
67 | |
68 | #if defined(QT_SUPPORTS_INT128) |
69 | __extension__ typedef __int128_t qint128; |
70 | __extension__ typedef __uint128_t quint128; |
71 | |
72 | // limits: |
73 | # ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */ |
74 | # define QT_C_STYLE_CAST(type, x) static_cast<type>(x) |
75 | # else /* but C doesn't have constructor-style casts */ |
76 | # define QT_C_STYLE_CAST(type, x) ((type)x) |
77 | # endif |
78 | # ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */ |
79 | # define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1) |
80 | # endif |
81 | # define Q_INT128_MAX QT_C_STYLE_CAST(qint128, (Q_UINT128_MAX / 2)) |
82 | # define Q_INT128_MIN (-Q_INT128_MAX - 1) |
83 | |
84 | # ifdef __cplusplus |
85 | namespace QtPrivate::NumberLiterals { |
86 | namespace detail { |
87 | template <quint128 accu, int base> |
88 | constexpr quint128 construct() { return accu; } |
89 | |
90 | template <quint128 accu, int base, char C, char...Cs> |
91 | constexpr quint128 construct() |
92 | { |
93 | if constexpr (C != '\'') { // ignore digit separators |
94 | const int digitValue = '0' <= C && C <= '9' ? C - '0' : |
95 | 'a' <= C && C <= 'z' ? C - 'a' + 10 : |
96 | 'A' <= C && C <= 'Z' ? C - 'A' + 10 : |
97 | /* else */ -1 ; |
98 | static_assert(digitValue >= 0 && digitValue < base, |
99 | "Invalid character" ); |
100 | // accu * base + digitValue <= MAX, but without overflow: |
101 | static_assert(accu <= (Q_UINT128_MAX - digitValue) / base, |
102 | "Overflow occurred" ); |
103 | return construct<accu * base + digitValue, base, Cs...>(); |
104 | } else { |
105 | return construct<accu, base, Cs...>(); |
106 | } |
107 | } |
108 | |
109 | template <char C, char...Cs> |
110 | constexpr quint128 parse0xb() |
111 | { |
112 | constexpr quint128 accu = 0; |
113 | if constexpr (C == 'x' || C == 'X') |
114 | return construct<accu, 16, Cs...>(); // base 16, skip 'x' |
115 | else if constexpr (C == 'b' || C == 'B') |
116 | return construct<accu, 2, Cs...>(); // base 2, skip 'b' |
117 | else |
118 | return construct<accu, 8, C, Cs...>(); // base 8, include C |
119 | } |
120 | |
121 | template <char...Cs> |
122 | constexpr quint128 parse0() |
123 | { |
124 | if constexpr (sizeof...(Cs) == 0) // this was just a literal 0 |
125 | return 0; |
126 | else |
127 | return parse0xb<Cs...>(); |
128 | } |
129 | |
130 | template <char C, char...Cs> |
131 | constexpr quint128 parse() |
132 | { |
133 | if constexpr (C == '0') |
134 | return parse0<Cs...>(); // base 2, 8, or 16 (or just a literal 0), skip '0' |
135 | else |
136 | return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C |
137 | } |
138 | } // namespace detail |
139 | template <char...Cs> |
140 | constexpr quint128 operator""_quint128 () noexcept |
141 | { return QtPrivate::NumberLiterals::detail::parse<Cs...>(); } |
142 | template <char...Cs> |
143 | constexpr qint128 operator""_qint128 () noexcept |
144 | { return qint128(QtPrivate::NumberLiterals::detail::parse<Cs...>()); } |
145 | |
146 | #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override |
147 | # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }()) |
148 | #endif |
149 | #ifndef Q_INT128_C // allow qcompilerdetection.h/user override |
150 | # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }()) |
151 | #endif |
152 | |
153 | } // namespace QtPrivate::NumberLiterals |
154 | # endif // __cplusplus |
155 | #endif // QT_SUPPORTS_INT128 |
156 | |
157 | #ifndef __cplusplus |
158 | // In C++ mode, we define below using QIntegerForSize template |
159 | static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions" ); |
160 | typedef ptrdiff_t qptrdiff; |
161 | typedef ptrdiff_t qsizetype; |
162 | typedef ptrdiff_t qintptr; |
163 | typedef size_t quintptr; |
164 | |
165 | #define PRIdQPTRDIFF "td" |
166 | #define PRIiQPTRDIFF "ti" |
167 | |
168 | #define PRIdQSIZETYPE "td" |
169 | #define PRIiQSIZETYPE "ti" |
170 | |
171 | #define PRIdQINTPTR "td" |
172 | #define PRIiQINTPTR "ti" |
173 | |
174 | #define PRIuQUINTPTR "zu" |
175 | #define PRIoQUINTPTR "zo" |
176 | #define PRIxQUINTPTR "zx" |
177 | #define PRIXQUINTPTR "zX" |
178 | #endif |
179 | |
180 | #if defined(QT_COORD_TYPE) |
181 | typedef QT_COORD_TYPE qreal; |
182 | #else |
183 | typedef double qreal; |
184 | #endif |
185 | |
186 | #if defined(__cplusplus) |
187 | /* |
188 | quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e. |
189 | |
190 | sizeof(void *) == sizeof(quintptr) |
191 | && sizeof(void *) == sizeof(qptrdiff) |
192 | |
193 | While size_t and qsizetype are not guaranteed to be the same size as a pointer, |
194 | they usually are and we do check for that in qtypes.cpp, just to be sure. |
195 | */ |
196 | template <int> struct QIntegerForSize; |
197 | template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; |
198 | template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; |
199 | template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; |
200 | template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; |
201 | #if defined(QT_SUPPORTS_INT128) |
202 | template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; }; |
203 | #endif |
204 | template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { }; |
205 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint; |
206 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint; |
207 | typedef QIntegerForSizeof<void *>::Unsigned quintptr; |
208 | typedef QIntegerForSizeof<void *>::Signed qptrdiff; |
209 | typedef qptrdiff qintptr; |
210 | using qsizetype = QIntegerForSizeof<std::size_t>::Signed; |
211 | |
212 | // These custom definitions are necessary as we're not defining our |
213 | // datatypes in terms of the language ones, but in terms of integer |
214 | // types that have the sime size. For instance, on a 32-bit platform, |
215 | // qptrdiff is int, while ptrdiff_t may be aliased to long; therefore |
216 | // using %td to print a qptrdiff would be wrong (and raise -Wformat |
217 | // warnings), although both int and long have same bit size on that |
218 | // platform. |
219 | // |
220 | // We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). |
221 | #if SIZE_MAX == 0xffffffffULL |
222 | #define PRIuQUINTPTR "u" |
223 | #define PRIoQUINTPTR "o" |
224 | #define PRIxQUINTPTR "x" |
225 | #define PRIXQUINTPTR "X" |
226 | |
227 | #define PRIdQPTRDIFF "d" |
228 | #define PRIiQPTRDIFF "i" |
229 | |
230 | #define PRIdQINTPTR "d" |
231 | #define PRIiQINTPTR "i" |
232 | |
233 | #define PRIdQSIZETYPE "d" |
234 | #define PRIiQSIZETYPE "i" |
235 | #elif SIZE_MAX == 0xffffffffffffffffULL |
236 | #define PRIuQUINTPTR "llu" |
237 | #define PRIoQUINTPTR "llo" |
238 | #define PRIxQUINTPTR "llx" |
239 | #define PRIXQUINTPTR "llX" |
240 | |
241 | #define PRIdQPTRDIFF "lld" |
242 | #define PRIiQPTRDIFF "lli" |
243 | |
244 | #define PRIdQINTPTR "lld" |
245 | #define PRIiQINTPTR "lli" |
246 | |
247 | #define PRIdQSIZETYPE "lld" |
248 | #define PRIiQSIZETYPE "lli" |
249 | #else |
250 | #error Unsupported platform (unknown value for SIZE_MAX) |
251 | #endif |
252 | |
253 | #endif // __cplusplus |
254 | |
255 | QT_END_NAMESPACE |
256 | |
257 | #endif // QTYPES_H |
258 | |