mdds
util.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * Copyright (c) 2021 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#ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_UTIL_HPP
30#define INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_UTIL_HPP
31
32#include "./types.hpp"
33
34#include <sstream>
35
36namespace mdds {
37
38namespace mtv {
39
45{
55 {
56 (void)block;
57 }
58
68 {
69 (void)block;
70 }
71};
72
77{
83
88 static constexpr lu_factor_t loop_unrolling = lu_factor_t::lu16;
89};
90
91} // namespace mtv
92
93namespace detail { namespace mtv {
94
95#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
96
97template<typename T, typename = void>
98struct has_trace : std::false_type
99{
100};
101
102template<typename T>
103struct has_trace<T, decltype((void)T::trace)> : std::true_type
104{
105};
106
107template<typename Trait>
108struct call_trace
109{
110 int& call_depth;
111
112 call_trace(int& _call_depth) : call_depth(_call_depth)
113 {
114 ++call_depth;
115 }
116 ~call_trace() noexcept
117 {
118 --call_depth;
119 }
120
121 void call(std::false_type, const ::mdds::mtv::trace_method_properties_t&) const
122 {
123 // sink
124 }
125
126 void call(std::true_type, const ::mdds::mtv::trace_method_properties_t& props) const
127 {
128 // In case of recursive calls, only trace the first encountered method.
129 if (call_depth <= 1)
130 Trait::trace(props);
131 }
132
133 void operator()(const ::mdds::mtv::trace_method_properties_t& props) const
134 {
135 call(has_trace<Trait>{}, props);
136 }
137};
138
139#endif
140
141inline void throw_block_position_not_found(
142 const char* method_sig, int line, size_t pos, size_t block_size, size_t container_size)
143{
144 std::ostringstream os;
145 os << method_sig << "#" << line << ": block position not found! (logical pos=" << pos
146 << ", block size=" << block_size << ", logical size=" << container_size << ")";
147 throw std::out_of_range(os.str());
148}
149
168template<typename _T, typename _SizeT>
169std::pair<_SizeT, bool> calc_input_end_position(const _T& it_begin, const _T& it_end, _SizeT pos, _SizeT total_size)
170{
171 using ret_type = std::pair<_SizeT, bool>;
172
173 _SizeT length = std::distance(it_begin, it_end);
174 if (!length)
175 // empty data array. nothing to do.
176 return ret_type(0, false);
177
178 _SizeT end_pos = pos + length - 1;
179 if (end_pos >= total_size)
180 throw std::out_of_range("Input data sequence is too long.");
181
182 return ret_type(end_pos, true);
183}
184
185template<typename T>
186T advance_position(const T& pos, int steps)
187{
188 T ret = pos;
189
190 if (steps > 0)
191 {
192 while (steps > 0)
193 {
194 if (ret.second + steps < ret.first->size)
195 {
196 // element is still in the same block.
197 ret.second += steps;
198 break;
199 }
200 else
201 {
202 steps -= static_cast<int>(ret.first->size - ret.second);
203 ++ret.first;
204 ret.second = 0;
205 }
206 }
207 }
208 else
209 {
210 while (steps < 0)
211 {
212 if (static_cast<int>(ret.second) >= -steps)
213 {
214 ret.second += steps;
215 break;
216 }
217 else
218 {
219 steps += static_cast<int>(ret.second + 1);
220 --ret.first;
221 ret.second = ret.first->size - 1;
222 }
223 }
224 }
225
226 return ret;
227}
228
229template<typename _Blk>
230inline typename _Blk::value_type get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset)
231{
232 return _Blk::at(data, offset);
233}
234
235#ifndef MDDS_MULTI_TYPE_VECTOR_USE_DEQUE
236
237template<>
238inline bool get_block_element_at<mdds::mtv::boolean_element_block>(
239 const mdds::mtv::base_element_block& data, size_t offset)
240{
241 auto it = mdds::mtv::boolean_element_block::cbegin(data);
242 std::advance(it, offset);
243 return *it;
244}
245
246#endif
247
248}} // namespace detail::mtv
249
250} // namespace mdds
251
252#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
253
254#define MDDS_MTV_TRACE(method_type) \
255 ::mdds::detail::mtv::call_trace<Trait> mdds_mtv_ct(m_trace_call_depth); \
256 mdds_mtv_ct({trace_method_t::method_type, this, __func__, "", __FILE__, __LINE__})
257
258#define MDDS_MTV_TRACE_ARGS(method_type, stream) \
259 ::mdds::detail::mtv::call_trace<Trait> mdds_mtv_ct(m_trace_call_depth); \
260 do \
261 { \
262 std::ostringstream _os_; \
263 _os_ << stream; \
264 mdds_mtv_ct({trace_method_t::method_type, this, __func__, _os_.str(), __FILE__, __LINE__}); \
265 } while (false)
266
267#else
268
269#define MDDS_MTV_TRACE(...)
270
271#define MDDS_MTV_TRACE_ARGS(...)
272
273#endif
274
275#endif
276
277/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: types.hpp:174
Definition: util.hpp:77
static constexpr lu_factor_t loop_unrolling
Definition: util.hpp:88
Definition: util.hpp:45
void element_block_acquired(const base_element_block *block)
Definition: util.hpp:54
void element_block_released(const base_element_block *block)
Definition: util.hpp:67