118 lines
2.6 KiB
C++
118 lines
2.6 KiB
C++
//
|
|
// Created by erki on 24/10/23.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <type_traits>
|
|
#include <array>
|
|
#include <cstring>
|
|
|
|
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]);
|
|
}
|
|
};
|
|
|
|
}
|