5#ifndef QCONTIGUOUSCACHE_H
6#define QCONTIGUOUSCACHE_H
8#include <QtCore/qatomic.h>
9#include <QtCore/qassert.h>
10#include <QtCore/qtclasshelpermacros.h>
11#include <QtCore/qtcoreexports.h>
12#include <QtCore/qminmax.h>
13#include <QtCore/qttypetraits.h>
14#include <QtCore/qtypeinfo.h>
22#undef QT_QCONTIGUOUSCACHE_DEBUG
33 static QContiguousCacheData *allocateData(qsizetype size, qsizetype alignment);
34 static void freeData(QContiguousCacheData *data);
36#ifdef QT_QCONTIGUOUSCACHE_DEBUG
68 inline void detach() {
if (d->ref.loadRelaxed() != 1) detach_helper(); }
69 inline bool isDetached()
const {
return d->ref.loadRelaxed() == 1; }
76 template <
typename U =
T>
91 template <
typename U =
T>
93 {
return !(*
this ==
other); }
110 const T &
at(qsizetype pos)
const;
112 const T &
operator[](qsizetype i)
const;
115 void append(
const T &value);
118 void insert(qsizetype pos, T &&value);
119 void insert(qsizetype pos,
const T &value);
122 inline bool containsIndex(qsizetype pos)
const {
return pos >= d->offset && pos - d->offset < d->count; }
126 inline const T &
first()
const { Q_ASSERT(!isEmpty());
return d->array[d->start]; }
127 inline const T &
last()
const { Q_ASSERT(!isEmpty());
return d->array[(d->start + d->count -1) % d->alloc]; }
128 inline T &
first() { Q_ASSERT(!isEmpty());
detach();
return d->array[d->start]; }
129 inline T &
last() { Q_ASSERT(!isEmpty());
detach();
return d->array[(d->start + d->count -1) % d->alloc]; }
138 {
return d->offset >= 0 && d->offset < (std::numeric_limits<qsizetype>::max)() - d->count && (d->offset % d->alloc) == d->start; }
142#ifdef QT_QCONTIGUOUSCACHE_DEBUG
146 void detach_helper();
148 Data *allocateData(qsizetype aalloc);
149 void freeData(Data *x);
155 Data *x = allocateData(d->alloc);
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);
188 x->count = qMin(d->count, asize);
189 x->offset = d->offset + d->count - x->count;
191 x->start = x->offset % x->alloc;
195 qsizetype oldcount = x->count;
198 T *dest = x->array + (x->start + x->count-1) % x->alloc;
199 T *src = d->array + (d->start + d->count-1) % d->alloc;
202 if (dest == x->array)
203 dest = x->array + x->alloc;
206 src = d->array + d->alloc;
218 if (d->ref.loadRelaxed() == 1) {
219 if (QTypeInfo<T>::isComplex) {
220 qsizetype oldcount = d->count;
221 T * i = d->array + d->start;
222 T * e = d->array + d->alloc;
230 d->count = d->start = d->offset = 0;
232 Data *x = allocateData(d->alloc);
234 x->count = x->start = x->offset = 0;
244 return static_cast<Data *>(QContiguousCacheData::allocateData(
sizeof(Data) + (aalloc - 1) *
sizeof(T),
alignof(Data)));
251 d = allocateData(cap);
253 d->count = d->start = d->offset = 0;
269 if (QTypeInfo<T>::isComplex) {
270 qsizetype oldcount = d->count;
271 T * i = d->array + d->start;
272 T * e = d->array + d->alloc;
288 if (d->count == d->alloc)
289 (d->array + (d->start+d->count) % d->alloc)->~T();
290 new (d->array + (d->start+d->count) % d->alloc) T(std::move(value));
292 if (d->count == d->alloc) {
294 d->start %= d->alloc;
307 if (d->count == d->alloc)
308 (d->array + (d->start+d->count) % d->alloc)->~T();
309 new (d->array + (d->start+d->count) % d->alloc) T(value);
311 if (d->count == d->alloc) {
313 d->start %= d->alloc;
329 d->start = d->alloc-1;
332 if (d->count != d->alloc)
335 (d->array + d->start)->~T();
337 new (d->array + d->start) T(std::move(value));
349 d->start = d->alloc-1;
352 if (d->count != d->alloc)
355 (d->array + d->start)->~T();
357 new (d->array + d->start) T(value);
363 Q_ASSERT_X(pos >= 0,
"QContiguousCache<T>::insert",
"index out of range");
367 if (containsIndex(pos)) {
368 d->array[pos % d->alloc] = std::move(value);
369 }
else if (pos == d->offset-1)
371 else if (pos == d->offset+d->count)
377 d->start = pos % d->alloc;
379 new (d->array + d->start) T(std::move(value));
386 return insert(pos, T(value));
390{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count,
"QContiguousCache<T>::at",
"index out of range");
return d->array[pos % d->alloc]; }
399 if (!containsIndex(pos))
401 return d->array[pos % d->alloc];
407 Q_ASSERT(d->count > 0);
410 if (QTypeInfo<T>::isComplex)
411 (d->array + d->start)->~T();
412 d->start = (d->start + 1) % d->alloc;
419 Q_ASSERT(d->count > 0);
422 if (QTypeInfo<T>::isComplex)
423 (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.