src/corelib/tools/qvarlengtharray.h
changeset 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QVARLENGTHARRAY_H
       
    43 #define QVARLENGTHARRAY_H
       
    44 
       
    45 #include <QtCore/qcontainerfwd.h>
       
    46 #include <QtCore/qglobal.h>
       
    47 #include <new>
       
    48 
       
    49 QT_BEGIN_HEADER
       
    50 
       
    51 QT_BEGIN_NAMESPACE
       
    52 
       
    53 QT_MODULE(Core)
       
    54 
       
    55 template<class T, int Prealloc>
       
    56 class QPodList;
       
    57 
       
    58 // Prealloc = 256 by default, specified in qcontainerfwd.h
       
    59 template<class T, int Prealloc>
       
    60 class QVarLengthArray
       
    61 {
       
    62 public:
       
    63     inline explicit QVarLengthArray(int size = 0);
       
    64 
       
    65     inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
       
    66         : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
       
    67     {
       
    68         append(other.constData(), other.size());
       
    69     }
       
    70 
       
    71     inline ~QVarLengthArray() {
       
    72         if (QTypeInfo<T>::isComplex) {
       
    73             T *i = ptr + s;
       
    74             while (i-- != ptr)
       
    75                 i->~T();
       
    76         }
       
    77         if (ptr != reinterpret_cast<T *>(array))
       
    78             qFree(ptr);
       
    79     }
       
    80     inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
       
    81     {
       
    82         if (this != &other) {
       
    83             clear();
       
    84             append(other.constData(), other.size());
       
    85         }
       
    86         return *this;
       
    87     }
       
    88 
       
    89     inline void removeLast() {
       
    90         Q_ASSERT(s > 0);
       
    91         realloc(s - 1, a);
       
    92     }
       
    93     inline int size() const { return s; }
       
    94     inline int count() const { return s; }
       
    95     inline bool isEmpty() const { return (s == 0); }
       
    96     inline void resize(int size);
       
    97     inline void clear() { resize(0); }
       
    98 
       
    99     inline int capacity() const { return a; }
       
   100     inline void reserve(int size);
       
   101 
       
   102     inline T &operator[](int idx) {
       
   103         Q_ASSERT(idx >= 0 && idx < s);
       
   104         return ptr[idx];
       
   105     }
       
   106     inline const T &operator[](int idx) const {
       
   107         Q_ASSERT(idx >= 0 && idx < s);
       
   108         return ptr[idx];
       
   109     }
       
   110 
       
   111     inline void append(const T &t) {
       
   112         if (s == a)   // i.e. s != 0
       
   113             realloc(s, s<<1);
       
   114         const int idx = s++;
       
   115         if (QTypeInfo<T>::isComplex) {
       
   116             new (ptr + idx) T(t);
       
   117         } else {
       
   118             ptr[idx] = t;
       
   119         }
       
   120     }
       
   121     void append(const T *buf, int size);
       
   122 
       
   123     inline T *data() { return ptr; }
       
   124     inline const T *data() const { return ptr; }
       
   125     inline const T * constData() const { return ptr; }
       
   126 
       
   127 private:
       
   128     friend class QPodList<T, Prealloc>;
       
   129     void realloc(int size, int alloc);
       
   130 
       
   131     int a;
       
   132     int s;
       
   133     T *ptr;
       
   134     union {
       
   135         // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
       
   136         char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
       
   137         qint64 q_for_alignment_1;
       
   138         double q_for_alignment_2;
       
   139     };
       
   140 };
       
   141 
       
   142 template <class T, int Prealloc>
       
   143 Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
       
   144     : s(asize) {
       
   145     if (s > Prealloc) {
       
   146         ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
       
   147         Q_CHECK_PTR(ptr);
       
   148         a = s;
       
   149     } else {
       
   150         ptr = reinterpret_cast<T *>(array);
       
   151         a = Prealloc;
       
   152     }
       
   153     if (QTypeInfo<T>::isComplex) {
       
   154         T *i = ptr + s;
       
   155         while (i != ptr)
       
   156             new (--i) T;
       
   157     }
       
   158 }
       
   159 
       
   160 template <class T, int Prealloc>
       
   161 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(int asize)
       
   162 { realloc(asize, qMax(asize, a)); }
       
   163 
       
   164 template <class T, int Prealloc>
       
   165 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
       
   166 { if (asize > a) realloc(s, asize); }
       
   167 
       
   168 template <class T, int Prealloc>
       
   169 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
       
   170 {
       
   171     Q_ASSERT(abuf);
       
   172     if (increment <= 0)
       
   173         return;
       
   174 
       
   175     const int asize = s + increment;
       
   176 
       
   177     if (asize >= a)
       
   178         realloc(s, qMax(s*2, asize));
       
   179 
       
   180     if (QTypeInfo<T>::isComplex) {
       
   181         // call constructor for new objects (which can throw)
       
   182         while (s < asize)
       
   183             new (ptr+(s++)) T(*abuf++);
       
   184     } else {
       
   185         qMemCopy(&ptr[s], abuf, increment * sizeof(T));
       
   186         s = asize;
       
   187     }
       
   188 }
       
   189 
       
   190 template <class T, int Prealloc>
       
   191 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
       
   192 {
       
   193     Q_ASSERT(aalloc >= asize);
       
   194     T *oldPtr = ptr;
       
   195     int osize = s;
       
   196     // s = asize;
       
   197 
       
   198     if (aalloc != a) {
       
   199         ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
       
   200         Q_CHECK_PTR(ptr);
       
   201         if (ptr) {
       
   202             s = 0;
       
   203             a = aalloc;
       
   204 
       
   205             if (QTypeInfo<T>::isStatic) {
       
   206                 QT_TRY {
       
   207                     // copy all the old elements
       
   208                     const int copySize = qMin(asize, osize);
       
   209                     while (s < copySize) {
       
   210                         new (ptr+s) T(*(oldPtr+s));
       
   211                         (oldPtr+s)->~T();
       
   212                         s++;
       
   213                     }
       
   214                 } QT_CATCH(...) {
       
   215                     // clean up all the old objects and then free the old ptr
       
   216                     int sClean = s;
       
   217                     while (sClean < osize)
       
   218                         (oldPtr+(sClean++))->~T();
       
   219                     if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
       
   220                         qFree(oldPtr);
       
   221                     QT_RETHROW;
       
   222                 }
       
   223             } else {
       
   224                 qMemCopy(ptr, oldPtr, qMin(asize, osize) * sizeof(T));
       
   225                 s = asize;
       
   226             }
       
   227         } else {
       
   228             ptr = oldPtr;
       
   229             return;
       
   230         }
       
   231     }
       
   232 
       
   233     if (QTypeInfo<T>::isComplex) {
       
   234         while (osize > asize)
       
   235             (oldPtr+(--osize))->~T();
       
   236         if( oldPtr == ptr )
       
   237             s = osize;
       
   238     }
       
   239 
       
   240     if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
       
   241         qFree(oldPtr);
       
   242 
       
   243     if (QTypeInfo<T>::isComplex) {
       
   244         // call default constructor for new objects (which can throw)
       
   245         while (s < asize)
       
   246             new (ptr+(s++)) T;
       
   247     } else {
       
   248         s = asize;
       
   249     }
       
   250 }
       
   251 
       
   252 QT_END_NAMESPACE
       
   253 
       
   254 QT_END_HEADER
       
   255 
       
   256 #endif // QVARLENGTHARRAY_H