Containers New Features

This commit is contained in:
IlushaShurupov 2023-07-07 00:11:04 +03:00
parent ec2a71ccdb
commit 72a25600a2
10 changed files with 1192 additions and 0 deletions

View file

@ -0,0 +1,77 @@
#pragma once
#include "common.h"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type, halni Step, halni Start=0, typename Index = halni, typename tAllocator>
class AddBuffer {
tAllocator mAlloc;
Type* mBuff = NULL;
Index mLoadIdx = 0;
Index mLength = 0;
public:
AddBuffer() {
MODULE_SANITY_CHECK(gModuleContainer);
mLength = Step + Start;
mBuff = new(mAlloc) [mLength];
}
void extend(Index aInputLen) {
auto old = mBuff;
auto old_len = mLength;
mLength += (aInputLen / Step) + Step;
mBuff = new(mAlloc) [mLength];
for (auto i = 0; i < old_len; i++) {
mBuff[i] = old[i];
}
delete[] (mAlloc, old);
}
void append(const Type* input, Index input_len) {
if (mLoadIdx >= mLength) {
extend(input_len);
}
for (auto i = 0; i < input_len; i++) {
mBuff[mLoadIdx + i] = input[i];
}
mLoadIdx += input_len;
}
Type& operator[] (Index idx) {
assert(idx >= 0 && idx <= mLoadIdx && "out of range");
return mBuff[idx];
}
const Type* buff() const {
return mBuff;
}
const Type& operator[] (Index idx) const {
assert(idx >= 0 && idx <= mLoadIdx && "out of range");
return mBuff[idx];
}
Index len() {
return mLoadIdx;
}
Index lenReserved() {
return mLength;
}
~AddBuffer() {
delete[] (mAlloc, mBuff);
}
};
};

View file

