summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qtypes.h
blob: db9ba38e4cfc7d5d2625655868790398f714ad1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
// Copyright (C) 2022 The Qt Company Ltd.
// Copyright (C) 2022 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QTYPES_H
#define QTYPES_H

#include <QtCore/qprocessordetection.h>
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qassert.h>

#ifdef __cplusplus
#  include <cstddef>
#  include <cstdint>
#  if defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>)
// P1467 implementation - https://wg21.link/p1467
#    include <stdfloat>
#  endif // defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>)
#else
#  include <assert.h>
#endif

#if 0
#pragma qt_class(QtTypes)
#pragma qt_class(QIntegerForSize)
#pragma qt_sync_stop_processing
#endif

/*
   Useful type definitions for Qt
*/
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

QT_BEGIN_NAMESPACE

/*
   Size-dependent types (architecture-dependent byte order)

   Make sure to update QMetaType when changing these typedefs
*/

typedef signed char qint8;         /* 8 bit signed */
typedef unsigned char quint8;      /* 8 bit unsigned */
typedef short qint16;              /* 16 bit signed */
typedef unsigned short quint16;    /* 16 bit unsigned */
typedef int qint32;                /* 32 bit signed */
typedef unsigned int quint32;      /* 32 bit unsigned */
// Unlike LL / ULL in C++, for historical reasons, we force the
// result to be of the requested type.
#ifdef __cplusplus
#  define Q_INT64_C(c) static_cast<long long>(c ## LL)     /* signed 64 bit constant */
#  define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */
#else
#  define Q_INT64_C(c) ((long long)(c ## LL))               /* signed 64 bit constant */
#  define Q_UINT64_C(c) ((unsigned long long)(c ## ULL))    /* unsigned 64 bit constant */
#endif
typedef long long qint64;           /* 64 bit signed */
typedef unsigned long long quint64; /* 64 bit unsigned */

typedef qint64 qlonglong;
typedef quint64 qulonglong;

#if defined(__SIZEOF_INT128__) && !defined(QT_NO_INT128)
#  define QT_SUPPORTS_INT128 __SIZEOF_INT128__
#else
#  undef QT_SUPPORTS_INT128
#endif

#if defined(QT_SUPPORTS_INT128)
__extension__ typedef __int128_t qint128;
__extension__ typedef __uint128_t quint128;

// limits:
#  ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */
#    define QT_C_STYLE_CAST(type, x) static_cast<type>(x)
#  else /* but C doesn't have constructor-style casts */
#    define QT_C_STYLE_CAST(type, x) ((type)(x))
#  endif
#  ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */
#    define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1)
#  endif
#  define Q_INT128_MAX QT_C_STYLE_CAST(qint128, Q_UINT128_MAX / 2)
#  define Q_INT128_MIN (-Q_INT128_MAX - 1)

#  ifdef __cplusplus
    namespace QtPrivate::NumberLiterals {
    namespace detail {
        template <quint128 accu, int base>
        constexpr quint128 construct() { return accu; }

        template <quint128 accu, int base, char C, char...Cs>
        constexpr quint128 construct()
        {
            if constexpr (C != '\'') { // ignore digit separators
                const int digitValue = '0' <= C && C <= '9' ? C - '0'      :
                                       'a' <= C && C <= 'z' ? C - 'a' + 10 :
                                       'A' <= C && C <= 'Z' ? C - 'A' + 10 :
                                       /* else */        -1 ;
                static_assert(digitValue >= 0 && digitValue < base,
                              "Invalid character");
                // accu * base + digitValue <= MAX, but without overflow:
                static_assert(accu <= (Q_UINT128_MAX - digitValue) / base,
                              "Overflow occurred");
                return construct<accu * base + digitValue, base, Cs...>();
            } else {
                return construct<accu, base, Cs...>();
            }
        }

        template <char C, char...Cs>
        constexpr quint128 parse0xb()
        {
            constexpr quint128 accu = 0;
            if constexpr (C == 'x' || C == 'X')
                return construct<accu, 16,   Cs...>(); // base 16, skip 'x'
            else if constexpr (C == 'b' || C == 'B')
                return construct<accu, 2,    Cs...>(); // base 2, skip 'b'
            else
                return construct<accu, 8, C, Cs...>(); // base 8, include C
        }

        template <char...Cs>
        constexpr quint128 parse0()
        {
            if constexpr (sizeof...(Cs) == 0) // this was just a literal 0
                return 0;
            else
                return parse0xb<Cs...>();
        }

        template <char C, char...Cs>
        constexpr quint128 parse()
        {
            if constexpr (C == '0')
                return parse0<Cs...>(); // base 2, 8, or 16 (or just a literal 0), skip '0'
            else
                return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C
        }
    } // namespace detail
    template <char...Cs>
    constexpr quint128 operator""_quint128() noexcept
    { return QtPrivate::NumberLiterals::detail::parse<Cs...>(); }
    template <char...Cs>
    constexpr qint128 operator""_qint128() noexcept
    { return qint128(QtPrivate::NumberLiterals::detail::parse<Cs...>()); }

    #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override
    #  define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }())
    #endif
    #ifndef Q_INT128_C // allow qcompilerdetection.h/user override
    #  define Q_INT128_C(c)  ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128;  }())
    #endif

    } // namespace QtPrivate::NumberLiterals
