9#ifndef H5CONVERTER_MISC_HPP
10#define H5CONVERTER_MISC_HPP
23#include <boost/serialization/vector.hpp>
24#include <boost/multi_array.hpp>
25#include <boost/numeric/ublas/matrix.hpp>
31#include "../H5Reference.hpp"
38inline bool is_1D(
const std::vector<size_t>& dims) {
39 return std::count_if(dims.begin(), dims.end(), [](
size_t i){ return i > 1; }) < 2;
42inline size_t compute_total_size(
const std::vector<size_t>& dims) {
43 return std::accumulate(dims.begin(), dims.end(),
size_t{1u},
44 std::multiplies<size_t>());
47inline void check_dimensions_vector(
size_t size_vec,
size_t size_dataset,
49 if (size_vec != size_dataset) {
50 std::ostringstream ss;
51 ss <<
"Mismatch between vector size (" << size_vec
52 <<
") and dataset size (" << size_dataset;
53 ss <<
") on dimension " << dimension;
54 throw DataSetException(ss.str());
64inline void vectors_to_single_buffer(
const std::vector<T>& vec_single_dim,
65 const std::vector<size_t>& dims,
66 const size_t current_dim,
67 std::vector<T>& buffer) {
69 check_dimensions_vector(vec_single_dim.size(), dims[current_dim], current_dim);
70 buffer.insert(buffer.end(), vec_single_dim.begin(), vec_single_dim.end());
74template <typename T, typename U = typename inspector<T>::base_type>
76vectors_to_single_buffer(
const std::vector<T>& vec_multi_dim,
77 const std::vector<size_t>& dims,
79 std::vector<U>& buffer) {
81 check_dimensions_vector(vec_multi_dim.size(), dims[current_dim], current_dim);
82 for (
const auto& it : vec_multi_dim) {
83 vectors_to_single_buffer(it, dims, current_dim + 1, buffer);
89inline typename std::vector<T>::const_iterator
90single_buffer_to_vectors(
typename std::vector<T>::const_iterator begin_buffer,
91 typename std::vector<T>::const_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 auto n_elems =
static_cast<long>(dims[current_dim]);
96 const auto end_copy_iter = std::min(begin_buffer + n_elems, end_buffer);
97 vec_single_dim.assign(begin_buffer, end_copy_iter);
101template <typename T, typename U = typename inspector<T>::base_type>
102inline typename std::vector<U>::const_iterator
103single_buffer_to_vectors(
typename std::vector<U>::const_iterator begin_buffer,
104 typename std::vector<U>::const_iterator end_buffer,
105 const std::vector<size_t>& dims,
106 const size_t current_dim,
107 std::vector<std::vector<T>>& vec_multi_dim) {
108 const size_t n_elems = dims[current_dim];
109 vec_multi_dim.resize(n_elems);
111 for (
auto& subvec : vec_multi_dim) {
112 begin_buffer = single_buffer_to_vectors(
113 begin_buffer, end_buffer, dims, current_dim + 1, subvec);
123template <
typename Scalar,
class Enable>
127 static_assert((std::is_arithmetic<Scalar>::value ||
128 std::is_enum<Scalar>::value ||
129 std::is_same<std::vector<const char*>, Scalar>::value ||
130 std::is_same<std::string, Scalar>::value ||
131 std::is_same<std::complex<float>, Scalar>::value ||
132 std::is_same<std::complex<double>, Scalar>::value),
133 "supported datatype should be an arithmetic value, a "
134 "std::string or a container/array");
137 inline Scalar* transform_read(Scalar& datamem)
const noexcept {
141 inline const Scalar* transform_write(
const Scalar& datamem)
const noexcept {
145 inline void process_result(Scalar&)
const noexcept {}
151template <
typename CArray>
153 typename std::enable_if<(is_c_array<CArray>::value)>::type> {
156 inline CArray& transform_read(CArray& datamem)
const noexcept {
160 inline const CArray& transform_write(
const CArray& datamem)
const noexcept {
164 inline void process_result(CArray&)
const noexcept {}
169template <
typename Container,
170 typename T =
typename inspector<Container>::base_type>
172 typedef T value_type;
175 : _space(space), _type(type) {}
178 inline value_type* transform_read(Container& vec) {
182 vec.resize(compute_total_size(dims));
186 inline const value_type* transform_write(
const Container& vec)
const noexcept {
190 inline void process_result(Container&)
noexcept {}
197template <typename Container, typename T = typename inspector<Container>::base_type>
199 typedef T value_type;
202 : _space(space), _type(type) {}
204 inline void getVLenMemberAndOffsets(
const DataType& type, std::vector<int>& vlen_members, std::vector<size_t>& member_offsets){
205 int nmembers = H5Tget_nmembers(type.
getId());
206 int start_offset = 0;
207 for (
int i = 0; i < nmembers; i++){
208 H5T_class_t memberclass = H5Tget_member_class(type.
getId(), i);
209 if (memberclass == H5T_STRING){
210 DataType str_type = DataType::FromId(H5Tget_member_type(type.
getId(), i),
false);
212 vlen_members.push_back(member_offsets.size());
214 }
else if (memberclass == H5T_COMPOUND){
215 DataType nested_compound_type = DataType::FromId(H5Tget_member_type(type.
getId(), i),
false);
216 member_offsets.push_back(start_offset + H5Tget_member_offset(type.
getId(), i));
217 getVLenMemberAndOffsets(nested_compound_type, vlen_members, member_offsets);
221 if (i == 0 && member_offsets.size() != 0){
222 start_offset = member_offsets[member_offsets.size()-1];
226 member_offsets.push_back(start_offset + H5Tget_member_offset(type.
getId(), i));
231 inline value_type* transform_read(Container& vec) {
235 vec.resize(compute_total_size(dims));
238 for (
size_t i = 0; i < vec.size(); i++){
239 vec[i].~value_type();
245 inline const value_type* transform_write(
const Container& vec)
const noexcept {
249 inline void process_result(Container& vec)
noexcept {
250 if (_type.
getClass() != DataTypeClass::Compound)
254 std::vector<int> vlen_members;
255 std::vector<size_t> member_offsets;
256 getVLenMemberAndOffsets(_type, vlen_members, member_offsets);
258 if (vlen_members.size() < 1)
261 size_t nmembers = member_offsets.size();
262 size_t type_size = _type.
getSize();
264 for (
size_t i = 0; i < vec.size(); i++){
266 for (
int member = 0; member < nmembers; member++){
267 if (ind < vlen_members.size() && member == vlen_members[ind]){
268 memcpy(&str_ptr, (
char *) vec.data() + member_offsets[member] + type_size*i,
sizeof(str_ptr));
270 ::new((
char *) vec.data() + member_offsets[member] + type_size*i) std::string(str_ptr);
287 typename std::enable_if<(
288 std::is_same<T, typename inspector<T>::base_type>::value &&
289 !std::is_same<T, Reference>::value &&
290 !std::is_class<T>::value
301 typename std::enable_if<(
302 std::is_same<T, typename inspector<T>::base_type>::value &&
303 !std::is_same<T, Reference>::value &&
304 std::is_class<T>::value
312template <
typename T, std::
size_t S>
315 typename std::enable_if<(
316 std::is_same<T, typename inspector<T>::base_type>::value)>::type>
326 if (compute_total_size(dims) != S) {
327 std::ostringstream ss;
328 ss <<
"Impossible to pair DataSet with " << compute_total_size(dims)
329 <<
" elements into an array with " << S <<
" elements.";
334inline T* transform_read(std::array<T, S>& vec)
const noexcept {
342template <
typename T, std::
size_t Dims>
345 using MultiArray = boost::multi_array<T, Dims>;
346 using value_type =
typename inspector<T>::base_type;
349 inline value_type* transform_read(MultiArray& array) {
350 auto&& dims = this->_space.getDimensions();
351 if (std::equal(dims.begin(), dims.end(), array.shape()) ==
false) {
352 boost::array<typename MultiArray::index, Dims> ext;
353 std::copy(dims.begin(), dims.end(), ext.begin());
363struct data_converter<boost::numeric::ublas::matrix<T>, void>
364 :
public container_converter<boost::numeric::ublas::matrix<T>> {
365 using Matrix = boost::numeric::ublas::matrix<T>;
366 using value_type =
typename inspector<T>::base_type;
368 inline data_converter(
const DataSpace& space,
const DataType& type) : container_converter<Matrix>(space) {
369 assert(space.getDimensions().size() == 2);
372 inline value_type* transform_read(Matrix& array) {
373 boost::array<std::size_t, 2> sizes = {{array.size1(), array.size2()}};
374 auto&& _dims = this->_space.getDimensions();
375 if (std::equal(_dims.begin(), _dims.end(), sizes.begin()) ==
false) {
376 array.resize(_dims[0], _dims[1],
false);
379 return &(array(0, 0));
382 inline const value_type* transform_write(
const Matrix& array)
const noexcept {
383 return &(array(0, 0));
392 typename std::enable_if<(is_container<T>::value)>::type> {
393 using value_type =
typename inspector<T>::base_type;
398 inline value_type* transform_read(std::vector<T>&) {
399 _vec_align.resize(compute_total_size(_dims));
400 return _vec_align.data();
403 inline const value_type* transform_write(
const std::vector<T>& vec) {
404 _vec_align.reserve(compute_total_size(_dims));
405 vectors_to_single_buffer<T>(vec, _dims, 0, _vec_align);
406 return _vec_align.data();
409 inline void process_result(std::vector<T>& vec)
const {
410 single_buffer_to_vectors(
411 _vec_align.cbegin(), _vec_align.cend(), _dims, 0, vec);
414 std::vector<size_t> _dims;
415 std::vector<typename inspector<T>::base_type> _vec_align;
422 using value_type =
const char*;
430 inline value_type* transform_read(std::string&)
noexcept {
434 inline const value_type* transform_write(
const std::string& str)
noexcept {
435 _c_vec = str.c_str();
439 inline void process_result(std::string& str) {
440 assert(_c_vec !=
nullptr);
441 str = std::string(_c_vec);
443 if (_c_vec !=
nullptr) {
445 (void)H5Dvlen_reclaim(str_type.
getId(
false), _space.getId(
false), H5P_DEFAULT,
457 using value_type =
const char*;
464 inline value_type* transform_read(std::vector<std::string>&) {
465 _c_vec.resize(_space.getDimensions()[0], NULL);
466 return _c_vec.data();
469 inline const value_type* transform_write(
const std::vector<std::string>& vec) {
470 _c_vec.resize(vec.size() + 1, NULL);
471 std::transform(vec.begin(), vec.end(), _c_vec.begin(),
472 [](
const std::string& str){ return str.c_str(); });
473 return _c_vec.data();
476 inline void process_result(std::vector<std::string>& vec) {
477 vec.resize(_c_vec.size());
478 for (
size_t i = 0; i < vec.size(); ++i) {
479 vec[i] = std::string(_c_vec[i]);
482 if (_c_vec.empty() ==
false && _c_vec[0] != NULL) {
484 (void)H5Dvlen_reclaim(str_type.
getId(
false), _space.getId(
false), H5P_DEFAULT,
489 std::vector<value_type> _c_vec;
496template <std::
size_t N>
511 inline hobj_ref_t* transform_read(std::vector<Reference>& vec) {
512 auto total_size = compute_total_size(_dims);
513 _vec_align.resize(total_size);
514 vec.resize(total_size);
515 return _vec_align.data();
518 inline const hobj_ref_t* transform_write(
const std::vector<Reference>& vec) {
519 _vec_align.resize(compute_total_size(_dims));
520 for (
size_t i = 0; i < vec.size(); ++i) {
521 vec[i].create_ref(&_vec_align[i]);
523 return _vec_align.data();
526 inline void process_result(std::vector<Reference>& vec)
const {
527 auto* href =
const_cast<hobj_ref_t*
>(_vec_align.data());
528 for (
auto& ref : vec) {
533 std::vector<size_t> _dims;
534 std::vector<typename inspector<hobj_ref_t>::base_type> _vec_align;
543#include "H5ConverterEigen_misc.hpp"
create an HDF5 DataType from a C++ type
Definition H5DataType.hpp:124
Exception specific to h5gt DataSpace interface.
Definition H5Exception.hpp:99
Class representing the space (dimensions) of a dataset.
Definition H5DataSpace.hpp:37
std::vector< size_t > getDimensions() const
getDimensions
Definition H5Dataspace_misc.hpp:103
HDF5 Data Type.
Definition H5DataType.hpp:48
size_t getSize() const
Returns the length (in bytes) of this type elements.
Definition H5DataType_misc.hpp:36
DataTypeClass getClass() const
Return the fundamental type.
Definition H5DataType_misc.hpp:32
bool isVariableStr() const
Returns whether the type is a variable-length string.
Definition H5DataType_misc.hpp:55
A structure representing a set of fixed-length strings.
Definition H5DataType.hpp:305
hid_t getId(const bool &increaseRefCount=false) const noexcept
getId
Definition H5Object_misc.hpp:172
An HDF5 (object) reference type.
Definition H5Reference.hpp:31
Definition H5Converter_misc.hpp:171
Definition H5Converter_misc.hpp:198
Definition H5Converter_misc.hpp:124