From 8a43a239d77333d0a012fae787a85367683034eb Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Sun, 16 Nov 2014 17:02:44 +0000 Subject: Make QCircularBuffer and QBoundedCircularBuffer private Change-Id: I298fbaf819a118a5da4453082ec7f1484835480a Reviewed-by: Paul Lemire --- src/core/resources/qboundedcircularbuffer.h | 140 --- src/core/resources/qboundedcircularbuffer_p.h | 140 +++ src/core/resources/qcircularbuffer.h | 1323 -------------------- src/core/resources/qcircularbuffer_p.h | 1323 ++++++++++++++++++++ src/core/resources/resources.pri | 4 +- src/render/backend/renderqueues_p.h | 2 +- .../qboundedcircularbuffer.pro | 2 +- .../tst_qboundedcircularbuffer.cpp | 2 +- .../auto/core/qcircularbuffer/qcircularbuffer.pro | 2 +- .../core/qcircularbuffer/tst_qcircularbuffer.cpp | 2 +- .../core/qcircularbuffer/qcircularbuffer.pro | 2 +- .../qcircularbuffer/tst_bench_qcircularbuffer.cpp | 2 +- 12 files changed, 1472 insertions(+), 1472 deletions(-) delete mode 100644 src/core/resources/qboundedcircularbuffer.h create mode 100644 src/core/resources/qboundedcircularbuffer_p.h delete mode 100644 src/core/resources/qcircularbuffer.h create mode 100644 src/core/resources/qcircularbuffer_p.h diff --git a/src/core/resources/qboundedcircularbuffer.h b/src/core/resources/qboundedcircularbuffer.h deleted file mode 100644 index 00dd93821..000000000 --- a/src/core/resources/qboundedcircularbuffer.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, 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, Digia gives you certain additional -** rights. These rights are described in the Digia 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. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3D_QBOUNDEDCIRCULARBUFFER_H -#define QT3D_QBOUNDEDCIRCULARBUFFER_H - -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3D { - -template -class QBoundedCircularBuffer -{ -public: - explicit QBoundedCircularBuffer(int capacity_) - : m_free( capacity_ ), - m_used( capacity_ ), - m_buffer( capacity_ ) - { - m_used.acquire(capacity_); - } - - int capacity() const { return m_buffer.capacity(); } - int freeSize() const { return m_free.available(); } - int size() const { return m_used.available(); } - bool isFull() const { return m_free.available() == 0; } - bool isEmpty() const { return m_used.available() == 0; } - - void push_back(const T &value) - { - m_free.acquire(); - QWriteLocker locker(&m_lock); - m_buffer.append(value); - locker.unlock(); - m_used.release(); - } - - void push(const T &t) { push_back(t); } - void append(const T &t) { push_back(t); } - - T pop_front() - { - m_used.acquire(); - QWriteLocker locker(&m_lock); - T value = m_buffer.first(); - m_buffer.remove(0); - locker.unlock(); - m_free.release(); - return value; - } - - T pop() { return pop_front(); } - T takeFirst() { return pop_front(); } - - void clear() - { - QWriteLocker locker(&m_lock); - m_buffer.clear(); - int used = m_used.available(); - m_free.release(used); - m_used.acquire(used); - } - - T at(int i) const - { - QReadLocker readLocker(&m_lock); - return m_buffer.at(i); - } - - T front() const - { - QReadLocker readLocker(&m_lock); - return m_buffer.front(); - } - - T back() const - { - QReadLocker readLocker(&m_lock); - return m_buffer.back(); - } - -protected: - Q_DISABLE_COPY(QBoundedCircularBuffer) - - QSemaphore m_free; - QSemaphore m_used; - QCircularBuffer m_buffer; - mutable QReadWriteLock m_lock; -}; - -} //Qt3D - -QT_END_NAMESPACE - -#endif // QT3D_QBOUNDEDCIRCULARBUFFER_H diff --git a/src/core/resources/qboundedcircularbuffer_p.h b/src/core/resources/qboundedcircularbuffer_p.h new file mode 100644 index 000000000..43adbe8e2 --- /dev/null +++ b/src/core/resources/qboundedcircularbuffer_p.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3D_QBOUNDEDCIRCULARBUFFER_P_H +#define QT3D_QBOUNDEDCIRCULARBUFFER_P_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3D { + +template +class QBoundedCircularBuffer +{ +public: + explicit QBoundedCircularBuffer(int capacity_) + : m_free( capacity_ ), + m_used( capacity_ ), + m_buffer( capacity_ ) + { + m_used.acquire(capacity_); + } + + int capacity() const { return m_buffer.capacity(); } + int freeSize() const { return m_free.available(); } + int size() const { return m_used.available(); } + bool isFull() const { return m_free.available() == 0; } + bool isEmpty() const { return m_used.available() == 0; } + + void push_back(const T &value) + { + m_free.acquire(); + QWriteLocker locker(&m_lock); + m_buffer.append(value); + locker.unlock(); + m_used.release(); + } + + void push(const T &t) { push_back(t); } + void append(const T &t) { push_back(t); } + + T pop_front() + { + m_used.acquire(); + QWriteLocker locker(&m_lock); + T value = m_buffer.first(); + m_buffer.remove(0); + locker.unlock(); + m_free.release(); + return value; + } + + T pop() { return pop_front(); } + T takeFirst() { return pop_front(); } + + void clear() + { + QWriteLocker locker(&m_lock); + m_buffer.clear(); + int used = m_used.available(); + m_free.release(used); + m_used.acquire(used); + } + + T at(int i) const + { + QReadLocker readLocker(&m_lock); + return m_buffer.at(i); + } + + T front() const + { + QReadLocker readLocker(&m_lock); + return m_buffer.front(); + } + + T back() const + { + QReadLocker readLocker(&m_lock); + return m_buffer.back(); + } + +protected: + Q_DISABLE_COPY(QBoundedCircularBuffer) + + QSemaphore m_free; + QSemaphore m_used; + QCircularBuffer m_buffer; + mutable QReadWriteLock m_lock; +}; + +} //Qt3D + +QT_END_NAMESPACE + +#endif // QT3D_QBOUNDEDCIRCULARBUFFER_P_H diff --git a/src/core/resources/qcircularbuffer.h b/src/core/resources/qcircularbuffer.h deleted file mode 100644 index 30dab5dc3..000000000 --- a/src/core/resources/qcircularbuffer.h +++ /dev/null @@ -1,1323 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, 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, Digia gives you certain additional -** rights. These rights are described in the Digia 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. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3D_QCIRCULARBUFFER_H -#define QT3D_QCIRCULARBUFFER_H - -#include -#include -#include -#include - -#include -#ifdef Q_COMPILER_INITIALIZER_LISTS -# include -#endif -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3D { - -class CircularBufferData : public QSharedData -{ -protected: - CircularBufferData() - : data(Q_NULLPTR), - capacity(0), - size(0), - first(-1), - last(-1) - {} - - ~CircularBufferData() - { - // Release the raw memory - deallocate(data); - } - - int wraparound(int index) const - { - index = index < capacity ? index : (index - capacity); - Q_ASSERT(index < capacity); // make sure that wrapping around once was enough - return index; - } - - void *allocate(int count, size_t sizeOfT) - { return operator new[](count * sizeOfT); } - void deallocate(void *p) - { operator delete[](p); } - - void *data; // Array of the actual data -public: - int capacity; // Size of the m_data array - int size; // Number of elements of m_data actually used - int first; // Index in m_data of the first element of the circular buffer - int last; // Index in m_data of the last element of the circular buffer -}; - -template -class TypedCircularBufferData : public CircularBufferData -{ - template - explicit TypedCircularBufferData(InputIterator f, InputIterator l, std::input_iterator_tag) Q_DECL_EQ_DELETE; -public: - TypedCircularBufferData() : CircularBufferData() {} - template - explicit TypedCircularBufferData(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) - { - const int n = int(std::distance(f, l)); - CircularBufferData::data = allocate(n); - std::uninitialized_copy(f, l, data()); - first = 0; - last = n - 1; - size = capacity = n; - } - ~TypedCircularBufferData() - { - if (QTypeInfo::isComplex && size != 0) { - // The type is complex so we manually call the destructor for each item - // since we used the placement new operator to instantiate them - if (first <= last) { - // Destroy items from first to last - T *b = data() + first; - T *i = b + size; - while (i-- != b) - i->~T(); - } else { - // Destroy items at end of data array - T *b = data() + first; - T *i = data() + capacity; - while (i-- != b) - i->~T(); - - // Destroy items at beginning of data array - b = data(); - i = b + last; - while (i-- != b) - i->~T(); - } - } - - } - -#ifndef Q_NO_USING_KEYWORD - using CircularBufferData::wraparound; -#else - inline int wraparound(int index) const { return CircularBufferData::wraparound(index); } -#endif - T *allocate(int count) { return static_cast(CircularBufferData::allocate(count, sizeof(T))); } -#ifndef Q_NO_USING_KEYWORD - using CircularBufferData::deallocate; -#else - inline void deallocate(void *p) { return CircularBufferData::deallocate(p); } -#endif - T *data() const { return static_cast(CircularBufferData::data); } - void setData(T *newdata) { CircularBufferData::data = static_cast(newdata); } -}; - -template -class QCircularBuffer -{ - typedef TypedCircularBufferData Data; -public: - typedef QPair array_range; - typedef QPair const_array_range; - typedef array_range ArrayRange; - typedef const_array_range ConstArrayRange; - - QCircularBuffer() - : d(new Data()) - {} - - explicit QCircularBuffer(int amount); - explicit QCircularBuffer(int amount, const T &val); - explicit QCircularBuffer(int amount, int initialSize, const T &value); -#ifdef Q_COMPILER_INITIALIZER_LISTS - QCircularBuffer(std::initializer_list list) - : d(new Data(list.begin(), list.end(), std::random_access_iterator_tag())) - {} -#endif - template - explicit QCircularBuffer(ForwardIterator f, ForwardIterator l) - : d(new Data(f, l, typename std::iterator_traits::iterator_category())) - {} - - QCircularBuffer(const QCircularBuffer &other) - : d(other.d) - {} - - void swap(QCircularBuffer &other) { d.swap(other.d); } - - QCircularBuffer &operator = (const QCircularBuffer &other) - { - d = other.d; - return *this; - } - - ~QCircularBuffer() {} - - class iterator - { - public: - typedef std::random_access_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T *pointer; - typedef T &reference; - - Q_DECL_CONSTEXPR iterator() : buffer(Q_NULLPTR), index(-1) {} - iterator(QCircularBuffer *buf, int idx) - : buffer(buf), index(idx) - {} - - T &operator*() const { return (*buffer)[ index ]; } - T *operator->() const { return &(*buffer)[index]; } - T &operator[](int j) const { return (*buffer)[ index + j ]; } - - bool operator==(const iterator &other) const - { - return (buffer == other.buffer && index == other.index); - } - - bool operator!=(const iterator &other) const - { - return (buffer != other.buffer || index != other.index); - } - - bool operator<(const iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<", "iterators use different buffers"); - return index < other.index; - } - - bool operator<=(const iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<=", "iterators use different buffers"); - return index <= other.index; - } - - bool operator>(const iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>", "iterators use different buffers"); - return index > other.index; - } - - bool operator>=(const iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>=", "iterators use different buffers"); - return index >= other.index; - } - - iterator &operator++() { ++index; return *this; } - iterator operator++(int) - { - iterator ans = *this; - ++index; - return ans; - } - - iterator &operator--() { --index; return *this; } - iterator operator--(int) - { - iterator ans = *this; - --index; - return ans; - } - - iterator &operator+=(int j) { index += j; return *this; } - iterator &operator-=(int j) { index -= j; return *this; } - iterator operator+(int j) const { return iterator(buffer, index + j); } - iterator operator-(int j) const { return iterator(buffer, index - j); } - int operator-(iterator other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator-", "iterators use different buffers"); - return index - other.index; - } - - private: - QCircularBuffer *buffer; - int index; - friend class QCircularBuffer; - }; - friend class iterator; - - class const_iterator - { - public: - typedef std::random_access_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef const T *pointer; - typedef const T &reference; - - Q_DECL_CONSTEXPR const_iterator() : buffer(Q_NULLPTR), index(-1) {} - const_iterator(const QCircularBuffer *buff, int idx) - : buffer(buff), index(idx) - {} - const_iterator(const iterator &other) - : buffer(other.buffer), index(other.index) - {} - - const T &operator*() const { return buffer->at(index); } - const T *operator->() const { return &buffer->at(index); } - const T &operator[](int j) const { return buffer->at(index + j); } - - bool operator==(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator==", "iterators use different buffers"); - return index == other.index; - } - - bool operator!=(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator!=", "iterators use different buffers"); - return index != other.index; - } - - bool operator<(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<", "iterators use different buffers"); - return index < other.index; - } - - bool operator<=(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<=", "iterators use different buffers"); - return index <= other.index; - } - - bool operator>(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>", "iterators use different buffers"); - return index > other.index; - } - - bool operator>=(const const_iterator &other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>=", "iterators use different buffers"); - return index >= other.index; - } - - const_iterator &operator++() { ++index; return *this; } - const_iterator operator++(int) - { - const_iterator ans = *this; - ++index; - return ans; - } - - const_iterator &operator--() { --index; return *this; } - const_iterator operator--(int) - { - const_iterator ans = *this; - --index; - return ans; - } - - const_iterator &operator+=(int j) { index += j; return *this; } - const_iterator &operator-=(int j) { index -= j; return *this; } - const_iterator operator+(int j) const { return const_iterator(buffer, index + j); } - const_iterator operator-(int j) const { return const_iterator(buffer, index - j); } - int operator-(const_iterator other) const - { - Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator-", "iterators use different buffers"); - return index - other.index; - } - - private: - const QCircularBuffer *buffer; - int index; - friend class QCircularBuffer; - }; - friend class const_iterator; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - iterator begin() { return iterator(this, 0); } - const_iterator begin() const { return const_iterator(this, 0); } - const_iterator cbegin() const { return const_iterator(this, 0); } - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } - const_iterator constBegin() const { return const_iterator(this, 0); } - iterator end() { return iterator(this, d->size); } - const_iterator end() const { return const_iterator(this, d->size); } - const_iterator cend() const { return const_iterator(this, d->size); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } - const_iterator constEnd() const { return const_iterator(this, d->size); } - iterator insert(const_iterator before, int number, const T &val) - { - insert(before.index, number, val); - return iterator(this, before.index); - } - iterator insert(const_iterator before, const T &val) { return insert(before, 1, val); } - iterator erase(const_iterator b, const_iterator e) - { - int number = e - b; - remove(b.index, number); - return iterator(this, e.index - number); - } - iterator erase(const_iterator pos) { return erase(pos, pos + 1); } - - // STL compatibility - typedef T value_type; - typedef value_type *pointer; - typedef const value_type *const_pointer; - typedef value_type &reference; - typedef const value_type &const_reference; - typedef ptrdiff_t difference_type; - typedef iterator Iterator; - typedef const_iterator ConstIterator; - typedef int size_type; - - void push_back(const T &t) { append(t); } - void push_front(const T &t) { prepend(t); } - void pop_back() { Q_ASSERT(!isEmpty()); erase(end() - 1); } - void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); } - bool empty() const { return isEmpty(); } - T &front() { return first(); } - const T &front() const { return first(); } - T &back() { return last(); } - const T &back() const { return last(); } - - QAtomicInt refCount() const { return d->ref; } - - void append(const T &val); - - const T &at(int i) const - { - Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::at", "index out of range"); - return d->data()[d->wraparound(d->first + i)]; - } - - const T &operator[](int i) const - { - Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); - return d->data()[d->wraparound(d->first + i)]; - } - - T &operator[](int i) - { - d.detach(); - Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); - return d->data()[d->wraparound(d->first + i)]; - } - - int capacity() const { return d->capacity; } - - void clear() { *this = QCircularBuffer(d->capacity); } - - bool contains(const T &val) const; - int count(const T &val) const; - int count() const { return size(); } - - array_range data() - { - d.detach(); - if (d->size == 0) - return array_range(Q_NULLPTR, 0); - if (!isLinearised()) - linearise(); - return array_range(d->data() + d->first, d->last - d->first + 1); - } - const_array_range data() const { return constData(); } - const_array_range constData() const - { - if (!isLinearised() || d->size == 0) - return const_array_range(Q_NULLPTR, 0); - return const_array_range(d->data() + d->first, d->last - d->first + 1); - } - - array_range dataOne() - { - d.detach(); - if (d->size == 0) - return array_range(Q_NULLPTR, 0); - if (isLinearised()) - return array_range(d->data() + d->first, d->last - d->first + 1); - else - return array_range(d->data() + d->first, d->capacity - d->first); - } - const_array_range dataOne() const { return constDataOne(); } - const_array_range constDataOne() const - { - if (d->size == 0) - return const_array_range(Q_NULLPTR, 0); - if (isLinearised()) - return const_array_range(d->data() + d->first, d->last - d->first + 1); - else - return const_array_range(d->data() + d->first, d->capacity - d->first); - } - - array_range dataTwo() - { - d.detach(); - if (d->size == 0 || isLinearised()) - return array_range(Q_NULLPTR, 0); - return array_range(d->data(), d->last + 1); - } - const_array_range dataTwo() const { return constDataTwo(); } - const_array_range constDataTwo() const - { - if (d->size == 0 || isLinearised()) - return const_array_range(Q_NULLPTR, 0); - return const_array_range(d->data(), d->last + 1); - } - - bool endsWith(const T &val) const { return !isEmpty() && last() == val; } - QCircularBuffer &fill(const T &val, int number = -1); - T &first() { Q_ASSERT(!isEmpty()); d.detach(); return d->data()[ d->first ]; } - const T &first() const { Q_ASSERT(!isEmpty()); return d->data()[ d->first ]; } - int freeSize() const { return sizeAvailable(); } - - static QCircularBuffer fromList(const QList &list) - { return QCircularBuffer(list.begin(), list.end()); } - static QCircularBuffer fromVector(const QVector &vector) - { return QCircularBuffer(vector.begin(), vector.end()); } - - int indexOf(const T &val, int from = 0) const; - void insert(int i, const T &val) { insert(i, 1, val); } - void insert(int i, int number, const T &val); - bool isEmpty() const { return d->size == 0; } - bool isFull() const { return d->size == d->capacity; } - bool isLinearised() const { return (d->last >= d->first); } - T &last() { Q_ASSERT(!isEmpty()); return d->data()[ d->last ]; } - const T &last() const { Q_ASSERT(!isEmpty()); return d->data()[ d->last ]; } - int lastIndexOf(const T &val, int from = -1) const; - void linearise() - { - if (!isLinearised()) { - QCircularBuffer linearized(this->cbegin(), this->cend()); - swap(linearized); - } - } - - void prepend(const T &val); - void remove(int i) { remove(i, 1); } - void remove(int i, int number); - - void replace(int i, const T &val) - { - Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::replace", "index out of range"); - const T copy(val); - (*this)[ i ] = copy; - } - - void reserve(int amount) { setCapacity(amount); } - void resize(int newSize); - void setCapacity(int amount); - int size() const { return d->size; } - Q_DECL_CONSTEXPR int max_size() const { return std::numeric_limits::max(); } - int sizeAvailable() const { return d->capacity - d->size; } - void squeeze() { setCapacity(size()); } - bool startsWith(const T &val) const { return !isEmpty() && first() == val; } - - QList toList() const; - QVector toVector() const; - - T value(int i) const - { - if (i < 0 || i >= d->size) - return T(); - return at(i); - } - - T value(int i, const T &defaultValue) const - { - if (i < 0 || i >= d->size) - return defaultValue; - return at(i); - } - - QCircularBuffer &operator+=(const T &other) { append(other); return *this; } - QCircularBuffer &operator+=(const QCircularBuffer &other); - QCircularBuffer &operator+=(const QVector &other); - QCircularBuffer &operator+=(const QList &other); - - QCircularBuffer &operator<<(const T &other) { append(other); return *this; } - QCircularBuffer &operator<<(const QCircularBuffer &other) { *this += other; return *this; } - QCircularBuffer &operator<<(const QVector &other) { *this += other; return *this; } - QCircularBuffer &operator<<(const QList &other) { *this += other; return *this; } - - inline bool isSharedWith(const QCircularBuffer &other) const { return d == other.d; } - -private: - QExplicitlySharedDataPointer d; -}; - -template -QCircularBuffer operator+(const QCircularBuffer &lhs, const QCircularBuffer &rhs); - -template -inline bool operator==(const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return lhs.isSharedWith(rhs) || (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin())); } - -template -inline bool operator!=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return !operator==(lhs, rhs); } - -template -inline void swap(QCircularBuffer &lhs, QCircularBuffer &rhs) -{ lhs.swap(rhs); } - -template -inline bool operator< (const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } - -template -inline bool operator> (const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return operator<(rhs, lhs); } - -template -inline bool operator>=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return !operator<(lhs, rhs); } - -template -inline bool operator<=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ return !operator>(lhs, rhs); } - -// out-of-line function implementations: - -template -QCircularBuffer::QCircularBuffer(int amount) - : d(new Data()) -{ - // Allocate some raw memory - d->setData(d->allocate(amount)); - d->capacity = amount; - - // Initialize memory block to zero - memset(d->data(), 0, amount * sizeof(T)); -} - -template -QCircularBuffer::QCircularBuffer(int amount, const T &val) - : d(new Data()) -{ - // Allocate some raw memory - d->setData(d->allocate(amount)); - d->capacity = amount; - - // Initialize the objects. In this case we always use the placement new operator - T *b = d->data(); - T *i = b + d->capacity; - while (i != b) - new (--i) T(val); - d->first = 0; - d->last = d->capacity - 1; - d->size = d->capacity; -} - -template -QCircularBuffer::QCircularBuffer(int amount, int initialSize, const T &val) - : d(new Data()) -{ - Q_ASSERT_X(amount >= initialSize, "QCircularBuffer::QCircularBuffer(int capacity, int size, const T &value)", "size is greater than capacity"); - - // Allocate some raw memory - d->setData(d->allocate(amount)); - d->capacity = amount; - - // Initialize the objects that need to be set to the specified value. - // In this case we always use the placement new operator - T *b = d->data(); - T *i = b + initialSize; - while (i != b) - new (--i) T(val); - - // Initialize the remaining memory to zero - memset(d->data() + initialSize, 0, (amount - initialSize) * sizeof(T)); - - d->first = 0; - d->last = initialSize - 1; - d->size = initialSize; -} - -template -void QCircularBuffer::append(const T &val) -{ - // If we have no capacity we do nothing - if (!d->capacity) - return; - d.detach(); - if (d->size == d->capacity) { - // Buffer is full. Overwrite earliest item and rotate - d->data()[ d->first ] = val; - d->first = d->wraparound(++d->first); - d->last = d->wraparound(++d->last); - } else if (d->size != 0) { - // Buffer is partially full. Append data to end of array using appropriate method - int index = d->wraparound(d->first + d->size); - if (QTypeInfo::isComplex) - new (d->data() + index) T(val); - else - d->data()[ index ] = val; - ++d->size; - ++d->last; - } else { - // Buffer is empty. Append data to end of array using appropriate method - d->size = 1; - d->first = d->last = 0; - if (QTypeInfo::isComplex) - new (d->data() + d->first) T(val); - else - d->data()[ d->first ] = val; - } -} - -template -bool QCircularBuffer::contains(const T &val) const -{ - if (isLinearised()) { - T *b = d->data() + d->first; - T *i = b + d->size; - while (i != b) - if (*--i == val) - return true; - return false; - } else { - // Check the array from m_first to the end - T *b = d->data() + d->first; - T *i = d->data() + d->capacity; - while (i != b) - if (*--i == val) - return true; - - // Check array from 0 to m_end - b = d->data(); - i = d->data() + d->last + 1; - while (i != b) - if (*--i == val) - return true; - - return false; - } -} - -template -int QCircularBuffer::count(const T &val) const -{ - int c = 0; - if (isLinearised()) { - T *b = d->data() + d->first; - T *i = b + d->size; - while (i != b) - if (*--i == val) - ++c; - } else { - // Check the array from m_first to the end - T *b = d->data() + d->first; - T *i = d->data() + d->capacity; - while (i != b) - if (*--i == val) - ++c; - - // Check array from 0 to m_end - b = d->data(); - i = d->data() + d->last + 1; - while (i != b) - if (*--i == val) - ++c; - } - return c; -} - -template -QCircularBuffer &QCircularBuffer::fill(const T &val, int number) -{ - Q_ASSERT_X(d->capacity >= number, "QCircularBuffer::fill", "size is greater than capacity"); - const T copy(val); - d.detach(); - int oldSize = d->size; - d->size = (number < 0 ? d->size : number); - d->first = (number == 0 ? -1 : 0); - d->last = d->size - 1; - - // Copy item into array size times - if (d->size) { - T *b = d->data(); - T *i = d->data() + d->size; - while (i != b) - *--i = copy; - } - - if (d->size < oldSize) { - // Cleanup old items beyond end of new array - T *b = d->data() + d->size; - T *i = d->data() + oldSize; - while (i-- != b) { - i->~T(); - //TODO: Optimize to a single memset call - memset(i, 0, sizeof(T)); - } - } - - return *this; -} - -template -int QCircularBuffer::indexOf(const T &val, int from) const -{ - Q_ASSERT_X(from < d->size, "QCircularBuffer::indexOf", "from is greater than last valid index"); - if (from < 0) - from = qMax(from + d->size, 0); - else if (from >= d->size) - from = d->size - 1; - for (int i = from; i < d->size; ++i) - if (at(i) == val) - return i; - return -1; -} - -template -void QCircularBuffer::insert(int i, int number, const T &val) -{ - Q_ASSERT_X(i >= 0 && i <= d->size, "QCircularBuffer::insert", "index out of range"); - d.detach(); - int freeCapacity = d->capacity - d->size; - - // Calculate number of elements that will actually be inserted. This - // depends upon where the insertion has been requested and any spare - // capacity left in the buffer. This is because elements at higher - // indices will be pushed to the right and will potentially wrap around - // to overwrite earlier elements. - int numToInsert = qMin(number, i + freeCapacity); - - // Calculate the number of elements at the beginning of the buffer that - // will be overwritten - int numToOverwrite = qMin(i, qMax(0, number - freeCapacity)); - - // Decide which way to shift to minimize the amount of copying required. - if (i < d->size / 2) { - // Inserting in lower half of buffer so we shift earlier items down - - // Shift data at the bottom end down. This may only be a subset if some - // of the early data is to be overwritten. - if (QTypeInfo::isStatic) { - int b = d->first + numToOverwrite; - int e = d->first + i - 1; - for (int j = b; j <= e; ++j) { - int srcIndex = j % d->capacity; - int dstIndex = (j - numToInsert + d->capacity) % d->capacity; - T *src = d->data() + srcIndex; - T *dst = d->data() + dstIndex; - - new (dst) T(*src); - } - } else { - // We have a movable type so a simple memcopy (or maybe two or - // three) will suffice to shift the data at the bottom end - int numToMove = i - numToOverwrite; - if (numToMove > 0) { - int srcBegin = (d->first + numToOverwrite) % d->capacity; - int srcEnd = (d->first + i - 1) % d->capacity; - int dstBegin = (srcBegin - numToInsert + d->capacity) % d->capacity; - int dstEnd = (srcEnd - numToInsert + d->capacity) % d->capacity; - - // Do we have any wrap-around problems to deal with? - bool srcRegionWraps = (srcEnd < srcBegin); - bool dstRegionWraps = (dstEnd < dstBegin); - if (!srcRegionWraps && dstRegionWraps) { - // Destination region wraps so do the move in two steps - int wrapCount = abs(srcBegin - numToInsert); - memmove(d->data() + d->capacity - wrapCount, d->data() + srcBegin, wrapCount * sizeof(T)); - memmove(d->data(), d->data() + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && !dstRegionWraps) { - // Source region wraps so do the move in two steps - int wrapCount = d->capacity - srcBegin; - memmove(d->data() + dstBegin, d->data() + d->capacity - wrapCount, wrapCount * sizeof(T)); - memmove(d->data() + dstBegin + numToInsert, d->data(), (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && dstRegionWraps) { - // Source and destination regions wrap so we have to do this in three steps - int srcWrapCount = d->capacity - srcBegin; - memmove(d->data() + dstBegin, d->data() + d->capacity - srcWrapCount, srcWrapCount * sizeof(T)); - memmove(d->data() + d->capacity - numToInsert, d->data(), numToInsert * sizeof(T)); - memmove(d->data(), d->data() + numToInsert, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); - } else { - // No wrap around - do a single memmove - memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); - } - } - } - - // Insert the new items - int e = d->first + i; - int b = e - numToInsert; - for (int j = b; j < e; ++j) { - T *p = d->data() + ((j + d->capacity) % d->capacity); - new (p) T(val); - } - - // Adjust the first, last and size indices as needed. - // NB. The last index never changes in this regime. - d->size += qMin(number, freeCapacity); - d->first = (d->first - (numToInsert - numToOverwrite) + d->capacity) % d->capacity; - } else { - // Inserting in upper half of buffer so we shift later items up - - // Shift data at the top end up which may or may not overwrite some - // of the earliest data - if (QTypeInfo::isStatic) { - int b = d->first + d->size - 1; - int e = d->first + i; - for (int j = b; j >= e; j--) { - int srcIndex = j % d->capacity; - int dstIndex = (j + numToInsert) % d->capacity; - T *src = d->data() + srcIndex; - T *dst = d->data() + dstIndex; - - new (dst) T(*src); - } - } else { - // We have a movable type so a simple memcopy (or maybe two or - // three) will suffice to shift the data at the top end - int numToMove = d->size - i; - if (numToMove > 0) { - int srcBegin = (d->first + i) % d->capacity; - int srcEnd = d->last; - int dstBegin = (srcBegin + numToInsert) % d->capacity; - int dstEnd = (srcEnd + numToInsert) % d->capacity; - - // Do we have any wrap-around problems to deal with? - bool srcRegionWraps = (srcEnd < srcBegin); - bool dstRegionWraps = (dstEnd < dstBegin); - if (!srcRegionWraps && dstRegionWraps) { - // Destination region wraps so do the move in two steps - int wrapCount = srcEnd + numToInsert - d->capacity + 1; - memmove(d->data(), d->data() + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && !dstRegionWraps) { - // Source region wraps so do the move in two steps - int wrapCount = d->last + 1; - memmove(d->data() + numToInsert, d->data(), wrapCount * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && dstRegionWraps) { - // Source and destination regions wrap so we have to do this in three steps - int srcWrapCount = d->last + 1; - memmove(d->data() + numToInsert, d->data(), srcWrapCount * sizeof(T)); - memmove(d->data(), d->data() + d->capacity - numToInsert, numToInsert * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); - } else { - // No wrap around - do a single memmove - memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); - } - } - } - - // Insert the new items - for (int j = d->first + i; j < d->first + i + numToInsert; ++j) { - T *p = d->data() + (j % d->capacity); - new (p) T(val); - } - - // Adjust the first, last and size indices as needed - d->size += qMin(number, freeCapacity); - d->first = (d->first + numToOverwrite) % d->capacity; - d->last = (d->last + numToInsert) % d->capacity; - } -} - -template -int QCircularBuffer::lastIndexOf(const T &val, int from) const -{ - if (from < 0) - from = qMax(from + d->size, 0); - else if (from >= d->size) - from = d->size - 1; - for (int i = from; i >= 0; --i) - if (at(i) == val) - return i; - return -1; -} - -template -void QCircularBuffer::prepend(const T &val) -{ - // If we have no capacity we do nothing - if (!d->capacity) - return; - - d.detach(); - if (d->size == d->capacity) { - // Buffer is full. Overwrite last item and rotate - d->data()[ d->last ] = val; - d->first = (--d->first + d->capacity) % d->capacity; - d->last = (--d->last + d->capacity) % d->capacity; - } else if (d->size != 0) { - // Buffer is partially full. Prepend data to start of array using appropriate method - d->first = (--d->first + d->capacity) % d->capacity; - ++d->size; - if (QTypeInfo::isComplex) - new (d->data() + d->first) T(val); - else - d->data()[ d->first ] = val; - } else { - // Buffer is empty. Prepend data to start of array using appropriate method - d->size = 1; - d->first = d->last = d->capacity - 1; - if (QTypeInfo::isComplex) - new (d->data() + d->first) T(val); - else - d->data()[ d->first ] = val; - } -} - -template -void QCircularBuffer::remove(int i, int number) -{ - Q_ASSERT_X(i >= 0 && number > 0 && i + number <= d->size, "QCircularBuffer::remove", "index out of range"); - d.detach(); - - // HACK (it actually makes sense, but requires some more thinking) - if ( i == 0 && !QTypeInfo::isComplex ) { - d->first = d->wraparound( d->first + number ); - d->size -= number; - return; - } - - // Calculate the number of items that need to be moved downward - int numToMoveDown = d->size - number - i; - int numToMoveUp = i; - - if (numToMoveDown < numToMoveUp) { - // Move higher items down - int numToMove = numToMoveDown; - - if (QTypeInfo::isComplex) { - // Copy items down from higher positions - int b = d->first + i; - int e = b + numToMove; - for (int j = b; j < e ; ++j) { - T *src = d->data() + ((j + number) % d->capacity); - T *dst = d->data() + (j % d->capacity); - new (dst) T(*src); - } - - // Clean up items at end of buffer - for (int j = d->last; j > d->last - number; --j) { - T *p = d->data() + ((j + d->capacity) % d->capacity); - p->~T(); - //TODO: Optimize to a single memset call - memset(p, 0, sizeof(T)); - } - } else { - if (isLinearised()) { - // With a linearised buffer we can do a simple move and removal of items - memmove(d->data() + d->last - numToMove - number + 1, d->data() + d->last - numToMove + 1, numToMove * sizeof(T)); - memset(d->data() + d->last - number + 1, 0, number * sizeof(T)); - } else { - // With a non-linearised buffer we need to be careful of wrapping issues - int srcBegin = (d->last - numToMove + 1 + d->capacity) % d->capacity; - int srcEnd = d->last; - int dstBegin = (d->first + i) % d->capacity; - int dstEnd = (dstBegin + numToMove - 1) % d->capacity; - - bool srcRegionWraps = (srcEnd < srcBegin); - bool dstRegionWraps = (dstEnd < dstBegin); - if (srcRegionWraps && !dstRegionWraps) { - // Source region wraps so do the move in two steps - int wrapCount = d->capacity - srcBegin; - memmove(d->data() + dstBegin, d->data() + srcBegin, wrapCount * sizeof(T)); - memmove(d->data() + dstBegin + wrapCount, d->data(), (numToMove - wrapCount) * sizeof(T)); - } else if (!srcRegionWraps && dstRegionWraps) { - // Destination region wraps so do the move in two steps - int wrapCount = number - srcBegin; - memmove(d->data() + d->capacity - wrapCount, d->data() + srcBegin, wrapCount * sizeof(T)); - memmove(d->data(), d->data() + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && dstRegionWraps) { - // Source and destination regions wrap so we have to do this in three steps - int srcWrapCount = d->capacity - srcBegin; - memmove(d->data() + dstBegin, d->data() + srcBegin, srcWrapCount * sizeof(T)); - memmove(d->data() + dstBegin + srcWrapCount, d->data(), number * sizeof(T)); - memmove(d->data(), d->data() + number, (numToMove - srcWrapCount - number) * sizeof(T)); - } else { - // No wrap around, so we can do this in one hit - memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); - } - - // We potentially have a disjoint region that needs zeroing - int zeroStart = (d->last - number + d->capacity + 1) % d->capacity; - int zeroEnd = d->last; - if (zeroEnd < zeroStart) { - // Region to be zeroed wraps. Do it in two steps. - memset(d->data(), 0, (d->last + 1) * sizeof(T)); - memset(d->data() + zeroStart, 0, (number - d->last - 1) * sizeof(T)); - } else { - // Region to be zeroed is contiguous - memset(d->data() + zeroStart, 0, number * sizeof(T)); - } - } - } - - // Adjust the indices - d->size -= number; - d->last = (d->last - number + d->capacity) % d->capacity; - } else { - // Move lower items up - int numToMove = numToMoveUp; - - if (QTypeInfo::isComplex) { - // Copy items up from lower positions - int b = d->first + i - 1; - int e = b - numToMove; - for (int j = b; j > e ; --j) { - T *src = d->data() + ((j + d->capacity) % d->capacity); - T *dst = d->data() + ((j + d->capacity + number) % d->capacity); - new (dst) T(*src); - } - - // Clean up items at start of buffer - for (int j = d->first; j < d->first + number; ++j) { - T *p = d->data() + (j % d->capacity); - p->~T(); - //TODO: Optimize to a single memset call - memset(p, 0, sizeof(T)); - } - } else { - if (isLinearised()) { - // With a linearised buffer we can do a simple move and removal of items - memmove(d->data() + d->first + number, d->data() + d->first, numToMove * sizeof(T)); - memset(d->data() + d->first, 0, number * sizeof(T)); - } else { - // With a non-linearised buffer we need to be careful of wrapping issues - int srcBegin = d->first; - int srcEnd = (srcBegin + numToMove - 1) % d->capacity; - int dstBegin = (srcBegin + number) % d->capacity; - int dstEnd = (dstBegin + numToMove - 1) % d->capacity; - - bool srcRegionWraps = (srcEnd < srcBegin); - bool dstRegionWraps = (dstEnd < dstBegin); - if (srcRegionWraps && !dstRegionWraps) { - // Source region wraps so do the move in two steps - int wrapCount = srcEnd + 1; - memmove(d->data() + dstEnd - wrapCount + 1, d->data(), wrapCount * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); - } else if (!srcRegionWraps && dstRegionWraps) { - // Destination region wraps so do the move in two steps - int wrapCount = dstEnd + 1; - memmove(d->data(), d->data() + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); - } else if (srcRegionWraps && dstRegionWraps) { - // Source and destination regions wrap so we have to do this in three steps - int srcWrapCount = srcEnd + 1; - memmove(d->data() + dstEnd - srcWrapCount + 1, d->data(), srcWrapCount * sizeof(T)); - memmove(d->data(), d->data() + d->capacity - number, number * sizeof(T)); - memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - srcWrapCount - number) * sizeof(T)); - } else { - // No wrap around, so we can do this in one hit - memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); - } - - // We potentially have a disjoint region that needs zeroing - int zeroStart = d->first; - int zeroEnd = (zeroStart + number - 1) % d->capacity; - if (zeroEnd < zeroStart) { - // Region to be zeroed wraps. Do it in two steps. - memset(d->data() + zeroStart, 0, (d->capacity - d->first) * sizeof(T)); - memset(d->data(), 0, (number - d->capacity + d->first) * sizeof(T)); - } else { - // Region to be zeroed is contiguous - memset(d->data() + zeroStart, 0, number * sizeof(T)); - } - } - } - - // Adjust the indices - d->size -= number; - d->first = (d->first + number) % d->capacity; - } -} - -template -void QCircularBuffer::setCapacity(int amount) -{ - if (amount == d->capacity) - return; - - d.detach(); - // Allocate some new raw memory - T *newData = d->allocate(amount); - - // How many items can we copy across? - int newSize = qMin(d->size, amount); - - if (QTypeInfo::isComplex) { - // Copy across the elements from the original array - for (int i = 0; i < newSize; ++i) { - T *src = d->data() + ((d->first + i) % d->capacity); - T *dst = newData + i; - new (dst) T(*src); - } - - // Destroy the original items. - // The type is complex so we manually call the destructor for each item - // since we used the placement new operator to instantiate them - T *b = d->data(); - T *i = b + d->capacity; - while (i-- != b) - i->~T(); - } else { - // Copy across the elements from the original array. The source region - // potentially wraps so we may have to do this in one or two steps - if (isLinearised()) { - memmove(newData, d->data() + d->first, newSize * sizeof(T)); - } else { - int step1Size = qMin(newSize, d->capacity - d->first); - memmove(newData, d->data() + d->first, step1Size * sizeof(T)); - int step2Size = qMax(0, qMin(newSize - d->capacity + d->first, d->last + 1)); - memmove(newData + step1Size, d->data(), step2Size * sizeof(T)); - } - } - - // Initialize any memory outside of the valid buffer (ie the unused items) - memset(newData + newSize, 0, (amount - newSize) * sizeof(T)); - - // Release the raw memory for the old array - d->deallocate(d->data()); - - // Assign the new memory to be our buffer data and fix indices - d->setData(newData); - d->capacity = amount; - d->first = 0; - d->size = newSize; - d->last = d->size - 1; -} - -template -void QCircularBuffer::resize(int newSize) -{ - Q_ASSERT_X(newSize >= 0 && newSize <= d->capacity, "QCircularBuffer::resize", "size out of range"); - d.detach(); - if (newSize < d->size) { - remove(newSize, d->size - newSize); - } else if (newSize > d->size) { - const T t = T(); - insert(d->size, newSize - d->size, t); - } -} - -template -QCircularBuffer &QCircularBuffer::operator+=(const QCircularBuffer &other) -{ - d.detach(); - // How many items do we need to copy? No point in ever copying across a number - // greater than capacity - int numToCopy = qMin(other.size(), d->capacity); - int offset = other.size() - numToCopy; - for (int i = 0; i < numToCopy; ++i) - append(other.at(offset + i)); - return *this; -} - -template -QCircularBuffer &QCircularBuffer::operator+=(const QVector &other) -{ - d.detach(); - // How many items do we need to copy? No point in ever copying across a number - // greater than capacity - int numToCopy = qMin(other.size(), d->capacity); - int offset = other.size() - numToCopy; - for (int i = 0; i < numToCopy; ++i) - append(other.at(offset + i)); - return *this; -} - -template -QCircularBuffer &QCircularBuffer::operator+=(const QList &other) -{ - d.detach(); - // How many items do we need to copy? No point in ever copying across a number - // greater than capacity - int numToCopy = qMin(other.size(), d->capacity); - int offset = other.size() - numToCopy; - for (int i = 0; i < numToCopy; ++i) - append(other.at(offset + i)); - return *this; -} - -template -QList QCircularBuffer::toList() const -{ - QList list; - list.reserve(size()); - for (int i = 0; i < size(); ++i) - list.append(at(i)); - return list; -} - -template -QVector QCircularBuffer::toVector() const -{ - QVector vector; - vector.reserve(size()); - for (int i = 0; i < size(); ++i) - vector.append(at(i)); - return vector; -} - -template -QCircularBuffer operator+(const QCircularBuffer &lhs, const QCircularBuffer &rhs) -{ - QCircularBuffer circ(lhs.size() + rhs.size()); - for (int i = 0; i < lhs.size(); ++i) - circ.append(lhs.at(i)); - for (int i = 0; i < rhs.size(); ++i) - circ.append(rhs.at(i)); - return circ; -} - -Q_DECLARE_SEQUENTIAL_ITERATOR(CircularBuffer) -Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(CircularBuffer) - -} //Qt3D - -QT_END_NAMESPACE - -#endif // QT3D_QCIRCULARBUFFER_H diff --git a/src/core/resources/qcircularbuffer_p.h b/src/core/resources/qcircularbuffer_p.h new file mode 100644 index 000000000..30dab5dc3 --- /dev/null +++ b/src/core/resources/qcircularbuffer_p.h @@ -0,0 +1,1323 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3D_QCIRCULARBUFFER_H +#define QT3D_QCIRCULARBUFFER_H + +#include +#include +#include +#include + +#include +#ifdef Q_COMPILER_INITIALIZER_LISTS +# include +#endif +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3D { + +class CircularBufferData : public QSharedData +{ +protected: + CircularBufferData() + : data(Q_NULLPTR), + capacity(0), + size(0), + first(-1), + last(-1) + {} + + ~CircularBufferData() + { + // Release the raw memory + deallocate(data); + } + + int wraparound(int index) const + { + index = index < capacity ? index : (index - capacity); + Q_ASSERT(index < capacity); // make sure that wrapping around once was enough + return index; + } + + void *allocate(int count, size_t sizeOfT) + { return operator new[](count * sizeOfT); } + void deallocate(void *p) + { operator delete[](p); } + + void *data; // Array of the actual data +public: + int capacity; // Size of the m_data array + int size; // Number of elements of m_data actually used + int first; // Index in m_data of the first element of the circular buffer + int last; // Index in m_data of the last element of the circular buffer +}; + +template +class TypedCircularBufferData : public CircularBufferData +{ + template + explicit TypedCircularBufferData(InputIterator f, InputIterator l, std::input_iterator_tag) Q_DECL_EQ_DELETE; +public: + TypedCircularBufferData() : CircularBufferData() {} + template + explicit TypedCircularBufferData(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) + { + const int n = int(std::distance(f, l)); + CircularBufferData::data = allocate(n); + std::uninitialized_copy(f, l, data()); + first = 0; + last = n - 1; + size = capacity = n; + } + ~TypedCircularBufferData() + { + if (QTypeInfo::isComplex && size != 0) { + // The type is complex so we manually call the destructor for each item + // since we used the placement new operator to instantiate them + if (first <= last) { + // Destroy items from first to last + T *b = data() + first; + T *i = b + size; + while (i-- != b) + i->~T(); + } else { + // Destroy items at end of data array + T *b = data() + first; + T *i = data() + capacity; + while (i-- != b) + i->~T(); + + // Destroy items at beginning of data array + b = data(); + i = b + last; + while (i-- != b) + i->~T(); + } + } + + } + +#ifndef Q_NO_USING_KEYWORD + using CircularBufferData::wraparound; +#else + inline int wraparound(int index) const { return CircularBufferData::wraparound(index); } +#endif + T *allocate(int count) { return static_cast(CircularBufferData::allocate(count, sizeof(T))); } +#ifndef Q_NO_USING_KEYWORD + using CircularBufferData::deallocate; +#else + inline void deallocate(void *p) { return CircularBufferData::deallocate(p); } +#endif + T *data() const { return static_cast(CircularBufferData::data); } + void setData(T *newdata) { CircularBufferData::data = static_cast(newdata); } +}; + +template +class QCircularBuffer +{ + typedef TypedCircularBufferData Data; +public: + typedef QPair array_range; + typedef QPair const_array_range; + typedef array_range ArrayRange; + typedef const_array_range ConstArrayRange; + + QCircularBuffer() + : d(new Data()) + {} + + explicit QCircularBuffer(int amount); + explicit QCircularBuffer(int amount, const T &val); + explicit QCircularBuffer(int amount, int initialSize, const T &value); +#ifdef Q_COMPILER_INITIALIZER_LISTS + QCircularBuffer(std::initializer_list list) + : d(new Data(list.begin(), list.end(), std::random_access_iterator_tag())) + {} +#endif + template + explicit QCircularBuffer(ForwardIterator f, ForwardIterator l) + : d(new Data(f, l, typename std::iterator_traits::iterator_category())) + {} + + QCircularBuffer(const QCircularBuffer &other) + : d(other.d) + {} + + void swap(QCircularBuffer &other) { d.swap(other.d); } + + QCircularBuffer &operator = (const QCircularBuffer &other) + { + d = other.d; + return *this; + } + + ~QCircularBuffer() {} + + class iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + Q_DECL_CONSTEXPR iterator() : buffer(Q_NULLPTR), index(-1) {} + iterator(QCircularBuffer *buf, int idx) + : buffer(buf), index(idx) + {} + + T &operator*() const { return (*buffer)[ index ]; } + T *operator->() const { return &(*buffer)[index]; } + T &operator[](int j) const { return (*buffer)[ index + j ]; } + + bool operator==(const iterator &other) const + { + return (buffer == other.buffer && index == other.index); + } + + bool operator!=(const iterator &other) const + { + return (buffer != other.buffer || index != other.index); + } + + bool operator<(const iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<", "iterators use different buffers"); + return index < other.index; + } + + bool operator<=(const iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<=", "iterators use different buffers"); + return index <= other.index; + } + + bool operator>(const iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>", "iterators use different buffers"); + return index > other.index; + } + + bool operator>=(const iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>=", "iterators use different buffers"); + return index >= other.index; + } + + iterator &operator++() { ++index; return *this; } + iterator operator++(int) + { + iterator ans = *this; + ++index; + return ans; + } + + iterator &operator--() { --index; return *this; } + iterator operator--(int) + { + iterator ans = *this; + --index; + return ans; + } + + iterator &operator+=(int j) { index += j; return *this; } + iterator &operator-=(int j) { index -= j; return *this; } + iterator operator+(int j) const { return iterator(buffer, index + j); } + iterator operator-(int j) const { return iterator(buffer, index - j); } + int operator-(iterator other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator-", "iterators use different buffers"); + return index - other.index; + } + + private: + QCircularBuffer *buffer; + int index; + friend class QCircularBuffer; + }; + friend class iterator; + + class const_iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + Q_DECL_CONSTEXPR const_iterator() : buffer(Q_NULLPTR), index(-1) {} + const_iterator(const QCircularBuffer *buff, int idx) + : buffer(buff), index(idx) + {} + const_iterator(const iterator &other) + : buffer(other.buffer), index(other.index) + {} + + const T &operator*() const { return buffer->at(index); } + const T *operator->() const { return &buffer->at(index); } + const T &operator[](int j) const { return buffer->at(index + j); } + + bool operator==(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator==", "iterators use different buffers"); + return index == other.index; + } + + bool operator!=(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator!=", "iterators use different buffers"); + return index != other.index; + } + + bool operator<(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<", "iterators use different buffers"); + return index < other.index; + } + + bool operator<=(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<=", "iterators use different buffers"); + return index <= other.index; + } + + bool operator>(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>", "iterators use different buffers"); + return index > other.index; + } + + bool operator>=(const const_iterator &other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>=", "iterators use different buffers"); + return index >= other.index; + } + + const_iterator &operator++() { ++index; return *this; } + const_iterator operator++(int) + { + const_iterator ans = *this; + ++index; + return ans; + } + + const_iterator &operator--() { --index; return *this; } + const_iterator operator--(int) + { + const_iterator ans = *this; + --index; + return ans; + } + + const_iterator &operator+=(int j) { index += j; return *this; } + const_iterator &operator-=(int j) { index -= j; return *this; } + const_iterator operator+(int j) const { return const_iterator(buffer, index + j); } + const_iterator operator-(int j) const { return const_iterator(buffer, index - j); } + int operator-(const_iterator other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator-", "iterators use different buffers"); + return index - other.index; + } + + private: + const QCircularBuffer *buffer; + int index; + friend class QCircularBuffer; + }; + friend class const_iterator; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + iterator begin() { return iterator(this, 0); } + const_iterator begin() const { return const_iterator(this, 0); } + const_iterator cbegin() const { return const_iterator(this, 0); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + const_iterator constBegin() const { return const_iterator(this, 0); } + iterator end() { return iterator(this, d->size); } + const_iterator end() const { return const_iterator(this, d->size); } + const_iterator cend() const { return const_iterator(this, d->size); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } + const_iterator constEnd() const { return const_iterator(this, d->size); } + iterator insert(const_iterator before, int number, const T &val) + { + insert(before.index, number, val); + return iterator(this, before.index); + } + iterator insert(const_iterator before, const T &val) { return insert(before, 1, val); } + iterator erase(const_iterator b, const_iterator e) + { + int number = e - b; + remove(b.index, number); + return iterator(this, e.index - number); + } + iterator erase(const_iterator pos) { return erase(pos, pos + 1); } + + // STL compatibility + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; + typedef iterator Iterator; + typedef const_iterator ConstIterator; + typedef int size_type; + + void push_back(const T &t) { append(t); } + void push_front(const T &t) { prepend(t); } + void pop_back() { Q_ASSERT(!isEmpty()); erase(end() - 1); } + void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); } + bool empty() const { return isEmpty(); } + T &front() { return first(); } + const T &front() const { return first(); } + T &back() { return last(); } + const T &back() const { return last(); } + + QAtomicInt refCount() const { return d->ref; } + + void append(const T &val); + + const T &at(int i) const + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::at", "index out of range"); + return d->data()[d->wraparound(d->first + i)]; + } + + const T &operator[](int i) const + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); + return d->data()[d->wraparound(d->first + i)]; + } + + T &operator[](int i) + { + d.detach(); + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); + return d->data()[d->wraparound(d->first + i)]; + } + + int capacity() const { return d->capacity; } + + void clear() { *this = QCircularBuffer(d->capacity); } + + bool contains(const T &val) const; + int count(const T &val) const; + int count() const { return size(); } + + array_range data() + { + d.detach(); + if (d->size == 0) + return array_range(Q_NULLPTR, 0); + if (!isLinearised()) + linearise(); + return array_range(d->data() + d->first, d->last - d->first + 1); + } + const_array_range data() const { return constData(); } + const_array_range constData() const + { + if (!isLinearised() || d->size == 0) + return const_array_range(Q_NULLPTR, 0); + return const_array_range(d->data() + d->first, d->last - d->first + 1); + } + + array_range dataOne() + { + d.detach(); + if (d->size == 0) + return array_range(Q_NULLPTR, 0); + if (isLinearised()) + return array_range(d->data() + d->first, d->last - d->first + 1); + else + return array_range(d->data() + d->first, d->capacity - d->first); + } + const_array_range dataOne() const { return constDataOne(); } + const_array_range constDataOne() const + { + if (d->size == 0) + return const_array_range(Q_NULLPTR, 0); + if (isLinearised()) + return const_array_range(d->data() + d->first, d->last - d->first + 1); + else + return const_array_range(d->data() + d->first, d->capacity - d->first); + } + + array_range dataTwo() + { + d.detach(); + if (d->size == 0 || isLinearised()) + return array_range(Q_NULLPTR, 0); + return array_range(d->data(), d->last + 1); + } + const_array_range dataTwo() const { return constDataTwo(); } + const_array_range constDataTwo() const + { + if (d->size == 0 || isLinearised()) + return const_array_range(Q_NULLPTR, 0); + return const_array_range(d->data(), d->last + 1); + } + + bool endsWith(const T &val) const { return !isEmpty() && last() == val; } + QCircularBuffer &fill(const T &val, int number = -1); + T &first() { Q_ASSERT(!isEmpty()); d.detach(); return d->data()[ d->first ]; } + const T &first() const { Q_ASSERT(!isEmpty()); return d->data()[ d->first ]; } + int freeSize() const { return sizeAvailable(); } + + static QCircularBuffer fromList(const QList &list) + { return QCircularBuffer(list.begin(), list.end()); } + static QCircularBuffer fromVector(const QVector &vector) + { return QCircularBuffer(vector.begin(), vector.end()); } + + int indexOf(const T &val, int from = 0) const; + void insert(int i, const T &val) { insert(i, 1, val); } + void insert(int i, int number, const T &val); + bool isEmpty() const { return d->size == 0; } + bool isFull() const { return d->size == d->capacity; } + bool isLinearised() const { return (d->last >= d->first); } + T &last() { Q_ASSERT(!isEmpty()); return d->data()[ d->last ]; } + const T &last() const { Q_ASSERT(!isEmpty()); return d->data()[ d->last ]; } + int lastIndexOf(const T &val, int from = -1) const; + void linearise() + { + if (!isLinearised()) { + QCircularBuffer linearized(this->cbegin(), this->cend()); + swap(linearized); + } + } + + void prepend(const T &val); + void remove(int i) { remove(i, 1); } + void remove(int i, int number); + + void replace(int i, const T &val) + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::replace", "index out of range"); + const T copy(val); + (*this)[ i ] = copy; + } + + void reserve(int amount) { setCapacity(amount); } + void resize(int newSize); + void setCapacity(int amount); + int size() const { return d->size; } + Q_DECL_CONSTEXPR int max_size() const { return std::numeric_limits::max(); } + int sizeAvailable() const { return d->capacity - d->size; } + void squeeze() { setCapacity(size()); } + bool startsWith(const T &val) const { return !isEmpty() && first() == val; } + + QList toList() const; + QVector toVector() const; + + T value(int i) const + { + if (i < 0 || i >= d->size) + return T(); + return at(i); + } + + T value(int i, const T &defaultValue) const + { + if (i < 0 || i >= d->size) + return defaultValue; + return at(i); + } + + QCircularBuffer &operator+=(const T &other) { append(other); return *this; } + QCircularBuffer &operator+=(const QCircularBuffer &other); + QCircularBuffer &operator+=(const QVector &other); + QCircularBuffer &operator+=(const QList &other); + + QCircularBuffer &operator<<(const T &other) { append(other); return *this; } + QCircularBuffer &operator<<(const QCircularBuffer &other) { *this += other; return *this; } + QCircularBuffer &operator<<(const QVector &other) { *this += other; return *this; } + QCircularBuffer &operator<<(const QList &other) { *this += other; return *this; } + + inline bool isSharedWith(const QCircularBuffer &other) const { return d == other.d; } + +private: + QExplicitlySharedDataPointer d; +}; + +template +QCircularBuffer operator+(const QCircularBuffer &lhs, const QCircularBuffer &rhs); + +template +inline bool operator==(const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return lhs.isSharedWith(rhs) || (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin())); } + +template +inline bool operator!=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return !operator==(lhs, rhs); } + +template +inline void swap(QCircularBuffer &lhs, QCircularBuffer &rhs) +{ lhs.swap(rhs); } + +template +inline bool operator< (const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } + +template +inline bool operator> (const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return operator<(rhs, lhs); } + +template +inline bool operator>=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return !operator<(lhs, rhs); } + +template +inline bool operator<=(const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ return !operator>(lhs, rhs); } + +// out-of-line function implementations: + +template +QCircularBuffer::QCircularBuffer(int amount) + : d(new Data()) +{ + // Allocate some raw memory + d->setData(d->allocate(amount)); + d->capacity = amount; + + // Initialize memory block to zero + memset(d->data(), 0, amount * sizeof(T)); +} + +template +QCircularBuffer::QCircularBuffer(int amount, const T &val) + : d(new Data()) +{ + // Allocate some raw memory + d->setData(d->allocate(amount)); + d->capacity = amount; + + // Initialize the objects. In this case we always use the placement new operator + T *b = d->data(); + T *i = b + d->capacity; + while (i != b) + new (--i) T(val); + d->first = 0; + d->last = d->capacity - 1; + d->size = d->capacity; +} + +template +QCircularBuffer::QCircularBuffer(int amount, int initialSize, const T &val) + : d(new Data()) +{ + Q_ASSERT_X(amount >= initialSize, "QCircularBuffer::QCircularBuffer(int capacity, int size, const T &value)", "size is greater than capacity"); + + // Allocate some raw memory + d->setData(d->allocate(amount)); + d->capacity = amount; + + // Initialize the objects that need to be set to the specified value. + // In this case we always use the placement new operator + T *b = d->data(); + T *i = b + initialSize; + while (i != b) + new (--i) T(val); + + // Initialize the remaining memory to zero + memset(d->data() + initialSize, 0, (amount - initialSize) * sizeof(T)); + + d->first = 0; + d->last = initialSize - 1; + d->size = initialSize; +} + +template +void QCircularBuffer::append(const T &val) +{ + // If we have no capacity we do nothing + if (!d->capacity) + return; + d.detach(); + if (d->size == d->capacity) { + // Buffer is full. Overwrite earliest item and rotate + d->data()[ d->first ] = val; + d->first = d->wraparound(++d->first); + d->last = d->wraparound(++d->last); + } else if (d->size != 0) { + // Buffer is partially full. Append data to end of array using appropriate method + int index = d->wraparound(d->first + d->size); + if (QTypeInfo::isComplex) + new (d->data() + index) T(val); + else + d->data()[ index ] = val; + ++d->size; + ++d->last; + } else { + // Buffer is empty. Append data to end of array using appropriate method + d->size = 1; + d->first = d->last = 0; + if (QTypeInfo::isComplex) + new (d->data() + d->first) T(val); + else + d->data()[ d->first ] = val; + } +} + +template +bool QCircularBuffer::contains(const T &val) const +{ + if (isLinearised()) { + T *b = d->data() + d->first; + T *i = b + d->size; + while (i != b) + if (*--i == val) + return true; + return false; + } else { + // Check the array from m_first to the end + T *b = d->data() + d->first; + T *i = d->data() + d->capacity; + while (i != b) + if (*--i == val) + return true; + + // Check array from 0 to m_end + b = d->data(); + i = d->data() + d->last + 1; + while (i != b) + if (*--i == val) + return true; + + return false; + } +} + +template +int QCircularBuffer::count(const T &val) const +{ + int c = 0; + if (isLinearised()) { + T *b = d->data() + d->first; + T *i = b + d->size; + while (i != b) + if (*--i == val) + ++c; + } else { + // Check the array from m_first to the end + T *b = d->data() + d->first; + T *i = d->data() + d->capacity; + while (i != b) + if (*--i == val) + ++c; + + // Check array from 0 to m_end + b = d->data(); + i = d->data() + d->last + 1; + while (i != b) + if (*--i == val) + ++c; + } + return c; +} + +template +QCircularBuffer &QCircularBuffer::fill(const T &val, int number) +{ + Q_ASSERT_X(d->capacity >= number, "QCircularBuffer::fill", "size is greater than capacity"); + const T copy(val); + d.detach(); + int oldSize = d->size; + d->size = (number < 0 ? d->size : number); + d->first = (number == 0 ? -1 : 0); + d->last = d->size - 1; + + // Copy item into array size times + if (d->size) { + T *b = d->data(); + T *i = d->data() + d->size; + while (i != b) + *--i = copy; + } + + if (d->size < oldSize) { + // Cleanup old items beyond end of new array + T *b = d->data() + d->size; + T *i = d->data() + oldSize; + while (i-- != b) { + i->~T(); + //TODO: Optimize to a single memset call + memset(i, 0, sizeof(T)); + } + } + + return *this; +} + +template +int QCircularBuffer::indexOf(const T &val, int from) const +{ + Q_ASSERT_X(from < d->size, "QCircularBuffer::indexOf", "from is greater than last valid index"); + if (from < 0) + from = qMax(from + d->size, 0); + else if (from >= d->size) + from = d->size - 1; + for (int i = from; i < d->size; ++i) + if (at(i) == val) + return i; + return -1; +} + +template +void QCircularBuffer::insert(int i, int number, const T &val) +{ + Q_ASSERT_X(i >= 0 && i <= d->size, "QCircularBuffer::insert", "index out of range"); + d.detach(); + int freeCapacity = d->capacity - d->size; + + // Calculate number of elements that will actually be inserted. This + // depends upon where the insertion has been requested and any spare + // capacity left in the buffer. This is because elements at higher + // indices will be pushed to the right and will potentially wrap around + // to overwrite earlier elements. + int numToInsert = qMin(number, i + freeCapacity); + + // Calculate the number of elements at the beginning of the buffer that + // will be overwritten + int numToOverwrite = qMin(i, qMax(0, number - freeCapacity)); + + // Decide which way to shift to minimize the amount of copying required. + if (i < d->size / 2) { + // Inserting in lower half of buffer so we shift earlier items down + + // Shift data at the bottom end down. This may only be a subset if some + // of the early data is to be overwritten. + if (QTypeInfo::isStatic) { + int b = d->first + numToOverwrite; + int e = d->first + i - 1; + for (int j = b; j <= e; ++j) { + int srcIndex = j % d->capacity; + int dstIndex = (j - numToInsert + d->capacity) % d->capacity; + T *src = d->data() + srcIndex; + T *dst = d->data() + dstIndex; + + new (dst) T(*src); + } + } else { + // We have a movable type so a simple memcopy (or maybe two or + // three) will suffice to shift the data at the bottom end + int numToMove = i - numToOverwrite; + if (numToMove > 0) { + int srcBegin = (d->first + numToOverwrite) % d->capacity; + int srcEnd = (d->first + i - 1) % d->capacity; + int dstBegin = (srcBegin - numToInsert + d->capacity) % d->capacity; + int dstEnd = (srcEnd - numToInsert + d->capacity) % d->capacity; + + // Do we have any wrap-around problems to deal with? + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = abs(srcBegin - numToInsert); + memmove(d->data() + d->capacity - wrapCount, d->data() + srcBegin, wrapCount * sizeof(T)); + memmove(d->data(), d->data() + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->capacity - srcBegin; + memmove(d->data() + dstBegin, d->data() + d->capacity - wrapCount, wrapCount * sizeof(T)); + memmove(d->data() + dstBegin + numToInsert, d->data(), (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->capacity - srcBegin; + memmove(d->data() + dstBegin, d->data() + d->capacity - srcWrapCount, srcWrapCount * sizeof(T)); + memmove(d->data() + d->capacity - numToInsert, d->data(), numToInsert * sizeof(T)); + memmove(d->data(), d->data() + numToInsert, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); + } else { + // No wrap around - do a single memmove + memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); + } + } + } + + // Insert the new items + int e = d->first + i; + int b = e - numToInsert; + for (int j = b; j < e; ++j) { + T *p = d->data() + ((j + d->capacity) % d->capacity); + new (p) T(val); + } + + // Adjust the first, last and size indices as needed. + // NB. The last index never changes in this regime. + d->size += qMin(number, freeCapacity); + d->first = (d->first - (numToInsert - numToOverwrite) + d->capacity) % d->capacity; + } else { + // Inserting in upper half of buffer so we shift later items up + + // Shift data at the top end up which may or may not overwrite some + // of the earliest data + if (QTypeInfo::isStatic) { + int b = d->first + d->size - 1; + int e = d->first + i; + for (int j = b; j >= e; j--) { + int srcIndex = j % d->capacity; + int dstIndex = (j + numToInsert) % d->capacity; + T *src = d->data() + srcIndex; + T *dst = d->data() + dstIndex; + + new (dst) T(*src); + } + } else { + // We have a movable type so a simple memcopy (or maybe two or + // three) will suffice to shift the data at the top end + int numToMove = d->size - i; + if (numToMove > 0) { + int srcBegin = (d->first + i) % d->capacity; + int srcEnd = d->last; + int dstBegin = (srcBegin + numToInsert) % d->capacity; + int dstEnd = (srcEnd + numToInsert) % d->capacity; + + // Do we have any wrap-around problems to deal with? + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = srcEnd + numToInsert - d->capacity + 1; + memmove(d->data(), d->data() + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->last + 1; + memmove(d->data() + numToInsert, d->data(), wrapCount * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->last + 1; + memmove(d->data() + numToInsert, d->data(), srcWrapCount * sizeof(T)); + memmove(d->data(), d->data() + d->capacity - numToInsert, numToInsert * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); + } else { + // No wrap around - do a single memmove + memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); + } + } + } + + // Insert the new items + for (int j = d->first + i; j < d->first + i + numToInsert; ++j) { + T *p = d->data() + (j % d->capacity); + new (p) T(val); + } + + // Adjust the first, last and size indices as needed + d->size += qMin(number, freeCapacity); + d->first = (d->first + numToOverwrite) % d->capacity; + d->last = (d->last + numToInsert) % d->capacity; + } +} + +template +int QCircularBuffer::lastIndexOf(const T &val, int from) const +{ + if (from < 0) + from = qMax(from + d->size, 0); + else if (from >= d->size) + from = d->size - 1; + for (int i = from; i >= 0; --i) + if (at(i) == val) + return i; + return -1; +} + +template +void QCircularBuffer::prepend(const T &val) +{ + // If we have no capacity we do nothing + if (!d->capacity) + return; + + d.detach(); + if (d->size == d->capacity) { + // Buffer is full. Overwrite last item and rotate + d->data()[ d->last ] = val; + d->first = (--d->first + d->capacity) % d->capacity; + d->last = (--d->last + d->capacity) % d->capacity; + } else if (d->size != 0) { + // Buffer is partially full. Prepend data to start of array using appropriate method + d->first = (--d->first + d->capacity) % d->capacity; + ++d->size; + if (QTypeInfo::isComplex) + new (d->data() + d->first) T(val); + else + d->data()[ d->first ] = val; + } else { + // Buffer is empty. Prepend data to start of array using appropriate method + d->size = 1; + d->first = d->last = d->capacity - 1; + if (QTypeInfo::isComplex) + new (d->data() + d->first) T(val); + else + d->data()[ d->first ] = val; + } +} + +template +void QCircularBuffer::remove(int i, int number) +{ + Q_ASSERT_X(i >= 0 && number > 0 && i + number <= d->size, "QCircularBuffer::remove", "index out of range"); + d.detach(); + + // HACK (it actually makes sense, but requires some more thinking) + if ( i == 0 && !QTypeInfo::isComplex ) { + d->first = d->wraparound( d->first + number ); + d->size -= number; + return; + } + + // Calculate the number of items that need to be moved downward + int numToMoveDown = d->size - number - i; + int numToMoveUp = i; + + if (numToMoveDown < numToMoveUp) { + // Move higher items down + int numToMove = numToMoveDown; + + if (QTypeInfo::isComplex) { + // Copy items down from higher positions + int b = d->first + i; + int e = b + numToMove; + for (int j = b; j < e ; ++j) { + T *src = d->data() + ((j + number) % d->capacity); + T *dst = d->data() + (j % d->capacity); + new (dst) T(*src); + } + + // Clean up items at end of buffer + for (int j = d->last; j > d->last - number; --j) { + T *p = d->data() + ((j + d->capacity) % d->capacity); + p->~T(); + //TODO: Optimize to a single memset call + memset(p, 0, sizeof(T)); + } + } else { + if (isLinearised()) { + // With a linearised buffer we can do a simple move and removal of items + memmove(d->data() + d->last - numToMove - number + 1, d->data() + d->last - numToMove + 1, numToMove * sizeof(T)); + memset(d->data() + d->last - number + 1, 0, number * sizeof(T)); + } else { + // With a non-linearised buffer we need to be careful of wrapping issues + int srcBegin = (d->last - numToMove + 1 + d->capacity) % d->capacity; + int srcEnd = d->last; + int dstBegin = (d->first + i) % d->capacity; + int dstEnd = (dstBegin + numToMove - 1) % d->capacity; + + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->capacity - srcBegin; + memmove(d->data() + dstBegin, d->data() + srcBegin, wrapCount * sizeof(T)); + memmove(d->data() + dstBegin + wrapCount, d->data(), (numToMove - wrapCount) * sizeof(T)); + } else if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = number - srcBegin; + memmove(d->data() + d->capacity - wrapCount, d->data() + srcBegin, wrapCount * sizeof(T)); + memmove(d->data(), d->data() + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->capacity - srcBegin; + memmove(d->data() + dstBegin, d->data() + srcBegin, srcWrapCount * sizeof(T)); + memmove(d->data() + dstBegin + srcWrapCount, d->data(), number * sizeof(T)); + memmove(d->data(), d->data() + number, (numToMove - srcWrapCount - number) * sizeof(T)); + } else { + // No wrap around, so we can do this in one hit + memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); + } + + // We potentially have a disjoint region that needs zeroing + int zeroStart = (d->last - number + d->capacity + 1) % d->capacity; + int zeroEnd = d->last; + if (zeroEnd < zeroStart) { + // Region to be zeroed wraps. Do it in two steps. + memset(d->data(), 0, (d->last + 1) * sizeof(T)); + memset(d->data() + zeroStart, 0, (number - d->last - 1) * sizeof(T)); + } else { + // Region to be zeroed is contiguous + memset(d->data() + zeroStart, 0, number * sizeof(T)); + } + } + } + + // Adjust the indices + d->size -= number; + d->last = (d->last - number + d->capacity) % d->capacity; + } else { + // Move lower items up + int numToMove = numToMoveUp; + + if (QTypeInfo::isComplex) { + // Copy items up from lower positions + int b = d->first + i - 1; + int e = b - numToMove; + for (int j = b; j > e ; --j) { + T *src = d->data() + ((j + d->capacity) % d->capacity); + T *dst = d->data() + ((j + d->capacity + number) % d->capacity); + new (dst) T(*src); + } + + // Clean up items at start of buffer + for (int j = d->first; j < d->first + number; ++j) { + T *p = d->data() + (j % d->capacity); + p->~T(); + //TODO: Optimize to a single memset call + memset(p, 0, sizeof(T)); + } + } else { + if (isLinearised()) { + // With a linearised buffer we can do a simple move and removal of items + memmove(d->data() + d->first + number, d->data() + d->first, numToMove * sizeof(T)); + memset(d->data() + d->first, 0, number * sizeof(T)); + } else { + // With a non-linearised buffer we need to be careful of wrapping issues + int srcBegin = d->first; + int srcEnd = (srcBegin + numToMove - 1) % d->capacity; + int dstBegin = (srcBegin + number) % d->capacity; + int dstEnd = (dstBegin + numToMove - 1) % d->capacity; + + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = srcEnd + 1; + memmove(d->data() + dstEnd - wrapCount + 1, d->data(), wrapCount * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = dstEnd + 1; + memmove(d->data(), d->data() + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = srcEnd + 1; + memmove(d->data() + dstEnd - srcWrapCount + 1, d->data(), srcWrapCount * sizeof(T)); + memmove(d->data(), d->data() + d->capacity - number, number * sizeof(T)); + memmove(d->data() + dstBegin, d->data() + srcBegin, (numToMove - srcWrapCount - number) * sizeof(T)); + } else { + // No wrap around, so we can do this in one hit + memmove(d->data() + dstBegin, d->data() + srcBegin, numToMove * sizeof(T)); + } + + // We potentially have a disjoint region that needs zeroing + int zeroStart = d->first; + int zeroEnd = (zeroStart + number - 1) % d->capacity; + if (zeroEnd < zeroStart) { + // Region to be zeroed wraps. Do it in two steps. + memset(d->data() + zeroStart, 0, (d->capacity - d->first) * sizeof(T)); + memset(d->data(), 0, (number - d->capacity + d->first) * sizeof(T)); + } else { + // Region to be zeroed is contiguous + memset(d->data() + zeroStart, 0, number * sizeof(T)); + } + } + } + + // Adjust the indices + d->size -= number; + d->first = (d->first + number) % d->capacity; + } +} + +template +void QCircularBuffer::setCapacity(int amount) +{ + if (amount == d->capacity) + return; + + d.detach(); + // Allocate some new raw memory + T *newData = d->allocate(amount); + + // How many items can we copy across? + int newSize = qMin(d->size, amount); + + if (QTypeInfo::isComplex) { + // Copy across the elements from the original array + for (int i = 0; i < newSize; ++i) { + T *src = d->data() + ((d->first + i) % d->capacity); + T *dst = newData + i; + new (dst) T(*src); + } + + // Destroy the original items. + // The type is complex so we manually call the destructor for each item + // since we used the placement new operator to instantiate them + T *b = d->data(); + T *i = b + d->capacity; + while (i-- != b) + i->~T(); + } else { + // Copy across the elements from the original array. The source region + // potentially wraps so we may have to do this in one or two steps + if (isLinearised()) { + memmove(newData, d->data() + d->first, newSize * sizeof(T)); + } else { + int step1Size = qMin(newSize, d->capacity - d->first); + memmove(newData, d->data() + d->first, step1Size * sizeof(T)); + int step2Size = qMax(0, qMin(newSize - d->capacity + d->first, d->last + 1)); + memmove(newData + step1Size, d->data(), step2Size * sizeof(T)); + } + } + + // Initialize any memory outside of the valid buffer (ie the unused items) + memset(newData + newSize, 0, (amount - newSize) * sizeof(T)); + + // Release the raw memory for the old array + d->deallocate(d->data()); + + // Assign the new memory to be our buffer data and fix indices + d->setData(newData); + d->capacity = amount; + d->first = 0; + d->size = newSize; + d->last = d->size - 1; +} + +template +void QCircularBuffer::resize(int newSize) +{ + Q_ASSERT_X(newSize >= 0 && newSize <= d->capacity, "QCircularBuffer::resize", "size out of range"); + d.detach(); + if (newSize < d->size) { + remove(newSize, d->size - newSize); + } else if (newSize > d->size) { + const T t = T(); + insert(d->size, newSize - d->size, t); + } +} + +template +QCircularBuffer &QCircularBuffer::operator+=(const QCircularBuffer &other) +{ + d.detach(); + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QCircularBuffer &QCircularBuffer::operator+=(const QVector &other) +{ + d.detach(); + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QCircularBuffer &QCircularBuffer::operator+=(const QList &other) +{ + d.detach(); + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QList QCircularBuffer::toList() const +{ + QList list; + list.reserve(size()); + for (int i = 0; i < size(); ++i) + list.append(at(i)); + return list; +} + +template +QVector QCircularBuffer::toVector() const +{ + QVector vector; + vector.reserve(size()); + for (int i = 0; i < size(); ++i) + vector.append(at(i)); + return vector; +} + +template +QCircularBuffer operator+(const QCircularBuffer &lhs, const QCircularBuffer &rhs) +{ + QCircularBuffer circ(lhs.size() + rhs.size()); + for (int i = 0; i < lhs.size(); ++i) + circ.append(lhs.at(i)); + for (int i = 0; i < rhs.size(); ++i) + circ.append(rhs.at(i)); + return circ; +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(CircularBuffer) +Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(CircularBuffer) + +} //Qt3D + +QT_END_NAMESPACE + +#endif // QT3D_QCIRCULARBUFFER_H diff --git a/src/core/resources/resources.pri b/src/core/resources/resources.pri index d1befe69f..fc9e289e7 100644 --- a/src/core/resources/resources.pri +++ b/src/core/resources/resources.pri @@ -2,8 +2,8 @@ HEADERS += \ $$PWD/qhandle.h \ $$PWD/qhandlemanager.h \ $$PWD/qresourcemanager_p.h \ - $$PWD/qcircularbuffer.h \ - $$PWD/qboundedcircularbuffer.h \ + $$PWD/qcircularbuffer_p.h \ + $$PWD/qboundedcircularbuffer_p.h \ $$PWD/qframeallocator.h \ $$PWD/qframeallocator_p.h diff --git a/src/render/backend/renderqueues_p.h b/src/render/backend/renderqueues_p.h index 63fd0d7e1..0416d5caa 100644 --- a/src/render/backend/renderqueues_p.h +++ b/src/render/backend/renderqueues_p.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/tests/auto/core/qboundedcircularbuffer/qboundedcircularbuffer.pro b/tests/auto/core/qboundedcircularbuffer/qboundedcircularbuffer.pro index d67dab8ee..80ae30b67 100644 --- a/tests/auto/core/qboundedcircularbuffer/qboundedcircularbuffer.pro +++ b/tests/auto/core/qboundedcircularbuffer/qboundedcircularbuffer.pro @@ -1,7 +1,7 @@ TARGET = tst_qboundedcircularbuffer CONFIG += testcase TEMPLATE = app -QT += testlib 3dcore +QT += testlib 3dcore 3dcore-private DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/core/qboundedcircularbuffer/tst_qboundedcircularbuffer.cpp b/tests/auto/core/qboundedcircularbuffer/tst_qboundedcircularbuffer.cpp index 2b1e7ccd1..6c76c4de5 100644 --- a/tests/auto/core/qboundedcircularbuffer/tst_qboundedcircularbuffer.cpp +++ b/tests/auto/core/qboundedcircularbuffer/tst_qboundedcircularbuffer.cpp @@ -42,7 +42,7 @@ #include #include -#include +#include using namespace Qt3D; diff --git a/tests/auto/core/qcircularbuffer/qcircularbuffer.pro b/tests/auto/core/qcircularbuffer/qcircularbuffer.pro index 29ca2eca8..24fc35ff3 100644 --- a/tests/auto/core/qcircularbuffer/qcircularbuffer.pro +++ b/tests/auto/core/qcircularbuffer/qcircularbuffer.pro @@ -1,7 +1,7 @@ TARGET = tst_qcircularbuffer CONFIG += testcase TEMPLATE = app -QT += testlib 3dcore +QT += testlib 3dcore 3dcore-private DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp index fe6e4b356..f2ae5bde6 100644 --- a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp +++ b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp @@ -42,7 +42,7 @@ #include #include -#include +#include using namespace Qt3D; diff --git a/tests/benchmarks/core/qcircularbuffer/qcircularbuffer.pro b/tests/benchmarks/core/qcircularbuffer/qcircularbuffer.pro index 1928f5829..4843a99a6 100644 --- a/tests/benchmarks/core/qcircularbuffer/qcircularbuffer.pro +++ b/tests/benchmarks/core/qcircularbuffer/qcircularbuffer.pro @@ -1,7 +1,7 @@ TARGET = tst_bench_qcircularbuffer CONFIG += release TEMPLATE = app -QT += testlib 3dcore +QT += testlib 3dcore 3dcore-private DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/benchmarks/core/qcircularbuffer/tst_bench_qcircularbuffer.cpp b/tests/benchmarks/core/qcircularbuffer/tst_bench_qcircularbuffer.cpp index 6b408bc47..668cde89a 100644 --- a/tests/benchmarks/core/qcircularbuffer/tst_bench_qcircularbuffer.cpp +++ b/tests/benchmarks/core/qcircularbuffer/tst_bench_qcircularbuffer.cpp @@ -42,7 +42,7 @@ #include #include -#include +#include using namespace Qt3D; -- cgit v1.2.3