LCOV - code coverage report
Current view: top level - usr/include/x86_64-linux-gnu/qt5/QtCore - qarraydata.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 11 24 45.8 %
Date: 2016-09-12 13:07:23 Functions: 9 16 56.2 %

          Line data    Source code
       1             : /****************************************************************************
       2             : **
       3             : ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
       4             : ** Contact: http://www.qt-project.org/legal
       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 Digia.  For licensing terms and
      14             : ** conditions see http://qt.digia.com/licensing.  For further information
      15             : ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
      20             : ** Foundation and appearing in the file LICENSE.LGPL included in the
      21             : ** packaging of this file.  Please review the following information to
      22             : ** ensure the GNU Lesser General Public License version 2.1 requirements
      23             : ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
      24             : **
      25             : ** In addition, as a special exception, Digia gives you certain additional
      26             : ** rights.  These rights are described in the Digia Qt LGPL Exception
      27             : ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
      28             : **
      29             : ** GNU General Public License Usage
      30             : ** Alternatively, this file may be used under the terms of the GNU
      31             : ** General Public License version 3.0 as published by the Free Software
      32             : ** Foundation and appearing in the file LICENSE.GPL included in the
      33             : ** packaging of this file.  Please review the following information to
      34             : ** ensure the GNU General Public License version 3.0 requirements will be
      35             : ** met: http://www.gnu.org/copyleft/gpl.html.
      36             : **
      37             : **
      38             : ** $QT_END_LICENSE$
      39             : **
      40             : ****************************************************************************/
      41             : 
      42             : #ifndef QARRAYDATA_H
      43             : #define QARRAYDATA_H
      44             : 
      45             : #include <QtCore/qrefcount.h>
      46             : #include <string.h>
      47             : 
      48             : QT_BEGIN_NAMESPACE
      49             : 
      50             : struct Q_CORE_EXPORT QArrayData
      51             : {
      52             :     QtPrivate::RefCount ref;
      53             :     int size;
      54             :     uint alloc : 31;
      55             :     uint capacityReserved : 1;
      56             : 
      57             :     qptrdiff offset; // in bytes from beginning of header
      58             : 
      59         123 :     void *data()
      60             :     {
      61         246 :         Q_ASSERT(size == 0
      62         123 :                 || offset < 0 || size_t(offset) >= sizeof(QArrayData));
      63         123 :         return reinterpret_cast<char *>(this) + offset;
      64             :     }
      65             : 
      66             :     const void *data() const
      67             :     {
      68             :         Q_ASSERT(size == 0
      69             :                 || offset < 0 || size_t(offset) >= sizeof(QArrayData));
      70             :         return reinterpret_cast<const char *>(this) + offset;
      71             :     }
      72             : 
      73             :     // This refers to array data mutability, not "header data" represented by
      74             :     // data members in QArrayData. Shared data (array and header) must still
      75             :     // follow COW principles.
      76             :     bool isMutable() const
      77             :     {
      78             :         return alloc != 0;
      79             :     }
      80             : 
      81             :     enum AllocationOption {
      82             :         CapacityReserved    = 0x1,
      83             : #if QT_SUPPORTS(UNSHARABLE_CONTAINERS)
      84             :         Unsharable          = 0x2,
      85             : #endif
      86             :         RawData             = 0x4,
      87             :         Grow                = 0x8,
      88             : 
      89             :         Default = 0
      90             :     };
      91             : 
      92             :     Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)
      93             : 
      94             :     size_t detachCapacity(size_t newSize) const
      95             :     {
      96             :         if (capacityReserved && newSize < alloc)
      97             :             return alloc;
      98             :         return newSize;
      99             :     }
     100             : 
     101           0 :     AllocationOptions detachFlags() const
     102             :     {
     103           0 :         AllocationOptions result;
     104             : #if QT_SUPPORTS(UNSHARABLE_CONTAINERS)
     105           0 :         if (!ref.isSharable())
     106           0 :             result |= Unsharable;
     107             : #endif
     108           0 :         if (capacityReserved)
     109           0 :             result |= CapacityReserved;
     110           0 :         return result;
     111             :     }
     112             : 
     113             :     AllocationOptions cloneFlags() const
     114             :     {
     115             :         AllocationOptions result;
     116             :         if (capacityReserved)
     117             :             result |= CapacityReserved;
     118             :         return result;
     119             :     }
     120             : 
     121             :     static QArrayData *allocate(size_t objectSize, size_t alignment,
     122             :             size_t capacity, AllocationOptions options = Default)
     123             :         Q_REQUIRED_RESULT;
     124             :     static void deallocate(QArrayData *data, size_t objectSize,
     125             :             size_t alignment);
     126             : 
     127             :     static const QArrayData shared_null[2];
     128         282 :     static QArrayData *sharedNull() { return const_cast<QArrayData*>(shared_null); }
     129             : };
     130             : 
     131             : Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocationOptions)
     132             : 
     133             : template <class T>
     134             : struct QTypedArrayData
     135             :     : QArrayData
     136             : {
     137             : #ifdef QT_STRICT_ITERATORS
     138             :     class iterator {
     139             :     public:
     140             :         T *i;
     141             :         typedef std::random_access_iterator_tag  iterator_category;
     142             :         typedef int difference_type;
     143             :         typedef T value_type;
     144             :         typedef T *pointer;
     145             :         typedef T &reference;
     146             : 
     147             :         inline iterator() : i(0) {}
     148             :         inline iterator(T *n) : i(n) {}
     149             :         inline iterator(const iterator &o): i(o.i){} // #### Qt 6: remove, the implicit version is fine
     150             :         inline T &operator*() const { return *i; }
     151             :         inline T *operator->() const { return i; }
     152             :         inline T &operator[](int j) const { return *(i + j); }
     153             :         inline bool operator==(const iterator &o) const { return i == o.i; }
     154             :         inline bool operator!=(const iterator &o) const { return i != o.i; }
     155             :         inline bool operator<(const iterator& other) const { return i < other.i; }
     156             :         inline bool operator<=(const iterator& other) const { return i <= other.i; }
     157             :         inline bool operator>(const iterator& other) const { return i > other.i; }
     158             :         inline bool operator>=(const iterator& other) const { return i >= other.i; }
     159             :         inline iterator &operator++() { ++i; return *this; }
     160             :         inline iterator operator++(int) { T *n = i; ++i; return n; }
     161             :         inline iterator &operator--() { i--; return *this; }
     162             :         inline iterator operator--(int) { T *n = i; i--; return n; }
     163             :         inline iterator &operator+=(int j) { i+=j; return *this; }
     164             :         inline iterator &operator-=(int j) { i-=j; return *this; }
     165             :         inline iterator operator+(int j) const { return iterator(i+j); }
     166             :         inline iterator operator-(int j) const { return iterator(i-j); }
     167             :         inline int operator-(iterator j) const { return i - j.i; }
     168             :         inline operator T*() const { return i; }
     169             :     };
     170             :     friend class iterator;
     171             : 
     172             :     class const_iterator {
     173             :     public:
     174             :         const T *i;
     175             :         typedef std::random_access_iterator_tag  iterator_category;
     176             :         typedef int difference_type;
     177             :         typedef T value_type;
     178             :         typedef const T *pointer;
     179             :         typedef const T &reference;
     180             : 
     181             :         inline const_iterator() : i(0) {}
     182             :         inline const_iterator(const T *n) : i(n) {}
     183             :         inline const_iterator(const const_iterator &o): i(o.i) {} // #### Qt 6: remove, the default version is fine
     184             :         inline explicit const_iterator(const iterator &o): i(o.i) {}
     185             :         inline const T &operator*() const { return *i; }
     186             :         inline const T *operator->() const { return i; }
     187             :         inline const T &operator[](int j) const { return *(i + j); }
     188             :         inline bool operator==(const const_iterator &o) const { return i == o.i; }
     189             :         inline bool operator!=(const const_iterator &o) const { return i != o.i; }
     190             :         inline bool operator<(const const_iterator& other) const { return i < other.i; }
     191             :         inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
     192             :         inline bool operator>(const const_iterator& other) const { return i > other.i; }
     193             :         inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
     194             :         inline const_iterator &operator++() { ++i; return *this; }
     195             :         inline const_iterator operator++(int) { const T *n = i; ++i; return n; }
     196             :         inline const_iterator &operator--() { i--; return *this; }
     197             :         inline const_iterator operator--(int) { const T *n = i; i--; return n; }
     198             :         inline const_iterator &operator+=(int j) { i+=j; return *this; }
     199             :         inline const_iterator &operator-=(int j) { i-=j; return *this; }
     200             :         inline const_iterator operator+(int j) const { return const_iterator(i+j); }
     201             :         inline const_iterator operator-(int j) const { return const_iterator(i-j); }
     202             :         inline int operator-(const_iterator j) const { return i - j.i; }
     203             :         inline operator const T*() const { return i; }
     204             :     };
     205             :     friend class const_iterator;
     206             : #else
     207             :     typedef T* iterator;
     208             :     typedef const T* const_iterator;
     209             : #endif
     210             : 
     211         123 :     T *data() { return static_cast<T *>(QArrayData::data()); }
     212             :     const T *data() const { return static_cast<const T *>(QArrayData::data()); }
     213             : 
     214           0 :     iterator begin(iterator = iterator()) { return data(); }
     215           0 :     iterator end(iterator = iterator()) { return data() + size; }
     216             :     const_iterator begin(const_iterator = const_iterator()) const { return data(); }
     217             :     const_iterator end(const_iterator = const_iterator()) const { return data() + size; }
     218             :     const_iterator constBegin(const_iterator = const_iterator()) const { return data(); }
     219             :     const_iterator constEnd(const_iterator = const_iterator()) const { return data() + size; }
     220             : 
     221             :     class AlignmentDummy { QArrayData header; T data; };
     222             : 
     223           0 :     static QTypedArrayData *allocate(size_t capacity,
     224             :             AllocationOptions options = Default) Q_REQUIRED_RESULT
     225             :     {
     226             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     227             :         return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
     228           0 :                     Q_ALIGNOF(AlignmentDummy), capacity, options));
     229             :     }
     230             : 
     231         156 :     static void deallocate(QArrayData *data)
     232             :     {
     233             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     234         156 :         QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));
     235         156 :     }
     236             : 
     237             :     static QTypedArrayData *fromRawData(const T *data, size_t n,
     238             :             AllocationOptions options = Default)
     239             :     {
     240             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     241             :         QTypedArrayData *result = allocate(0, options | RawData);
     242             :         if (result) {
     243             :             Q_ASSERT(!result->ref.isShared()); // No shared empty, please!
     244             : 
     245             :             result->offset = reinterpret_cast<const char *>(data)
     246             :                 - reinterpret_cast<const char *>(result);
     247             :             result->size = int(n);
     248             :         }
     249             :         return result;
     250             :     }
     251             : 
     252         282 :     static QTypedArrayData *sharedNull()
     253             :     {
     254             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     255         282 :         return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
     256             :     }
     257             : 
     258             :     static QTypedArrayData *sharedEmpty()
     259             :     {
     260             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     261             :         return allocate(/* capacity */ 0);
     262             :     }
     263             : 
     264           0 :     static QTypedArrayData *unsharableEmpty()
     265             :     {
     266             :         Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
     267           0 :         return allocate(/* capacity */ 0, Unsharable);
     268             :     }
     269             : };
     270             : 
     271             : template <class T, size_t N>
     272             : struct QStaticArrayData
     273             : {
     274             :     QArrayData header;
     275             :     T data[N];
     276             : };
     277             : 
     278             : // Support for returning QArrayDataPointer<T> from functions
     279             : template <class T>
     280             : struct QArrayDataPointerRef
     281             : {
     282             :     QTypedArrayData<T> *ptr;
     283             : };
     284             : 
     285             : #define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
     286             :     { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } \
     287             :     /**/
     288             : 
     289             : #define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(type, size) \
     290             :     Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size,\
     291             :         ((sizeof(QArrayData) + (Q_ALIGNOF(type) - 1)) & ~(Q_ALIGNOF(type) - 1) )) \
     292             :     /**/
     293             : 
     294             : ////////////////////////////////////////////////////////////////////////////////
     295             : //  Q_ARRAY_LITERAL
     296             : 
     297             : // The idea here is to place a (read-only) copy of header and array data in an
     298             : // mmappable portion of the executable (typically, .rodata section). This is
     299             : // accomplished by hiding a static const instance of QStaticArrayData, which is
     300             : // POD.
     301             : 
     302             : #if defined(Q_COMPILER_VARIADIC_MACROS)
     303             : #if defined(Q_COMPILER_LAMBDA)
     304             : // Hide array inside a lambda
     305             : #define Q_ARRAY_LITERAL(Type, ...)                                              \
     306             :     ([]() -> QArrayDataPointerRef<Type> {                                       \
     307             :             /* MSVC 2010 Doesn't support static variables in a lambda, but */   \
     308             :             /* happily accepts them in a static function of a lambda-local */   \
     309             :             /* struct :-) */                                                    \
     310             :             struct StaticWrapper {                                              \
     311             :                 static QArrayDataPointerRef<Type> get()                         \
     312             :                 {                                                               \
     313             :                     Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__)                     \
     314             :                     return ref;                                                 \
     315             :                 }                                                               \
     316             :             };                                                                  \
     317             :             return StaticWrapper::get();                                        \
     318             :         }())                                                                    \
     319             :     /**/
     320             : #endif
     321             : #endif // defined(Q_COMPILER_VARIADIC_MACROS)
     322             : 
     323             : #if defined(Q_ARRAY_LITERAL)
     324             : #define Q_ARRAY_LITERAL_IMPL(Type, ...)                                         \
     325             :     union { Type type_must_be_POD; } dummy; Q_UNUSED(dummy)                     \
     326             :                                                                                 \
     327             :     /* Portable compile-time array size computation */                          \
     328             :     Type data[] = { __VA_ARGS__ }; Q_UNUSED(data)                               \
     329             :     enum { Size = sizeof(data) / sizeof(data[0]) };                             \
     330             :                                                                                 \
     331             :     static const QStaticArrayData<Type, Size> literal = {                       \
     332             :         Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(Type, Size), { __VA_ARGS__ } };  \
     333             :                                                                                 \
     334             :     QArrayDataPointerRef<Type> ref =                                            \
     335             :         { static_cast<QTypedArrayData<Type> *>(                                 \
     336             :             const_cast<QArrayData *>(&literal.header)) };                       \
     337             :     /**/
     338             : #else
     339             : // As a fallback, memory is allocated and data copied to the heap.
     340             : 
     341             : // The fallback macro does NOT use variadic macros and does NOT support
     342             : // variable number of arguments. It is suitable for char arrays.
     343             : 
     344             : namespace QtPrivate {
     345             :     template <class T, size_t N>
     346             :     inline QArrayDataPointerRef<T> qMakeArrayLiteral(const T (&array)[N])
     347             :     {
     348             :         union { T type_must_be_POD; } dummy; Q_UNUSED(dummy)
     349             : 
     350             :         QArrayDataPointerRef<T> result = { QTypedArrayData<T>::allocate(N) };
     351             :         Q_CHECK_PTR(result.ptr);
     352             : 
     353             :         ::memcpy(result.ptr->data(), array, N * sizeof(T));
     354             :         result.ptr->size = N;
     355             : 
     356             :         return result;
     357             :     }
     358             : }
     359             : 
     360             : #define Q_ARRAY_LITERAL(Type, Array) \
     361             :     QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
     362             : #endif // !defined(Q_ARRAY_LITERAL)
     363             : 
     364             : QT_END_NAMESPACE
     365             : 
     366             : #endif // include guard

Generated by: LCOV version 1.11