#  endif // __cplusplus
#endif // QT_SUPPORTS_INT128

#ifndef __cplusplus
// In C++ mode, we define below using QIntegerForSize template
static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions");
typedef ptrdiff_t qptrdiff;
typedef ptrdiff_t qsizetype;
typedef ptrdiff_t qintptr;
typedef size_t quintptr;

#define PRIdQPTRDIFF "td"
#define PRIiQPTRDIFF "ti"

#define PRIdQSIZETYPE "td"
#define PRIiQSIZETYPE "ti"

#define PRIdQINTPTR "td"
#define PRIiQINTPTR "ti"

#define PRIuQUINTPTR "zu"
#define PRIoQUINTPTR "zo"
#define PRIxQUINTPTR "zx"
#define PRIXQUINTPTR "zX"
#endif

#if defined(QT_COORD_TYPE)
typedef QT_COORD_TYPE qreal;
#else
typedef double qreal;
#endif

#if defined(__cplusplus)
/*
  quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e.

      sizeof(void *) == sizeof(quintptr)
      && sizeof(void *) == sizeof(qptrdiff)

  While size_t and qsizetype are not guaranteed to be the same size as a pointer,
  they usually are and we do check for that in qtypes.cpp, just to be sure.
*/
template <int> struct QIntegerForSize;
template <>    struct QIntegerForSize<1> { typedef quint8  Unsigned; typedef qint8  Signed; };
template <>    struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; };
template <>    struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
template <>    struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
#if defined(QT_SUPPORTS_INT128)
template <>    struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; };
#endif
template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint;
typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint;
typedef QIntegerForSizeof<void *>::Unsigned quintptr;
typedef QIntegerForSizeof<void *>::Signed qptrdiff;
typedef qptrdiff qintptr;
using qsizetype = QIntegerForSizeof<std::size_t>::Signed;

// These custom definitions are necessary as we're not defining our
// datatypes in terms of the language ones, but in terms of integer
// types that have the sime size. For instance, on a 32-bit platform,
// qptrdiff is int, while ptrdiff_t may be aliased to long; therefore
// using %td to print a qptrdiff would be wrong (and raise -Wformat
// warnings), although both int and long have same bit size on that
// platform.
//
// We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff).
#if SIZE_MAX == 0xffffffffULL
#define PRIuQUINTPTR "u"
#define PRIoQUINTPTR "o"
#define PRIxQUINTPTR "x"
#define PRIXQUINTPTR "X"

#define PRIdQPTRDIFF "d"
#define PRIiQPTRDIFF "i"

#define PRIdQINTPTR "d"
#define PRIiQINTPTR "i"

#define PRIdQSIZETYPE "d"
#define PRIiQSIZETYPE "i"
#elif SIZE_MAX == 0xffffffffffffffffULL
#define PRIuQUINTPTR "llu"
#define PRIoQUINTPTR "llo"
#define PRIxQUINTPTR "llx"
#define PRIXQUINTPTR "llX"

#define PRIdQPTRDIFF "lld"
#define PRIiQPTRDIFF "lli"

#define PRIdQINTPTR "lld"
#define PRIiQINTPTR "lli"

#define PRIdQSIZETYPE "lld"
#define PRIiQSIZETYPE "lli"
#else
#error Unsupported platform (unknown value for SIZE_MAX)
#endif

// Define a native float16 type
namespace QtPrivate {
#if defined(__STDCPP_FLOAT16_T__)
#  define QFLOAT16_IS_NATIVE        1
using NativeFloat16Type = std::float16_t;
#elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0
// disabled due to https://github.com/llvm/llvm-project/issues/56963
#  define QFLOAT16_IS_NATIVE        1
using NativeFloat16Type = decltype(__FLT16_MAX__);
#elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__)
#  define QFLOAT16_IS_NATIVE        1
#  ifdef __ARM_FP16_FORMAT_IEEE
using NativeFloat16Type = __fp16;
#  else
using NativeFloat16Type = _Float16;
#  endif
#else
#  define QFLOAT16_IS_NATIVE        0
using NativeFloat16Type = void;
#endif
} // QtPrivate

#endif // __cplusplus

QT_END_NAMESPACE

#endif // QTYPES_H