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);
157 x->offset = d->offset;
160 T *dest = x->array + x->start;
161 T *src = d->array + d->start;
162 qsizetype oldcount = x->count;
166 if (dest == x->array + x->alloc)
169 if (src == d->array + d->alloc)
181 Q_ASSERT(asize >= 0);
182 if (asize == d->alloc)
185 Data *x = allocateData(asize);
187 x->count = qMin(d->count, asize);
188 x->offset = d->offset + d->count - x->count;
190 x->start = x->offset % x->alloc;
194 qsizetype oldcount = x->count;
197 T *dest = x->array + (x->start + x->count-1) % x->alloc;
198 T *src = d->array + (d->start + d->count-1) % d->alloc;
201 if (dest == x->array)
202 dest = x->array + x->alloc;
205 src = d->array + d->alloc;
217 if (d->ref.loadRelaxed() == 1) {
218 if (QTypeInfo<T>::isComplex) {
219 qsizetype oldcount = d->count;
220 T * i = d->array + d->start;
221 T * e = d->array + d->alloc;
229 d->count = d->start = d->offset = 0;
231 Data *x = allocateData(d->alloc);
233 x->count = x->start = x->offset = 0;
243 return static_cast<Data *>(QContiguousCacheData::allocateData(
sizeof(Data) + (aalloc - 1) *
sizeof(T),
alignof(Data)));
250 d = allocateData(cap);
252 d->count = d->start = d->offset = 0;
268 if (QTypeInfo<T>::isComplex) {
269 qsizetype oldcount = d->count;
270 T * i = d->array + d->start;
271 T * e = d->array + d->alloc;
287 if (d->count == d->alloc)
288 (d->array + (d->start+d->count) % d->alloc)->~T();
289 new (d->array + (d->start+d->count) % d->alloc) T(std::move(value));
291 if (d->count == d->alloc) {
293 d->start %= d->alloc;
306 if (d->count == d->alloc)
307 (d->array + (d->start+d->count) % d->alloc)->~T();
308 new (d->array + (d->start+d->count) % d->alloc) T(value);
310 if (d->count == d->alloc) {
312 d->start %= d->alloc;
328 d->start = d->alloc-1;
331 if (d->count != d->alloc)
334 (d->array + d->start)->~T();
336 new (d->array + d->start) T(std::move(value));
348 d->start = d->alloc-1;
351 if (d->count != d->alloc)
354 (d->array + d->start)->~T();
356 new (d->array + d->start) T(value);
362 Q_ASSERT_X(pos >= 0,
"QContiguousCache<T>::insert",
"index out of range");
366 if (containsIndex(pos)) {
367 d->array[pos % d->alloc] = std::move(value);
368 }
else if (pos == d->offset-1)
370 else if (pos == d->offset+d->count)
376 d->start = pos % d->alloc;
378 new (d->array + d->start) T(std::move(value));
385 return insert(pos, T(value));
389{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count,
"QContiguousCache<T>::at",
"index out of range");
return d->array[pos % d->alloc]; }
398 if (!containsIndex(pos))
400 return d->array[pos % d->alloc];
406 Q_ASSERT(d->count > 0);
409 if (QTypeInfo<T>::isComplex)
410 (d->array + d->start)->~T();
411 d->start = (d->start + 1) % d->alloc;
418 Q_ASSERT(d->count > 0);
421 if (QTypeInfo<T>::isComplex)
422 (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.