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.arraydata; 13 extern(C++): 14 15 import qt.config; 16 import qt.core.basicatomic; 17 import qt.core.flags; 18 import qt.core.global; 19 import qt.core.pair; 20 import qt.helpers; 21 22 23 struct QArrayData 24 { 25 enum AllocationOption { 26 Grow, 27 KeepSize 28 } 29 30 enum GrowthPosition { 31 GrowsAtEnd, 32 GrowsAtBeginning 33 } 34 35 enum ArrayOption { 36 ArrayOptionDefault = 0, 37 CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it 38 } 39 /+ Q_DECLARE_FLAGS(ArrayOptions, ArrayOption) +/ 40 alias ArrayOptions = QFlags!(ArrayOption); 41 QBasicAtomicInt ref__; 42 ArrayOptions flags; 43 qsizetype alloc; 44 45 qsizetype allocatedCapacity()/+ noexcept+/ 46 { 47 return alloc; 48 } 49 50 qsizetype constAllocatedCapacity() const/+ noexcept+/ 51 { 52 return alloc; 53 } 54 55 /// Returns true if sharing took place 56 bool ref_()/+ noexcept+/ 57 { 58 ref__.ref_(); 59 return true; 60 } 61 62 /// Returns false if deallocation is necessary 63 bool deref()/+ noexcept+/ 64 { 65 return ref__.deref(); 66 } 67 68 bool isShared() const/+ noexcept+/ 69 { 70 return ref__.loadRelaxed() != 1; 71 } 72 73 // Returns true if a detach is necessary before modifying the data 74 // This method is intentionally not const: if you want to know whether 75 // detaching is necessary, you should be in a non-const function already 76 bool needsDetach() const/+ noexcept+/ 77 { 78 return ref__.loadRelaxed() > 1; 79 } 80 81 qsizetype detachCapacity(qsizetype newSize) const/+ noexcept+/ 82 { 83 if (flags & ArrayOption.CapacityReserved && newSize < constAllocatedCapacity()) 84 return constAllocatedCapacity(); 85 return newSize; 86 } 87 88 /+ [[nodiscard]] +/ 89 /+ #if defined(Q_CC_GNU) +/ 90 /+ __attribute__((__malloc__)) +/ 91 /+ #endif +/ 92 /+ Q_CORE_EXPORT +/ static void* allocate(QArrayData** pdata, qsizetype objectSize, qsizetype alignment, 93 qsizetype capacity, AllocationOption option = AllocationOption.KeepSize)/+ noexcept+/; 94 /+ [[nodiscard]] +/ /+ Q_CORE_EXPORT +/ static qt.core.pair.QPair!(QArrayData*, void*) reallocateUnaligned(QArrayData* data, void* dataPointer, 95 qsizetype objectSize, qsizetype newCapacity, AllocationOption option)/+ noexcept+/; 96 /+ Q_CORE_EXPORT +/ static void deallocate(QArrayData* data, qsizetype objectSize, 97 qsizetype alignment)/+ noexcept+/; 98 } 99 /+pragma(inline, true) QFlags!(QArrayData.ArrayOptions.enum_type) operator |(QArrayData.ArrayOptions.enum_type f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/{return QFlags!(QArrayData.ArrayOptions.enum_type)(f1)|f2;}+/ 100 /+pragma(inline, true) QFlags!(QArrayData.ArrayOptions.enum_type) operator |(QArrayData.ArrayOptions.enum_type f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/{return f2|f1;}+/ 101 /+pragma(inline, true) QFlags!(QArrayData.ArrayOptions.enum_type) operator &(QArrayData.ArrayOptions.enum_type f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/{return QFlags!(QArrayData.ArrayOptions.enum_type)(f1)&f2;}+/ 102 /+pragma(inline, true) QFlags!(QArrayData.ArrayOptions.enum_type) operator &(QArrayData.ArrayOptions.enum_type f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/{return f2&f1;}+/ 103 /+pragma(inline, true) void operator +(QArrayData.ArrayOptions.enum_type f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/;+/ 104 /+pragma(inline, true) void operator +(QArrayData.ArrayOptions.enum_type f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/;+/ 105 /+pragma(inline, true) void operator +(int f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/;+/ 106 /+pragma(inline, true) void operator -(QArrayData.ArrayOptions.enum_type f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/;+/ 107 /+pragma(inline, true) void operator -(QArrayData.ArrayOptions.enum_type f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/;+/ 108 /+pragma(inline, true) void operator -(int f1, QFlags!(QArrayData.ArrayOptions.enum_type) f2)/+noexcept+/;+/ 109 /+pragma(inline, true) QIncompatibleFlag operator |(QArrayData.ArrayOptions.enum_type f1, int f2)/+noexcept+/{return QIncompatibleFlag(int(f1)|f2);}+/ 110 /+pragma(inline, true) void operator +(int f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/;+/ 111 /+pragma(inline, true) void operator +(QArrayData.ArrayOptions.enum_type f1, int f2)/+noexcept+/;+/ 112 /+pragma(inline, true) void operator -(int f1, QArrayData.ArrayOptions.enum_type f2)/+noexcept+/;+/ 113 /+pragma(inline, true) void operator -(QArrayData.ArrayOptions.enum_type f1, int f2)/+noexcept+/;+/ 114 115 /+ Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions) +/ 116 struct QTypedArrayData(T) 117 { 118 QArrayData base0; 119 alias base0 this; 120 alias AllocationOption = QArrayData.AllocationOption; 121 struct AlignmentDummy { QArrayData header; T data; } 122 123 /+ [[nodiscard]] +/ static qt.core.pair.QPair!(QTypedArrayData*, T*) allocate(qsizetype capacity, AllocationOption option = QArrayData.AllocationOption.KeepSize) 124 { 125 static assert(QTypedArrayData.sizeof == QArrayData.sizeof); 126 QArrayData* d; 127 void* result = QArrayData.allocate(&d, T.sizeof, AlignmentDummy.alignof, capacity, option); 128 static if((configValue!"__has_builtin___builtin_assume_aligned" && defined!"__has_builtin___builtin_assume_aligned")) 129 { 130 result = __builtin_assume_aligned(result, /+ Q_ALIGNOF +/AlignmentDummy.alignof); 131 } 132 return qMakePair(static_cast!(QTypedArrayData*)(d), static_cast!(T*)(result)); 133 } 134 135 static qt.core.pair.QPair!(QTypedArrayData*, T*) 136 reallocateUnaligned(QTypedArrayData* data, T* dataPointer, qsizetype capacity, AllocationOption option) 137 { 138 static assert(QTypedArrayData.sizeof == QArrayData.sizeof); 139 qt.core.pair.QPair!(QArrayData*, void*) pair = 140 QArrayData.reallocateUnaligned(cast(QArrayData*)data, dataPointer, T.sizeof, capacity, option); 141 return qMakePair(static_cast!(QTypedArrayData*)(pair.first), static_cast!(T*)(pair.second)); 142 } 143 144 static void deallocate(QArrayData* data)/+ noexcept+/ 145 { 146 static assert(QTypedArrayData.sizeof == QArrayData.sizeof); 147 QArrayData.deallocate(data, T.sizeof, AlignmentDummy.alignof); 148 } 149 150 static T* dataStart(QArrayData* data, qsizetype alignment)/+ noexcept+/ 151 { 152 // Alignment is a power of two 153 (mixin(Q_ASSERT(q{alignment >= qsizetype(QArrayData.alignof) && !(alignment & (alignment - 1))}))); 154 void* start = reinterpret_cast!(void*)( 155 (cast(quintptr)(data) + QArrayData.sizeof + alignment - 1) & ~(alignment - 1)); 156 return static_cast!(T*)(start); 157 } 158 } 159 160 extern(C++, "QtPrivate") { 161 struct /+ Q_CORE_EXPORT +/ QContainerImplHelper 162 { 163 enum CutResult { Null, Empty, Full, Subset } 164 /+ static CutResult mid(qsizetype originalLength, qsizetype* _position, qsizetype* _length) 165 { 166 ref qsizetype position = *_position; 167 ref qsizetype length = *_length; 168 if (position > originalLength) { 169 position = 0; 170 length = 0; 171 return CutResult.Null; 172 } 173 174 if (position < 0) { 175 if (length < 0 || length + position >= originalLength) { 176 position = 0; 177 length = originalLength; 178 return CutResult.Full; 179 } 180 if (length + position <= 0) { 181 position = length = 0; 182 return CutResult.Null; 183 } 184 length += position; 185 position = 0; 186 } else if (size_t(length) > size_t(originalLength - position)) { 187 length = originalLength - position; 188 } 189 190 if (position == 0 && length == originalLength) 191 return CutResult.Full; 192 193 return length > 0 ? CutResult.Subset : CutResult.Empty; 194 } +/ 195 } 196 } 197