From 2c92e07f337e42cf58970443f9de678f85a9b2a4 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Thu, 19 Oct 2023 22:50:07 -0700 Subject: The great renaming: switch to "module style" --- source/10-common/RingBuffer.hpp | 191 ---------------------------------------- 1 file changed, 191 deletions(-) delete mode 100644 source/10-common/RingBuffer.hpp (limited to 'source/10-common/RingBuffer.hpp') diff --git a/source/10-common/RingBuffer.hpp b/source/10-common/RingBuffer.hpp deleted file mode 100644 index 4eaa007..0000000 --- a/source/10-common/RingBuffer.hpp +++ /dev/null @@ -1,191 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class RingBufferSentinel {}; - -template -class RingBufferIterator { -public: - using difference_type = TContainer::difference_type; - using value_type = TContainer::value_type; // C++20 relaxed usage requirements of `typename`, now locations where a type is required (like here in a using statement) it's no longer mandatory - using pointer = value_type*; - using reference = value_type&; - using iterator_category = std::random_access_iterator_tag; - -public: - TContainer* container; - TContainer::size_type curr; // C++20 relaxed usage requirements of `typename`, same here - bool needsWrapAround; - bool hasWrappedAround = false; - -public: - reference operator*() const { - return container->mRing[curr]; - } - - RingBufferIterator& operator++() { - assert(*this != RingBufferSentinel{}); - ++curr; - if (needsWrapAround && curr == container->mCapacity) { - hasWrappedAround = true; - curr = 0; - } - return *this; - } - - bool operator==(const RingBufferIterator& that) const { - assert(this->container == that.container); - return this->curr == that.curr; - } - - bool operator==(const RingBufferSentinel&) const { - return curr == container->mTailIdx && (!needsWrapAround || hasWrappedAround); - } -}; - -template -class RingBuffer { -public: - using value_type = T; - using reference = T&; - using const_reference = const T&; - friend class RingBufferIterator; - using iterator = RingBufferIterator; - friend class RingBufferIterator; - using const_iterator = RingBufferIterator; - using sentinel = RingBufferSentinel; // Not a part of C++'s Container named requirements, added here for convenience - using difference_type = ptrdiff_t; - using size_type = size_t; - -private: - T* mRing = nullptr; - size_type mHeadIdx = 0; - size_type mTailIdx = 0; - size_type mCapacity = 0; - size_type mSize = 0; - -public: - RingBuffer() noexcept = default; - - ~RingBuffer() noexcept { - delete[] mRing; - } - - RingBuffer(const RingBuffer&) noexcept = delete; - RingBuffer& operator=(const RingBuffer&) noexcept = delete; - - RingBuffer(RingBuffer&& that) noexcept - : mRing{ that.mRing } - , mHeadIdx{ that.mHeadIdx } - , mTailIdx{ that.mTailIdx } - , mCapacity{ that.mCapacity } - , mSize{ that.mSize } { - that.mRing = nullptr; - } - - RingBuffer& operator=(RingBuffer&& that) noexcept { - if (this != &that) { - auto oldThisRing = this->mRing; - this->mRing = that.mRing; - that.mRing = nullptr; - delete oldThisRing; - - this->mHeadIdx = that.mHeadIdx; - this->mTailIdx = that.mTailIdx; - this->mCapacity = that.mCapacity; - this->mSize = that.mSize; - } - - return *this; - } - - [[nodiscard]] iterator begin() { - return { - .container = this, - .curr = mHeadIdx, - .needsWrapAround = mHeadIdx >= mTailIdx, - }; - } - - [[nodiscard]] const_iterator begin() const { return cbegin(); } - - // Same type for both const this and non-const `this` - [[nodiscard]] sentinel end() const { return sentinel{}; } - - [[nodiscard]] const_iterator cbegin() const { - return { - .container = this, - .curr = mHeadIdx, - .needsWrapAround = mHeadIdx >= mTailIdx, - }; - } - - [[nodiscard]] sentinel cend() const { return sentinel{}; } - - [[nodiscard]] T& operator[](size_type i) { return const_cast(const_cast(*this)[i]); } - [[nodiscard]] const T& operator[](size_type i) const { - assert(mRing != nullptr); - size_type idx = mHeadIdx + i; - if (idx >= mCapacity) { - idx -= mCapacity; - } - return mRing[idx]; - } - - void push_back(T t) { - assert(mRing != nullptr); - if (mTailIdx == mCapacity) { - // Ring buffer is filled to the right, warp around to the beginning - // mHeadIdx > 0 must be true, since we checked that as condition (1) above - mRing[0] = std::move(t); - mTailIdx = 1; - } else { - mRing[mTailIdx] = std::move(t); - mTailIdx += 1; - } - - // Push mHeadIdx backwards if overwrote element in a filled buffer - bool bufferFilled = mSize == mCapacity; - if (bufferFilled && mTailIdx > mHeadIdx) { - mHeadIdx += 1; - if (mHeadIdx == mCapacity) { - mHeadIdx = 0; - } - } - - if (!bufferFilled) { - ++mSize; - } - } - - [[nodiscard]] size_type capacity() const { - return mCapacity; - } - - [[nodiscard]] size_type size() const { - return mSize; - } - - [[nodiscard]] T* GetBuffer() const { return mRing; } - [[nodiscard]] size_type GetHeadIdx() const { return mHeadIdx; } - [[nodiscard]] size_type GetTailIdx() const { return mTailIdx; } - - void resize(size_type newCapacity) { - auto size = this->size(); - - auto oldRing = mRing; - auto newRing = mRing = new T[newCapacity]; - if (oldRing != nullptr) { - std::rotate_copy(oldRing, oldRing + mHeadIdx, oldRing + mCapacity, newRing); - delete[] oldRing; - } - - mCapacity = newCapacity; - mHeadIdx = 0; - mTailIdx = size; - } -}; -- cgit v1.2.3-70-g09d2