Reputation: 95
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
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