diff --git a/stack.cpp b/stack.cpp index 954a5a5..8f125ed 100644 --- a/stack.cpp +++ b/stack.cpp @@ -1,48 +1,160 @@ #include "stack.hpp" #include - -// TODO: remove me -#define UNUSED(VAR) (void)(VAR) +#include +#include +#include +#include +#include namespace stack { -Handle create() -{ - return -1; -} + struct Node { + std::vector data; + Node* next; -void destroy(const Handle handle) -{ - UNUSED(handle); -} + Node(const void* data_ptr, std::size_t data_size) + : data(static_cast(data_ptr), + static_cast(data_ptr) + data_size), + next(nullptr) { + } + }; -bool valid(const Handle handle) -{ - UNUSED(handle); - return false; -} + struct Stack { + Node* top; + std::size_t count; + + Stack() : top(nullptr), count(0) { + } + }; -std::size_t count(const Handle handle) -{ - UNUSED(handle); - return 0u; -} + std::unordered_map stacks; + std::queue available_handles; + Handle next_new_handle = 0; -void push(const Handle handle, const void* const data, const std::size_t size) -{ - UNUSED(handle); - UNUSED(data); - UNUSED(size); -} + Handle allocate_handle() { + if (!available_handles.empty()) { + Handle handle = available_handles.front(); + available_handles.pop(); + return handle; + } + + if (next_new_handle < std::numeric_limits::max()) { + return next_new_handle++; + } + + return -1; + } + + void deallocate_handle(Handle handle) { + if (handle != -1) { + available_handles.push(handle); + } + } -std::size_t pop(const Handle handle, void* const data, const std::size_t size) -{ - UNUSED(handle); - UNUSED(data); - UNUSED(size); - return 0u; -} + Handle create() + { + try { + Handle handle = allocate_handle(); + if (handle == -1) { + return -1; + } + + stacks.emplace(handle, Stack()); + return handle; + } catch (...) { + return -1; + } + } + + void destroy(const Handle handle) + { + auto it = stacks.find(handle); + if (it == stacks.end()) { + return; + } + + Stack& stack = it->second; + Node* current = stack.top; + while (current != nullptr) { + Node* next = current->next; + delete current; + current = next; + } + + stacks.erase(it); + deallocate_handle(handle); + } + + bool valid(const Handle handle) + { + return stacks.find(handle) != stacks.end(); + } + + std::size_t count(const Handle handle) + { + auto it = stacks.find(handle); + if (it == stacks.end()) { + return 0; + } + return it->second.count; + } + + void push(const Handle handle, const void* const data, const std::size_t size) + { + if (data == nullptr || size == 0) { + return ; + } + + auto it = stacks.find(handle); + if (it == stacks.end()) { + return; + } + + Stack& stack = it->second; + + try { + Node* new_node = new Node(data, size); + + new_node->next = stack.top; + stack.top = new_node; + stack.count++; + + } catch (...) { + } + } + + std::size_t pop(const Handle handle, void* const data, const std::size_t size) + { + if (data == nullptr || size == 0) { + return 0; + } + + auto it = stacks.find(handle); + if (it == stacks.end() || it->second.top == nullptr) { + return 0; + } + + Stack& stack = it->second; + Node* top_node = stack.top; + + if (size < top_node->data.size()) { + return 0; + } + + std::size_t copy_size = std::min(size, top_node->data.size()); + const char* source_data = top_node->data.data(); + char* dest_data = static_cast(data); + + for (std::size_t i = 0; i < copy_size; ++i) { + dest_data[i] = source_data[i]; + } + + stack.top = top_node->next; + delete top_node; + stack.count--; + return copy_size; + } } // namespace stack