H5Converter_misc.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 H5CONVERTER_MISC_HPP
10 #define H5CONVERTER_MISC_HPP
11 
12 #include <algorithm>
13 #include <cassert>
14 #include <functional>
15 #include <numeric>
16 #include <sstream>
17 #include <string>
18 #include <array>
19 
20 #ifdef H5_USE_BOOST
21 #include <boost/multi_array.hpp>
22 #include <boost/numeric/ublas/matrix.hpp>
23 #endif
24 
25 #include <H5Dpublic.h>
26 #include <H5Ppublic.h>
27 
28 #include "../H5DataSpace.hpp"
29 #include "../H5DataType.hpp"
30 
31 #include "H5Utils.hpp"
32 
33 namespace HighFive {
34 
35 namespace details {
36 
37 inline bool is_1D(const std::vector<size_t>& dims)
38 {
39  return std::count_if(dims.begin(), dims.end(),
40  [](size_t i){ return i > 1; }) < 2;
41 }
42 
43 inline size_t compute_total_size(const std::vector<size_t>& dims)
44 {
45  return std::accumulate(dims.begin(), dims.end(), 1,
46  std::multiplies<size_t>());
47 }
48 
49 inline void check_dimensions_vector(size_t size_vec, size_t size_dataset,
50  size_t dimension) {
51  if (size_vec != size_dataset) {
52  std::ostringstream ss;
53  ss << "Mismatch between vector size (" << size_vec
54  << ") and dataset size (" << size_dataset;
55  ss << ") on dimension " << dimension;
56  throw DataSetException(ss.str());
57  }
58 }
59 
60 // copy multi dimensional vector in C++ in one C-style multi dimensional buffer
61 template <typename T>
62 inline void vectors_to_single_buffer(const std::vector<T>& vec_single_dim,
63  const std::vector<size_t>& dims,
64  const size_t current_dim,
65  std::vector<T>& buffer) {
66 
67  check_dimensions_vector(vec_single_dim.size(), dims[current_dim],
68  current_dim);
69  buffer.insert(buffer.end(), vec_single_dim.begin(), vec_single_dim.end());
70 }
71 
72 template <typename T>
73 inline void
74 vectors_to_single_buffer(const std::vector<T>& vec_multi_dim,
75  const std::vector<size_t>& dims, size_t current_dim,
76  std::vector<typename type_of_array<T>::type>& buffer) {
77 
78  check_dimensions_vector(vec_multi_dim.size(), dims[current_dim],
79  current_dim);
80  for (typename std::vector<T>::const_iterator it = vec_multi_dim.begin();
81  it < vec_multi_dim.end(); ++it) {
82  vectors_to_single_buffer(*it, dims, current_dim + 1, buffer);
83  }
84 }
85 
86 // copy single buffer to multi dimensional vector, following dimensions
87 // specified
88 template <typename T>
89 inline typename std::vector<T>::iterator
90 single_buffer_to_vectors(typename std::vector<T>::iterator begin_buffer,
91  typename std::vector<T>::iterator end_buffer,
92  const std::vector<size_t>& dims,
93  const size_t current_dim,
94  std::vector<T>& vec_single_dim) {
95  const size_t n_elems = dims[current_dim];
96  typename std::vector<T>::iterator end_copy_iter =
97  std::min(begin_buffer + n_elems, end_buffer);
98  vec_single_dim.assign(begin_buffer, end_copy_iter);
99  return end_copy_iter;
100 }
101 
102 template <typename T, typename U>
103 inline typename std::vector<T>::iterator
104 single_buffer_to_vectors(typename std::vector<T>::iterator begin_buffer,
105  typename std::vector<T>::iterator end_buffer,
106  const std::vector<size_t>& dims,
107  const size_t current_dim,
108  std::vector<U>& vec_multi_dim) {
109 
110  const size_t n_elems = dims[current_dim];
111  vec_multi_dim.resize(n_elems);
112 
113  for (typename std::vector<U>::iterator it = vec_multi_dim.begin();
114  it < vec_multi_dim.end(); ++it) {
115  begin_buffer = single_buffer_to_vectors(begin_buffer, end_buffer, dims,
116  current_dim + 1, *it);
117  }
118  return begin_buffer;
119 }
120 
121 // apply conversion operations to basic scalar type
122 template <typename Scalar, class Enable = void>
124  inline data_converter(Scalar&, DataSpace&) {
125 
126  static_assert((std::is_arithmetic<Scalar>::value ||
127  std::is_enum<Scalar>::value ||
128  std::is_same<std::string, Scalar>::value),
129  "supported datatype should be an arithmetic value, a "
130  "std::string or a container/array");
131  }
132 
133  inline Scalar* transform_read(Scalar& datamem) { return &datamem; }
134 
135  inline Scalar* transform_write(Scalar& datamem) { return &datamem; }
136 
137  inline void process_result(Scalar&) {}
138 };
139 
140 // apply conversion operations to the incoming data
141 // if they are a cstyle array
142 template <typename CArray>
143 struct data_converter<CArray,
144  typename std::enable_if<(is_c_array<CArray>::value)>::type> {
145  inline data_converter(CArray&, DataSpace&) {}
146 
147  inline CArray& transform_read(CArray& datamem) { return datamem; }
148 
149  inline CArray& transform_write(CArray& datamem) { return datamem; }
150 
151  inline void process_result(CArray&) {}
152 };
153 
154 // apply conversion for vectors 1D
155 template <typename T>
157  std::vector<T>,
158  typename std::enable_if<(
159  std::is_same<T, typename type_of_array<T>::type>::value)>::type> {
160  inline data_converter(std::vector<T>&, DataSpace& space)
161  : _space(space) {
162  assert(is_1D(_space.getDimensions()));
163  }
164 
165  inline typename type_of_array<T>::type*
166  transform_read(std::vector<T>& vec) {
167  vec.resize(compute_total_size(_space.getDimensions()));
168  return vec.data();
169  }
170 
171  inline typename type_of_array<T>::type*
172  transform_write(std::vector<T>& vec) {
173  return vec.data();
174  }
175 
176  inline void process_result(std::vector<T>&) {}
177 
179 };
180 
181 // apply conversion to std::array
182 template <typename T, std::size_t S>
184  std::array<T, S>,
185  typename std::enable_if<(
186  std::is_same<T, typename type_of_array<T>::type>::value)>::type> {
187  inline data_converter(std::array<T, S>&, DataSpace& space) {
188  const auto dims = space.getDimensions();
189  if (!is_1D(dims)) {
190  throw DataSpaceException("Only 1D std::array supported currently.");
191  }
192  if (compute_total_size(dims) != S) {
193  std::ostringstream ss;
194  ss << "Impossible to pair DataSet with " << compute_total_size(dims)
195  << " elements into an array with " << S << " elements.";
196  throw DataSpaceException(ss.str());
197  }
198  }
199 
200  inline typename type_of_array<T>::type*
201  transform_read(std::array<T, S>& vec) {
202  return vec.data();
203  }
204 
205  inline typename type_of_array<T>::type*
206  transform_write(std::array<T, S>& vec) {
207  return vec.data();
208  }
209 
210  inline void process_result(std::array<T, S>&) {}
211 };
212 
213 #ifdef H5_USE_BOOST
214 // apply conversion to boost multi array
215 template <typename T, std::size_t Dims>
216 struct data_converter<boost::multi_array<T, Dims>, void> {
217 
218  typedef typename boost::multi_array<T, Dims> MultiArray;
219 
220  inline data_converter(MultiArray&, DataSpace& space)
221  : _dims(space.getDimensions()) {
222  assert(_dims.size() == Dims);
223  }
224 
225  inline typename type_of_array<T>::type* transform_read(MultiArray& array) {
226  if (std::equal(_dims.begin(), _dims.end(), array.shape()) == false) {
227  boost::array<typename MultiArray::index, Dims> ext;
228  std::copy(_dims.begin(), _dims.end(), ext.begin());
229  array.resize(ext);
230  }
231  return array.data();
232  }
233 
234  inline typename type_of_array<T>::type* transform_write(MultiArray& array) {
235  return array.data();
236  }
237 
238  inline void process_result(MultiArray&) {}
239 
240  std::vector<size_t> _dims;
241 };
242 
243 // apply conversion to boost matrix ublas
244 template <typename T>
245 struct data_converter<boost::numeric::ublas::matrix<T>, void> {
246 
247  typedef typename boost::numeric::ublas::matrix<T> Matrix;
248 
249  inline data_converter(Matrix&, DataSpace& space)
250  : _dims(space.getDimensions()) {
251  assert(_dims.size() == 2);
252  }
253 
254  inline typename type_of_array<T>::type* transform_read(Matrix& array) {
255  boost::array<std::size_t, 2> sizes = {{array.size1(), array.size2()}};
256 
257  if (std::equal(_dims.begin(), _dims.end(), sizes.begin()) == false) {
258  array.resize(_dims[0], _dims[1], false);
259  array(0, 0) = 0; // force initialization
260  }
261 
262  return &(array(0, 0));
263  }
264 
265  inline typename type_of_array<T>::type* transform_write(Matrix& array) {
266  return &(array(0, 0));
267  }
268 
269  inline void process_result(Matrix&) {}
270 
271  std::vector<size_t> _dims;
272 };
273 #endif
274 
275 // apply conversion for vectors nested vectors
276 template <typename T>
277 struct data_converter<std::vector<T>,
278  typename std::enable_if<(is_container<T>::value)>::type> {
279  inline data_converter(std::vector<T>&, DataSpace& space)
280  : _dims(space.getDimensions()) {}
281 
282  inline typename type_of_array<T>::type*
283  transform_read(std::vector<T>&) {
284  _vec_align.resize(compute_total_size(_dims));
285  return _vec_align.data();
286  }
287 
288  inline typename type_of_array<T>::type*
289  transform_write(std::vector<T>& vec) {
290  _vec_align.reserve(compute_total_size(_dims));
291  vectors_to_single_buffer<T>(vec, _dims, 0, _vec_align);
292  return _vec_align.data();
293  }
294 
295  inline void process_result(std::vector<T>& vec) {
296  single_buffer_to_vectors<typename type_of_array<T>::type, T>(
297  _vec_align.begin(), _vec_align.end(), _dims, 0, vec);
298  }
299 
300  std::vector<size_t> _dims;
301  std::vector<typename type_of_array<T>::type> _vec_align;
302 };
303 
304 
305 // apply conversion to scalar string
306 template <>
307 struct data_converter<std::string, void> {
308  inline data_converter(std::string& vec, DataSpace& space)
309  : _c_vec(nullptr), _space(space) {
310  (void)vec;
311  }
312 
313  // create a C vector adapted to HDF5
314  // fill last element with NULL to identify end
315  inline char** transform_read(std::string&) { return (&_c_vec); }
316 
317  static inline char* char_converter(const std::string& str) {
318  return const_cast<char*>(str.c_str());
319  }
320 
321  inline char** transform_write(std::string& str) {
322  _c_vec = const_cast<char*>(str.c_str());
323  return &_c_vec;
324  }
325 
326  inline void process_result(std::string& str) {
327  assert(_c_vec != nullptr);
328  str = std::string(_c_vec);
329 
330  if (_c_vec != NULL) {
331  AtomicType<std::string> str_type;
332  (void)H5Dvlen_reclaim(str_type.getId(), _space.getId(), H5P_DEFAULT,
333  &_c_vec);
334  }
335  }
336 
337  char* _c_vec;
339 };
340 
341 // apply conversion for vectors of string (derefence)
342 template <>
343 struct data_converter<std::vector<std::string>, void> {
344  inline data_converter(std::vector<std::string>& vec, DataSpace& space)
345  : _space(space) {
346  (void)vec;
347  }
348 
349  // create a C vector adapted to HDF5
350  // fill last element with NULL to identify end
351  inline char** transform_read(std::vector<std::string>& vec) {
352  (void)vec;
353  _c_vec.resize(_space.getDimensions()[0], NULL);
354  return (&_c_vec[0]);
355  }
356 
357  static inline char* char_converter(const std::string& str) {
358  return const_cast<char*>(str.c_str());
359  }
360 
361  inline char** transform_write(std::vector<std::string>& vec) {
362  _c_vec.resize(vec.size() + 1, NULL);
363  std::transform(vec.begin(), vec.end(), _c_vec.begin(), &char_converter);
364  return (&_c_vec[0]);
365  }
366 
367  inline void process_result(std::vector<std::string>& vec) {
368  (void)vec;
369  vec.resize(_c_vec.size());
370  for (size_t i = 0; i < vec.size(); ++i) {
371  vec[i] = std::string(_c_vec[i]);
372  }
373 
374  if (_c_vec.empty() == false && _c_vec[0] != NULL) {
375  AtomicType<std::string> str_type;
376  (void)H5Dvlen_reclaim(str_type.getId(), _space.getId(), H5P_DEFAULT,
377  &(_c_vec[0]));
378  }
379  }
380 
381  std::vector<char*> _c_vec;
383 };
384 }
385 }
386 
387 #endif // H5CONVERTER_MISC_HPP
const size_t size_dataset
static char * char_converter(const std::string &str)
Exception specific to HighFive DataSet interface.
void vectors_to_single_buffer(const std::vector< T > &vec_single_dim, const std::vector< size_t > &dims, const size_t current_dim, std::vector< T > &buffer)
Exception specific to HighFive DataSpace interface.
Definition: H5Exception.hpp:98
data_converter(Scalar &, DataSpace &)
hid_t getId() const
getId
Scalar * transform_write(Scalar &datamem)
size_t compute_total_size(const std::vector< size_t > &dims)
bool equal(InputIterator p1, InputIterator p2)
Determines if two points have the exact same coordinates.
Definition: psimpl.h:192
std::vector< size_t > getDimensions(const HighFive::Group &g, const std::string &datasetName)
Scalar * transform_read(Scalar &datamem)
std::vector< T >::iterator single_buffer_to_vectors(typename std::vector< T >::iterator begin_buffer, typename std::vector< T >::iterator end_buffer, const std::vector< size_t > &dims, const size_t current_dim, std::vector< T > &vec_single_dim)
create an HDF5 DataType from a C++ type
Definition: H5DataType.hpp:41
data_converter(std::vector< std::string > &vec, DataSpace &space)
bool is_1D(const std::vector< size_t > &dims)
void check_dimensions_vector(size_t size_vec, size_t size_dataset, size_t dimension)
#define NULL
Definition: mydefs.hpp:141
std::vector< size_t > getDimensions() const
getDimensions
PointBufferPtr transform(PointBufferPtr pc_in, const Transformd &T)
Definition: qttf.cpp:32


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06