- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

# qvarlengtharray.h

Go to the documentation of this file.

    00001 /****************************************************************************
    00002 **
    00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
    00004 ** All rights reserved.
    00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
    00006 **
    00007 ** This file is part of the QtCore module of the Qt Toolkit.
    00008 **
    00009 ** $QT_BEGIN_LICENSE:LGPL$
    00010 ** Commercial Usage
    00011 ** Licensees holding valid Qt Commercial licenses may use this file in
    00012 ** accordance with the Qt Commercial License Agreement provided with the
    00013 ** Software or, alternatively, in accordance with the terms contained in
    00014 ** a written agreement between you and Nokia.
    00015 **
    00016 ** GNU Lesser General Public License Usage
    00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
    00018 ** General Public License version 2.1 as published by the Free Software
    00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
    00020 ** packaging of this file.  Please review the following information to
    00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
    00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    00023 **
    00024 ** In addition, as a special exception, Nokia gives you certain additional
    00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
    00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
    00027 **
    00028 ** GNU General Public License Usage
    00029 ** Alternatively, this file may be used under the terms of the GNU
    00030 ** General Public License version 3.0 as published by the Free Software
    00031 ** Foundation and appearing in the file LICENSE.GPL included in the
    00032 ** packaging of this file.  Please review the following information to
    00033 ** ensure the GNU General Public License version 3.0 requirements will be
    00034 ** met: http://www.gnu.org/copyleft/gpl.html.
    00035 **
    00036 ** If you have questions regarding the use of this file, please contact
    00037 ** Nokia at qt-info@nokia.com.
    00038 ** $QT_END_LICENSE$
    00039 **
    00040 ****************************************************************************/
    00041
    00042 #ifndef QVARLENGTHARRAY_H
    00043 #define QVARLENGTHARRAY_H
    00044
    00045 #include <QtCore/qcontainerfwd.h>
    00046 #include <QtCore/qglobal.h>
    00047 #include <new>
    00048
    00049 QT_BEGIN_HEADER
    00050
    00051 QT_BEGIN_NAMESPACE
    00052
    00053 QT_MODULE(Core)
    00054
    00055 template<class T, int Prealloc>
    00056 class QPodList;
    00057
    00058 // Prealloc = 256 by default, specified in qcontainerfwd.h
    00059 template<class T, int Prealloc>
    00060 class QVarLengthArray
    00061 {
    00062 public:
    00063     inline explicit QVarLengthArray(int size = 0);
    00064
    00065     inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other)
    00066         : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
    00067     {
    00068         append(other.constData(), other.size());
    00069     }
    00070
    00071     inline ~QVarLengthArray() {
    00072         if (QTypeInfo<T>::isComplex) {
    00073             T *i = ptr + s;
    00074             while (i-- != ptr)
    00075                 i->~T();
    00076         }
    00077         if (ptr != reinterpret_cast<T *>(array))
    00078             qFree(ptr);
    00079     }
    00080     inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
    00081     {
    00082         if (this != &other) {
    00083             clear();
    00084             append(other.constData(), other.size());
    00085         }
    00086         return *this;
    00087     }
    00088
    00089     inline void removeLast() {
    00090         Q_ASSERT(s > 0);
    00091         realloc(s - 1, a);
    00092     }
    00093     inline int size() const { return s; }
    00094     inline int count() const { return s; }
    00095     inline bool isEmpty() const { return (s == 0); }
    00096     inline void resize(int size);
    00097     inline void clear() { resize(0); }
    00098
    00099     inline int capacity() const { return a; }
    00100     inline void reserve(int size);
    00101
    00102     inline T &operator[](int idx) {
    00103         Q_ASSERT(idx >= 0 && idx < s);
    00104         return ptr[idx];
    00105     }
    00106     inline const T &operator[](int idx) const {
    00107         Q_ASSERT(idx >= 0 && idx < s);
    00108         return ptr[idx];
    00109     }
    00110     inline const T &at(int idx) const { return operator[](idx); }
    00111
    00112     T value(int i) const;
    00113     T value(int i, const T &defaultValue) const;
    00114
    00115     inline void append(const T &t) {
    00116         if (s == a)   // i.e. s != 0
    00117             realloc(s, s<<1);
    00118         const int idx = s++;
    00119         if (QTypeInfo<T>::isComplex) {
    00120             new (ptr + idx) T(t);
    00121         } else {
    00122             ptr[idx] = t;
    00123         }
    00124     }
    00125     void append(const T *buf, int size);
    00126
    00127     inline T *data() { return ptr; }
    00128     inline const T *data() const { return ptr; }
    00129     inline const T * constData() const { return ptr; }
    00130     typedef int size_type;
    00131     typedef T value_type;
    00132     typedef value_type *pointer;
    00133     typedef const value_type *const_pointer;
    00134     typedef value_type &reference;
    00135     typedef const value_type &const_reference;
    00136     typedef qptrdiff difference_type;
    00137
    00138 private:
    00139     friend class QPodList<T, Prealloc>;
    00140     void realloc(int size, int alloc);
    00141
    00142     int a;      // capacity
    00143     int s;      // size
    00144     T *ptr;     // data
    00145     union {
    00146         // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
    00147         char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
    00148         qint64 q_for_alignment_1;
    00149         double q_for_alignment_2;
    00150     };
    00151 };
    00152
    00153 template <class T, int Prealloc>
    00154 Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize)
    00155     : s(asize) {
    00156     if (s > Prealloc) {
    00157         ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T)));
    00158         Q_CHECK_PTR(ptr);
    00159         a = s;
    00160     } else {
    00161         ptr = reinterpret_cast<T *>(array);
    00162         a = Prealloc;
    00163     }
    00164     if (QTypeInfo<T>::isComplex) {
    00165         T *i = ptr + s;
    00166         while (i != ptr)
    00167             new (--i) T;
    00168     }
    00169 }
    00170
    00171 template <class T, int Prealloc>
    00172 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(int asize)
    00173 { realloc(asize, qMax(asize, a)); }
    00174
    00175 template <class T, int Prealloc>
    00176 Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize)
    00177 { if (asize > a) realloc(s, asize); }
    00178
    00179 template <class T, int Prealloc>
    00180 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int increment)
    00181 {
    00182     Q_ASSERT(abuf);
    00183     if (increment <= 0)
    00184         return;
    00185
    00186     const int asize = s + increment;
    00187
    00188     if (asize >= a)
    00189         realloc(s, qMax(s*2, asize));
    00190
    00191     if (QTypeInfo<T>::isComplex) {
    00192         // call constructor for new objects (which can throw)
    00193         while (s < asize)
    00194             new (ptr+(s++)) T(*abuf++);
    00195     } else {
    00196         qMemCopy(&ptr[s], abuf, increment * sizeof(T));
    00197         s = asize;
    00198     }
    00199 }
    00200
    00201 template <class T, int Prealloc>
    00202 Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
    00203 {
    00204     Q_ASSERT(aalloc >= asize);
    00205     T *oldPtr = ptr;
    00206     int osize = s;
    00207
    00208     const int copySize = qMin(asize, osize);
    00209     if (aalloc != a) {
    00210         ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
    00211         Q_CHECK_PTR(ptr);
    00212         if (ptr) {
    00213             s = 0;
    00214             a = aalloc;
    00215
    00216             if (QTypeInfo<T>::isStatic) {
    00217                 QT_TRY {
    00218                     // copy all the old elements
    00219                     while (s < copySize) {
    00220                         new (ptr+s) T(*(oldPtr+s));
    00221                         (oldPtr+s)->~T();
    00222                         s++;
    00223                     }
    00224                 } QT_CATCH(...) {
    00225                     // clean up all the old objects and then free the old ptr
    00226                     int sClean = s;
    00227                     while (sClean < osize)
    00228                         (oldPtr+(sClean++))->~T();
    00229                     if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
    00230                         qFree(oldPtr);
    00231                     QT_RETHROW;
    00232                 }
    00233             } else {
    00234                 qMemCopy(ptr, oldPtr, copySize * sizeof(T));
    00235             }
    00236         } else {
    00237             ptr = oldPtr;
    00238             return;
    00239         }
    00240     }
    00241     s = copySize;
    00242
    00243     if (QTypeInfo<T>::isComplex) {
    00244         // destroy remaining old objects
    00245         while (osize > asize)
    00246             (oldPtr+(--osize))->~T();
    00247     }
    00248
    00249     if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
    00250         qFree(oldPtr);
    00251
    00252     if (QTypeInfo<T>::isComplex) {
    00253         // call default constructor for new objects (which can throw)
    00254         while (s < asize)
    00255             new (ptr+(s++)) T;
    00256     } else {
    00257         s = asize;
    00258     }
    00259 }
    00260
    00261 template <class T, int Prealloc>
    00262 Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i) const
    00263 {
    00264     if (i < 0 || i >= size()) {
    00265         return T();
    00266     }
    00267     return at(i);
    00268 }
    00269 template <class T, int Prealloc>
    00270 Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i, const T &defaultValue) const
    00271 {
    00272     return (i < 0 || i >= size()) ? defaultValue : at(i);
    00273 }
    00274
    00275
    00276 QT_END_NAMESPACE
    00277
    00278 QT_END_HEADER
    00279
    00280 #endif // QVARLENGTHARRAY_H