From 559ad0d570db114a51dfbac22b742ac18db3916d Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Mon, 4 Dec 2023 09:13:11 +0100 Subject: [PATCH] Wrap all used H5T functions. --- include/highfive/H5DataType.hpp | 20 +-- include/highfive/bits/H5Attribute_misc.hpp | 2 +- include/highfive/bits/H5DataType_misc.hpp | 50 +++--- include/highfive/bits/H5Node_traits_misc.hpp | 11 +- include/highfive/bits/H5Slice_traits_misc.hpp | 3 +- include/highfive/bits/h5_wrapper.hpp | 12 ++ include/highfive/bits/h5t_wrapper.hpp | 158 ++++++++++++++++++ 7 files changed, 204 insertions(+), 52 deletions(-) create mode 100644 include/highfive/bits/h5_wrapper.hpp diff --git a/include/highfive/H5DataType.hpp b/include/highfive/H5DataType.hpp index 1c28626bf..0d596965f 100644 --- a/include/highfive/H5DataType.hpp +++ b/include/highfive/H5DataType.hpp @@ -19,6 +19,9 @@ #include "bits/string_padding.hpp" #include "H5PropertyList.hpp" +#include "bits/h5_wrapper.hpp" +#include "bits/h5t_wrapper.hpp" + namespace HighFive { @@ -235,21 +238,16 @@ class CompoundType: public DataType { ss << "hid " << _hid << " does not refer to a compound data type"; throw DataTypeException(ss.str()); } - int result = H5Tget_nmembers(_hid); - if (result < 0) { - throw DataTypeException("Could not get members of compound datatype"); - } - size_t n_members = static_cast(result); + size_t n_members = static_cast(detail::h5t_get_nmembers(_hid)); members.reserve(n_members); for (unsigned i = 0; i < n_members; i++) { - char* name = H5Tget_member_name(_hid, i); - size_t offset = H5Tget_member_offset(_hid, i); - hid_t member_hid = H5Tget_member_type(_hid, i); + char* name = detail::h5t_get_member_name(_hid, i); + size_t offset = detail::h5t_get_member_offset(_hid, i); + hid_t member_hid = detail::h5t_get_member_type(_hid, i); DataType member_type{member_hid}; members.emplace_back(std::string(name), member_type, offset); - if (H5free_memory(name) < 0) { - throw DataTypeException("Could not free names from the compound datatype"); - } + + detail::h5_free_memory(name); } } diff --git a/include/highfive/bits/H5Attribute_misc.hpp b/include/highfive/bits/H5Attribute_misc.hpp index 651678829..939e111fd 100644 --- a/include/highfive/bits/H5Attribute_misc.hpp +++ b/include/highfive/bits/H5Attribute_misc.hpp @@ -94,7 +94,7 @@ inline void Attribute::read(T& array) const { if (c == DataTypeClass::VarLen || t.isVariableStr()) { #if H5_VERSION_GE(1, 12, 0) // This one have been created in 1.12.0 - (void) H5Treclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer()); + (void) detail::h5t_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer()); #else // This one is deprecated since 1.12.0 (void) H5Dvlen_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer()); diff --git a/include/highfive/bits/H5DataType_misc.hpp b/include/highfive/bits/H5DataType_misc.hpp index e579d611d..698d8fa28 100644 --- a/include/highfive/bits/H5DataType_misc.hpp +++ b/include/highfive/bits/H5DataType_misc.hpp @@ -16,7 +16,6 @@ #endif #include -#include #ifdef H5_USE_HALF_FLOAT #include @@ -38,7 +37,7 @@ inline bool DataType::empty() const noexcept { } inline DataTypeClass DataType::getClass() const { - return convert_type_class(H5Tget_class(_hid)); + return convert_type_class(detail::h5t_get_class(_hid)); } inline size_t DataType::getSize() const { @@ -46,7 +45,7 @@ inline size_t DataType::getSize() const { } inline bool DataType::operator==(const DataType& other) const { - return (H5Tequal(_hid, other._hid) > 0); + return detail::h5t_equal(_hid, other._hid) > 0; } inline bool DataType::operator!=(const DataType& other) const { @@ -54,11 +53,7 @@ inline bool DataType::operator!=(const DataType& other) const { } inline bool DataType::isVariableStr() const { - auto var_value = H5Tis_variable_str(_hid); - if (var_value < 0) { - HDF5ErrMapper::ToException("Unable to define datatype size to variable"); - } - return static_cast(var_value); + return detail::h5t_is_variable_str(_hid) > 0; } inline bool DataType::isFixedLenStr() const { @@ -66,7 +61,7 @@ inline bool DataType::isFixedLenStr() const { } inline bool DataType::isReference() const { - return H5Tequal(_hid, H5T_STD_REF_OBJ) > 0; + return detail::h5t_equal(_hid, H5T_STD_REF_OBJ) > 0; } inline StringType DataType::asStringType() const { @@ -183,11 +178,11 @@ template <> inline AtomicType::AtomicType() { _hid = detail::h5t_copy(H5T_NATIVE_FLOAT); // Sign position, exponent position, exponent size, mantissa position, mantissa size - H5Tset_fields(_hid, 15, 10, 5, 0, 10); + detail::h5t_set_fields(_hid, 15, 10, 5, 0, 10); // Total datatype size (in bytes) detail::h5t_set_size(_hid, 2); // Floating point exponent bias - H5Tset_ebias(_hid, 15); + detail::h5t_set_ebias(_hid, 15); } #endif @@ -316,8 +311,8 @@ inline AtomicType::AtomicType() { inline size_t find_first_atomic_member_size(hid_t hid) { // Recursive exit condition - if (H5Tget_class(hid) == H5T_COMPOUND) { - auto number_of_members = H5Tget_nmembers(hid); + if (detail::h5t_get_class(hid) == H5T_COMPOUND) { + auto number_of_members = detail::h5t_get_nmembers(hid); if (number_of_members == -1) { throw DataTypeException("Cannot get members of CompoundType with hid: " + std::to_string(hid)); @@ -327,11 +322,11 @@ inline size_t find_first_atomic_member_size(hid_t hid) { std::to_string(hid)); } - auto member_type = H5Tget_member_type(hid, 0); + auto member_type = detail::h5t_get_member_type(hid, 0); auto size = find_first_atomic_member_size(member_type); - H5Tclose(member_type); + detail::h5t_close(member_type); return size; - } else if (H5Tget_class(hid) == H5T_STRING) { + } else if (detail::h5t_get_class(hid) == H5T_STRING) { return 1; } return detail::h5t_get_size(hid); @@ -391,43 +386,36 @@ inline void CompoundType::create(size_t size) { } // Create the HDF5 type - if ((_hid = H5Tcreate(H5T_COMPOUND, size)) < 0) { - HDF5ErrMapper::ToException("Could not create new compound datatype"); - } + _hid = detail::h5t_create(H5T_COMPOUND, size); // Loop over all the members and insert them into the datatype for (const auto& member: members) { - if (H5Tinsert(_hid, member.name.c_str(), member.offset, member.base_type.getId()) < 0) { - HDF5ErrMapper::ToException("Could not add new member to datatype"); - } + detail::h5t_insert(_hid, member.name.c_str(), member.offset, member.base_type.getId()); } } #undef _H5_STRUCT_PADDING inline void CompoundType::commit(const Object& object, const std::string& name) const { - H5Tcommit2(object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + detail::h5t_commit2( + object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); } template inline void EnumType::create() { // Create the HDF5 type - if ((_hid = H5Tenum_create(AtomicType::type>{}.getId())) < 0) { - HDF5ErrMapper::ToException("Could not create new enum datatype"); - } + _hid = detail::h5t_enum_create(AtomicType::type>{}.getId()); // Loop over all the members and insert them into the datatype for (const auto& member: members) { - if (H5Tenum_insert(_hid, member.name.c_str(), &(member.value)) < 0) { - HDF5ErrMapper::ToException( - "Could not add new member to this enum datatype"); - } + detail::h5t_enum_insert(_hid, member.name.c_str(), &(member.value)); } } template inline void EnumType::commit(const Object& object, const std::string& name) const { - H5Tcommit2(object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + detail::h5t_commit2( + object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); } namespace { diff --git a/include/highfive/bits/H5Node_traits_misc.hpp b/include/highfive/bits/H5Node_traits_misc.hpp index 420842da2..d7ab82b61 100644 --- a/include/highfive/bits/H5Node_traits_misc.hpp +++ b/include/highfive/bits/H5Node_traits_misc.hpp @@ -177,14 +177,9 @@ inline Group NodeTraits::getGroup(const std::string& group_name) const template inline DataType NodeTraits::getDataType(const std::string& type_name, const DataTypeAccessProps& accessProps) const { - const auto hid = H5Topen2(static_cast(this)->getId(), - type_name.c_str(), - accessProps.getId()); - if (hid < 0) { - HDF5ErrMapper::ToException( - std::string("Unable to open the datatype \"") + type_name + "\":"); - } - return DataType(hid); + return DataType(detail::h5t_open2(static_cast(this)->getId(), + type_name.c_str(), + accessProps.getId())); } template diff --git a/include/highfive/bits/H5Slice_traits_misc.hpp b/include/highfive/bits/H5Slice_traits_misc.hpp index 7b07c9abf..313343d4e 100644 --- a/include/highfive/bits/H5Slice_traits_misc.hpp +++ b/include/highfive/bits/H5Slice_traits_misc.hpp @@ -205,7 +205,8 @@ inline void SliceTraits::read(T& array, const DataTransferProps& xfer_ if (c == DataTypeClass::VarLen || t.isVariableStr()) { #if H5_VERSION_GE(1, 12, 0) // This one have been created in 1.12.0 - (void) H5Treclaim(t.getId(), mem_space.getId(), xfer_props.getId(), r.getPointer()); + (void) + detail::h5t_reclaim(t.getId(), mem_space.getId(), xfer_props.getId(), r.getPointer()); #else // This one is deprecated since 1.12.0 (void) H5Dvlen_reclaim(t.getId(), mem_space.getId(), xfer_props.getId(), r.getPointer()); diff --git a/include/highfive/bits/h5_wrapper.hpp b/include/highfive/bits/h5_wrapper.hpp new file mode 100644 index 000000000..cfde5b8e6 --- /dev/null +++ b/include/highfive/bits/h5_wrapper.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace HighFive { +namespace detail { +inline void h5_free_memory(void* mem) { + if (H5free_memory(mem) < 0) { + throw DataTypeException("Could not free memory allocated by HDF5"); + } +} +} // namespace detail +} // namespace HighFive diff --git a/include/highfive/bits/h5t_wrapper.hpp b/include/highfive/bits/h5t_wrapper.hpp index a8be1b52b..f2c7bb098 100644 --- a/include/highfive/bits/h5t_wrapper.hpp +++ b/include/highfive/bits/h5t_wrapper.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include namespace HighFive { @@ -59,6 +60,53 @@ inline void h5t_set_strpad(hid_t hid, H5T_str_t strpad) { } } +inline int h5t_get_nmembers(hid_t hid) { + auto result = H5Tget_nmembers(hid); + + if (result < 0) { + throw DataTypeException("Could not get members of compound datatype"); + } + + return result; +} + +inline char* h5t_get_member_name(hid_t type_id, unsigned membno) { + char* name = H5Tget_member_name(type_id, membno); + if (name == nullptr) { + throw DataTypeException("Failed to get member names of compound datatype"); + } + + return name; +} + + +inline size_t h5t_get_member_offset(hid_t type_id, unsigned membno) { + // Note, this function is peculiar. On failure it returns 0, yet 0 is also + // what's returned on failure. + return H5Tget_member_offset(type_id, membno); +} + +inline hid_t h5t_get_member_type(hid_t type_id, unsigned membno) { + hid_t member_id = H5Tget_member_type(type_id, membno); + + if (member_id < 0) { + throw DataTypeException("Failed to get member type of compound datatype"); + } + + return member_id; +} + +#if H5_VERSION_GE(1, 12, 0) +inline herr_t h5t_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void* buf) { + herr_t err = H5Treclaim(type_id, space_id, plist_id, buf); + if (err < 0) { + throw DataTypeException("Failed to reclaim HDF5 internal memory"); + } + + return err; +} +#endif + inline H5T_class_t h5t_get_class(hid_t type_id) { H5T_class_t class_id = H5Tget_class(type_id); if (class_id == H5T_NO_CLASS) { @@ -68,5 +116,115 @@ inline H5T_class_t h5t_get_class(hid_t type_id) { return class_id; } +inline htri_t h5t_equal(hid_t type1_id, hid_t type2_id) { + htri_t equal = H5Tequal(type1_id, type2_id); + if (equal < 0) { + throw DataTypeException("Failed to compare two datatypes"); + } + + return equal; +} + +inline htri_t h5t_is_variable_str(hid_t type_id) { + htri_t is_variable = H5Tis_variable_str(type_id); + if (is_variable < 0) { + HDF5ErrMapper::ToException( + "Failed to check if string is variable length"); + } + return is_variable; +} + +inline herr_t h5t_set_fields(hid_t type_id, + size_t spos, + size_t epos, + size_t esize, + size_t mpos, + size_t msize) { + herr_t err = H5Tset_fields(type_id, spos, epos, esize, mpos, msize); + if (err < 0) { + HDF5ErrMapper::ToException( + "Failed to create custom floating point data type"); + } + return err; +} + +inline herr_t h5t_set_ebias(hid_t type_id, size_t ebias) { + herr_t err = H5Tset_ebias(type_id, ebias); + if (err < 0) { + HDF5ErrMapper::ToException( + "Failed to exponent bias of floating point data type"); + } + + return err; +} + +inline hid_t h5t_create(H5T_class_t type, size_t size) { + hid_t type_id = H5Tcreate(type, size); + if (type_id == H5I_INVALID_HID) { + HDF5ErrMapper::ToException("Failed to datatype"); + } + + return type_id; +} + +inline herr_t h5t_insert(hid_t parent_id, const char* name, size_t offset, hid_t member_id) { + herr_t err = H5Tinsert(parent_id, name, offset, member_id); + if (err < 0) { + HDF5ErrMapper::ToException("Failed to not add new member to datatype"); + } + + return err; +} + +inline herr_t h5t_commit2(hid_t loc_id, + const char* name, + hid_t type_id, + hid_t lcpl_id, + hid_t tcpl_id, + hid_t tapl_id) { + herr_t err = H5Tcommit2(loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id); + if (err < 0) { + HDF5ErrMapper::ToException("Failed to commit datatype"); + } + + return err; +} + +inline herr_t h5t_close(hid_t type_id) { + auto err = H5Tclose(type_id); + if (err < 0) { + HDF5ErrMapper::ToException("Failed to close datatype"); + } + + return err; +} + +inline hid_t h5t_enum_create(hid_t base_id) { + hid_t type_id = H5Tenum_create(base_id); + if (type_id == H5I_INVALID_HID) { + HDF5ErrMapper::ToException("Failed to create new enum datatype"); + } + return type_id; +} + +inline herr_t h5t_enum_insert(hid_t type, const char* name, const void* value) { + herr_t err = H5Tenum_insert(type, name, value); + if (err < 0) { + HDF5ErrMapper::ToException( + "Failed to add new member to this enum datatype"); + } + return err; +} + +inline hid_t h5t_open2(hid_t loc_id, const char* name, hid_t tapl_id) { + hid_t datatype_id = H5Topen2(loc_id, name, tapl_id); + if (datatype_id == H5I_INVALID_HID) { + HDF5ErrMapper::ToException( + std::string("Unable to open the datatype \"") + name + "\":"); + } + + return datatype_id; +} + } // namespace detail } // namespace HighFive