Kylin/DataStructure/StaticLinkedList.h
2023-12-27 10:29:16 +08:00

68 lines
2.1 KiB
C++

#ifndef STATICLINKEDLIST_H
#define STATICLINKEDLIST_H
#include "LinkedList.h"
namespace Kylin {
template <typename T, size_t N>
class StaticLinkedList : public LinkedList<T> {
using Node = typename LinkedList<T>::Node;
struct StaticNode : public Node {
void *operator new(size_t /*size*/, void *p) { return p; }
};
public:
StaticLinkedList() = default;
StaticLinkedList(const StaticLinkedList &other) {
auto sourceNode = other.m_header.next;
auto targetNode = reinterpret_cast<Node *>(&this->m_header);
while (sourceNode != nullptr) {
auto newNode = create();
if (newNode == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node...");
newNode->value = sourceNode->value;
targetNode->next = newNode;
targetNode = newNode;
sourceNode = sourceNode->next;
this->m_size++;
targetNode->next = nullptr;
this->m_last = targetNode;
}
}
~StaticLinkedList() { this->clear(); }
size_t capacity() const { return N; }
void swap(StaticLinkedList & /*other*/) {
THROW_EXCEPTION(InvalidOperationException, "StaticLinkedList can`t do swap operate.");
}
protected:
Node *create() override {
Node *ret = nullptr;
for (size_t i = 0; i < N; i++) {
if (m_used[i]) continue;
ret = reinterpret_cast<StaticNode *>(m_space) + i;
ret = new (ret) StaticNode();
m_used[i] = true;
break;
}
return ret;
}
void destroy(Node *p) override {
auto del = dynamic_cast<StaticNode *>(p);
for (size_t i = 0; i < N; i++) {
if ((reinterpret_cast<StaticNode *>(m_space) + i) != del) continue;
m_used[i] = false;
del->~StaticNode();
break;
}
}
private:
uint8_t m_space[N * sizeof(StaticNode)];
bool m_used[N]{false};
};
} // namespace Kylin
#endif // STATICLINKEDLIST_H