1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QARRAYDATAOPS_H
43 #define QARRAYDATAOPS_H
45 #include <QtCore/qarraydata.h>
60 void appendInitialize(size_t newSize)
62 Q_ASSERT(!this->ref.isShared());
63 Q_ASSERT(newSize > uint(this->size));
64 Q_ASSERT(newSize <= this->alloc);
66 ::memset(this->end(), 0, (newSize - this->size) * sizeof(T));
70 void copyAppend(const T *b, const T *e)
72 Q_ASSERT(!this->ref.isShared());
74 Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
76 ::memcpy(this->end(), b, (e - b) * sizeof(T));
80 void copyAppend(size_t n, const T &t)
82 Q_ASSERT(!this->ref.isShared());
83 Q_ASSERT(n <= this->alloc - uint(this->size));
85 T *iter = this->end();
86 const T *const end = iter + n;
87 for (; iter != end; ++iter)
88 ::memcpy(iter, &t, sizeof(T));
92 void truncate(size_t newSize)
94 Q_ASSERT(!this->ref.isShared());
95 Q_ASSERT(newSize < size_t(this->size));
100 void destroyAll() // Call from destructors, ONLY!
102 Q_ASSERT(this->ref.atomic.load() == 0);
104 // As this is to be called only from destructor, it doesn't need to be
105 // exception safe; size not updated.
108 void insert(T *where, const T *b, const T *e)
110 Q_ASSERT(!this->ref.isShared());
111 Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
113 Q_ASSERT(e <= where || b > this->end()); // No overlap
114 Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
116 ::memmove(where + (e - b), where, (this->end() - where) * sizeof(T));
117 ::memcpy(where, b, (e - b) * sizeof(T));
118 this->size += (e - b);
123 struct QGenericArrayOps
126 void appendInitialize(size_t newSize)
128 Q_ASSERT(!this->ref.isShared());
129 Q_ASSERT(newSize > uint(this->size));
130 Q_ASSERT(newSize <= this->alloc);
132 T *const begin = this->begin();
134 new (begin + this->size) T();
135 } while (uint(++this->size) != newSize);
138 void copyAppend(const T *b, const T *e)
140 Q_ASSERT(!this->ref.isShared());
142 Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
144 T *iter = this->end();
145 for (; b != e; ++iter, ++b) {
151 void copyAppend(size_t n, const T &t)
153 Q_ASSERT(!this->ref.isShared());
154 Q_ASSERT(n <= this->alloc - uint(this->size));
156 T *iter = this->end();
157 const T *const end = iter + n;
158 for (; iter != end; ++iter) {
164 void truncate(size_t newSize)
166 Q_ASSERT(!this->ref.isShared());
167 Q_ASSERT(newSize < size_t(this->size));
169 const T *const b = this->begin();
171 (b + --this->size)->~T();
172 } while (uint(this->size) != newSize);
175 void destroyAll() // Call from destructors, ONLY
177 // As this is to be called only from destructor, it doesn't need to be
178 // exception safe; size not updated.
180 Q_ASSERT(this->ref.atomic.load() == 0);
182 const T *const b = this->begin();
183 const T *i = this->end();
189 void insert(T *where, const T *b, const T *e)
191 Q_ASSERT(!this->ref.isShared());
192 Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
194 Q_ASSERT(e <= where || b > this->end()); // No overlap
195 Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
197 // Array may be truncated at where in case of exceptions
199 T *const end = this->end();
200 const T *readIter = end;
201 T *writeIter = end + (e - b);
203 const T *const step1End = where + qMax(e - b, end - where);
220 for (; *iter != end; --*iter)
226 } destroyer(writeIter);
228 // Construct new elements in array
230 --readIter, --writeIter;
231 new (writeIter) T(*readIter);
232 } while (writeIter != step1End);
234 while (writeIter != end) {
236 new (writeIter) T(*e);
240 this->size += destroyer.end - end;
242 // Copy assign over existing elements
243 while (readIter != where) {
244 --readIter, --writeIter;
245 *writeIter = *readIter;
248 while (writeIter != where) {
256 struct QMovableArrayOps
257 : QGenericArrayOps<T>
259 // using QGenericArrayOps<T>::appendInitialize;
260 // using QGenericArrayOps<T>::copyAppend;
261 // using QGenericArrayOps<T>::truncate;
262 // using QGenericArrayOps<T>::destroyAll;
264 void insert(T *where, const T *b, const T *e)
266 Q_ASSERT(!this->ref.isShared());
267 Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
269 Q_ASSERT(e <= where || b > this->end()); // No overlap
270 Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
272 // Provides strong exception safety guarantee,
273 // provided T::~T() nothrow
275 struct ReversibleDisplace
277 ReversibleDisplace(T *start, T *finish, size_t diff)
282 ::memmove(begin + displace, begin, (end - begin) * sizeof(T));
285 void commit() { displace = 0; }
287 ~ReversibleDisplace()
290 ::memmove(begin, begin + displace, (end - begin) * sizeof(T));
297 } displace(where, this->end(), size_t(e - b));
299 struct CopyConstructor
301 CopyConstructor(T *w) : where(w) {}
303 void copy(const T *src, const T *const srcEnd)
306 for (; src != srcEnd; ++src) {
307 new (where + n) T(*src);
325 this->size += (e - b);
329 template <class T, class = void>
330 struct QArrayOpsSelector
332 typedef QGenericArrayOps<T> Type;
336 struct QArrayOpsSelector<T,
338 !QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
341 typedef QPodArrayOps<T> Type;
345 struct QArrayOpsSelector<T,
347 QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
350 typedef QMovableArrayOps<T> Type;
353 } // namespace QtPrivate
357 : QtPrivate::QArrayOpsSelector<T>::Type
365 #endif // include guard