4#ifndef QCONTIGUOUSCACHE_H
5#define QCONTIGUOUSCACHE_H
7#include <QtCore/qatomic.h>
8#include <QtCore/qassert.h>
9#include <QtCore/qtclasshelpermacros.h>
10#include <QtCore/qtcoreexports.h>
11#include <QtCore/qminmax.h>
12#include <QtCore/qttypetraits.h>
13#include <QtCore/qtypeinfo.h>
21#undef QT_QCONTIGUOUSCACHE_DEBUG
32 static QContiguousCacheData *allocateData(qsizetype size, qsizetype alignment);
33 static void freeData(QContiguousCacheData *data);
35#ifdef QT_QCONTIGUOUSCACHE_DEBUG
67 inline void detach() {
if (d->ref.loadRelaxed() != 1) detach_helper(); }
68 inline bool isDetached()
const {
return d->ref.loadRelaxed() == 1; }
75 template <
typename U =
T>
90 template <
typename U =
T>
92 {
return !(*
this ==
other); }
109 const T &
at(qsizetype pos)
const;
111 const T &
operator[](qsizetype i)
const;
114 void append(
const T &value);
117 void insert(qsizetype pos, T &&value);
118 void insert(qsizetype pos,
const T &value);
121 inline bool containsIndex(qsizetype pos)
const {
return pos >= d->offset && pos - d->offset < d->count; }
125 inline const T &
first()
const { Q_ASSERT(!isEmpty());
return d->array[d->start]; }
126 inline const T &
last()
const { Q_ASSERT(!isEmpty());
return d->array[(d->start + d->count -1) % d->alloc]; }
127 inline T &
first() { Q_ASSERT(!isEmpty());
detach();
return d->array[d->start]; }
128 inline T &
last() { Q_ASSERT(!isEmpty());
detach();
return d->array[(d->start + d->count -1) % d->alloc]; }
137 {
return d->offset >= 0 && d->offset < (std::numeric_limits<qsizetype>::max)() - d->count && (d->offset % d->alloc) == d->start; }
141#ifdef QT_QCONTIGUOUSCACHE_DEBUG
145 void detach_helper();
147 Data *allocateData(qsizetype aalloc);
148 void freeData(Data *x);
154 Data *x = allocateData(d->alloc);
155 x->ref.storeRelaxed(1);
158 x->offset = d->offset;
161 T *dest = x->array + x->start;
162 T *src = d->array + d->start;
163 qsizetype oldcount = x->count;
167 if (dest == x->array + x->alloc)
170 if (src == d->array + d->alloc)
182 Q_ASSERT(asize >= 0);
183 if (asize == d->alloc)
186 Data *x = allocateData(asize);
187 x->ref.storeRelaxed(1);
189 x->count = qMin(d->count, asize);
190 x->offset = d->offset + d->count - x->count;
192 x->start = x->offset % x->alloc;
196 qsizetype oldcount = x->count;
199 T *dest = x->array + (x->start + x->count-1) % x->alloc;
200 T *src = d->array + (d->start + d->count-1) % d->alloc;
203 if (dest == x->array)
204 dest = x->array + x->alloc;
207 src = d->array + d->alloc;
219 if (d->ref.loadRelaxed() == 1) {
220 if (QTypeInfo<T>::isComplex) {
221 qsizetype oldcount = d->count;
222 T * i = d->array + d->start;
223 T * e = d->array + d->alloc;
231 d->count = d->start = d->offset = 0;
233 Data *x = allocateData(d->alloc);
234 x->ref.storeRelaxed(1);
236 x->count = x->start = x->offset = 0;
246 return static_cast<Data *>(QContiguousCacheData::allocateData(
sizeof(Data) + (aalloc - 1) *
sizeof(T),
alignof(Data)));
253 d = allocateData(cap);
254 d->ref.storeRelaxed(1);
256 d->count = d->start = d->offset = 0;
272 if (QTypeInfo<T>::isComplex) {
273 qsizetype oldcount = d->count;
274 T * i = d->array + d->start;
275 T * e = d->array + d->alloc;
291 if (d->count == d->alloc)
292 (d->array + (d->start+d->count) % d->alloc)->~T();
293 new (d->array + (d->start+d->count) % d->alloc) T(std::move(value));
295 if (d->count == d->alloc) {
297 d->start %= d->alloc;
310 if (d->count == d->alloc)
311 (d->array + (d->start+d->count) % d->alloc)->~T();
312 new (d->array + (d->start+d->count) % d->alloc) T(value);
314 if (d->count == d->alloc) {
316 d->start %= d->alloc;
332 d->start = d->alloc-1;
335 if (d->count != d->alloc)
338 (d->array + d->start)->~T();
340 new (d->array + d->start) T(std::move(value));
352 d->start = d->alloc-1;
355 if (d->count != d->alloc)
358 (d->array + d->start)->~T();
360 new (d->array + d->start) T(value);
366 Q_ASSERT_X(pos >= 0,
"QContiguousCache<T>::insert",
"index out of range");
370 if (containsIndex(pos)) {
371 d->array[pos % d->alloc] = std::move(value);
372 }
else if (pos == d->offset-1)
374 else if (pos == d->offset+d->count)
380 d->start = pos % d->alloc;
382 new (d->array + d->start) T(std::move(value));
389 return insert(pos, T(value));
393{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count,
"QContiguousCache<T>::at",
"index out of range");
return d->array[pos % d->alloc]; }
402 if (!containsIndex(pos))
404 return d->array[pos % d->alloc];
410 Q_ASSERT(d->count > 0);
413 if (QTypeInfo<T>::isComplex)
414 (d->array + d->start)->~T();
415 d->start = (d->start + 1) % d->alloc;
422 Q_ASSERT(d->count > 0);
425 if (QTypeInfo<T>::isComplex)
426 (d->array + (d->start + d->count) % d->alloc)->~T();
T takeFirst()
Removes the first item in the cache and returns it.
void setCapacity(qsizetype size)
Sets the capacity of the cache to the given size.
~QContiguousCache()
Destroys the cache.
bool areIndexesValid() const
Returns whether the indexes for items stored in the cache are valid.
const T & at(qsizetype pos) const
Returns the item at index position i in the cache.
T & last()
Returns a reference to the last item in the cache.
void removeFirst()
Removes the first item from the cache.
void insert(qsizetype pos, T &&value)
void append(const T &value)
Inserts value at the end of the cache.
const T & operator[](qsizetype i) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void prepend(const T &value)
Inserts value at the start of the cache.
const value_type & const_reference
const value_type * const_pointer
const T & first() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
QContiguousCache(qsizetype capacity=0)
Constructs a cache with the given capacity.
QContiguousCache< T > & operator=(const QContiguousCache< T > &other)
Assigns other to this cache and returns a reference to this cache.
qsizetype firstIndex() const
Returns the first valid index in the cache.
T & first()
Returns a reference to the first item in the cache.
void insert(qsizetype pos, const T &value)
Inserts the value at the index position i.
bool containsIndex(qsizetype pos) const
Returns true if the cache's index range includes the given index i.
QContiguousCache(const QContiguousCache< T > &v)
Constructs a copy of other.
const T & last() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
T & operator[](qsizetype i)
Returns the item at index position i as a modifiable reference.
void removeLast()
Removes the last item from the cache.
qsizetype lastIndex() const
Returns the last valid index in the cache.
void normalizeIndexes()
Moves the first index and last index of the cache such that they point to valid indexes.
T takeLast()
Removes the last item in the cache and returns it.
Combined button and popup list for selecting options.