@ -0,0 +1,257 @@
#pragma once
#include "Cassert.hpp"
#include "Sort.h"
#include "Filesystem.hpp"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type>
class ArrayIterator;
template <typename Type, typename tAllocator>
class Array {
void allocate(alni p_bufflen) {
mLength = p_bufflen;
mBuff = new(mAlloc.Allocate(mLength * sizeof(Type))) Type[mLength]();
}
void free() {
if (mBuff) {
mLength = 0;
delete[] (mAlloc, mBuff);
mBuff = NULL;
}
}
tAllocator mAlloc;
Type* mBuff;
alni mLength;
public:
Array() {
MODULE_SANITY_CHECK(gModuleContainer);
mLength = 0;
mBuff = nullptr;
}
Array(tp::init_list<Type> list) {
mLength = 0;
mBuff = nullptr;
this->operator=(list);
}
Array(alni p_length) {
mLength = p_length;
mBuff = nullptr;
reserve(mLength);
}
alni length() const {
return mLength;
}
Type* buff() const {
return mBuff;
}
void reserve(alni p_bufflen) {
free();
allocate(alni p_bufflen);
}
void insert(Type& p_block, alni idx) {
Type* current = mBuff;
allocate(mLength + 1);
for (alni befor = 0; befor < idx; befor++) {
mBuff[befor] = current[befor];
}
for (alni after = idx; after < mLength - 1; after++) {
mBuff[after + 1] = current[after];
}
mBuff[idx] = p_block;
if (current) {
delete[] (mAlloc, current);
}
}
void remove(alni p_idx) {
Type* current = mBuff;
allocate(mLength - 1);
for (alni befor = 0; befor < p_idx; befor++) {
mBuff[befor] = current[befor];
}
for (alni after = p_idx + 1; after < mLength + 1; after++) {
mBuff[after - 1] = current[after];
}
delete[] (mAlloc, current);
}
void removeVal(Type val) {
for (int i = 0; i < mLength; i++) {
if (mBuff[i] == val) {
remove(i);
}
}
}
Type& last() {
return mBuff[mLength - 1];
}
void extend(tp::ualni new_len) {
if ((tp::ualni)mLength >= new_len) {
return;
}
if (!mBuff) {
reserve(new_len);
}
auto old_buff = mBuff;
auto old_len = (tp::ualni) mLength;
mBuff = new Type[new_len]();
mLength = new_len;
for (tp::ualni idx = 0; idx < old_len; idx++) {
mBuff[idx] = old_buff[idx];
}
delete[] (mAlloc, old_buff);
}
void operator=(const Array& array) {
reserve(array.mLength);
for (int i = 0; i < array.mLength; i++) {
mBuff[i] = array.mBuff[i];
}
}
void operator+=(const Array& array) {
if (!mBuff) {
return operator=(array);
}
alni new_len = array.mLength + mLength;
Type* newbuff = new Type[new_len]();
for (halni i = 0; i < mLength; i++) {
newbuff[i] = mBuff[i];
}
for (halni i = 0; i < array.mLength; i++) {
newbuff[mLength + i] = array.mBuff[i];
}
delete[] (mAlloc, mBuff);
mBuff = newbuff;
mLength = new_len;
}
void operator=(tp::init_list<Type> list) {
reserve(list.size());
uhalni idx = 0;
for (Type item : list) {
mBuff[idx] = item;
idx++;
}
}
inline Type& operator[](alni idx) {
assert(idx >= 0 && idx < mLength);
return mBuff[idx];
}
inline const Type& operator[](alni idx) const {
assert(idx >= 0 && idx < mLength);
return mBuff[idx];
}
void pushBack(Type block) {
insert(block, mLength);
}
Array(const Array& array) {
allocate(array.mLength);
for (int i = 0; i < array.mLength; i++) {
mBuff[i] = array.mBuff[i];
}
}
ArrayIterator<Type> begin() { return ArrayIterator<Type>(this); }
alni end() { return mLength; }
alni saveSize() {
return mLength * sizeof(Type) + sizeof(mLength);
}
void save(File& file) {
file.write(&mLength);
file.write_bytes((int1*) mBuff, mLength * sizeof(Type));
}
void load(File& file) {
file.read(&mLength);
reserve(mLength);
file.read_bytes((int1*) mBuff, mLength * sizeof(Type));
}
~Array() {
free();
}
alni sizeAllocatedMem() {
alni out = 0;
out += sizeof(alni);
out += sizeof(Type*);
if (mBuff) {
out += sizeof(Type) * mLength;
}
return out;
}
template <typename SortPolicy = SortMerge>
void sort(bool (*grater)(Type const& item1, Type const& item2)) {
SortPolicy sorter;
sorter.sort(mBuff, (int) mLength, grater);
}
alni sizeUsedMem() {
return sizeAllocatedMem();
}
};
template <typename Type>
class ArrayIterator {
alni mIdx = 0;
Array<Type>* mArrayPtr;
public:
ArrayIterator(Array<Type>* array) : mArrayPtr(array) {}
Type& data() const { return (*mArrayPtr)[mIdx]; }
ualni idx() const { return mIdx; }
operator alni() { return mIdx; }
Type* operator->() { return &(*mArrayPtr)[mIdx]; }
const ArrayIterator& operator*() { return *this; }
inline void operator++() { mIdx++; }
bool operator==(alni p_idx) { return mIdx == p_idx; }
bool operator!=(alni p_idx) { return mIdx != p_idx; }
bool operator>(alni p_idx) { return mIdx > p_idx; }
bool operator<(alni p_idx) { return mIdx < p_idx; }
bool operator>=(alni p_idx) { return mIdx >= p_idx; }
bool operator<=(alni p_idx) { return mIdx <= p_idx; }
};
};

View file

