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