mdds
block_funcs.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2022 Kohei Yoshida
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  ************************************************************************/
28 
29 #pragma once
30 
31 #include "./types.hpp"
32 #include "../global.hpp"
33 
34 #include <unordered_map>
35 #include <functional>
36 #include <sstream>
37 
38 namespace mdds { namespace mtv {
39 
40 namespace detail {
41 
42 inline void throw_unknown_block(const char* func, const mdds::mtv::element_t type)
43 {
44  std::ostringstream os;
45  os << func << ": failed to map to a element block function (type=" << type << ")";
46  throw general_error(os.str());
47 }
48 
49 template<typename Ret, typename... Args>
50 auto& find_func(
51  const std::unordered_map<element_t, std::function<Ret(Args...)>>& func_map, element_t type,
52  const char* src_func_name)
53 {
54  auto it = func_map.find(type);
55  if (it == func_map.end())
56  detail::throw_unknown_block(src_func_name, type);
57 
58  return it->second;
59 }
60 
61 } // namespace detail
62 
63 template<typename... Ts>
65 {
66  static base_element_block* create_new_block(element_t type, std::size_t init_size)
67  {
68  static const std::unordered_map<element_t, std::function<base_element_block*(std::size_t)>> func_map{
69  {Ts::block_type, Ts::create_block}...};
70 
71  auto& f = detail::find_func(func_map, type, __func__);
72  return f(init_size);
73  }
74 
75  static base_element_block* clone_block(const base_element_block& block)
76  {
77  static const std::unordered_map<element_t, std::function<base_element_block*(const base_element_block&)>>
78  func_map{{Ts::block_type, Ts::clone_block}...};
79 
80  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
81  return f(block);
82  }
83 
84  static void delete_block(const base_element_block* p)
85  {
86  if (!p)
87  return;
88 
89  static const std::unordered_map<element_t, std::function<void(const base_element_block*)>> func_map{
90  {Ts::block_type, Ts::delete_block}...};
91 
92  // TODO: We should not throw an exception here as this gets called
93  // from a destructor and destructors should not throw exceptions.
94  auto& f = detail::find_func(func_map, get_block_type(*p), __func__);
95  f(p);
96  }
97 
98  static void resize_block(base_element_block& block, std::size_t new_size)
99  {
100  static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
101  {Ts::block_type, Ts::resize_block}...};
102 
103  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
104  f(block, new_size);
105  }
106 
107  static void print_block(const base_element_block& block)
108  {
109  static const std::unordered_map<element_t, std::function<void(const base_element_block&)>> func_map{
110  {Ts::block_type, Ts::print_block}...};
111 
112  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
113  f(block);
114  }
115 
116  static void erase(base_element_block& block, std::size_t pos)
117  {
118  static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t)>> func_map{
119  {Ts::block_type, Ts::erase_value}...};
120 
121  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
122  f(block, pos);
123  }
124 
125  static void erase(base_element_block& block, std::size_t pos, std::size_t size)
126  {
127  static const std::unordered_map<element_t, std::function<void(base_element_block&, std::size_t, std::size_t)>>
128  func_map{{Ts::block_type, Ts::erase_values}...};
129 
130  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
131  f(block, pos, size);
132  }
133 
134  static void append_block(base_element_block& dest, const base_element_block& src)
135  {
136  static const std::unordered_map<element_t, std::function<void(base_element_block&, const base_element_block&)>>
137  func_map{{Ts::block_type, Ts::append_block}...};
138 
139  auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
140  f(dest, src);
141  }
142 
143  static void append_values_from_block(
144  base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
145  {
146  using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
147  static const std::unordered_map<element_t, func_type> func_map{
148  {Ts::block_type, Ts::append_values_from_block}...};
149 
150  auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
151  f(dest, src, begin_pos, len);
152  }
153 
154  static void assign_values_from_block(
155  base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
156  {
157  using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
158  static const std::unordered_map<element_t, func_type> func_map{
159  {Ts::block_type, Ts::assign_values_from_block}...};
160 
161  auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
162  f(dest, src, begin_pos, len);
163  }
164 
165  static void prepend_values_from_block(
166  base_element_block& dest, const base_element_block& src, std::size_t begin_pos, std::size_t len)
167  {
168  using func_type = std::function<void(base_element_block&, const base_element_block&, std::size_t, std::size_t)>;
169  static const std::unordered_map<element_t, func_type> func_map{
170  {Ts::block_type, Ts::prepend_values_from_block}...};
171 
172  auto& f = detail::find_func(func_map, get_block_type(dest), __func__);
173  f(dest, src, begin_pos, len);
174  }
175 
176  static void swap_values(
177  base_element_block& blk1, base_element_block& blk2, std::size_t pos1, std::size_t pos2, std::size_t len)
178  {
179  element_t blk1_type = get_block_type(blk1);
180  assert(blk1_type == get_block_type(blk2));
181 
182  using func_type =
183  std::function<void(base_element_block&, base_element_block&, std::size_t, std::size_t, std::size_t)>;
184  static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::swap_values}...};
185 
186  auto& f = detail::find_func(func_map, blk1_type, __func__);
187  f(blk1, blk2, pos1, pos2, len);
188  }
189 
190  static bool equal_block(const base_element_block& left, const base_element_block& right)
191  {
192  element_t block_type = get_block_type(left);
193  if (block_type != get_block_type(right))
194  return false;
195 
196  using func_type = std::function<bool(const base_element_block&, const base_element_block&)>;
197  static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::equal_block}...};
198 
199  auto& f = detail::find_func(func_map, block_type, __func__);
200  return f(left, right);
201  }
202 
203  static void overwrite_values(base_element_block& block, std::size_t pos, std::size_t len)
204  {
205  using func_type = std::function<void(base_element_block&, std::size_t, std::size_t)>;
206  static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::overwrite_values}...};
207 
208  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
209  f(block, pos, len);
210  }
211 
212  static void shrink_to_fit(base_element_block& block)
213  {
214  using func_type = std::function<void(base_element_block&)>;
215  static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::shrink_to_fit}...};
216 
217  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
218  f(block);
219  }
220 
221  static std::size_t size(const base_element_block& block)
222  {
223  using func_type = std::function<std::size_t(const base_element_block&)>;
224  static const std::unordered_map<element_t, func_type> func_map{{Ts::block_type, Ts::size}...};
225 
226  auto& f = detail::find_func(func_map, get_block_type(block), __func__);
227  return f(block);
228  }
229 };
230 
231 }} // namespace mdds::mtv
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: flat_segment_tree.hpp:46
Definition: block_funcs.hpp:64
Definition: types.hpp:159