LCOV - code coverage report
Current view: top level - home/aheinecke/dev/main/qt5/include/QtCore - qvector.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 151 49.7 %
Date: 2018-11-14 16:53:58 Functions: 25 42 59.5 %

          Line data    Source code
       1             : /****************************************************************************
       2             : **
       3             : ** Copyright (C) 2016 The Qt Company Ltd.
       4             : ** Contact: https://www.qt.io/licensing/
       5             : **
       6             : ** This file is part of the QtCore module of the Qt Toolkit.
       7             : **
       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 The Qt Company. For licensing terms
      14             : ** and conditions see https://www.qt.io/terms-conditions. For further
      15             : ** information use the contact form at https://www.qt.io/contact-us.
      16             : **
      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 3 as published by the Free Software
      20             : ** Foundation and appearing in the file LICENSE.LGPL3 included in the
      21             : ** packaging of this file. Please review the following information to
      22             : ** ensure the GNU Lesser General Public License version 3 requirements
      23             : ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
      24             : **
      25             : ** GNU General Public License Usage
      26             : ** Alternatively, this file may be used under the terms of the GNU
      27             : ** General Public License version 2.0 or (at your option) the GNU General
      28             : ** Public license version 3 or any later version approved by the KDE Free
      29             : ** Qt Foundation. The licenses are as published by the Free Software
      30             : ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
      31             : ** included in the packaging of this file. Please review the following
      32             : ** information to ensure the GNU General Public License requirements will
      33             : ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
      34             : ** https://www.gnu.org/licenses/gpl-3.0.html.
      35             : **
      36             : ** $QT_END_LICENSE$
      37             : **
      38             : ****************************************************************************/
      39             : 
      40             : #ifndef QVECTOR_H
      41             : #define QVECTOR_H
      42             : 
      43             : #include <QtCore/qalgorithms.h>
      44             : #include <QtCore/qiterator.h>
      45             : #include <QtCore/qlist.h>
      46             : #include <QtCore/qrefcount.h>
      47             : #include <QtCore/qarraydata.h>
      48             : #include <QtCore/qhashfunctions.h>
      49             : 
      50             : #include <iterator>
      51             : #include <vector>
      52             : #include <stdlib.h>
      53             : #include <string.h>
      54             : #ifdef Q_COMPILER_INITIALIZER_LISTS
      55             : #include <initializer_list>
      56             : #endif
      57             : 
      58             : #include <algorithm>
      59             : 
      60             : QT_BEGIN_NAMESPACE
      61             : 
      62             : class QRegion;
      63             : 
      64             : template <typename T>
      65             : class QVector
      66             : {
      67             :     typedef QTypedArrayData<T> Data;
      68             :     Data *d;
      69             : 
      70             : public:
      71          19 :     inline QVector() Q_DECL_NOTHROW : d(Data::sharedNull()) { }
      72             :     explicit QVector(int size);
      73             :     QVector(int size, const T &t);
      74             :     inline QVector(const QVector<T> &v);
      75          22 :     inline ~QVector() { if (!d->ref.deref()) freeData(d); }
      76             :     QVector<T> &operator=(const QVector<T> &v);
      77             : #ifdef Q_COMPILER_RVALUE_REFS
      78           3 :     QVector(QVector<T> &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
      79           2 :     QVector<T> &operator=(QVector<T> &&other) Q_DECL_NOTHROW
      80           2 :     { QVector moved(std::move(other)); swap(moved); return *this; }
      81             : #endif
      82           2 :     void swap(QVector<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
      83             : #ifdef Q_COMPILER_INITIALIZER_LISTS
      84             :     inline QVector(std::initializer_list<T> args);
      85             : #endif
      86             :     bool operator==(const QVector<T> &v) const;
      87             :     inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
      88             : 
      89           2 :     inline int size() const { return d->size; }
      90             : 
      91             :     inline bool isEmpty() const { return d->size == 0; }
      92             : 
      93             :     void resize(int size);
      94             : 
      95           8 :     inline int capacity() const { return int(d->alloc); }
      96             :     void reserve(int size);
      97             :     inline void squeeze()
      98             :     {
      99             :         reallocData(d->size, d->size);
     100             :         if (d->capacityReserved) {
     101             :             // capacity reserved in a read only memory would be useless
     102             :             // this checks avoid writing to such memory.
     103             :             d->capacityReserved = 0;
     104             :         }
     105             :     }
     106             : 
     107             :     inline void detach();
     108          18 :     inline bool isDetached() const { return !d->ref.isShared(); }
     109             : #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
     110             :     inline void setSharable(bool sharable)
     111             :     {
     112             :         if (sharable == d->ref.isSharable())
     113             :             return;
     114             :         if (!sharable)
     115             :             detach();
     116             : 
     117             :         if (d == Data::unsharableEmpty()) {
     118             :             if (sharable)
     119             :                 d = Data::sharedNull();
     120             :         } else {
     121             :             d->ref.setSharable(sharable);
     122             :         }
     123             :         Q_ASSERT(d->ref.isSharable() == sharable);
     124             :     }
     125             : #endif
     126             : 
     127             :     inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
     128             : 
     129             :     inline T *data() { detach(); return d->begin(); }
     130             :     inline const T *data() const { return d->begin(); }
     131             :     inline const T *constData() const { return d->begin(); }
     132             :     void clear();
     133             : 
     134             :     const T &at(int i) const;
     135             :     T &operator[](int i);
     136             :     const T &operator[](int i) const;
     137             :     void append(const T &t);
     138             : #ifdef Q_COMPILER_RVALUE_REFS
     139             :     void append(T &&t);
     140             : #endif
     141             :     inline void append(const QVector<T> &l) { *this += l; }
     142             :     void prepend(const T &t);
     143             :     void insert(int i, const T &t);
     144             :     void insert(int i, int n, const T &t);
     145             :     void replace(int i, const T &t);
     146             :     void remove(int i);
     147             :     void remove(int i, int n);
     148             :     inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(d->begin()); }
     149             :     inline void removeLast();
     150             :     T takeFirst() { Q_ASSERT(!isEmpty()); T r = std::move(first()); removeFirst(); return r; }
     151             :     T takeLast()  { Q_ASSERT(!isEmpty()); T r = std::move(last()); removeLast(); return r; }
     152             : 
     153             :     QVector<T> &fill(const T &t, int size = -1);
     154             : 
     155             :     int indexOf(const T &t, int from = 0) const;
     156             :     int lastIndexOf(const T &t, int from = -1) const;
     157             :     bool contains(const T &t) const;
     158             :     int count(const T &t) const;
     159             : 
     160             :     // QList compatibility
     161             :     void removeAt(int i) { remove(i); }
     162             :     int removeAll(const T &t)
     163             :     {
     164             :         const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
     165             :         if (cit == ce)
     166             :             return 0;
     167             :         // next operation detaches, so ce, cit, t may become invalidated:
     168             :         const T tCopy = t;
     169             :         const int firstFoundIdx = std::distance(this->cbegin(), cit);
     170             :         const iterator e = end(), it = std::remove(begin() + firstFoundIdx, e, tCopy);
     171             :         const int result = std::distance(it, e);
     172             :         erase(it, e);
     173             :         return result;
     174             :     }
     175             :     bool removeOne(const T &t)
     176             :     {
     177             :         const int i = indexOf(t);
     178             :         if (i < 0)
     179             :             return false;
     180             :         remove(i);
     181             :         return true;
     182             :     }
     183             :     int length() const { return size(); }
     184             :     T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; }
     185             :     void move(int from, int to)
     186             :     {
     187             :         Q_ASSERT_X(from >= 0 && from < size(), "QVector::move(int,int)", "'from' is out-of-range");
     188             :         Q_ASSERT_X(to >= 0 && to < size(), "QVector::move(int,int)", "'to' is out-of-range");
     189             :         if (from == to) // don't detach when no-op
     190             :             return;
     191             :         detach();
     192             :         T * const b = d->begin();
     193             :         if (from < to)
     194             :             std::rotate(b + from, b + from + 1, b + to + 1);
     195             :         else
     196             :             std::rotate(b + to, b + from, b + from + 1);
     197             :     }
     198             : 
     199             :     // STL-style
     200             :     typedef typename Data::iterator iterator;
     201             :     typedef typename Data::const_iterator const_iterator;
     202             :     typedef std::reverse_iterator<iterator> reverse_iterator;
     203             :     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     204             : #if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC)
     205           0 :     inline iterator begin() { detach(); return d->begin(); }
     206           6 :     inline const_iterator begin() const Q_DECL_NOTHROW { return d->constBegin(); }
     207             :     inline const_iterator cbegin() const Q_DECL_NOTHROW { return d->constBegin(); }
     208           0 :     inline const_iterator constBegin() const Q_DECL_NOTHROW { return d->constBegin(); }
     209           0 :     inline iterator end() { detach(); return d->end(); }
     210          36 :     inline const_iterator end() const Q_DECL_NOTHROW { return d->constEnd(); }
     211             :     inline const_iterator cend() const Q_DECL_NOTHROW { return d->constEnd(); }
     212           0 :     inline const_iterator constEnd() const Q_DECL_NOTHROW { return d->constEnd(); }
     213             : #else
     214             :     inline iterator begin(iterator = iterator()) { detach(); return d->begin(); }
     215             :     inline const_iterator begin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
     216             :     inline const_iterator cbegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
     217             :     inline const_iterator constBegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
     218             :     inline iterator end(iterator = iterator()) { detach(); return d->end(); }
     219             :     inline const_iterator end(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
     220             :     inline const_iterator cend(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
     221             :     inline const_iterator constEnd(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
     222             : #endif
     223             :     reverse_iterator rbegin() { return reverse_iterator(end()); }
     224             :     reverse_iterator rend() { return reverse_iterator(begin()); }
     225             :     const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
     226             :     const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
     227             :     const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
     228             :     const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
     229             :     iterator insert(iterator before, int n, const T &x);
     230             :     inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
     231             :     iterator erase(iterator begin, iterator end);
     232             :     inline iterator erase(iterator pos) { return erase(pos, pos+1); }
     233             : 
     234             :     // more Qt
     235          16 :     inline int count() const { return d->size; }
     236             :     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
     237             :     inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
     238             :     inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
     239             :     inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
     240             :     inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
     241             :     inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
     242             :     inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
     243             :     inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
     244             :     QVector<T> mid(int pos, int len = -1) const;
     245             : 
     246             :     T value(int i) const;
     247             :     T value(int i, const T &defaultValue) const;
     248             : 
     249             :     // STL compatibility
     250             :     typedef T value_type;
     251             :     typedef value_type* pointer;
     252             :     typedef const value_type* const_pointer;
     253             :     typedef value_type& reference;
     254             :     typedef const value_type& const_reference;
     255             :     typedef qptrdiff difference_type;
     256             :     typedef iterator Iterator;
     257             :     typedef const_iterator ConstIterator;
     258             :     typedef int size_type;
     259           5 :     inline void push_back(const T &t) { append(t); }
     260             : #ifdef Q_COMPILER_RVALUE_REFS
     261           5 :     void push_back(T &&t) { append(std::move(t)); }
     262             : #endif
     263             :     inline void push_front(const T &t) { prepend(t); }
     264             :     void pop_back() { removeLast(); }
     265             :     void pop_front() { removeFirst(); }
     266           1 :     inline bool empty() const
     267           1 :     { return d->size == 0; }
     268             :     inline T& front() { return first(); }
     269             :     inline const_reference front() const { return first(); }
     270             :     inline reference back() { return last(); }
     271             :     inline const_reference back() const { return last(); }
     272             :     void shrink_to_fit() { squeeze(); }
     273             : 
     274             :     // comfort
     275             :     QVector<T> &operator+=(const QVector<T> &l);
     276             :     inline QVector<T> operator+(const QVector<T> &l) const
     277             :     { QVector n = *this; n += l; return n; }
     278             :     inline QVector<T> &operator+=(const T &t)
     279             :     { append(t); return *this; }
     280           0 :     inline QVector<T> &operator<< (const T &t)
     281           0 :     { append(t); return *this; }
     282             :     inline QVector<T> &operator<<(const QVector<T> &l)
     283             :     { *this += l; return *this; }
     284             : 
     285             :     QList<T> toList() const;
     286             : 
     287             :     static QVector<T> fromList(const QList<T> &list);
     288             : 
     289             :     static inline QVector<T> fromStdVector(const std::vector<T> &vector)
     290             :     { QVector<T> tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
     291             :     inline std::vector<T> toStdVector() const
     292             :     { return std::vector<T>(d->begin(), d->end()); }
     293             : private:
     294             :     friend class QRegion; // Optimization for QRegion::rects()
     295             : 
     296             :     // ### Qt6: remove const from int parameters
     297             :     void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
     298             :     void reallocData(const int sz) { reallocData(sz, d->alloc); }
     299             :     void freeData(Data *d);
     300             :     void defaultConstruct(T *from, T *to);
     301             :     void copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom);
     302             :     void destruct(T *from, T *to);
     303             :     bool isValidIterator(const iterator &i) const
     304             :     {
     305             :         return (i <= d->end()) && (d->begin() <= i);
     306             :     }
     307             :     class AlignmentDummy { Data header; T array[1]; };
     308             : };
     309             : 
     310             : #ifdef Q_CC_MSVC
     311             : // behavior change: an object of POD type constructed with an initializer of the form ()
     312             : // will be default-initialized
     313             : #   pragma warning ( push )
     314             : #   pragma warning ( disable : 4345 )
     315             : #   pragma warning(disable : 4127) // conditional expression is constant
     316             : #endif
     317             : 
     318             : template <typename T>
     319           0 : void QVector<T>::defaultConstruct(T *from, T *to)
     320             : {
     321             :     if (QTypeInfo<T>::isComplex) {
     322           0 :         while (from != to) {
     323           0 :             new (from++) T();
     324             :         }
     325             :     } else {
     326           0 :         ::memset(static_cast<void *>(from), 0, (to - from) * sizeof(T));
     327             :     }
     328           0 : }
     329             : 
     330             : template <typename T>
     331           0 : void QVector<T>::copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom)
     332             : {
     333             :     if (QTypeInfo<T>::isComplex) {
     334           0 :         while (srcFrom != srcTo)
     335           0 :             new (dstFrom++) T(*srcFrom++);
     336             :     } else {
     337             :         ::memcpy(static_cast<void *>(dstFrom), static_cast<const void *>(srcFrom), (srcTo - srcFrom) * sizeof(T));
     338             :     }
     339           0 : }
     340             : 
     341             : template <typename T>
     342          16 : void QVector<T>::destruct(T *from, T *to)
     343             : {
     344             :     if (QTypeInfo<T>::isComplex) {
     345          28 :         while (from != to) {
     346          12 :             from++->~T();
     347             :         }
     348             :     }
     349           4 : }
     350             : 
     351             : template <typename T>
     352           0 : inline QVector<T>::QVector(const QVector<T> &v)
     353             : {
     354           0 :     if (v.d->ref.ref()) {
     355           0 :         d = v.d;
     356             :     } else {
     357           0 :         if (v.d->capacityReserved) {
     358           0 :             d = Data::allocate(v.d->alloc);
     359           0 :             Q_CHECK_PTR(d);
     360           0 :             d->capacityReserved = true;
     361             :         } else {
     362           0 :             d = Data::allocate(v.d->size);
     363           0 :             Q_CHECK_PTR(d);
     364             :         }
     365           0 :         if (d->alloc) {
     366           0 :             copyConstruct(v.d->begin(), v.d->end(), d->begin());
     367           0 :             d->size = v.d->size;
     368             :         }
     369             :     }
     370           0 : }
     371             : 
     372             : #if defined(Q_CC_MSVC)
     373             : #pragma warning( pop )
     374             : #endif
     375             : 
     376             : template <typename T>
     377           0 : void QVector<T>::detach()
     378             : {
     379           0 :     if (!isDetached()) {
     380             : #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
     381           0 :         if (!d->alloc)
     382           0 :             d = Data::unsharableEmpty();
     383             :         else
     384             : #endif
     385           0 :             reallocData(d->size, int(d->alloc));
     386             :     }
     387           0 :     Q_ASSERT(isDetached());
     388           0 : }
     389             : 
     390             : template <typename T>
     391           8 : void QVector<T>::reserve(int asize)
     392             : {
     393           8 :     if (asize > int(d->alloc))
     394           2 :         reallocData(d->size, asize);
     395          16 :     if (isDetached()
     396             : #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
     397           8 :             && d != Data::unsharableEmpty()
     398             : #endif
     399             :             )
     400           2 :         d->capacityReserved = 1;
     401           8 :     Q_ASSERT(capacity() >= asize);
     402           8 : }
     403             : 
     404             : template <typename T>
     405           0 : void QVector<T>::resize(int asize)
     406             : {
     407             :     int newAlloc;
     408           0 :     const int oldAlloc = int(d->alloc);
     409           0 :     QArrayData::AllocationOptions opt;
     410             : 
     411           0 :     if (asize > oldAlloc) { // there is not enough space
     412           0 :         newAlloc = asize;
     413           0 :         opt = QArrayData::Grow;
     414             :     } else {
     415           0 :         newAlloc = oldAlloc;
     416             :     }
     417           0 :     reallocData(asize, newAlloc, opt);
     418           0 : }
     419             : template <typename T>
     420           0 : inline void QVector<T>::clear()
     421           0 : { resize(0); }
     422             : template <typename T>
     423           0 : inline const T &QVector<T>::at(int i) const
     424           0 : { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
     425           0 :   return d->begin()[i]; }
     426             : template <typename T>
     427             : inline const T &QVector<T>::operator[](int i) const
     428             : { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
     429             :   return d->begin()[i]; }
     430             : template <typename T>
     431             : inline T &QVector<T>::operator[](int i)
     432             : { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
     433             :   return data()[i]; }
     434             : template <typename T>
     435             : inline void QVector<T>::insert(int i, const T &t)
     436             : { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
     437             :   insert(begin() + i, 1, t); }
     438             : template <typename T>
     439             : inline void QVector<T>::insert(int i, int n, const T &t)
     440             : { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
     441             :   insert(begin() + i, n, t); }
     442             : template <typename T>
     443             : inline void QVector<T>::remove(int i, int n)
     444             : { Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range");
     445             :   erase(d->begin() + i, d->begin() + i + n); }
     446             : template <typename T>
     447             : inline void QVector<T>::remove(int i)
     448             : { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range");
     449             :   erase(d->begin() + i, d->begin() + i + 1); }
     450             : template <typename T>
     451             : inline void QVector<T>::prepend(const T &t)
     452             : { insert(begin(), 1, t); }
     453             : 
     454             : template <typename T>
     455             : inline void QVector<T>::replace(int i, const T &t)
     456             : {
     457             :     Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
     458             :     const T copy(t);
     459             :     data()[i] = copy;
     460             : }
     461             : 
     462             : template <typename T>
     463             : QVector<T> &QVector<T>::operator=(const QVector<T> &v)
     464             : {
     465             :     if (v.d != d) {
     466             :         QVector<T> tmp(v);
     467             :         tmp.swap(*this);
     468             :     }
     469             :     return *this;
     470             : }
     471             : 
     472             : template <typename T>
     473             : QVector<T>::QVector(int asize)
     474             : {
     475             :     Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
     476             :     if (Q_LIKELY(asize > 0)) {
     477             :         d = Data::allocate(asize);
     478             :         Q_CHECK_PTR(d);
     479             :         d->size = asize;
     480             :         defaultConstruct(d->begin(), d->end());
     481             :     } else {
     482             :         d = Data::sharedNull();
     483             :     }
     484             : }
     485             : 
     486             : template <typename T>
     487             : QVector<T>::QVector(int asize, const T &t)
     488             : {
     489             :     Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
     490             :     if (asize > 0) {
     491             :         d = Data::allocate(asize);
     492             :         Q_CHECK_PTR(d);
     493             :         d->size = asize;
     494             :         T* i = d->end();
     495             :         while (i != d->begin())
     496             :             new (--i) T(t);
     497             :     } else {
     498             :         d = Data::sharedNull();
     499             :     }
     500             : }
     501             : 
     502             : #ifdef Q_COMPILER_INITIALIZER_LISTS
     503             : # if defined(Q_CC_MSVC)
     504             : QT_WARNING_PUSH
     505             : QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant
     506             : # endif // Q_CC_MSVC
     507             : 
     508             : template <typename T>
     509             : QVector<T>::QVector(std::initializer_list<T> args)
     510             : {
     511             :     if (args.size() > 0) {
     512             :         d = Data::allocate(args.size());
     513             :         Q_CHECK_PTR(d);
     514             :         // std::initializer_list<T>::iterator is guaranteed to be
     515             :         // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
     516             :         copyConstruct(args.begin(), args.end(), d->begin());
     517             :         d->size = int(args.size());
     518             :     } else {
     519             :         d = Data::sharedNull();
     520             :     }
     521             : }
     522             : # if defined(Q_CC_MSVC)
     523             : QT_WARNING_POP
     524             : # endif // Q_CC_MSVC
     525             : #endif // Q_COMPILER_INITALIZER_LISTS
     526             : 
     527             : template <typename T>
     528           4 : void QVector<T>::freeData(Data *x)
     529             : {
     530           4 :     destruct(x->begin(), x->end());
     531           4 :     Data::deallocate(x);
     532           4 : }
     533             : 
     534             : #if defined(Q_CC_MSVC)
     535             : QT_WARNING_PUSH
     536             : QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant
     537             : #endif
     538             : 
     539             : template <typename T>
     540           4 : void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::AllocationOptions options)
     541             : {
     542           4 :     Q_ASSERT(asize >= 0 && asize <= aalloc);
     543           4 :     Data *x = d;
     544             : 
     545           4 :     const bool isShared = d->ref.isShared();
     546             : 
     547           4 :     if (aalloc != 0) {
     548           4 :         if (aalloc != int(d->alloc) || isShared) {
     549             :             QT_TRY {
     550             :                 // allocate memory
     551           4 :                 x = Data::allocate(aalloc, options);
     552           4 :                 Q_CHECK_PTR(x);
     553             :                 // aalloc is bigger then 0 so it is not [un]sharedEmpty
     554             : #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
     555           4 :                 Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
     556             : #endif
     557           4 :                 Q_ASSERT(!x->ref.isStatic());
     558           4 :                 x->size = asize;
     559             : 
     560           4 :                 T *srcBegin = d->begin();
     561           4 :                 T *srcEnd = asize > d->size ? d->end() : d->begin() + asize;
     562           4 :                 T *dst = x->begin();
     563             : 
     564             :                 if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) {
     565             :                     // we can not move the data, we need to copy construct it
     566           8 :                     while (srcBegin != srcEnd) {
     567           2 :                         new (dst++) T(*srcBegin++);
     568             :                     }
     569             :                 } else {
     570           0 :                     ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T));
     571           0 :                     dst += srcEnd - srcBegin;
     572             : 
     573             :                     // destruct unused / not moved data
     574           0 :                     if (asize < d->size)
     575           0 :                         destruct(d->begin() + asize, d->end());
     576             :                 }
     577             : 
     578           4 :                 if (asize > d->size) {
     579             :                     // construct all new objects when growing
     580             :                     QT_TRY {
     581           0 :                         defaultConstruct(dst, x->end());
     582           0 :                     } QT_CATCH (...) {
     583             :                         // destruct already copied objects
     584           0 :                         destruct(x->begin(), dst);
     585           0 :                         QT_RETHROW;
     586             :                     }
     587             :                 }
     588           0 :             } QT_CATCH (...) {
     589           0 :                 Data::deallocate(x);
     590           0 :                 QT_RETHROW;
     591             :             }
     592           4 :             x->capacityReserved = d->capacityReserved;
     593             :         } else {
     594           0 :             Q_ASSERT(int(d->alloc) == aalloc); // resize, without changing allocation size
     595           0 :             Q_ASSERT(isDetached());       // can be done only on detached d
     596           0 :             Q_ASSERT(x == d);             // in this case we do not need to allocate anything
     597           0 :             if (asize <= d->size) {
     598           0 :                 destruct(x->begin() + asize, x->end()); // from future end to current end
     599             :             } else {
     600           0 :                 defaultConstruct(x->end(), x->begin() + asize); // from current end to future end
     601             :             }
     602           0 :             x->size = asize;
     603             :         }
     604             :     } else {
     605           0 :         x = Data::sharedNull();
     606             :     }
     607           4 :     if (d != x) {
     608           4 :         if (!d->ref.deref()) {
     609           0 :             if (!QTypeInfoQuery<T>::isRelocatable || !aalloc || (isShared && QTypeInfo<T>::isComplex)) {
     610             :                 // data was copy constructed, we need to call destructors
     611             :                 // or if !alloc we did nothing to the old 'd'.
     612           1 :                 freeData(d);
     613             :             } else {
     614           0 :                 Data::deallocate(d);
     615             :             }
     616             :         }
     617           4 :         d = x;
     618             :     }
     619             : 
     620           4 :     Q_ASSERT(d->data());
     621           4 :     Q_ASSERT(uint(d->size) <= d->alloc);
     622             : #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
     623           4 :     Q_ASSERT(d != Data::unsharableEmpty());
     624             : #endif
     625           4 :     Q_ASSERT(aalloc ? d != Data::sharedNull() : d == Data::sharedNull());
     626           4 :     Q_ASSERT(d->alloc >= uint(aalloc));
     627           4 :     Q_ASSERT(d->size == asize);
     628           4 : }
     629             : 
     630             : #if defined(Q_CC_MSVC)
     631             : QT_WARNING_POP
     632             : #endif
     633             : 
     634             : template<typename T>
     635             : Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
     636             : {
     637             :     if (uint(i) >= uint(d->size)) {
     638             :         return T();
     639             :     }
     640             :     return d->begin()[i];
     641             : }
     642             : template<typename T>
     643             : Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
     644             : {
     645             :     return uint(i) >= uint(d->size) ? defaultValue : d->begin()[i];
     646             : }
     647             : 
     648             : template <typename T>
     649           5 : void QVector<T>::append(const T &t)
     650             : {
     651           5 :     const bool isTooSmall = uint(d->size + 1) > d->alloc;
     652           5 :     if (!isDetached() || isTooSmall) {
     653           0 :         T copy(t);
     654           0 :         QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
     655           0 :         reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
     656             : 
     657             :         if (QTypeInfo<T>::isComplex)
     658           0 :             new (d->end()) T(qMove(copy));
     659             :         else
     660           0 :             *d->end() = qMove(copy);
     661             : 
     662             :     } else {
     663             :         if (QTypeInfo<T>::isComplex)
     664           5 :             new (d->end()) T(t);
     665             :         else
     666           0 :             *d->end() = t;
     667             :     }
     668           5 :     ++d->size;
     669           5 : }
     670             : 
     671             : #ifdef Q_COMPILER_RVALUE_REFS
     672             : template <typename T>
     673           5 : void QVector<T>::append(T &&t)
     674             : {
     675           5 :     const bool isTooSmall = uint(d->size + 1) > d->alloc;
     676           5 :     if (!isDetached() || isTooSmall) {
     677           2 :         QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
     678           2 :         reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
     679             :     }
     680             : 
     681           5 :     new (d->end()) T(std::move(t));
     682             : 
     683           5 :     ++d->size;
     684           5 : }
     685             : #endif
     686             : 
     687             : template <typename T>
     688             : void QVector<T>::removeLast()
     689             : {
     690             :     Q_ASSERT(!isEmpty());
     691             :     Q_ASSERT(d->alloc);
     692             : 
     693             :     if (!d->ref.isShared()) {
     694             :         --d->size;
     695             :         if (QTypeInfo<T>::isComplex)
     696             :             (d->data() + d->size)->~T();
     697             :     } else {
     698             :         reallocData(d->size - 1);
     699             :     }
     700             : }
     701             : 
     702             : template <typename T>
     703             : typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
     704             : {
     705             :     Q_ASSERT_X(isValidIterator(before),  "QVector::insert", "The specified iterator argument 'before' is invalid");
     706             : 
     707             :     const auto offset = std::distance(d->begin(), before);
     708             :     if (n != 0) {
     709             :         const T copy(t);
     710             :         if (!isDetached() || d->size + n > int(d->alloc))
     711             :             reallocData(d->size, d->size + n, QArrayData::Grow);
     712             :         if (!QTypeInfoQuery<T>::isRelocatable) {
     713             :             T *b = d->end();
     714             :             T *i = d->end() + n;
     715             :             while (i != b)
     716             :                 new (--i) T;
     717             :             i = d->end();
     718             :             T *j = i + n;
     719             :             b = d->begin() + offset;
     720             :             while (i != b)
     721             :                 *--j = *--i;
     722             :             i = b+n;
     723             :             while (i != b)
     724             :                 *--i = copy;
     725             :         } else {
     726             :             T *b = d->begin() + offset;
     727             :             T *i = b + n;
     728             :             memmove(i, b, (d->size - offset) * sizeof(T));
     729             :             while (i != b)
     730             :                 new (--i) T(copy);
     731             :         }
     732             :         d->size += n;
     733             :     }
     734             :     return d->begin() + offset;
     735             : }
     736             : 
     737             : template <typename T>
     738             : typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
     739             : {
     740             :     Q_ASSERT_X(isValidIterator(abegin), "QVector::erase", "The specified iterator argument 'abegin' is invalid");
     741             :     Q_ASSERT_X(isValidIterator(aend), "QVector::erase", "The specified iterator argument 'aend' is invalid");
     742             : 
     743             :     const auto itemsToErase = aend - abegin;
     744             : 
     745             :     if (!itemsToErase)
     746             :         return abegin;
     747             : 
     748             :     Q_ASSERT(abegin >= d->begin());
     749             :     Q_ASSERT(aend <= d->end());
     750             :     Q_ASSERT(abegin <= aend);
     751             : 
     752             :     const auto itemsUntouched = abegin - d->begin();
     753             : 
     754             :     // FIXME we could do a proper realloc, which copy constructs only needed data.
     755             :     // FIXME we are about to delete data - maybe it is good time to shrink?
     756             :     // FIXME the shrink is also an issue in removeLast, that is just a copy + reduce of this.
     757             :     if (d->alloc) {
     758             :         detach();
     759             :         abegin = d->begin() + itemsUntouched;
     760             :         aend = abegin + itemsToErase;
     761             :         if (!QTypeInfoQuery<T>::isRelocatable) {
     762             :             iterator moveBegin = abegin + itemsToErase;
     763             :             iterator moveEnd = d->end();
     764             :             while (moveBegin != moveEnd) {
     765             :                 if (QTypeInfo<T>::isComplex)
     766             :                     static_cast<T *>(abegin)->~T();
     767             :                 new (abegin++) T(*moveBegin++);
     768             :             }
     769             :             if (abegin < d->end()) {
     770             :                 // destroy rest of instances
     771             :                 destruct(abegin, d->end());
     772             :             }
     773             :         } else {
     774             :             destruct(abegin, aend);
     775             :             // QTBUG-53605: static_cast<void *> masks clang errors of the form
     776             :             // error: destination for this 'memmove' call is a pointer to class containing a dynamic class
     777             :             // FIXME maybe use std::is_polymorphic (as soon as allowed) to avoid the memmove
     778             :             memmove(static_cast<void *>(abegin), static_cast<void *>(aend),
     779             :                     (d->size - itemsToErase - itemsUntouched) * sizeof(T));
     780             :         }
     781             :         d->size -= int(itemsToErase);
     782             :     }
     783             :     return d->begin() + itemsUntouched;
     784             : }
     785             : 
     786             : template <typename T>
     787             : bool QVector<T>::operator==(const QVector<T> &v) const
     788             : {
     789             :     if (d == v.d)
     790             :         return true;
     791             :     if (d->size != v.d->size)
     792             :         return false;
     793             :     const T *vb = v.d->begin();
     794             :     const T *b  = d->begin();
     795             :     const T *e  = d->end();
     796             :     return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(vb, v.d->size));
     797             : }
     798             : 
     799             : template <typename T>
     800             : QVector<T> &QVector<T>::fill(const T &from, int asize)
     801             : {
     802             :     const T copy(from);
     803             :     resize(asize < 0 ? d->size : asize);
     804             :     if (d->size) {
     805             :         T *i = d->end();
     806             :         T *b = d->begin();
     807             :         while (i != b)
     808             :             *--i = copy;
     809             :     }
     810             :     return *this;
     811             : }
     812             : 
     813             : template <typename T>
     814             : QVector<T> &QVector<T>::operator+=(const QVector &l)
     815             : {
     816             :     if (d == Data::sharedNull()) {
     817             :         *this = l;
     818             :     } else {
     819             :         uint newSize = d->size + l.d->size;
     820             :         const bool isTooSmall = newSize > d->alloc;
     821             :         if (!isDetached() || isTooSmall) {
     822             :             QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
     823             :             reallocData(d->size, isTooSmall ? newSize : d->alloc, opt);
     824             :         }
     825             : 
     826             :         if (d->alloc) {
     827             :             T *w = d->begin() + newSize;
     828             :             T *i = l.d->end();
     829             :             T *b = l.d->begin();
     830             :             while (i != b) {
     831             :                 if (QTypeInfo<T>::isComplex)
     832             :                     new (--w) T(*--i);
     833             :                 else
     834             :                     *--w = *--i;
     835             :             }
     836             :             d->size = newSize;
     837             :         }
     838             :     }
     839             :     return *this;
     840             : }
     841             : 
     842             : template <typename T>
     843             : int QVector<T>::indexOf(const T &t, int from) const
     844             : {
     845             :     if (from < 0)
     846             :         from = qMax(from + d->size, 0);
     847             :     if (from < d->size) {
     848             :         T* n = d->begin() + from - 1;
     849             :         T* e = d->end();
     850             :         while (++n != e)
     851             :             if (*n == t)
     852             :                 return n - d->begin();
     853             :     }
     854             :     return -1;
     855             : }
     856             : 
     857             : template <typename T>
     858             : int QVector<T>::lastIndexOf(const T &t, int from) const
     859             : {
     860             :     if (from < 0)
     861             :         from += d->size;
     862             :     else if (from >= d->size)
     863             :         from = d->size-1;
     864             :     if (from >= 0) {
     865             :         T* b = d->begin();
     866             :         T* n = d->begin() + from + 1;
     867             :         while (n != b) {
     868             :             if (*--n == t)
     869             :                 return n - b;
     870             :         }
     871             :     }
     872             :     return -1;
     873             : }
     874             : 
     875             : template <typename T>
     876             : bool QVector<T>::contains(const T &t) const
     877             : {
     878             :     const T *b = d->begin();
     879             :     const T *e = d->end();
     880             :     return std::find(b, e, t) != e;
     881             : }
     882             : 
     883             : template <typename T>
     884             : int QVector<T>::count(const T &t) const
     885             : {
     886             :     const T *b = d->begin();
     887             :     const T *e = d->end();
     888             :     return int(std::count(b, e, t));
     889             : }
     890             : 
     891             : template <typename T>
     892             : Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
     893             : {
     894             :     using namespace QtPrivate;
     895             :     switch (QContainerImplHelper::mid(d->size, &pos, &len)) {
     896             :     case QContainerImplHelper::Null:
     897             :     case QContainerImplHelper::Empty:
     898             :         return QVector<T>();
     899             :     case QContainerImplHelper::Full:
     900             :         return *this;
     901             :     case QContainerImplHelper::Subset:
     902             :         break;
     903             :     }
     904             : 
     905             :     QVector<T> midResult;
     906             :     midResult.reallocData(0, len);
     907             :     T *srcFrom = d->begin() + pos;
     908             :     T *srcTo = d->begin() + pos + len;
     909             :     midResult.copyConstruct(srcFrom, srcTo, midResult.data());
     910             :     midResult.d->size = len;
     911             :     return midResult;
     912             : }
     913             : 
     914             : template <typename T>
     915             : Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
     916             : {
     917             :     QList<T> result;
     918             :     result.reserve(size());
     919             :     for (int i = 0; i < size(); ++i)
     920             :         result.append(at(i));
     921             :     return result;
     922             : }
     923             : 
     924             : template <typename T>
     925             : Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
     926             : {
     927             :     QVector<T> result(size());
     928             :     for (int i = 0; i < size(); ++i)
     929             :         result[i] = at(i);
     930             :     return result;
     931             : }
     932             : 
     933             : template <typename T>
     934             : QVector<T> QVector<T>::fromList(const QList<T> &list)
     935             : {
     936             :     return list.toVector();
     937             : }
     938             : 
     939             : template <typename T>
     940             : QList<T> QList<T>::fromVector(const QVector<T> &vector)
     941             : {
     942             :     return vector.toList();
     943             : }
     944             : 
     945             : Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
     946             : Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector)
     947             : 
     948             : template <typename T>
     949             : uint qHash(const QVector<T> &key, uint seed = 0)
     950             :     Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
     951             : {
     952             :     return qHashRange(key.cbegin(), key.cend(), seed);
     953             : }
     954             : 
     955             : template <typename T>
     956             : bool operator<(const QVector<T> &lhs, const QVector<T> &rhs)
     957             :     Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
     958             :                                                                rhs.begin(), rhs.end())))
     959             : {
     960             :     return std::lexicographical_compare(lhs.begin(), lhs.end(),
     961             :                                         rhs.begin(), rhs.end());
     962             : }
     963             : 
     964             : template <typename T>
     965             : inline bool operator>(const QVector<T> &lhs, const QVector<T> &rhs)
     966             :     Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
     967             : {
     968             :     return rhs < lhs;
     969             : }
     970             : 
     971             : template <typename T>
     972             : inline bool operator<=(const QVector<T> &lhs, const QVector<T> &rhs)
     973             :     Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
     974             : {
     975             :     return !(lhs > rhs);
     976             : }
     977             : 
     978             : template <typename T>
     979             : inline bool operator>=(const QVector<T> &lhs, const QVector<T> &rhs)
     980             :     Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
     981             : {
     982             :     return !(lhs < rhs);
     983             : }
     984             : 
     985             : /*
     986             :    ### Qt 5:
     987             :    ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
     988             :    ### Qt exports QPolygon and QPolygonF that inherit QVector<QPoint> and
     989             :    ### QVector<QPointF> respectively.
     990             : */
     991             : 
     992             : #ifdef Q_CC_MSVC
     993             : QT_BEGIN_INCLUDE_NAMESPACE
     994             : #include <QtCore/qpoint.h>
     995             : QT_END_INCLUDE_NAMESPACE
     996             : 
     997             : #ifndef Q_TEMPLATE_EXTERN
     998             : #if defined(QT_BUILD_CORE_LIB)
     999             : #define Q_TEMPLATE_EXTERN
    1000             : #else
    1001             : #define Q_TEMPLATE_EXTERN extern
    1002             : #endif
    1003             : #endif
    1004             : Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
    1005             : Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
    1006             : #endif
    1007             : 
    1008             : QVector<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
    1009             : 
    1010             : QT_END_NAMESPACE
    1011             : 
    1012             : #endif // QVECTOR_H

Generated by: LCOV version 1.13