mdds
Loading...
Searching...
No Matches
block_funcs.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3// SPDX-FileCopyrightText: 2022 - 2025 Kohei Yoshida
4//
5// SPDX-License-Identifier: MIT
6
7#pragma once
8
9#include "./types.hpp"
10#include "../global.hpp"
11
12#include <unordered_map>
13#include <functional>
14#include <sstream>
15
16namespace mdds { namespace mtv {
17
18namespace detail {
19
20inline void throw_unknown_block(const char* func, const mdds::mtv::element_t type)
21{
22 std::ostringstream os;
23 os << func << ": failed to map to a element block function (type=" << type << ")";
24 throw general_error(os.str());
25}
26
27template<typename Ret, typename... Args>
28auto& find_func(
29 const std::unordered_map<element_t, std::function<Ret(Args...)>>& func_map, element_t type,
30 const char* src_func_name)
31{
32 auto it = func_map.find(type);
33 if (it == func_map.end())
34 detail::throw_unknown_block(src_func_name, type);
35
36 return it->second;
37}
38
39} // namespace detail
40
41template<typename... Ts>
43{
44 static base_element_block* create_new_block(element_t type, std::size_t init_size)
45 {
46 static const std::unordered_map<element_t, std::function<base_element_block*(std::size_t)>> func_map{
47 {Ts::block_type, Ts::create_block}...};
48
49 auto& f = detail::find_func(func_map, type, __func__);
50 return f(init_size);
51 }
52
53 static base_element_block* copy_block(const base_element_block& block)
54 {
55 static const std::unordered_map<element_t, std::function<base_element_block*(const base_element_block&)>>
56 func_map{{Ts::block_type, Ts::copy_block}...};
57
58 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
59 return f(block);
60 }
61
62 static base_element_block* clone_block(const base_element_block& block)
63 {
64 static const std::unordered_map<element_t, std::function<base_element_block*(const base_element_block&)>>
65 func_map{{Ts::block_type, Ts::clone_block}...};
66
67 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
68 return f(block);
69 }
70
71 static void delete_block(const base_element_block* p)
72 {
73 if (!p)
74 return;
75
76 static const std::unordered_map<element_t, std::function<void(const base_element_block*)>> func_map{
77 {Ts::block_type, Ts::delete_block}...};
78
79 // TODO: We should not throw an exception here as this gets called
80 // from a destructor and destructors should not throw exceptions.
81 auto& f = detail::find_func(func_map, get_block_type(*p), __func__);
82 f(p);
83 }
84
85 static void resize_block(base_element_block& block, std::size_t new_size)
86 {
87 static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
88 {Ts::block_type, Ts::resize_block}...};
89
90 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
91 f(block, new_size);
92 }
93
94 static void print_block(const base_element_block& block)
95 {
96 static const std::unordered_map<element_t, std::function<void(const base_element_block&)>> func_map{
97 {Ts::block_type, Ts::print_block}...};
98
99 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
100 f(block);
101 }
102
103 static void erase(base_element_block& block, std::size_t pos)
104 {
105 static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
106 {Ts::block_type, Ts::erase_value}...};
107
108 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
109 f(block, pos);
110 }
111
112 static void erase(base_element_block& block, std::size_t pos, std::size_t size)
113 {
114 static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t, std::size_t)>>
115 func_map{{Ts::block_type, Ts::erase_values}...};
116
117 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
118 f(block, pos, size);
119 }
120
121 static void append_block(base_element_block& dest, const base_element_block& src)
122 {
123 static const std::unordered_map<element_t, std::function<void(base_element_block&, const base_element_block&)>>
124 func_map{{Ts::block_type, Ts::append_block}...};
125
126 auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
127 f(dest, src);
128 }
129
130 static void append_values_from_block(
131 base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
132 {
133 using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
134 static const std::unordered_map<element_t, func_type> func_map{
135 {Ts::block_type, Ts::append_values_from_block}...};
136
137 auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
138 f(dest, src, begin_pos, len);
139 }
140
141 static void assign_values_from_block(
142 base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
143 {
144 using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
145 static const std::unordered_map<element_t, func_type> func_map{
146 {Ts::block_type, Ts::assign_values_from_block}...};
147
148 auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
149 f(dest, src, begin_pos, len);
150 }
151
152 static void prepend_values_from_block(
153 base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
154 {
155 using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
156 static const std::unordered_map<element_t, func_type> func_map{
157 {Ts::block_type, Ts::prepend_values_from_block}...};
158
159 auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
160 f(dest, src, begin_pos, len);
161 }
162
163 static void swap_values(
164 base_element_block& blk1, base_element_block& blk2, std::size_t pos1, std::size_t pos2, std::size_t len)
165 {
166 element_t blk1_type = get_block_type(blk1);
167 assert(blk1_type == get_block_type(blk2));
168
169 using func_type =
170 std::function<void(base_element_block&, base_element_block&, std::size_t, std::size_t, std::size_t)>;
171 static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::swap_values}...};
172
173 auto& f = detail::find_func(func_map, blk1_type, __func__);
174 f(blk1, blk2, pos1, pos2, len);
175 }
176
177 static bool equal_block(const base_element_block& left, const base_element_block& right)
178 {
179 element_t block_type = get_block_type(left);
180 if (block_type != get_block_type(right))
181 return false;
182
183 using func_type = std::function<bool(const base_element_block&, const base_element_block&)>;
184 static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::equal_block}...};
185
186 auto& f = detail::find_func(func_map, block_type, __func__);
187 return f(left, right);
188 }
189
190 static void overwrite_values(base_element_block& block, std::size_t pos, std::size_t len)
191 {
192 using func_type = std::function<void(base_element_block&, std::size_t, std::size_t)>;
193 static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::overwrite_values}...};
194
195 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
196 f(block, pos, len);
197 }
198
199 static void shrink_to_fit(base_element_block& block)
200 {
201 using func_type = std::function<void(base_element_block&)>;
202 static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::shrink_to_fit}...};
203
204 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
205 f(block);
206 }
207
208 static std::size_t size(const base_element_block& block)
209 {
210 using func_type = std::function<std::size_t(const base_element_block&)>;
211 static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::size}...};
212
213 auto& f = detail::find_func(func_map, get_block_type(block), __func__);
214 return f(block);
215 }
216};
217
218}} // namespace mdds::mtv
219
220/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition types.hpp:135
Definition block_funcs.hpp:43