Use RefCount::setSharable feature in QVector
[profile/ivi/qtbase.git] / src / corelib / tools / qvector.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QVECTOR_H
43 #define QVECTOR_H
44
45 #include <QtCore/qalgorithms.h>
46 #include <QtCore/qiterator.h>
47 #include <QtCore/qlist.h>
48 #include <QtCore/qrefcount.h>
49
50 #ifndef QT_NO_STL
51 #include <iterator>
52 #include <vector>
53 #endif
54 #include <stdlib.h>
55 #include <string.h>
56 #ifdef Q_COMPILER_INITIALIZER_LISTS
57 #include <initializer_list>
58 #endif
59
60 QT_BEGIN_HEADER
61
62 QT_BEGIN_NAMESPACE
63
64 QT_MODULE(Core)
65
66 struct Q_CORE_EXPORT QVectorData
67 {
68     QtPrivate::RefCount ref;
69     int alloc;
70     int size;
71 #if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
72     // workaround for bug in gcc 3.4.2
73     uint capacity;
74     uint reserved;
75 #else
76     uint capacity : 1;
77     uint reserved : 31;
78 #endif
79
80     static const QVectorData shared_null;
81     // ### Qt 5: rename to 'allocate()'. The current name causes problems for
82     // some debugges when the QVector is member of a class within an unnamed namespace.
83     // ### Qt 5: can be removed completely. (Ralf)
84     static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
85     static QVectorData *allocate(int size, int alignment);
86     static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
87     static void free(QVectorData *data, int alignment);
88     static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
89 };
90
91 template <typename T>
92 struct QVectorTypedData : private QVectorData
93 { // private inheritance as we must not access QVectorData member thought QVectorTypedData
94   // as this would break strict aliasing rules. (in the case of shared_null)
95     T array[1];
96
97     static inline void free(QVectorTypedData<T> *x, int alignment) { QVectorData::free(static_cast<QVectorData *>(x), alignment); }
98 };
99
100 class QRegion;
101
102 template <typename T>
103 class QVector
104 {
105     typedef QVectorTypedData<T> Data;
106     union {
107         QVectorData *d;
108 #if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
109         QVectorTypedData<T> *p;
110 #else
111         Data *p;
112 #endif
113     };
114
115 public:
116     // ### Qt 5: Consider making QVector non-shared to get at least one
117     // "really fast" container. See tests/benchmarks/corelib/tools/qvector/
118     inline QVector() : d(const_cast<QVectorData *>(&QVectorData::shared_null)) { }
119     explicit QVector(int size);
120     QVector(int size, const T &t);
121     inline QVector(const QVector<T> &v)
122     {
123         if (v.d->ref.ref()) {
124             d = v.d;
125         } else {
126             d = const_cast<QVectorData *>(&QVectorData::shared_null);
127             realloc(0, v.d->alloc);
128             qCopy(v.p->array, v.p->array + v.d->size, p->array);
129             d->size = v.d->size;
130             d->capacity = v.d->capacity;
131         }
132     }
133
134     inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
135     QVector<T> &operator=(const QVector<T> &v);
136 #ifdef Q_COMPILER_RVALUE_REFS
137     inline QVector<T> operator=(QVector<T> &&other)
138     { qSwap(p, other.p); return *this; }
139 #endif
140     inline void swap(QVector<T> &other) { qSwap(d, other.d); }
141 #ifdef Q_COMPILER_INITIALIZER_LISTS
142     inline QVector(std::initializer_list<T> args);
143 #endif
144     bool operator==(const QVector<T> &v) const;
145     inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
146
147     inline int size() const { return d->size; }
148
149     inline bool isEmpty() const { return d->size == 0; }
150
151     void resize(int size);
152
153     inline int capacity() const { return d->alloc; }
154     void reserve(int size);
155     inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
156
157     inline void detach() { if (!isDetached()) detach_helper(); }
158     inline bool isDetached() const { return !d->ref.isShared(); }
159     inline void setSharable(bool sharable)
160     {
161         if (sharable == d->ref.isSharable())
162             return;
163         if (!sharable)
164             detach();
165         if (d != &QVectorData::shared_null)
166             d->ref.setSharable(sharable);
167     }
168
169     inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
170
171     inline T *data() { detach(); return p->array; }
172     inline const T *data() const { return p->array; }
173     inline const T *constData() const { return p->array; }
174     void clear();
175
176     const T &at(int i) const;
177     T &operator[](int i);
178     const T &operator[](int i) const;
179     void append(const T &t);
180     void prepend(const T &t);
181     void insert(int i, const T &t);
182     void insert(int i, int n, const T &t);
183     void replace(int i, const T &t);
184     void remove(int i);
185     void remove(int i, int n);
186
187     QVector<T> &fill(const T &t, int size = -1);
188
189     int indexOf(const T &t, int from = 0) const;
190     int lastIndexOf(const T &t, int from = -1) const;
191     bool contains(const T &t) const;
192     int count(const T &t) const;
193
194 #ifdef QT_STRICT_ITERATORS
195     class iterator {
196     public:
197         T *i;
198         typedef std::random_access_iterator_tag  iterator_category;
199         typedef qptrdiff difference_type;
200         typedef T value_type;
201         typedef T *pointer;
202         typedef T &reference;
203
204         inline iterator() : i(0) {}
205         inline iterator(T *n) : i(n) {}
206         inline iterator(const iterator &o): i(o.i){}
207         inline T &operator*() const { return *i; }
208         inline T *operator->() const { return i; }
209         inline T &operator[](int j) const { return *(i + j); }
210         inline bool operator==(const iterator &o) const { return i == o.i; }
211         inline bool operator!=(const iterator &o) const { return i != o.i; }
212         inline bool operator<(const iterator& other) const { return i < other.i; }
213         inline bool operator<=(const iterator& other) const { return i <= other.i; }
214         inline bool operator>(const iterator& other) const { return i > other.i; }
215         inline bool operator>=(const iterator& other) const { return i >= other.i; }
216         inline iterator &operator++() { ++i; return *this; }
217         inline iterator operator++(int) { T *n = i; ++i; return n; }
218         inline iterator &operator--() { i--; return *this; }
219         inline iterator operator--(int) { T *n = i; i--; return n; }
220         inline iterator &operator+=(int j) { i+=j; return *this; }
221         inline iterator &operator-=(int j) { i-=j; return *this; }
222         inline iterator operator+(int j) const { return iterator(i+j); }
223         inline iterator operator-(int j) const { return iterator(i-j); }
224         inline int operator-(iterator j) const { return i - j.i; }
225     };
226     friend class iterator;
227
228     class const_iterator {
229     public:
230         T *i;
231         typedef std::random_access_iterator_tag  iterator_category;
232         typedef qptrdiff difference_type;
233         typedef T value_type;
234         typedef const T *pointer;
235         typedef const T &reference;
236
237         inline const_iterator() : i(0) {}
238         inline const_iterator(T *n) : i(n) {}
239         inline const_iterator(const const_iterator &o): i(o.i) {}
240         inline explicit const_iterator(const iterator &o): i(o.i) {}
241         inline const T &operator*() const { return *i; }
242         inline const T *operator->() const { return i; }
243         inline const T &operator[](int j) const { return *(i + j); }
244         inline bool operator==(const const_iterator &o) const { return i == o.i; }
245         inline bool operator!=(const const_iterator &o) const { return i != o.i; }
246         inline bool operator<(const const_iterator& other) const { return i < other.i; }
247         inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
248         inline bool operator>(const const_iterator& other) const { return i > other.i; }
249         inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
250         inline const_iterator &operator++() { ++i; return *this; }
251         inline const_iterator operator++(int) { T *n = i; ++i; return n; }
252         inline const_iterator &operator--() { i--; return *this; }
253         inline const_iterator operator--(int) { T *n = i; i--; return n; }
254         inline const_iterator &operator+=(int j) { i+=j; return *this; }
255         inline const_iterator &operator-=(int j) { i-=j; return *this; }
256         inline const_iterator operator+(int j) const { return const_iterator(i+j); }
257         inline const_iterator operator-(int j) const { return const_iterator(i-j); }
258         inline int operator-(const_iterator j) const { return i - j.i; }
259     };
260     friend class const_iterator;
261 #else
262     // STL-style
263     typedef T* iterator;
264     typedef const T* const_iterator;
265 #endif
266     inline iterator begin() { detach(); return p->array; }
267     inline const_iterator begin() const { return p->array; }
268     inline const_iterator constBegin() const { return p->array; }
269     inline iterator end() { detach(); return p->array + d->size; }
270     inline const_iterator end() const { return p->array + d->size; }
271     inline const_iterator constEnd() const { return p->array + d->size; }
272     iterator insert(iterator before, int n, const T &x);
273     inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
274     iterator erase(iterator begin, iterator end);
275     inline iterator erase(iterator pos) { return erase(pos, pos+1); }
276
277     // more Qt
278     inline int count() const { return d->size; }
279     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
280     inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
281     inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
282     inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
283     inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
284     inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
285     QVector<T> mid(int pos, int length = -1) const;
286
287     T value(int i) const;
288     T value(int i, const T &defaultValue) const;
289
290     // STL compatibility
291     typedef T value_type;
292     typedef value_type* pointer;
293     typedef const value_type* const_pointer;
294     typedef value_type& reference;
295     typedef const value_type& const_reference;
296     typedef qptrdiff difference_type;
297     typedef iterator Iterator;
298     typedef const_iterator ConstIterator;
299     typedef int size_type;
300     inline void push_back(const T &t) { append(t); }
301     inline void push_front(const T &t) { prepend(t); }
302     void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
303     void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
304     inline bool empty() const
305     { return d->size == 0; }
306     inline T& front() { return first(); }
307     inline const_reference front() const { return first(); }
308     inline reference back() { return last(); }
309     inline const_reference back() const { return last(); }
310
311     // comfort
312     QVector<T> &operator+=(const QVector<T> &l);
313     inline QVector<T> operator+(const QVector<T> &l) const
314     { QVector n = *this; n += l; return n; }
315     inline QVector<T> &operator+=(const T &t)
316     { append(t); return *this; }
317     inline QVector<T> &operator<< (const T &t)
318     { append(t); return *this; }
319     inline QVector<T> &operator<<(const QVector<T> &l)
320     { *this += l; return *this; }
321
322     QList<T> toList() const;
323
324     static QVector<T> fromList(const QList<T> &list);
325
326 #ifndef QT_NO_STL
327     static inline QVector<T> fromStdVector(const std::vector<T> &vector)
328     { QVector<T> tmp; tmp.reserve(int(vector.size())); qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
329     inline std::vector<T> toStdVector() const
330     { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
331 #endif
332 private:
333     friend class QRegion; // Optimization for QRegion::rects()
334
335     void detach_helper();
336     QVectorData *malloc(int alloc);
337     void realloc(int size, int alloc);
338     void free(Data *d);
339     int sizeOfTypedData() {
340         // this is more or less the same as sizeof(Data), except that it doesn't
341         // count the padding at the end
342         return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
343     }
344     inline int alignOfTypedData() const
345     {
346 #ifdef Q_ALIGNOF
347         return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
348 #else
349         return 0;
350 #endif
351     }
352 };
353
354 template <typename T>
355 void QVector<T>::detach_helper()
356 { realloc(d->size, d->alloc); }
357 template <typename T>
358 void QVector<T>::reserve(int asize)
359 { if (asize > d->alloc) realloc(d->size, asize); if (isDetached()) d->capacity = 1; }
360 template <typename T>
361 void QVector<T>::resize(int asize)
362 { realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
363           QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
364           : d->alloc); }
365 template <typename T>
366 inline void QVector<T>::clear()
367 { *this = QVector<T>(); }
368 template <typename T>
369 inline const T &QVector<T>::at(int i) const
370 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
371   return p->array[i]; }
372 template <typename T>
373 inline const T &QVector<T>::operator[](int i) const
374 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
375   return p->array[i]; }
376 template <typename T>
377 inline T &QVector<T>::operator[](int i)
378 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
379   return data()[i]; }
380 template <typename T>
381 inline void QVector<T>::insert(int i, const T &t)
382 { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
383   insert(begin() + i, 1, t); }
384 template <typename T>
385 inline void QVector<T>::insert(int i, int n, const T &t)
386 { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
387   insert(begin() + i, n, t); }
388 template <typename T>
389 inline void QVector<T>::remove(int i, int n)
390 { Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range");
391   erase(begin() + i, begin() + i + n); }
392 template <typename T>
393 inline void QVector<T>::remove(int i)
394 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range");
395   erase(begin() + i, begin() + i + 1); }
396 template <typename T>
397 inline void QVector<T>::prepend(const T &t)
398 { insert(begin(), 1, t); }
399
400 template <typename T>
401 inline void QVector<T>::replace(int i, const T &t)
402 {
403     Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
404     const T copy(t);
405     data()[i] = copy;
406 }
407
408 template <typename T>
409 QVector<T> &QVector<T>::operator=(const QVector<T> &v)
410 {
411     if (v.d != d) {
412         QVector<T> tmp(v);
413         tmp.swap(*this);
414     }
415     return *this;
416 }
417
418 template <typename T>
419 inline QVectorData *QVector<T>::malloc(int aalloc)
420 {
421     QVectorData *vectordata = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
422     Q_CHECK_PTR(vectordata);
423     return vectordata;
424 }
425
426 template <typename T>
427 QVector<T>::QVector(int asize)
428 {
429     d = malloc(asize);
430     d->ref.initializeOwned();
431     d->alloc = d->size = asize;
432     d->capacity = false;
433     if (QTypeInfo<T>::isComplex) {
434         T* b = p->array;
435         T* i = p->array + d->size;
436         while (i != b)
437             new (--i) T;
438     } else {
439         qMemSet(p->array, 0, asize * sizeof(T));
440     }
441 }
442
443 template <typename T>
444 QVector<T>::QVector(int asize, const T &t)
445 {
446     d = malloc(asize);
447     d->ref.initializeOwned();
448     d->alloc = d->size = asize;
449     d->capacity = false;
450     T* i = p->array + d->size;
451     while (i != p->array)
452         new (--i) T(t);
453 }
454
455 #ifdef Q_COMPILER_INITIALIZER_LISTS
456 template <typename T>
457 QVector<T>::QVector(std::initializer_list<T> args)
458 {
459     d = malloc(int(args.size()));
460     d->ref.initializeOwned();
461     d->alloc = d->size = int(args.size());
462     d->capacity = false;
463     T* i = p->array + d->size;
464     auto it = args.end();
465     while (i != p->array)
466         new (--i) T(*(--it));
467 }
468 #endif
469
470 template <typename T>
471 void QVector<T>::free(Data *x)
472 {
473     if (QTypeInfo<T>::isComplex) {
474         T* b = x->array;
475         union { QVectorData *d; Data *p; } u;
476         u.p = x;
477         T* i = b + u.d->size;
478         while (i-- != b)
479              i->~T();
480     }
481     x->free(x, alignOfTypedData());
482 }
483
484 template <typename T>
485 void QVector<T>::realloc(int asize, int aalloc)
486 {
487     Q_ASSERT(asize <= aalloc);
488     T *pOld;
489     T *pNew;
490     union { QVectorData *d; Data *p; } x;
491     x.d = d;
492
493     if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
494         // call the destructor on all objects that need to be
495         // destroyed when shrinking
496         pOld = p->array + d->size;
497         pNew = p->array + asize;
498         while (asize < d->size) {
499             (--pOld)->~T();
500             d->size--;
501         }
502     }
503
504     if (aalloc != d->alloc || !isDetached()) {
505         // (re)allocate memory
506         if (QTypeInfo<T>::isStatic) {
507             x.d = malloc(aalloc);
508             Q_CHECK_PTR(x.p);
509             x.d->size = 0;
510         } else if (!isDetached()) {
511             x.d = malloc(aalloc);
512             Q_CHECK_PTR(x.p);
513             if (QTypeInfo<T>::isComplex) {
514                 x.d->size = 0;
515             } else {
516                 ::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, d->alloc) - 1) * sizeof(T));
517                 x.d->size = d->size;
518             }
519         } else {
520             QT_TRY {
521                 QVectorData *mem = QVectorData::reallocate(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T),
522                                                            sizeOfTypedData() + (d->alloc - 1) * sizeof(T), alignOfTypedData());
523                 Q_CHECK_PTR(mem);
524                 x.d = d = mem;
525                 x.d->size = d->size;
526             } QT_CATCH (const std::bad_alloc &) {
527                 if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
528                     QT_RETHROW;
529             }
530         }
531         x.d->ref.initializeOwned();
532         x.d->alloc = aalloc;
533         x.d->capacity = d->capacity;
534         x.d->reserved = 0;
535     }
536
537     if (QTypeInfo<T>::isComplex) {
538         QT_TRY {
539             pOld = p->array + x.d->size;
540             pNew = x.p->array + x.d->size;
541             // copy objects from the old array into the new array
542             const int toMove = qMin(asize, d->size);
543             while (x.d->size < toMove) {
544                 new (pNew++) T(*pOld++);
545                 x.d->size++;
546             }
547             // construct all new objects when growing
548             while (x.d->size < asize) {
549                 new (pNew++) T;
550                 x.d->size++;
551             }
552         } QT_CATCH (...) {
553             free(x.p);
554             QT_RETHROW;
555         }
556
557     } else if (asize > x.d->size) {
558         // initialize newly allocated memory to 0
559         qMemSet(x.p->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
560     }
561     x.d->size = asize;
562
563     if (d != x.d) {
564         if (!d->ref.deref())
565             free(p);
566         d = x.d;
567     }
568 }
569
570 template<typename T>
571 Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
572 {
573     if (i < 0 || i >= d->size) {
574         return T();
575     }
576     return p->array[i];
577 }
578 template<typename T>
579 Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
580 {
581     return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
582 }
583
584 template <typename T>
585 void QVector<T>::append(const T &t)
586 {
587     if (!isDetached() || d->size + 1 > d->alloc) {
588         const T copy(t);
589         realloc(d->size, (d->size + 1 > d->alloc) ?
590                     QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
591                     : d->alloc);
592         if (QTypeInfo<T>::isComplex)
593             new (p->array + d->size) T(copy);
594         else
595             p->array[d->size] = copy;
596     } else {
597         if (QTypeInfo<T>::isComplex)
598             new (p->array + d->size) T(t);
599         else
600             p->array[d->size] = t;
601     }
602     ++d->size;
603 }
604
605 template <typename T>
606 Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
607 {
608     int offset = int(before - p->array);
609     if (n != 0) {
610         const T copy(t);
611         if (!isDetached() || d->size + n > d->alloc)
612             realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
613                                                QTypeInfo<T>::isStatic));
614         if (QTypeInfo<T>::isStatic) {
615             T *b = p->array + d->size;
616             T *i = p->array + d->size + n;
617             while (i != b)
618                 new (--i) T;
619             i = p->array + d->size;
620             T *j = i + n;
621             b = p->array + offset;
622             while (i != b)
623                 *--j = *--i;
624             i = b+n;
625             while (i != b)
626                 *--i = copy;
627         } else {
628             T *b = p->array + offset;
629             T *i = b + n;
630             memmove(i, b, (d->size - offset) * sizeof(T));
631             while (i != b)
632                 new (--i) T(copy);
633         }
634         d->size += n;
635     }
636     return p->array + offset;
637 }
638
639 template <typename T>
640 Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
641 {
642     int f = int(abegin - p->array);
643     int l = int(aend - p->array);
644     int n = l - f;
645     detach();
646     if (QTypeInfo<T>::isComplex) {
647         qCopy(p->array+l, p->array+d->size, p->array+f);
648         T *i = p->array+d->size;
649         T* b = p->array+d->size-n;
650         while (i != b) {
651             --i;
652             i->~T();
653         }
654     } else {
655         memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
656     }
657     d->size -= n;
658     return p->array + f;
659 }
660
661 template <typename T>
662 bool QVector<T>::operator==(const QVector<T> &v) const
663 {
664     if (d->size != v.d->size)
665         return false;
666     if (d == v.d)
667         return true;
668     T* b = p->array;
669     T* i = b + d->size;
670     T* j = v.p->array + d->size;
671     while (i != b)
672         if (!(*--i == *--j))
673             return false;
674     return true;
675 }
676
677 template <typename T>
678 QVector<T> &QVector<T>::fill(const T &from, int asize)
679 {
680     const T copy(from);
681     resize(asize < 0 ? d->size : asize);
682     if (d->size) {
683         T *i = p->array + d->size;
684         T *b = p->array;
685         while (i != b)
686             *--i = copy;
687     }
688     return *this;
689 }
690
691 template <typename T>
692 QVector<T> &QVector<T>::operator+=(const QVector &l)
693 {
694     int newSize = d->size + l.d->size;
695     realloc(d->size, newSize);
696
697     T *w = p->array + newSize;
698     T *i = l.p->array + l.d->size;
699     T *b = l.p->array;
700     while (i != b) {
701         if (QTypeInfo<T>::isComplex)
702             new (--w) T(*--i);
703         else
704             *--w = *--i;
705     }
706     d->size = newSize;
707     return *this;
708 }
709
710 template <typename T>
711 int QVector<T>::indexOf(const T &t, int from) const
712 {
713     if (from < 0)
714         from = qMax(from + d->size, 0);
715     if (from < d->size) {
716         T* n = p->array + from - 1;
717         T* e = p->array + d->size;
718         while (++n != e)
719             if (*n == t)
720                 return n - p->array;
721     }
722     return -1;
723 }
724
725 template <typename T>
726 int QVector<T>::lastIndexOf(const T &t, int from) const
727 {
728     if (from < 0)
729         from += d->size;
730     else if (from >= d->size)
731         from = d->size-1;
732     if (from >= 0) {
733         T* b = p->array;
734         T* n = p->array + from + 1;
735         while (n != b) {
736             if (*--n == t)
737                 return n - b;
738         }
739     }
740     return -1;
741 }
742
743 template <typename T>
744 bool QVector<T>::contains(const T &t) const
745 {
746     T* b = p->array;
747     T* i = p->array + d->size;
748     while (i != b)
749         if (*--i == t)
750             return true;
751     return false;
752 }
753
754 template <typename T>
755 int QVector<T>::count(const T &t) const
756 {
757     int c = 0;
758     T* b = p->array;
759     T* i = p->array + d->size;
760     while (i != b)
761         if (*--i == t)
762             ++c;
763     return c;
764 }
765
766 template <typename T>
767 Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int length) const
768 {
769     if (length < 0)
770         length = size() - pos;
771     if (pos == 0 && length == size())
772         return *this;
773     if (pos + length > size())
774         length = size() - pos;
775     QVector<T> copy;
776     copy.reserve(length);
777     for (int i = pos; i < pos + length; ++i)
778         copy += at(i);
779     return copy;
780 }
781
782 template <typename T>
783 Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
784 {
785     QList<T> result;
786     result.reserve(size());
787     for (int i = 0; i < size(); ++i)
788         result.append(at(i));
789     return result;
790 }
791
792 template <typename T>
793 Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
794 {
795     QVector<T> result(size());
796     for (int i = 0; i < size(); ++i)
797         result[i] = at(i);
798     return result;
799 }
800
801 template <typename T>
802 QVector<T> QVector<T>::fromList(const QList<T> &list)
803 {
804     return list.toVector();
805 }
806
807 template <typename T>
808 QList<T> QList<T>::fromVector(const QVector<T> &vector)
809 {
810     return vector.toList();
811 }
812
813 Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
814 Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector)
815
816 /*
817    ### Qt 5:
818    ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
819    ### Qt exports QPolygon and QPolygonF that inherit QVector<QPoint> and
820    ### QVector<QPointF> respectively.
821 */
822
823 #ifdef Q_CC_MSVC
824 QT_BEGIN_INCLUDE_NAMESPACE
825 #include <QtCore/QPointF>
826 #include <QtCore/QPoint>
827 QT_END_INCLUDE_NAMESPACE
828
829 #if defined(QT_BUILD_CORE_LIB)
830 #define Q_TEMPLATE_EXTERN
831 #else
832 #define Q_TEMPLATE_EXTERN extern
833 #endif
834 Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
835 Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
836 #endif
837
838 QT_END_NAMESPACE
839
840 QT_END_HEADER
841
842 #endif // QVECTOR_H