@ -0,0 +1,123 @@
#pragma once
#include "allocators.h"
#include "vec.h"
#include "rect.h"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type>
class Array2D {
vec2<uhalni> mSize;
Type* mBuff = nullptr;
public:
Array2D() {
MODULE_SANITY_CHECK(gModuleContainer);
}
Array2D(vec2<uhalni> size) { reserve(size); }
vec2<uhalni> size() const { return mSize; }
Type* buff() const { return mBuff; }
inline Type& get(uhalni x, uhalni y) {
assert(x < mSize.x && y < mSize.y && x >= 0 && y >= 0);
return *(mBuff + mSize.x * y + x);
}
inline void set(uhalni x, uhalni y, Type value) {
assert(x < mSize.x && y < mSize.y && x >= 0 && y >= 0);
*(mBuff + mSize.x * y + x) = value;
}
void reserve(vec2<uhalni> newsize) {
if (mSize.x != newsize.x || mSize.y != newsize.y) {
if (mBuff)
delete mBuff;
mBuff = new Type[newsize.x * newsize.y];
mSize = newsize;
}
}
void project(Array2D<Type>* in, vec2<uhalni> pos) {
recti unclamped_fromrect(pos, in->mBuff);
recti fromrect;
recti torect(vec2<uhalni>(), mBuff);
torect.intersection(unclamped_fromrect, fromrect);
vec2<uhalni> clampsize(unclamped_fromrect.size - fromrect.size);
vec2<bool> mns(unclamped_fromrect.pos.x < 0, unclamped_fromrect.pos.y < 0);
if (mns.x && mns.y) {
for (int i = 0; i < fromrect.size.x; i++) {
for (int j = 0; j < fromrect.size.y; j++) {
int to = mSize.x * (fromrect.pos.y + j) + (fromrect.pos.x + i);
mBuff[to] = in->mBuff[in->mSize.x * (j + clampsize.y) + (i + clampsize.x)];
}
}
} else if (!mns.x && !mns.y) {
for (int i = 0; i < fromrect.size.x; i++) {
for (int j = 0; j < fromrect.size.y; j++) {
int to = mSize.x * (fromrect.pos.y + j) + (fromrect.pos.x + i);
mBuff[to] = in->mBuff[in->mSize.x * j + i];
}
}
} else if (!mns.x && mns.y) {
for (int i = 0; i < fromrect.size.x; i++) {
for (int j = 0; j < fromrect.size.y; j++) {
int to = mSize.x * (fromrect.pos.y + j) + (fromrect.pos.x + i);
mBuff[to] = in->mBuff[in->mSize.x * (j + clampsize.y) + i];
}
}
} else {
for (int i = 0; i < fromrect.size.x; i++) {
for (int j = 0; j < fromrect.size.y; j++) {
int to = mSize.x * (fromrect.pos.y + j) + (fromrect.pos.x + i);
mBuff[to] = in->mBuff[in->mSize.x * j + (i + clampsize.x)];
}
}
}
}
void assign(Type value) {
uhalni len = mSize.x * mSize.y;
for (uhalni i = 0; i < len; i++) {
mBuff[i] = value;
}
}
alni sizeAllocatedMem() {
alni out = 0;
out += mSize.sizeAllocatedMem();
out += sizeof(Type*);
if (mBuff) {
out += sizeof(Type) * mSize.x * mSize.y;
}
return out;
}
alni sizeUsedMem() {
alni out = 0;
out += mSize.sizeAllocatedMem();
out += sizeof(Type*);
if (mBuff) {
out += sizeof(Type) * mSize.x * mSize.y;
}
return out;
}
~Array2D() {
delete mBuff;
}
};
};

View file

@ -0,0 +1,115 @@
#pragma once
#include "List.h"
namespace tp {
// TODO : insert and remove by range
// IN DEVELOPMENT
template <typename Type>
class PersistentList {
public:
struct UndoNode {
ListNode<Type>* mNode = NULL;
enum { NONE, ADD, REMOVE, UNDO_MARK } mType = NONE;
};
private:
List<Type> mList;
List<UndoNode> mHystory;
ListNode<UndoNode>* mCurrentState = NULL;
void clearFuture() {
auto iter = mHystory.last();
while (iter && iter != mCurrentState) {
auto del = iter;
iter = iter->prev;
mHystory.detach(del);
mHystory.deleteNode(del);
}
}
public:
PersistentList() {
pushUndoPoint();
}
void pushUndoPoint() {
mHystory.pushBack(UndoNode{ 0, UndoNode::UNDO_MARK });
mCurrentState = mHystory.last();
}
const List<Type>& list() const {
return mList;
}
const List<UndoNode>& hystory() const {
return mHystory;
}
// returns new node inserted after aNode
ListNode<Type>* insertAfter(ListNode<Type>* aNode) {
clearFuture();
auto node = mList.newNode();
mList.attach(node, aNode);
mHystory.pushBack(UndoNode{ node, UndoNode::ADD });
return node;
}
void remove(ListNode<Type>* aNode) {
clearFuture();
mHystory.pushBack(UndoNode{ aNode, UndoNode::REMOVE });
mList.detach(aNode);
}
void undo() {
if (!mCurrentState->prev) {
return;
}
while (mCurrentState->data.mType != UndoNode::UNDO_MARK) {
if (mCurrentState->data.mType != UndoNode::ADD) {
mList.detach(mCurrentState->data.mNode);
}
else {
mList.attach(mCurrentState->data.mNode, mCurrentState->data.mNode->prev);
}
mCurrentState = mCurrentState->prev;
}
}
void redo() {
if (!mCurrentState->next) {
return;
}
while (mCurrentState->data.mType != UndoNode::UNDO_MARK) {
if (mCurrentState->data.mType != UndoNode::ADD) {
mList.attach(mCurrentState->data.mNode, mCurrentState->data.mNode->prev);
}
else {
mList.detach(mCurrentState->data.mNode);
}
mCurrentState = mCurrentState->next;
}
}
void clearHystory() {
// TODO : mem leaks
//for (auto node : mHystory) {
//delete node->data();
//}
//mHystory.free();
}
~PersistentList() {
}
};
};

