1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #ifndef QVARLENGTHARRAY_H
43 #define QVARLENGTHARRAY_H
45 #include <QtCore/qcontainerfwd.h>
46 #include <QtCore/qglobal.h>
47 #include <QtCore/qalgorithms.h>
58 template<class T, int Prealloc>
61 // Prealloc = 256 by default, specified in qcontainerfwd.h
62 template<class T, int Prealloc>
66 inline explicit QVarLengthArray(int size = 0);
68 inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
69 : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
71 append(other.constData(), other.size());
74 inline ~QVarLengthArray() {
75 if (QTypeInfo<T>::isComplex) {
80 if (ptr != reinterpret_cast<T *>(array))
83 inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
87 append(other.constData(), other.size());
92 inline void removeLast() {
96 inline int size() const { return s; }
97 inline int count() const { return s; }
98 inline int length() const { return s; }
99 inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
100 inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
101 T& last() { Q_ASSERT(!isEmpty()); return *(end() - 1); }
102 const T& last() const { Q_ASSERT(!isEmpty()); return *(end() - 1); }
103 inline bool isEmpty() const { return (s == 0); }
104 inline void resize(int size);
105 inline void clear() { resize(0); }
107 inline int capacity() const { return a; }
108 inline void reserve(int size);
110 inline T &operator[](int idx) {
111 Q_ASSERT(idx >= 0 && idx < s);
114 inline const T &operator[](int idx) const {
115 Q_ASSERT(idx >= 0 && idx < s);
118 inline const T &at(int idx) const { return operator[](idx); }
120 T value(int i) const;
121 T value(int i, const T &defaultValue) const;
123 inline void append(const T &t) {
124 if (s == a) // i.e. s != 0
127 if (QTypeInfo<T>::isComplex) {
128 new (ptr + idx) T(t);
133 void append(const T *buf, int size);
134 inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
135 { append(t); return *this; }
136 inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
137 { append(t); return *this; }
139 void prepend(const T &t);
140 void insert(int i, const T &t);
141 void insert(int i, int n, const T &t);
142 void replace(int i, const T &t);
144 void remove(int i, int n);
147 inline T *data() { return ptr; }
148 inline const T *data() const { return ptr; }
149 inline const T * constData() const { return ptr; }
150 typedef int size_type;
151 typedef T value_type;
152 typedef value_type *pointer;
153 typedef const value_type *const_pointer;
154 typedef value_type &reference;
155 typedef const value_type &const_reference;
156 typedef qptrdiff difference_type;
160 typedef const T* const_iterator;
162 inline iterator begin() { return ptr; }
163 inline const_iterator begin() const { return ptr; }
164 inline const_iterator cbegin() const { return ptr; }
165 inline const_iterator constBegin() const { return ptr; }
166 inline iterator end() { return ptr + s; }
167 inline const_iterator end() const { return ptr + s; }
168 inline const_iterator cend() const { return ptr + s; }
169 inline const_iterator constEnd() const { return ptr + s; }
170 iterator insert(const_iterator before, int n, const T &x);
171 inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
172 iterator erase(const_iterator begin, const_iterator end);
173 inline iterator erase(const_iterator pos) { return erase(pos, pos+1); }
175 // STL compatibility:
176 inline bool empty() const { return isEmpty(); }
177 inline void push_back(const T &t) { append(t); }
178 inline void pop_back() { removeLast(); }
179 inline T &front() { return first(); }
180 inline const T &front() const { return first(); }
181 inline T &back() { return last(); }
182 inline const T &back() const { return last(); }
185 friend class QPodList<T, Prealloc>;
186 void realloc(int size, int alloc);
192 char array[Prealloc * sizeof(T)];
193 qint64 q_for_alignment_1;
194 double q_for_alignment_2;
198 template <class T, int Prealloc>
199 Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
202 ptr = reinterpret_cast<T *>(malloc(s * sizeof(T)));
206 ptr = reinterpret_cast<T *>(array);
209 if (QTypeInfo<T>::isComplex) {
216 template <class T, int Prealloc>
217 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(int asize)
218 { realloc(asize, qMax(asize, a)); }
220 template <class T, int Prealloc>
221 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
222 { if (asize > a) realloc(s, asize); }
224 template <class T, int Prealloc>
225 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
231 const int asize = s + increment;
234 realloc(s, qMax(s*2, asize));
236 if (QTypeInfo<T>::isComplex) {
237 // call constructor for new objects (which can throw)
239 new (ptr+(s++)) T(*abuf++);
241 memcpy(&ptr[s], abuf, increment * sizeof(T));
246 template <class T, int Prealloc>
247 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
249 Q_ASSERT(aalloc >= asize);
253 const int copySize = qMin(asize, osize);
255 T* newPtr = reinterpret_cast<T *>(malloc(aalloc * sizeof(T)));
256 Q_CHECK_PTR(newPtr); // could throw
257 // by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
261 if (QTypeInfo<T>::isStatic) {
263 // copy all the old elements
264 while (s < copySize) {
265 new (ptr+s) T(*(oldPtr+s));
270 // clean up all the old objects and then free the old ptr
272 while (sClean < osize)
273 (oldPtr+(sClean++))->~T();
274 if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
279 memcpy(ptr, oldPtr, copySize * sizeof(T));
284 if (QTypeInfo<T>::isComplex) {
285 // destroy remaining old objects
286 while (osize > asize)
287 (oldPtr+(--osize))->~T();
290 if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
293 if (QTypeInfo<T>::isComplex) {
294 // call default constructor for new objects (which can throw)
302 template <class T, int Prealloc>
303 Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i) const
305 if (i < 0 || i >= size()) {
310 template <class T, int Prealloc>
311 Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i, const T &defaultValue) const
313 return (i < 0 || i >= size()) ? defaultValue : at(i);
316 template <class T, int Prealloc>
317 inline void QVarLengthArray<T, Prealloc>::insert(int i, const T &t)
318 { Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
319 insert(begin() + i, 1, t); }
320 template <class T, int Prealloc>
321 inline void QVarLengthArray<T, Prealloc>::insert(int i, int n, const T &t)
322 { Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range");
323 insert(begin() + i, n, t); }
324 template <class T, int Prealloc>
325 inline void QVarLengthArray<T, Prealloc>::remove(int i, int n)
326 { Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= s, "QVarLengthArray::remove", "index out of range");
327 erase(begin() + i, begin() + i + n); }
328 template <class T, int Prealloc>
329 inline void QVarLengthArray<T, Prealloc>::remove(int i)
330 { Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::remove", "index out of range");
331 erase(begin() + i, begin() + i + 1); }
332 template <class T, int Prealloc>
333 inline void QVarLengthArray<T, Prealloc>::prepend(const T &t)
334 { insert(begin(), 1, t); }
336 template <class T, int Prealloc>
337 inline void QVarLengthArray<T, Prealloc>::replace(int i, const T &t)
339 Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::replace", "index out of range");
345 template <class T, int Prealloc>
346 Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, size_type n, const T &t)
348 int offset = int(before - ptr);
352 if (QTypeInfo<T>::isStatic) {
364 memmove(i, b, (s - offset - n) * sizeof(T));
372 template <class T, int Prealloc>
373 Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::erase(const_iterator abegin, const_iterator aend)
375 int f = int(abegin - ptr);
376 int l = int(aend - ptr);
378 if (QTypeInfo<T>::isComplex) {
379 qCopy(ptr + l, ptr + s, ptr + f);
387 memmove(ptr + f, ptr + l, (s - l) * sizeof(T));
393 template <typename T, int Prealloc1, int Prealloc2>
394 bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
396 if (l.size() != r.size())
398 for (int i = 0; i < l.size(); i++) {
399 if (l.at(i) != r.at(i))
405 template <typename T, int Prealloc1, int Prealloc2>
406 bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
415 #endif // QVARLENGTHARRAY_H