HighFive  2.3.1
HighFive - Header-only C++ HDF5 interface
H5Utils.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
3  *
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  */
9 #ifndef H5UTILS_HPP
10 #define H5UTILS_HPP
11 
12 // internal utilities functions
13 #include <algorithm>
14 #include <array>
15 #include <cstddef> // __GLIBCXX__
16 #include <exception>
17 #include <string>
18 #include <type_traits>
19 #include <vector>
20 
21 #ifdef H5_USE_BOOST
22 # include <boost/multi_array.hpp>
23 # include <boost/numeric/ublas/matrix.hpp>
24 #endif
25 #ifdef H5_USE_EIGEN
26 # include <Eigen/Eigen>
27 #endif
28 
29 #include <H5public.h>
30 
31 #include "../H5Exception.hpp"
32 
33 namespace HighFive {
34 
35 // If ever used, recognize dimensions of FixedLenStringArray
36 template <std::size_t N>
37 class FixedLenStringArray;
38 
39 
40 template <typename T>
41 using unqualified_t = typename std::remove_const<typename std::remove_reference<T>::type
42  >::type;
43 
44 namespace details {
45 template <typename T>
46 struct inspector {
47  using type = T;
48  using base_type = unqualified_t<T>;
49 
50  static constexpr size_t ndim = 0;
51  static constexpr size_t recursive_ndim = ndim;
52 
53  static std::array<size_t, recursive_ndim> getDimensions(const type& /* val */) {
54  return std::array<size_t, recursive_ndim>();
55  }
56 };
57 
58 template <size_t N>
59 struct inspector<FixedLenStringArray<N>> {
60  using type = FixedLenStringArray<N>;
61  using base_type = FixedLenStringArray<N>;
62 
63  static constexpr size_t ndim = 1;
64  static constexpr size_t recursive_ndim = ndim;
65 
66  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
67  return std::array<size_t, recursive_ndim>{val.size()};
68  }
69 };
70 
71 template <typename T>
72 struct inspector<std::vector<T>> {
73  using type = std::vector<T>;
74  using value_type = T;
75  using base_type = typename inspector<value_type>::base_type;
76 
77  static constexpr size_t ndim = 1;
78  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
79 
80  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
81  std::array<size_t, recursive_ndim> sizes{val.size()};
82  size_t index = ndim;
83  for (const auto& s: inspector<value_type>::getDimensions(val[0])) {
84  sizes[index++] = s;
85  }
86  return sizes;
87  }
88 };
89 
90 template <typename T>
91 struct inspector<T*> {
92  using type = T*;
93  using value_type = T;
94  using base_type = typename inspector<value_type>::base_type;
95 
96  static constexpr size_t ndim = 1;
97  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
98 
99  static std::array<size_t, recursive_ndim> getDimensions(const type& /* val */) {
100  throw std::string("Not possible to have size of a T*");
101  }
102 };
103 
104 template <typename T, size_t N>
105 struct inspector<T[N]> {
106  using type = T[N];
107  using value_type = T;
108  using base_type = typename inspector<value_type>::base_type;
109 
110  static constexpr size_t ndim = 1;
111  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
112 
113  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
114  std::array<size_t, recursive_ndim> sizes{N};
115  size_t index = ndim;
116  for (const auto& s: inspector<value_type>::getDimensions(val[0])) {
117  sizes[index++] = s;
118  }
119  return sizes;
120  }
121 };
122 
123 template <typename T, size_t N>
124 struct inspector<std::array<T, N>> {
125  using type = std::array<T, N>;
126  using value_type = T;
127  using base_type = typename inspector<value_type>::base_type;
128 
129  static constexpr size_t ndim = 1;
130  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
131 
132  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
133  std::array<size_t, recursive_ndim> sizes{N};
134  size_t index = ndim;
135  for (const auto& s: inspector<value_type>::getDimensions(val[0])) {
136  sizes[index++] = s;
137  }
138  return sizes;
139  }
140 };
141 
142 #ifdef H5_USE_EIGEN
143 template <typename T, int M, int N>
144 struct inspector<Eigen::Matrix<T, M, N>> {
145  using type = Eigen::Matrix<T, M, N>;
146  using value_type = T;
147  using base_type = typename inspector<value_type>::base_type;
148 
149  static constexpr size_t ndim = 2;
150  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
151 
152  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
153  std::array<size_t, recursive_ndim> sizes{static_cast<size_t>(val.rows()), static_cast<size_t>(val.cols())};
154  size_t index = ndim;
155  for (const auto& s: inspector<value_type>::getDimensions(val.data()[0])) {
156  sizes[index++] = s;
157  }
158  return sizes;
159  }
160 };
161 #endif
162 
163 #ifdef H5_USE_BOOST
164 template <typename T, size_t Dims>
165 struct inspector<boost::multi_array<T, Dims>> {
166  using type = boost::multi_array<T, Dims>;
167  using value_type = T;
168  using base_type = typename inspector<value_type>::base_type;
169 
170  static constexpr size_t ndim = Dims;
171  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
172 
173  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
174  std::array<size_t, recursive_ndim> sizes;
175  for (size_t i = 0; i < ndim; ++i) {
176  sizes[i] = val.shape()[i];
177  }
178 
179  size_t index = ndim;
180  for (const auto& s: inspector<value_type>::getDimensions(val.data()[0])) {
181  sizes[index++] = s;
182  }
183  return sizes;
184  }
185 };
186 
187 template <typename T>
188 struct inspector<boost::numeric::ublas::matrix<T>> {
189  using type = boost::numeric::ublas::matrix<T>;
190  using value_type = T;
191  using base_type = typename inspector<value_type>::base_type;
192 
193  static constexpr size_t ndim = 2;
194  static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
195 
196  static std::array<size_t, recursive_ndim> getDimensions(const type& val) {
197  std::array<size_t, recursive_ndim> sizes{val.size1(), val.size2()};
198  size_t index = ndim;
199  for (const auto& s: inspector<value_type>::getDimensions(val(0, 0))) {
200  sizes[index++] = s;
201  }
202  return sizes;
203  }
204 };
205 #endif
206 
207 
208 // Find the type of an eventual char array, otherwise void
209 template <typename>
210 struct type_char_array {
211  typedef void type;
212 };
213 
214 template <typename T>
215 struct type_char_array<T*> {
216  typedef typename std::conditional<
217  std::is_same<unqualified_t<T>, char>::value,
218  char*,
219  typename type_char_array<T>::type
220  >::type type;
221 };
222 
223 template <typename T, std::size_t N>
224 struct type_char_array<T[N]> {
225  typedef typename std::conditional<
226  std::is_same<unqualified_t<T>, char>::value,
227  char[N],
228  typename type_char_array<T>::type
229  >::type type;
230 };
231 
232 
233 // check if the type is a container ( only vector supported for now )
234 template <typename>
235 struct is_container {
236  static const bool value = false;
237 };
238 
239 template <typename T>
240 struct is_container<std::vector<T> > {
241  static const bool value = true;
242 };
243 
244 // check if the type is a basic C-Array
245 template <typename>
246 struct is_c_array {
247  static const bool value = false;
248 };
249 
250 template <typename T>
251 struct is_c_array<T*> {
252  static const bool value = true;
253 };
254 
255 template <typename T, std::size_t N>
256 struct is_c_array<T[N]> {
257  static const bool value = true;
258 };
259 
260 
261 // converter function for hsize_t -> size_t when hsize_t != size_t
262 template <typename Size>
263 inline std::vector<std::size_t> to_vector_size_t(const std::vector<Size>& vec) {
264  static_assert(std::is_same<Size, std::size_t>::value == false,
265  " hsize_t != size_t mandatory here");
266  std::vector<size_t> res(vec.size());
267  std::transform(vec.cbegin(), vec.cend(), res.begin(), [](Size e) {
268  return static_cast<size_t>(e);
269  });
270  return res;
271 }
272 
273 // converter function for hsize_t -> size_t when size_t == hsize_t
274 inline std::vector<std::size_t> to_vector_size_t(const std::vector<std::size_t>& vec) {
275  return vec;
276 }
277 
278 // read name from a H5 object using the specified function
279 template<typename T>
280 inline std::string get_name(T fct) {
281  const size_t maxLength = 255;
282  char buffer[maxLength + 1];
283  ssize_t retcode = fct(buffer, static_cast<hsize_t>(maxLength) + 1);
284  if (retcode < 0) {
285  HDF5ErrMapper::ToException<GroupException>("Error accessing object name");
286  }
287  const size_t length = static_cast<std::size_t>(retcode);
288  if (length <= maxLength) {
289  return std::string(buffer, length);
290  }
291  std::vector<char> bigBuffer(length + 1, 0);
292  fct(bigBuffer.data(), static_cast<hsize_t>(length) + 1);
293  return std::string(bigBuffer.data(), length);
294 }
295 
296 } // namespace details
297 } // namespace HighFive
298 
299 #endif // H5UTILS_HPP
A structure representing a set of fixed-length strings.
Definition: H5DataType.hpp:239
std::size_t size() const noexcept
Definition: H5DataType.hpp:281
Definition: H5_definitions.hpp:15
typename std::remove_const< typename std::remove_reference< T >::type >::type unqualified_t
Definition: H5Utils.hpp:42