mdds
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 
16 namespace mdds { namespace mtv {
17 
18 namespace detail {
19 
20 inline 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 
27 template<typename Ret, typename... Args>
28 auto& 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 
41 template<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 
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:157
Definition: cref_wrapper.hpp:12
Definition: block_funcs.hpp:42
Definition: types.hpp:134