Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qarraydata.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2019 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// Qt-Security score:significant reason:default
5
6#ifndef QARRAYDATA_H
7#define QARRAYDATA_H
8
9#include <QtCore/qpair.h>
10#include <QtCore/qatomic.h>
11#include <QtCore/qflags.h>
12#include <QtCore/qcontainerfwd.h>
13#include <string.h>
14
15QT_BEGIN_NAMESPACE
16
17#if __has_cpp_attribute(gnu::malloc)
18# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]]
19#elif Q_CC_MSVC_ONLY
20# define Q_DECL_MALLOCLIKE [[nodiscard]] __declspec(allocator) __declspec(restrict)
21#else
22# define Q_DECL_MALLOCLIKE [[nodiscard]]
23#endif
24
25template <class T> struct QTypedArrayData;
26
27template <class T>
29{
31 T *ptr;
32
33 [[deprecated]]
34 operator std::pair<QTypedArrayData<T>*, T*>() const noexcept { return {header, ptr}; }
35};
36
38{
43
48
51 CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it
52 };
53 Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
54
58
60 {
61 return alloc;
62 }
63
65 {
66 return alloc;
67 }
68
69 /// Returns true if sharing took place
70 bool ref() noexcept
71 {
72 ref_.refRelaxed(); // suffices for ref-counting
73 return true;
74 }
75
76 /// Returns false if deallocation is necessary
77 bool deref() noexcept
78 {
79 return ref_.deref();
80 }
81
82 bool isShared() const noexcept
83 {
84 return ref_.loadRelaxed() != 1;
85 }
86
87 // Returns true if a detach is necessary before modifying the data
88 // This method is intentionally not const: if you want to know whether
89 // detaching is necessary, you should be in a non-const function already
90 bool needsDetach() noexcept
91 {
92 return ref_.loadRelaxed() > 1;
93 }
94
95 qsizetype detachCapacity(qsizetype newSize) const noexcept
96 {
97 if (flags & CapacityReserved && newSize < constAllocatedCapacity())
98 return constAllocatedCapacity();
99 return newSize;
100 }
101
103 static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
104 qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
106 static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity,
107 AllocationOption option = QArrayData::KeepSize) noexcept;
109 static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity,
110 AllocationOption option = QArrayData::KeepSize) noexcept;
111
114 static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
115 qsizetype alignment) noexcept;
116};
117
118Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
119
120namespace QtPrivate {
121// QArrayData with strictest alignment requirements supported by malloc()
122#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU)
123// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit
124// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all
125// GCC-like compilers in case they decide to follow GCC's lead in being wrong.
126constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *);
127#else
129#endif
130
134}
135
136template <class T>
137struct QTypedArrayData
138 : QArrayData
139{
141
142 [[nodiscard]] static QTypedArrayAllocationResult<T>
143 allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize)
144 {
145 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
146 Q_DECL_UNINITIALIZED
147 QArrayData *d;
148 void *result;
149 if constexpr (sizeof(T) == 1) {
150 // necessarily, alignof(T) == 1
151 result = allocate1(&d, capacity, option);
152 } else if constexpr (sizeof(T) == 2) {
153 // alignof(T) may be 1, but that makes no difference
154 result = allocate2(&d, capacity, option);
155 } else {
156 result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
157 }
158#if __has_builtin(__builtin_assume_aligned)
159 // and yet we do offer results that have stricter alignment
160 result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
161#endif
162 return {static_cast<QTypedArrayData *>(d), static_cast<T *>(result)};
163 }
164
166 reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
167 {
168 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
169 std::pair<QArrayData *, void *> pair =
170 QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
171 return {static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)};
172 }
173
174 static void deallocate(QArrayData *data) noexcept
175 {
176 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
177 QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
178 }
179
180 static T *dataStart(QArrayData *data, qsizetype alignment) noexcept
181 {
182 // Alignment is a power of two
183 Q_ASSERT(alignment >= qsizetype(alignof(QArrayData)) && !(alignment & (alignment - 1)));
184 void *start = reinterpret_cast<void *>((quintptr(data) + sizeof(QArrayData) + alignment - 1)
185 & ~quintptr(alignment - 1));
186 return static_cast<T *>(start);
187 }
188
189 constexpr static qsizetype maxSize() noexcept
190 {
191 // -1 to deal with the pointer one-past-the-end
192 return (QtPrivate::MaxAllocSize - sizeof(QtPrivate::AlignedQArrayData) - 1) / sizeof(T);
193 }
194 constexpr static qsizetype max_size() noexcept
195 {
196 return maxSize();
197 }
198};
199
200namespace QtPrivate {
201struct Q_CORE_EXPORT QContainerImplHelper
202{
205 {
208 if (position > originalLength) {
209 position = 0;
210 length = 0;
211 return Null;
212 }
213
214 if (position < 0) {
215 if (length < 0 || length + position >= originalLength) {
216 position = 0;
218 return Full;
219 }
220 if (length + position <= 0) {
221 position = length = 0;
222 return Null;
223 }
224 length += position;
225 position = 0;
226 } else if (size_t(length) > size_t(originalLength - position)) {
228 }
229
230 if (position == 0 && length == originalLength)
231 return Full;
232
233 return length > 0 ? Subset : Empty;
234 }
235};
236}
237
238#undef Q_DECL_MALLOCLIKE
239
240QT_END_NAMESPACE
241
242#endif // include guard
constexpr size_t MaxPrimitiveAlignment
Definition qarraydata.h:128
#define Q_DECL_MALLOCLIKE
Definition qarraydata.h:22
#define __has_builtin(x)
#define __has_cpp_attribute(x)
qsizetype detachCapacity(qsizetype newSize) const noexcept
Definition qarraydata.h:95
@ CapacityReserved
the capacity was reserved by the user, try to keep it
Definition qarraydata.h:51
@ ArrayOptionDefault
Definition qarraydata.h:50
bool deref() noexcept
Returns false if deallocation is necessary.
Definition qarraydata.h:77
ArrayOptions flags
Definition qarraydata.h:56
bool isShared() const noexcept
Definition qarraydata.h:82
qsizetype alloc
Definition qarraydata.h:57
qsizetype constAllocatedCapacity() const noexcept
Definition qarraydata.h:64
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize, qsizetype alignment) noexcept
bool needsDetach() noexcept
Definition qarraydata.h:90
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate2(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
qsizetype allocatedCapacity() noexcept
Definition qarraydata.h:59
@ GrowsAtBeginning
Definition qarraydata.h:46
bool ref() noexcept
Returns true if sharing took place.
Definition qarraydata.h:70
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate1(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
QTypedArrayData< T > * header
Definition qarraydata.h:30
QtPrivate::AlignedQArrayData header
Definition qarraydata.h:140
static constexpr qsizetype maxSize() noexcept
Definition qarraydata.h:189
static constexpr qsizetype max_size() noexcept
Definition qarraydata.h:194
static void deallocate(QArrayData *data) noexcept
Definition qarraydata.h:174
static T * dataStart(QArrayData *data, qsizetype alignment) noexcept
Definition qarraydata.h:180
static QTypedArrayAllocationResult< T > allocate(qsizetype capacity, AllocationOption option=QArrayData::KeepSize)
Definition qarraydata.h:143
static QTypedArrayAllocationResult< T > reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
Definition qarraydata.h:166