View file

@ -0,0 +1,112 @@
#pragma once
#include "allocators.h"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type>
class Queue {
public:
template <typename NodeType>
class Node {
public:
Node<NodeType>* below;
NodeType data;
public:
Node(NodeType data, Node<NodeType>* below) {
this->below = below;
this->data = data;
}
};
template <typename IterType>
struct Iterator {
Node<IterType>* mIter;
IterType& operator->() { return mIter->data; }
IterType& data() { return mIter->data; }
const Iterator& operator*() { return *this; }
inline void operator++() { mIter = mIter->below; }
bool operator==(const Iterator& end) { return mIter == NULL; }
bool operator!=(const Iterator& end) { return mIter != NULL; }
};
alni length;
Node<Type>* top;
Node<Type>* bottom;
Queue() {
MODULE_SANITY_CHECK(gModuleContainer);
length = 0;
top = nullptr;
bottom = nullptr;
}
~Queue() {
free();
}
// pushes the node on the bottom of the stack
void push(Type data) {
Node<Type>* new_node = new Node<Type>(data, NULL);
if (bottom) {
bottom->below = new_node;
} else {
top = new_node;
}
bottom = new_node;
length++;
}
// pops the top node of the stack
void pop() {
assert(top);
Node<Type>* del = top;
top = top->below;
delete del;
length--;
if (!top) {
bottom = NULL;
}
}
// deletes all nodes
void free() {
Node<Type>* del = top;
for (alni i = 0; i < length; i++) {
Node<Type>* below = del->below;
delete del;
del = below;
}
length = 0;
top = NULL;
bottom = NULL;
}
alni sizeAllocatedMem() {
alni out = 0;
out += sizeof(Node<Type>*) * 2;
out += sizeof(alni);
out += sizeof(Node<Type>) * length;
return out;
}
alni sizeUsedMem() {
return sizeAllocatedMem();
}
Iterator<Type> begin() const {
return {top};
}
Iterator<Type> end() const {
return {};
}
};
};

View file

