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 QARRAYDATAPOINTER_H
41 #define QARRAYDATAPOINTER_H
42 
43 #include <QtCore/qarraydataops.h>
44 
45 QT_BEGIN_NAMESPACE
46 
47 template <class T>
48 struct QArrayDataPointer
49 {
50 private:
51     typedef QTypedArrayData<T> Data;
52     typedef QArrayDataOps<T> DataOps;
53 
54 public:
QArrayDataPointerQArrayDataPointer55     QArrayDataPointer() noexcept
56         : d(Data::sharedNull())
57     {
58     }
59 
QArrayDataPointerQArrayDataPointer60     QArrayDataPointer(const QArrayDataPointer &other)
61         : d(other.d->ref.ref()
62             ? other.d
63             : other.clone(other.d->cloneFlags()))
64     {
65     }
66 
QArrayDataPointerQArrayDataPointer67     explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
68         : d(ptr)
69     {
70         Q_CHECK_PTR(ptr);
71     }
72 
QArrayDataPointerQArrayDataPointer73     QArrayDataPointer(QArrayDataPointerRef<T> ref)
74         : d(ref.ptr)
75     {
76     }
77 
78     QArrayDataPointer &operator=(const QArrayDataPointer &other)
79     {
80         QArrayDataPointer tmp(other);
81         this->swap(tmp);
82         return *this;
83     }
84 
QArrayDataPointerQArrayDataPointer85     QArrayDataPointer(QArrayDataPointer &&other) noexcept
86         : d(other.d)
87     {
88         other.d = Data::sharedNull();
89     }
90 
91     QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
92     {
93         QArrayDataPointer moved(std::move(other));
94         this->swap(moved);
95         return *this;
96     }
97 
98     DataOps &operator*() const
99     {
100         Q_ASSERT(d);
101         return *static_cast<DataOps *>(d);
102     }
103 
104     DataOps *operator->() const
105     {
106         Q_ASSERT(d);
107         return static_cast<DataOps *>(d);
108     }
109 
~QArrayDataPointerQArrayDataPointer110     ~QArrayDataPointer()
111     {
112         if (!d->ref.deref()) {
113             if (d->isMutable())
114                 (*this)->destroyAll();
115             Data::deallocate(d);
116         }
117     }
118 
isNullQArrayDataPointer119     bool isNull() const
120     {
121         return d == Data::sharedNull();
122     }
123 
dataQArrayDataPointer124     Data *data() const
125     {
126         return d;
127     }
128 
needsDetachQArrayDataPointer129     bool needsDetach() const
130     {
131         return (!d->isMutable() || d->ref.isShared());
132     }
133 
134 #if !defined(QT_NO_UNSHARABLE_CONTAINERS)
setSharableQArrayDataPointer135     void setSharable(bool sharable)
136     {
137         if (needsDetach()) {
138             Data *detached = clone(sharable
139                     ? d->detachFlags() & ~QArrayData::Unsharable
140                     : d->detachFlags() | QArrayData::Unsharable);
141             QArrayDataPointer old(d);
142             d = detached;
143         } else {
144             d->ref.setSharable(sharable);
145         }
146     }
147 
isSharableQArrayDataPointer148     bool isSharable() const { return d->isSharable(); }
149 #endif
150 
swapQArrayDataPointer151     void swap(QArrayDataPointer &other) noexcept
152     {
153         qSwap(d, other.d);
154     }
155 
clearQArrayDataPointer156     void clear()
157     {
158         QArrayDataPointer tmp(d);
159         d = Data::sharedNull();
160     }
161 
detachQArrayDataPointer162     bool detach()
163     {
164         if (needsDetach()) {
165             Data *copy = clone(d->detachFlags());
166             QArrayDataPointer old(d);
167             d = copy;
168             return true;
169         }
170 
171         return false;
172     }
173 
174 private:
cloneQArrayDataPointer175     Q_REQUIRED_RESULT Data *clone(QArrayData::AllocationOptions options) const
176     {
177         Data *x = Data::allocate(d->detachCapacity(d->size), options);
178         Q_CHECK_PTR(x);
179         QArrayDataPointer copy(x);
180 
181         if (d->size)
182             copy->copyAppend(d->begin(), d->end());
183 
184         Data *result = copy.d;
185         copy.d = Data::sharedNull();
186         return result;
187     }
188 
189     Data *d;
190 };
191 
192 template <class T>
193 inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
194 {
195     return lhs.data() == rhs.data();
196 }
197 
198 template <class T>
199 inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
200 {
201     return lhs.data() != rhs.data();
202 }
203 
204 template <class T>
swap(QArrayDataPointer<T> & p1,QArrayDataPointer<T> & p2)205 inline void swap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2)
206 {
207     p1.swap(p2);
208 }
209 
210 QT_END_NAMESPACE
211 
212 #endif // include guard
213