diff --git a/Containers/public/Buffer.hpp b/Containers/public/Buffer.hpp new file mode 100644 index 0000000..4c63166 --- /dev/null +++ b/Containers/public/Buffer.hpp @@ -0,0 +1,179 @@ + +#pragma once + +#include "ContainersCommon.hpp" + +namespace tp { + + template + inline ualni BufferResizeScaling(ualni const size) { return size * tScale; } + + template + inline ualni BufferResizeScalingDown(ualni const size) { return size / tScale; } + + template + inline ualni BufferResizeAddition(ualni const size) { return size + tAddition; } + + template + inline ualni BufferResizeAdditionDown(ualni const size) { return size - tAddition; } + + + template + class ConstSizeBuffer { + SelCopyArg Arg; + + private: + tType mBuff[tSize]; + + public: + ConstSizeBuffer() = default; + + public: + [[nodiscard]] ualni size() const { return tSize; } + + tType& first() { + return *mBuff; + } + + const tType& first() const { + return *mBuff; + } + + tType& last() { + return mBuff[tSize - 1]; + } + + const tType& last() const { + return mBuff[tSize - 1]; + } + + tType& operator[](ualni aIdx) { + DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize) + return mBuff[aIdx]; + } + + const tType& operator[](ualni aIdx) const { + DEBUG_ASSERT(aIdx >= 0 && aIdx < tSize) + return mBuff[aIdx]; + } + }; + + template< + typename tType, + class tAllocator = DefaultAllocator, + ualni (tResizePolicy)(ualni) = BufferResizeScaling<2>, + ualni (tResizePolicyDown)(ualni) = BufferResizeScalingDown<2>, + ualni tMinSize = 4 + > + class Buffer { + typedef SelCopyArg Arg; + + private: + tType* mBuff; + tAllocator mAllocator; + ualni mSize; + ualni mLoad; + + public: + Buffer() : mSize(tMinSize), mLoad(0) { + mBuff = (tType*) mAllocator.allocate(sizeof(tType) * tMinSize); + } + + explicit Buffer(ualni size) : mSize(size), mLoad(0) { + mBuff = (tType*) mAllocator.allocate(sizeof(tType) * tMinSize); + } + + Buffer(const Buffer& in) : mSize(in.mSize), mLoad(in.mLoad) { + mBuff = (tType*) mAllocator.allocate(sizeof(tType) * mSize); + for (ualni i = 0; i < mLoad; i++) new (&mBuff[i]) tType(in.mBuff[i]); + } + + Buffer& operator=(const Buffer& in) { + if (this == &in) return *this; + ~Buffer(); + new (this) Buffer(in); + return *this; + } + + ~Buffer() { + for (ualni i = 0; i < mLoad; i++) mBuff[i].~tType(); + mAllocator.deallocate(mBuff); + } + + public: + [[nodiscard]] ualni size() const { + return mLoad; + } + + [[nodiscard]] ualni getBuffSize() const { + return mSize; + } + + tType& first() { + DEBUG_ASSERT(mLoad) + return *mBuff; + } + + const tType& first() const { + DEBUG_ASSERT(mLoad) + return *mBuff; + } + + tType& last() { + DEBUG_ASSERT(mLoad) + return mBuff[mLoad - 1]; + } + + const tType& last() const { + DEBUG_ASSERT(mLoad) + return mBuff[mLoad - 1]; + } + + tType& operator[](ualni idx) { + DEBUG_ASSERT(idx < mLoad && idx >= 0) + return mBuff[idx]; + } + + const tType& operator[](ualni idx) const { + DEBUG_ASSERT(idx < mLoad && idx >= 0) + return mBuff[idx]; + } + + public: + bool operator==(const Buffer& in) const { + if (this == &in) return true; + if (mLoad != in.mLoad) return false; + for (ualni i = 0; i < mLoad; i++) { + if (mBuff[i] != in.mBuff[i]) return false; + } + return true; + } + + public: + void append(Arg data) { + if (mLoad == mSize) resizeBuffer(tResizePolicy(mSize)); + new (&mBuff[mLoad]) tType(data); + mLoad++; + } + + void pop() { + DEBUG_ASSERT(mLoad) + mBuff[mLoad].~tType(); + mLoad--; + ualni prevSize = tResizePolicyDown(mSize); + DEBUG_ASSERT(prevSize < mSize) + if (prevSize > mLoad) resizeBuffer(prevSize); + } + + private: + void resizeBuffer(ualni newSize) { + DEBUG_ASSERT(newSize >= mLoad) + auto const oldBuff = mBuff; + mBuff = (tType*) mAllocator.allocate(sizeof(tType) * newSize); + for (ualni i = 0; i < mLoad; i++) new (&mBuff[i]) tType(oldBuff[i]); + for (ualni i = 0; i < mLoad; i++) oldBuff[i].~tType(); + mAllocator.deallocate(oldBuff); + mSize = newSize; + } + }; +} \ No newline at end of file diff --git a/Containers/tests/BufferTest.cpp b/Containers/tests/BufferTest.cpp new file mode 100644 index 0000000..bcca3a8 --- /dev/null +++ b/Containers/tests/BufferTest.cpp @@ -0,0 +1,37 @@ + +#include "Tests.hpp" + +#include "Buffer.hpp" + +#include "Testing.hpp" + +#include + +using namespace tp; + +const ualni size = 1000; + +TEST_DEF_STATIC(Simple1) { + Buffer buff; + TEST(buff.size() == 0); + for (auto i : Range(size * 10)) { + buff.append(TestClass(i)); + } + TEST(buff.size() == size * 10); + while (buff.size()) buff.pop(); + TEST(buff.size() == 0); +} + +TEST_DEF_STATIC(Simple2) { + Buffer buff(size); + TEST(buff.size() == 0); + for (auto i : Range(size * 10)) buff.append(TestClass(i)); + TEST(buff.size() == size * 10); + while (buff.size()) buff.pop(); + TEST(buff.size() == 0); +} + +TEST_DEF(Buffer) { + testSimple1(); + testSimple2(); +} \ No newline at end of file diff --git a/Containers/tests/Tests.cpp b/Containers/tests/Tests.cpp index eee13e3..0cd960f 100644 --- a/Containers/tests/Tests.cpp +++ b/Containers/tests/Tests.cpp @@ -36,6 +36,7 @@ int main() { testList(); testMap(); testAvl(); + testBuffer(); testModule.deinitialize(); } diff --git a/Containers/tests/Tests.hpp b/Containers/tests/Tests.hpp index 63f3fe3..98d2c71 100644 --- a/Containers/tests/Tests.hpp +++ b/Containers/tests/Tests.hpp @@ -70,4 +70,5 @@ public: void testList(); void testMap(); -void testAvl(); \ No newline at end of file +void testAvl(); +void testBuffer(); \ No newline at end of file diff --git a/TODO b/TODO index a3f28d1..1573574 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,9 @@ Containers: - Avl read write ! - Add check copy times ! - Addbuff - Vector - Vector 2d - AVL dont copy data just swap ! + Read write + Buffer 2d ! + Add check copy times + AVL dont copy data just swap + More tests on buff and avl Strings: Implement