9#ifndef H5CONVERTER_MISC_HPP
10#define H5CONVERTER_MISC_HPP
22#include <boost/serialization/vector.hpp>
23#include <boost/multi_array.hpp>
24#include <boost/numeric/ublas/matrix.hpp>
30#include "../H5Reference.hpp"
37inline bool is_1D(
const std::vector<size_t>& dims) {
38 return std::count_if(dims.begin(), dims.end(), [](
size_t i){ return i > 1; }) < 2;
41inline size_t compute_total_size(
const std::vector<size_t>& dims) {
42 return std::accumulate(dims.begin(), dims.end(),
size_t{1u},
43 std::multiplies<size_t>());
46inline void check_dimensions_vector(
size_t size_vec,
size_t size_dataset,
48 if (size_vec != size_dataset) {
49 std::ostringstream ss;
50 ss <<
"Mismatch between vector size (" << size_vec
51 <<
") and dataset size (" << size_dataset;
52 ss <<
") on dimension " << dimension;
53 throw DataSetException(ss.str());
63inline void vectors_to_single_buffer(
const std::vector<T>& vec_single_dim,
64 const std::vector<size_t>& dims,
65 const size_t current_dim,
66 std::vector<T>& buffer) {
68 check_dimensions_vector(vec_single_dim.size(), dims[current_dim], current_dim);
69 buffer.insert(buffer.end(), vec_single_dim.begin(), vec_single_dim.end());
73template <typename T, typename U = typename inspector<T>::base_type>
75vectors_to_single_buffer(
const std::vector<T>& vec_multi_dim,
76 const std::vector<size_t>& dims,
78 std::vector<U>& buffer) {
80 check_dimensions_vector(vec_multi_dim.size(), dims[current_dim], current_dim);
81 for (
const auto& it : vec_multi_dim) {
82 vectors_to_single_buffer(it, dims, current_dim + 1, buffer);
88inline typename std::vector<T>::const_iterator
89single_buffer_to_vectors(
typename std::vector<T>::const_iterator begin_buffer,
90 typename std::vector<T>::const_iterator end_buffer,
91 const std::vector<size_t>& dims,
92 const size_t current_dim,
93 std::vector<T>& vec_single_dim) {
94 const auto n_elems =
static_cast<long>(dims[current_dim]);
95 const auto end_copy_iter = std::min(begin_buffer + n_elems, end_buffer);
96 vec_single_dim.assign(begin_buffer, end_copy_iter);
100template <typename T, typename U = typename inspector<T>::base_type>
101inline typename std::vector<U>::const_iterator
102single_buffer_to_vectors(
typename std::vector<U>::const_iterator begin_buffer,
103 typename std::vector<U>::const_iterator end_buffer,
104 const std::vector<size_t>& dims,
105 const size_t current_dim,
106 std::vector<std::vector<T>>& vec_multi_dim) {
107 const size_t n_elems = dims[current_dim];
108 vec_multi_dim.resize(n_elems);
110 for (
auto& subvec : vec_multi_dim) {
111 begin_buffer = single_buffer_to_vectors(
112 begin_buffer, end_buffer, dims, current_dim + 1, subvec);
122template <
typename Scalar,
class Enable>
123struct data_converter {
124 inline data_converter(
const DataSpace&)
noexcept {
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");
133 inline Scalar* transform_read(Scalar& datamem)
const noexcept {
137 inline const Scalar* transform_write(
const Scalar& datamem)
const noexcept {
141 inline void process_result(Scalar&)
const noexcept {}
147template <
typename CArray>
148struct data_converter<CArray,
149 typename std::enable_if<(is_c_array<CArray>::value)>::type> {
150 inline data_converter(
const DataSpace&)
noexcept {}
152 inline CArray& transform_read(CArray& datamem)
const noexcept {
156 inline const CArray& transform_write(
const CArray& datamem)
const noexcept {
160 inline void process_result(CArray&)
const noexcept {}
164template <typename Container, typename T = typename inspector<Container>::base_type>
165struct container_converter {
166 typedef T value_type;
168 inline container_converter(
const DataSpace& space)
172 inline value_type* transform_read(Container& vec)
const {
173 auto&& dims = _space.getDimensions();
175 throw DataSpaceException(
"Dataset cant be converted to 1D");
176 vec.resize(compute_total_size(dims));
180 inline const value_type* transform_write(
const Container& vec)
const noexcept {
184 inline void process_result(Container&)
const noexcept {}
192struct data_converter<
194 typename std::enable_if<(
195 std::is_same<T, typename inspector<T>::base_type>::value &&
196 !std::is_same<T, Reference>::value
198 :
public container_converter<std::vector<T>> {
200 using container_converter<std::vector<T>>::container_converter;
205template <
typename T, std::
size_t S>
206struct data_converter<
208 typename std::enable_if<(
209 std::is_same<T, typename inspector<T>::base_type>::value)>::type>
210 :
public container_converter<std::array<T, S>> {
212 inline data_converter(
const DataSpace& space)
213 : container_converter<std::array<T, S>>(space)
215 auto&& dims = space.getDimensions();
217 throw DataSpaceException(
"Only 1D std::array supported currently.");
219 if (compute_total_size(dims) != S) {
220 std::ostringstream ss;
221 ss <<
"Impossible to pair DataSet with " << compute_total_size(dims)
222 <<
" elements into an array with " << S <<
" elements.";
223 throw DataSpaceException(ss.str());
227 inline T* transform_read(std::array<T, S>& vec)
const noexcept {
235template <
typename T, std::
size_t Dims>
236struct data_converter<boost::multi_array<T, Dims>, void>
237 :
public container_converter<boost::multi_array<T, Dims>> {
238 using MultiArray = boost::multi_array<T, Dims>;
239 using value_type =
typename inspector<T>::base_type;
240 using container_converter<MultiArray>::container_converter;
242 inline value_type* transform_read(MultiArray& array) {
243 auto&& dims = this->_space.getDimensions();
244 if (std::equal(dims.begin(), dims.end(), array.shape()) ==
false) {
245 boost::array<typename MultiArray::index, Dims> ext;
246 std::copy(dims.begin(), dims.end(), ext.begin());
256struct data_converter<boost::numeric::ublas::matrix<T>, void>
257 :
public container_converter<boost::numeric::ublas::matrix<T>> {
258 using Matrix = boost::numeric::ublas::matrix<T>;
259 using value_type =
typename inspector<T>::base_type;
261 inline data_converter(
const DataSpace& space) : container_converter<Matrix>(space) {
262 assert(space.getDimensions().size() == 2);
265 inline value_type* transform_read(Matrix& array) {
266 boost::array<std::size_t, 2> sizes = {{array.size1(), array.size2()}};
267 auto&& _dims = this->_space.getDimensions();
268 if (std::equal(_dims.begin(), _dims.end(), sizes.begin()) ==
false) {
269 array.resize(_dims[0], _dims[1],
false);
272 return &(array(0, 0));
275 inline const value_type* transform_write(
const Matrix& array)
const noexcept {
276 return &(array(0, 0));
284struct data_converter<std::vector<T>,
285 typename std::enable_if<(is_container<T>::value)>::type> {
286 using value_type =
typename inspector<T>::base_type;
288 inline data_converter(
const DataSpace& space)
289 : _dims(space.getDimensions()) {}
291 inline value_type* transform_read(std::vector<T>&) {
292 _vec_align.resize(compute_total_size(_dims));
293 return _vec_align.data();
296 inline const value_type* transform_write(
const std::vector<T>& vec) {
297 _vec_align.reserve(compute_total_size(_dims));
298 vectors_to_single_buffer<T>(vec, _dims, 0, _vec_align);
299 return _vec_align.data();
302 inline void process_result(std::vector<T>& vec)
const {
303 single_buffer_to_vectors(
304 _vec_align.cbegin(), _vec_align.cend(), _dims, 0, vec);
307 std::vector<size_t> _dims;
308 std::vector<typename inspector<T>::base_type> _vec_align;
314struct data_converter<std::string, void> {
315 using value_type =
const char*;
317 inline data_converter(
const DataSpace& space) noexcept
323 inline value_type* transform_read(std::string&)
noexcept {
327 inline const value_type* transform_write(
const std::string& str)
noexcept {
328 _c_vec = str.c_str();
332 inline void process_result(std::string& str) {
333 assert(_c_vec !=
nullptr);
334 str = std::string(_c_vec);
336 if (_c_vec !=
nullptr) {
337 AtomicType<std::string> str_type;
338 (void)H5Dvlen_reclaim(str_type.getId(), _space.getId(), H5P_DEFAULT,
349struct data_converter<std::vector<std::string>, void> {
350 using value_type =
const char*;
352 inline data_converter(
const DataSpace& space) noexcept
357 inline value_type* transform_read(std::vector<std::string>&) {
358 _c_vec.resize(_space.getDimensions()[0], NULL);
359 return _c_vec.data();
362 inline const value_type* transform_write(
const std::vector<std::string>& vec) {
363 _c_vec.resize(vec.size() + 1, NULL);
364 std::transform(vec.begin(), vec.end(), _c_vec.begin(),
365 [](
const std::string& str){ return str.c_str(); });
366 return _c_vec.data();
369 inline void process_result(std::vector<std::string>& vec) {
370 vec.resize(_c_vec.size());
371 for (
size_t i = 0; i < vec.size(); ++i) {
372 vec[i] = std::string(_c_vec[i]);
375 if (_c_vec.empty() ==
false && _c_vec[0] != NULL) {
376 AtomicType<std::string> str_type;
377 (void)H5Dvlen_reclaim(str_type.getId(), _space.getId(), H5P_DEFAULT,
382 std::vector<value_type> _c_vec;
389template <std::
size_t N>
390struct data_converter<FixedLenStringArray<N>, void>
391 :
public container_converter<FixedLenStringArray<N>, char> {
392 using container_converter<FixedLenStringArray<N>,
char>::container_converter;
396struct data_converter<std::vector<Reference>, void> {
397 inline data_converter(
const DataSpace& space)
398 : _dims(space.getDimensions()) {
400 throw DataSpaceException(
"Only 1D std::array supported currently.");
404 inline hobj_ref_t* transform_read(std::vector<Reference>& vec) {
405 auto total_size = compute_total_size(_dims);
406 _vec_align.resize(total_size);
407 vec.resize(total_size);
408 return _vec_align.data();
411 inline const hobj_ref_t* transform_write(
const std::vector<Reference>& vec) {
412 _vec_align.resize(compute_total_size(_dims));
413 for (
size_t i = 0; i < vec.size(); ++i) {
414 vec[i].create_ref(&_vec_align[i]);
416 return _vec_align.data();
419 inline void process_result(std::vector<Reference>& vec)
const {
420 auto* href =
const_cast<hobj_ref_t*
>(_vec_align.data());
421 for (
auto& ref : vec) {
426 std::vector<size_t> _dims;
427 std::vector<typename inspector<hobj_ref_t>::base_type> _vec_align;
Definition H5_definitions.hpp:15