Loading...
Searching...
No Matches
block_funcs.hpp
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
// SPDX-FileCopyrightText: 2022 - 2025 Kohei Yoshida
//
// SPDX-License-Identifier: MIT
#pragma once
#include "./types.hpp"
#include "../global.hpp"
#include <unordered_map>
#include <functional>
#include <sstream>
namespace mdds { namespace mtv {
namespace detail {
inline void throw_unknown_block(const char* func, const mdds::mtv::element_t type)
{
std::ostringstream os;
os << func << ": failed to map to a element block function (type=" << type << ")";
throw general_error(os.str());
}
template<typename Ret, typename... Args>
auto& find_func(
const std::unordered_map<element_t, std::function<Ret(Args...)>>& func_map, element_t type,
const char* src_func_name)
{
auto it = func_map.find(type);
if (it == func_map.end())
detail::throw_unknown_block(src_func_name, type);
return it->second;
}
} // namespace detail
template<typename... Ts>
struct element_block_funcs
{
static base_element_block* create_new_block(element_t type, std::size_t init_size)
{
static const std::unordered_map<element_t, std::function<base_element_block*(std::size_t)>> func_map{
{Ts::block_type, Ts::create_block}...};
auto& f = detail::find_func(func_map, type, __func__);
return f(init_size);
}
static base_element_block* copy_block(const base_element_block& block)
{
static const std::unordered_map<element_t, std::function<base_element_block*(const base_element_block&)>>
func_map{{Ts::block_type, Ts::copy_block}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
return f(block);
}
static base_element_block* clone_block(const base_element_block& block)
{
static const std::unordered_map<element_t, std::function<base_element_block*(const base_element_block&)>>
func_map{{Ts::block_type, Ts::clone_block}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
return f(block);
}
static void delete_block(const base_element_block* p)
{
if (!p)
return;
static const std::unordered_map<element_t, std::function<void(const base_element_block*)>> func_map{
{Ts::block_type, Ts::delete_block}...};
// TODO: We should not throw an exception here as this gets called
// from a destructor and destructors should not throw exceptions.
auto& f = detail::find_func(func_map, get_block_type(*p), __func__);
f(p);
}
static void resize_block(base_element_block& block, std::size_t new_size)
{
static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
{Ts::block_type, Ts::resize_block}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block, new_size);
}
static void print_block(const base_element_block& block)
{
static const std::unordered_map<element_t, std::function<void(const base_element_block&)>> func_map{
{Ts::block_type, Ts::print_block}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block);
}
static void erase(base_element_block& block, std::size_t pos)
{
static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
{Ts::block_type, Ts::erase_value}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block, pos);
}
static void erase(base_element_block& block, std::size_t pos, std::size_t size)
{
static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t, std::size_t)>>
func_map{{Ts::block_type, Ts::erase_values}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block, pos, size);
}
static void append_block(base_element_block& dest, const base_element_block& src)
{
static const std::unordered_map<element_t, std::function<void(base_element_block&, const base_element_block&)>>
func_map{{Ts::block_type, Ts::append_block}...};
auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
f(dest, src);
}
static void append_values_from_block(
base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
{
using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
static const std::unordered_map<element_t, func_type> func_map{
{Ts::block_type, Ts::append_values_from_block}...};
auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
f(dest, src, begin_pos, len);
}
static void assign_values_from_block(
base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
{
using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
static const std::unordered_map<element_t, func_type> func_map{
{Ts::block_type, Ts::assign_values_from_block}...};
auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
f(dest, src, begin_pos, len);
}
static void prepend_values_from_block(
base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
{
using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
static const std::unordered_map<element_t, func_type> func_map{
{Ts::block_type, Ts::prepend_values_from_block}...};
auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
f(dest, src, begin_pos, len);
}
static void swap_values(
base_element_block& blk1, base_element_block& blk2, std::size_t pos1, std::size_t pos2, std::size_t len)
{
element_t blk1_type = get_block_type(blk1);
assert(blk1_type == get_block_type(blk2));
using func_type =
std::function<void(base_element_block&, base_element_block&, std::size_t, std::size_t, std::size_t)>;
static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::swap_values}...};
auto& f = detail::find_func(func_map, blk1_type, __func__);
f(blk1, blk2, pos1, pos2, len);
}
static bool equal_block(const base_element_block& left, const base_element_block& right)
{
element_t block_type = get_block_type(left);
if (block_type != get_block_type(right))
return false;
using func_type = std::function<bool(const base_element_block&, const base_element_block&)>;
static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::equal_block}...};
auto& f = detail::find_func(func_map, block_type, __func__);
return f(left, right);
}
static void overwrite_values(base_element_block& block, std::size_t pos, std::size_t len)
{
using func_type = std::function<void(base_element_block&, std::size_t, std::size_t)>;
static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::overwrite_values}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block, pos, len);
}
static void shrink_to_fit(base_element_block& block)
{
using func_type = std::function<void(base_element_block&)>;
static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::shrink_to_fit}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
f(block);
}
static std::size_t size(const base_element_block& block)
{
using func_type = std::function<std::size_t(const base_element_block&)>;
static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::size}...};
auto& f = detail::find_func(func_map, get_block_type(block), __func__);
return f(block);
}
};
}} // namespace mdds::mtv
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
mdds::mtv::base_element_block
Definition types.hpp:135
mdds::mtv::element_block_funcs
Definition block_funcs.hpp:43