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