Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 161 additions & 16 deletions stack.cpp
Original file line number Diff line number Diff line change
@@ -1,48 +1,193 @@
#include "stack.hpp"

#include <cstddef>

// TODO: remove me
#define UNUSED(VAR) (void)(VAR)
#include <cstdint>
#include <limits>
#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <vector>

namespace stack
{

class Node
{
public:
explicit Node(const uint8_t* data, size_t size) : size_(size)
{
data_ = std::make_unique<uint8_t[]>(size);
std::copy(data, data + size, data_.get());
}

size_t Size() const
{
return size_;
}

uint8_t* begin()
{
return data_.get();
}

uint8_t* end()
{
return data_.get() + size_;
}

private:
size_t size_;
std::unique_ptr<uint8_t[]> data_;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если в этой задаче нельзя использовать smart pointer'ы, то могу переписать на ручной деструктор

};

class LIFOStack
{
public:
explicit LIFOStack()
{
}

Handle Create()
{
auto next_handle = NextHandle();
mp_.insert({next_handle, std::vector<Node>()});

return next_handle;
}

void Destroy(const Handle handle)
{
mp_.erase(handle);
free_handles_.push_back(handle);
}

bool IsValid(const Handle handle) const
{
return mp_.find(handle) != mp_.end();
}

size_t Count(const Handle handle) const
{
if (!IsValid(handle))
{
return 0u;
}

const auto& stack = GetByHandle(handle);
return stack.size();
}

void Push(const Handle handle, const uint8_t* data, size_t size)
{
if (!IsValid(handle) || data == nullptr || size == 0)
{
return;
}

auto& stack = GetByHandle(handle);
stack.emplace_back(data, size);
}

size_t Pop(const Handle handle, uint8_t* data, size_t size)
{
if (!IsValid(handle) || data == nullptr || size == 0)
{
return 0u;
}

auto& stack = GetByHandle(handle);
if (stack.empty())
{
return 0u;
}

auto& last_node = stack.back();
if (last_node.Size() != size)
{
return 0u;
}

std::copy(last_node.begin(), last_node.end(), data);
stack.pop_back();

return size;
}

private:
const std::vector<Node>& GetByHandle(const Handle handle) const
{
return mp_.at(handle);
}

std::vector<Node>& GetByHandle(const Handle handle)
{
return mp_.at(handle);
}

Handle NextHandle()
{
if (current_handle_ != std::numeric_limits<Handle>::max())
{
return current_handle_++;
}

if (free_handles_.empty())
{
throw std::runtime_error("all handle numbers have been used");
}

auto free_handle = free_handles_.back();
free_handles_.pop_back();

return free_handle;
}

private:
std::unordered_map<Handle, std::vector<Node>> mp_{};
Handle current_handle_{};
std::vector<Handle> free_handles_{};
};

LIFOStack stack{};

Handle create()
{
return -1;
try
{
return stack.Create();
}
catch (...)
{
return -1;
}
}

void destroy(const Handle handle)
{
UNUSED(handle);
stack.Destroy(handle);
}

bool valid(const Handle handle)
{
UNUSED(handle);
return false;
return stack.IsValid(handle);
}

std::size_t count(const Handle handle)
{
UNUSED(handle);
return 0u;
return stack.Count(handle);
}

void push(const Handle handle, const void* const data, const std::size_t size)
{
UNUSED(handle);
UNUSED(data);
UNUSED(size);
auto data_to_insert = static_cast<const uint8_t*>(data);
stack.Push(handle, data_to_insert, size);
}

std::size_t pop(const Handle handle, void* const data, const std::size_t size)
{
UNUSED(handle);
UNUSED(data);
UNUSED(size);
return 0u;
auto data_to_fill = static_cast<uint8_t*>(data);
return stack.Pop(handle, data_to_fill, size);
}

} // namespace stack