This commit is contained in:
IlushaShurupov 2023-07-01 15:31:47 +03:00
parent a7d1ab44cc
commit ec2a71ccdb
5 changed files with 224 additions and 7 deletions

View file

@ -0,0 +1,179 @@
#pragma once
#include "ContainersCommon.hpp"
namespace tp {
template<ualni tScale = 2>
inline ualni BufferResizeScaling(ualni const size) { return size * tScale; }
template<ualni tScale = 2>
inline ualni BufferResizeScalingDown(ualni const size) { return size / tScale; }
template<ualni tAddition = 1>
inline ualni BufferResizeAddition(ualni const size) { return size + tAddition; }
template<ualni tAddition = 1>
inline ualni BufferResizeAdditionDown(ualni const size) { return size - tAddition; }
template<typename tType, ualni tSize>
class ConstSizeBuffer {
SelCopyArg<tType> 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<tType> 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;
}
};
}

View file

@ -0,0 +1,37 @@
#include "Tests.hpp"
#include "Buffer.hpp"
#include "Testing.hpp"
#include <iostream>
using namespace tp;
const ualni size = 1000;
TEST_DEF_STATIC(Simple1) {
Buffer<TestClass> 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<TestClass> 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();
}

View file

@ -36,6 +36,7 @@ int main() {
testList();
testMap();
testAvl();
testBuffer();
testModule.deinitialize();
}

View file

@ -70,4 +70,5 @@ public:
void testList();
void testMap();
void testAvl();
void testAvl();
void testBuffer();