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