2023-10-25 11:36:20 +03:00

119 lines
2.7 KiB
C++

//
// Created by erki on 24/10/23.
//
#pragma once
#include <array>
#include <cstring>
#include <memory>
#include <type_traits>
namespace cpptick
{
template<typename T>
concept TrivialClass = std::is_trivial_v<T> && std::is_trivially_destructible_v<T>;
template<typename T>
concept CopyableClass = !TrivialClass<T> && std::copy_constructible<T>;
template<typename T>
concept SlotArgument = TrivialClass<T> || CopyableClass<T>;
struct ArgStorage
{
std::array<char, sizeof(int) * 12> buffer;
std::array<char*, 12> pointer_buffer;
std::array<char*, 12>::iterator pointer_buffer_head;
std::size_t space_remaining;
ArgStorage() = default;
ArgStorage(const ArgStorage&) = default;
ArgStorage(ArgStorage&&) = default;
void reset()
{
space_remaining = buffer.size();
pointer_buffer_head = pointer_buffer.begin();
*pointer_buffer_head = buffer.data();
}
template<TrivialClass T>
void pushArg(T&& arg)
{
if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0)
std::exit(1);
void* memory_location = *pointer_buffer_head;
if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr)
std::exit(2);
std::memcpy(memory_location, &arg, sizeof(T));
pointer_buffer_head++;
if (pointer_buffer_head != pointer_buffer.end())
{
*pointer_buffer_head = (char*) memory_location + sizeof(T);
space_remaining -= sizeof(T);
}
}
template<CopyableClass T>
void pushArg(T&& arg)
{
if (pointer_buffer_head == pointer_buffer.end() || space_remaining == 0)
std::exit(1);
void* memory_location = *pointer_buffer_head;
if (std::align(alignof(T), sizeof(T), memory_location, space_remaining) == nullptr)
std::exit(2);
new (memory_location) T{arg};
pointer_buffer_head++;
if (pointer_buffer_head != pointer_buffer.end())
{
*pointer_buffer_head = (char*) memory_location + sizeof(T);
space_remaining -= sizeof(T);
}
}
template<TrivialClass T>
void cleanUp(const std::size_t)
{}
template<CopyableClass T>
void cleanUp(const std::size_t index)
{
T* item = reinterpret_cast<T*>(pointer_buffer[index]);
item->~T();
}
template<typename... Args, size_t... Is>
void cleanUp(std::index_sequence<Is...>)
{
(cleanUp<Args>(Is), ...);
}
template<typename... Args>
void cleanUp()
{
cleanUp<Args...>(std::make_index_sequence<sizeof...(Args)>{});
}
template<SlotArgument T>
T& at(const std::size_t idx)
{
return *((T*) pointer_buffer[idx]);
}
template<SlotArgument T>
const T& at(const std::size_t idx) const
{
return *((T*) pointer_buffer[idx]);
}
};
}// namespace cpptick