@ -0,0 +1,158 @@
#pragma once
#include "allocators.h"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type, typename Allocator = tp::PickAlloc>
class Stack {
public:
template <typename NodeType>
class Node {
public:
Node<NodeType>* below;
NodeType data;
public:
Node(NodeType data, Node<NodeType>* below) {
this->below = below;
this->data = data;
}
};
template <typename IterType>
struct Iterator {
Node<IterType>* mIter;
IterType& operator->() { return mIter->data; }
const Iterator& operator*() { return *this; }
inline void operator++() { mIter = mIter->below; }
bool operator==(alni end) { return mIter == NULL; }
};
alni length;
Node<Type>* top;
Allocator alloc;
Stack() {
MODULE_SANITY_CHECK(gModuleContainer);
length = 0;
top = nullptr;
}
~Stack() {
free();
}
// pushes the node on top of the stack
void push(Type data) {
Node<Type>* NewNode = new (alloc) Node<Type>(data, top);
top = NewNode;
length++;
}
// pops the top node of the stack
void pop() {
assert(top);
Node<Type>* del = top;
top = top->below;
delete del;
length--;
}
Node<Type>* last() {
return top;
}
// deletes all nodes
void free() {
Node<Type>* del = top;
for (alni i = 0; i < length; i++) {
Node<Type>* below = del->below;
delete del;
del = below;
}
length = 0;
top = NULL;
}
alni sizeAllocatedMem() {
alni out = 0;
out += sizeof(Node<Type>*);
out += sizeof(alni);
out += sizeof(Node<Type>) * length;
return out;
}
alni sizeUsedMem() {
return sizeAllocatedMem();
}
Iterator<Type> begin() const {
return {top};
}
alni end() const {
return NULL;
}
};
template <typename Type, const halni tSize, typename Index = halni>
class ConstSizeStack {
Type mBuff[tSize];
Index mLoadIdx = 0;
public:
ConstSizeStack() {}
Index loadLen() const {
return mLoadIdx;
}
void push(const Type& in) {
assert(mLoadIdx >= 0 && mLoadIdx < tSize && "out of range");
mBuff[mLoadIdx] = in;
mLoadIdx++;
}
void pop() {
mLoadIdx--;
}
Type& last() {
assert(mLoadIdx >= 0 && mLoadIdx < tSize && "out of range");
return mBuff[mLoadIdx - 1];
}
const Type& last() const {
assert(mLoadIdx >= 0 && mLoadIdx < tSize && "out of range");
return mBuff[mLoadIdx - 1];
}
Type* buff() {
return mBuff;
}
Type& operator[] (Index idx) {
assert(idx >= 0 && idx < tSize && "out of range");
return mBuff[idx];
}
const Type* buff() const {
return mBuff;
}
const Type& operator[] (Index idx) const {
assert(idx >= 0 && idx < tSize && "out of range");
return mBuff[idx];
}
constexpr Index len() {
return tSize;
}
};
};

View file

@ -0,0 +1,97 @@
#pragma once
#include "Array.h"
namespace tp {
extern ModuleManifest gModuleContainer;
template <typename Type, bool DEBUG = true>
class TimeLine {
tp::Array<Type> mMem;
tp::halni mStart = 0;
tp::halni mLoad = 0;
public:
TimeLine(tp::halni aNSnapshots) {
MODULE_SANITY_CHECK(gModuleContainer);
mMem.reserve(aNSnapshots);
}
Type* operator[](tp::halni aIdx) const {
assert(aIdx < mLoad);
auto const idx = mStart + aIdx;
if (idx >= mMem.length()) {
idx -= mMem.length();
}
return &mMem[idx];
}
void add(const Type& val) {
auto const len = mMem.length() - 1;
if (mLoad == len) {
if (mStart == len) {
mStart = 0;
}
mMem[mStart] = val;
mStart++;
}
else {
mMem[mLoad] = val;
mLoad++;
}
}
Type* left() {
return &mMem[mStart];
}
Type* right() {
if (mLoad == mMem.length() - 1) {
return &mMem[0];
}
return NULL;
}
const Type* left() const {
return &mMem[mStart];
}
const Type* right() const {
if (mLoad == mMem.length() - 1) {
return &mMem[0];
}
return NULL;
}
tp::halni leftLen() const {
if (mLoad == mMem.length() - 1) {
return mMem.length() - (mStart + 1);
}
return mLoad + 1;
}
tp::halni rightLen() const {
if (mLoad == mMem.length() - 1) {
return mStart + 1;
}
return 0;
}
};
template <typename Type>
class TimeLine<Type, false> {
public:
TimeLine(tp::halni dummy) {}
Type* operator[](tp::halni aIdx) const { return NULL; }
void add(const Type& val) {}
Type* left() { return NULL; }
Type* right() { return NULL; }
const Type* left() const { return NULL; }
const Type* right() const { return NULL; }
tp::halni leftLen() const { return NULL; }
tp::halni rightLen() const { return NULL; }
};
template <typename Type>
using DebugTimeline = TimeLine<Type, ENV_BUILD_DEBUG_VAR>;
};