Thomas
Thomas

Reputation: 95

C++ HDF5 extract one member of a compound data type

I am writting a c++ library that reads hdf5 files generated by another library.

Those hdf5 files contains a lot of compound dataset with various compound datatypes. I wish to translate each compound datatype to a C++ structure.

For strings (variable length or fixed sized array of characters), I want use std::string in the C++ structure.

Currently, I use an intermediate C structure (using char* or char[] variables) that I then convert to final C++ structure. However, this leads to a lot of boilerplate code.

If I could extract the data members by members, I could do something like:

std::string name = extract<std::string>(d,"name");

where d is a compound data set.

Is it possible

Upvotes: 0

Views: 1009

Answers (1)

Thomas
Thomas

Reputation: 95

I have found a working solution. I post it here, maybe someone will find it usefull. The idea is to create a CompoundExtractor object which contains a buffer in which the whole compound is read. Then, one can extract the members one by one using a template extract method. At this stage, appropriate specialisation (not reported here) allow an appropriate handling of strings. Regards,

struct MADNEX_VISIBILITY_EXPORT CompoundExtractor
{
  /*!
   * \brief constructor
   * \param[in] d: data set
   */
  CompoundExtractor(const DataSet&);
  //! destructor
  ~CompoundExtractor();
  /*!
   * \return a member of the compound of the given type
   * \param[in] n: member name
   */
  template<typename T>
  T extract(const std::string&) const;
  /*!
   * \return a member of the compound of the given type
   * \param[in] n: member name
   */
  template<typename T>
  T extract(const char *) const;
private:
  //! the description of the compound data type
  H5::CompType ctype;
  //! an intermediate storage for the compound data type
  std::vector<char> data;
}; // end of CompoundExtractor

template<typename T>
T CompoundExtractor::extract(const char *n) const{
  const auto i = this->ctype.getMemberIndex(n);
  const auto o = this->ctype.getMemberOffset(i);
  return *(reinterpret_cast<const T *>(this->data.data()+o));
} // end of CompoundExtractor::extract

template<typename T>
T CompoundExtractor::extract(const std::string& n) const{
  const auto i = this->ctype.getMemberIndex(n);
  const auto o = this->ctype.getMemberOffset(i);
  return *(reinterpret_cast<const T *>(this->data.data()+o));
} // end of CompoundExtractor::extract

CompoundExtractor::CompoundExtractor(const DataSet& d)
{
  const auto dtype = d.getDataType();
  if(dtype.getClass()!=H5T_COMPOUND){
    throw(std::runtime_error("CompoundExtractor: invalid data set"));
  }
  this->ctype = H5::CompType(d);
  this->data.resize(ctype.getSize());
  d.read(this->data.data(),ctype);
}

CompoundExtractor::~CompoundExtractor() = default;

Upvotes: 0

Related Questions