Introducing QArrayDataPointer

This class provides RAII functionality for handling QArrayData pointers.

Together with QArrayDataHeader and QArrayDataOps, this offers common
boilerplate code for implementing a container which, itself, defines its
own interface.

Change-Id: If38eba22fbe8f69038a06fff4acb50af434d229e
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
João Abecasis 2011-11-02 12:10:17 +01:00 committed by Qt by Nokia
parent 9c04f721a6
commit 7d16ea4033
2 changed files with 179 additions and 42 deletions

View File

@ -0,0 +1,161 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QARRAYDATAPOINTER_H
#define QARRAYDATAPOINTER_H
#include <QtCore/qarraydataops.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Core)
template <class T>
struct QArrayDataPointer
{
private:
typedef QTypedArrayData<T> Data;
typedef QArrayDataOps<T> DataOps;
public:
QArrayDataPointer()
: d(Data::sharedNull())
{
}
QArrayDataPointer(const QArrayDataPointer &other)
: d((other.d->ref.ref(), other.d))
{
}
explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
: d(ptr)
{
}
QArrayDataPointer &operator=(const QArrayDataPointer &other)
{
QArrayDataPointer tmp(other);
this->swap(tmp);
return *this;
}
DataOps &operator*() const
{
Q_ASSERT(d);
return *static_cast<DataOps *>(d);
}
DataOps *operator->() const
{
Q_ASSERT(d);
return static_cast<DataOps *>(d);
}
~QArrayDataPointer()
{
if (!d->ref.deref()) {
(*this)->destroyAll();
Data::deallocate(d);
}
}
bool isNull() const
{
return d == Data::sharedNull();
}
Data *data() const
{
return d;
}
void swap(QArrayDataPointer &other)
{
qSwap(d, other.d);
}
void clear()
{
QArrayDataPointer tmp(d);
d = Data::sharedEmpty();
}
private:
Data *d;
};
template <class T>
inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
{
return lhs.data() == rhs.data();
}
template <class T>
inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
{
return lhs.data() != rhs.data();
}
template <class T>
inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2)
{
p1.swap(p2);
}
QT_END_NAMESPACE
namespace std
{
template <class T>
inline void swap(
QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p1,
QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p2)
{
p1.swap(p2);
}
}
QT_END_HEADER
#endif // include guard

View File

@ -44,7 +44,7 @@
#define QARRAY_TEST_SIMPLE_VECTOR_H #define QARRAY_TEST_SIMPLE_VECTOR_H
#include <QtCore/qarraydata.h> #include <QtCore/qarraydata.h>
#include <QtCore/qarraydataops.h> #include <QtCore/qarraydatapointer.h>
#include <algorithm> #include <algorithm>
@ -53,7 +53,6 @@ struct SimpleVector
{ {
private: private:
typedef QTypedArrayData<T> Data; typedef QTypedArrayData<T> Data;
typedef QArrayDataOps<T> DataOps;
public: public:
typedef T value_type; typedef T value_type;
@ -61,28 +60,21 @@ public:
typedef typename Data::const_iterator const_iterator; typedef typename Data::const_iterator const_iterator;
SimpleVector() SimpleVector()
: d(Data::sharedNull())
{ {
} }
SimpleVector(const SimpleVector &vec)
: d(vec.d)
{
d->ref.ref();
}
SimpleVector(size_t n, const T &t) SimpleVector(size_t n, const T &t)
: d(Data::allocate(n)) : d(Data::allocate(n))
{ {
if (n) if (n)
static_cast<DataOps *>(d)->copyAppend(n, t); d->copyAppend(n, t);
} }
SimpleVector(const T *begin, const T *end) SimpleVector(const T *begin, const T *end)
: d(Data::allocate(end - begin)) : d(Data::allocate(end - begin))
{ {
if (end - begin) if (end - begin)
static_cast<DataOps *>(d)->copyAppend(begin, end); d->copyAppend(begin, end);
} }
explicit SimpleVector(Data *ptr) explicit SimpleVector(Data *ptr)
@ -90,23 +82,8 @@ public:
{ {
} }
~SimpleVector()
{
if (!d->ref.deref()) {
static_cast<DataOps *>(d)->destroyAll();
Data::deallocate(d);
}
}
SimpleVector &operator=(const SimpleVector &vec)
{
SimpleVector temp(vec);
this->swap(temp);
return *this;
}
bool empty() const { return d->size == 0; } bool empty() const { return d->size == 0; }
bool isNull() const { return d == Data::sharedNull(); } bool isNull() const { return d.isNull(); }
bool isEmpty() const { return this->empty(); } bool isEmpty() const { return this->empty(); }
bool isSharedWith(const SimpleVector &other) const { return d == other.d; } bool isSharedWith(const SimpleVector &other) const { return d == other.d; }
@ -142,7 +119,7 @@ public:
&& !d->capacityReserved && !d->capacityReserved
&& (d->ref != 1 || (d->capacityReserved = 1, false)))) { && (d->ref != 1 || (d->capacityReserved = 1, false)))) {
SimpleVector detached(Data::allocate(n, true)); SimpleVector detached(Data::allocate(n, true));
static_cast<DataOps *>(detached.d)->copyAppend(constBegin(), constEnd()); detached.d->copyAppend(constBegin(), constEnd());
detached.swap(*this); detached.swap(*this);
} }
} }
@ -163,14 +140,14 @@ public:
SimpleVector detached(Data::allocate( SimpleVector detached(Data::allocate(
qMax(capacity(), size() + (last - first)), d->capacityReserved)); qMax(capacity(), size() + (last - first)), d->capacityReserved));
static_cast<DataOps *>(detached.d)->copyAppend(first, last); detached.d->copyAppend(first, last);
static_cast<DataOps *>(detached.d)->copyAppend(begin, begin + d->size); detached.d->copyAppend(begin, begin + d->size);
detached.swap(*this); detached.swap(*this);
return; return;
} }
static_cast<DataOps *>(d)->insert(begin, first, last); d->insert(begin, first, last);
} }
void append(const_iterator first, const_iterator last) void append(const_iterator first, const_iterator last)
@ -185,15 +162,15 @@ public:
if (d->size) { if (d->size) {
const T *const begin = constBegin(); const T *const begin = constBegin();
static_cast<DataOps *>(detached.d)->copyAppend(begin, begin + d->size); detached.d->copyAppend(begin, begin + d->size);
} }
static_cast<DataOps *>(detached.d)->copyAppend(first, last); detached.d->copyAppend(first, last);
detached.swap(*this); detached.swap(*this);
return; return;
} }
static_cast<DataOps *>(d)->copyAppend(first, last); d->copyAppend(first, last);
} }
void insert(int position, const_iterator first, const_iterator last) void insert(int position, const_iterator first, const_iterator last)
@ -223,9 +200,9 @@ public:
qMax(capacity(), size() + (last - first)), d->capacityReserved)); qMax(capacity(), size() + (last - first)), d->capacityReserved));
if (position) if (position)
static_cast<DataOps *>(detached.d)->copyAppend(begin, where); detached.d->copyAppend(begin, where);
static_cast<DataOps *>(detached.d)->copyAppend(first, last); detached.d->copyAppend(first, last);
static_cast<DataOps *>(detached.d)->copyAppend(where, end); detached.d->copyAppend(where, end);
detached.swap(*this); detached.swap(*this);
return; return;
@ -235,11 +212,11 @@ public:
if ((first >= where && first < end) if ((first >= where && first < end)
|| (last > where && last <= end)) { || (last > where && last <= end)) {
SimpleVector tmp(first, last); SimpleVector tmp(first, last);
static_cast<DataOps *>(d)->insert(where, tmp.constBegin(), tmp.constEnd()); d->insert(where, tmp.constBegin(), tmp.constEnd());
return; return;
} }
static_cast<DataOps *>(d)->insert(where, first, last); d->insert(where, first, last);
} }
void swap(SimpleVector &other) void swap(SimpleVector &other)
@ -249,12 +226,11 @@ public:
void clear() void clear()
{ {
SimpleVector tmp(d); d.clear();
d = Data::sharedEmpty();
} }
private: private:
Data *d; QArrayDataPointer<T> d;
}; };
template <class T> template <class T>