Files
FESADev/src/fesa/io/hdf5/hdf5_raii.h
T

111 lines
2.7 KiB
C++

#ifndef FESA_IO_HDF5_HDF5_RAII_H_
#define FESA_IO_HDF5_HDF5_RAII_H_
#include <hdf5.h>
#include <stdexcept>
#include <string>
namespace fesa::hdf5_internal {
/// @brief Owns one HDF5 identifier and its matching close operation.
/// @note This move-only wrapper never crosses the private HDF5 boundary.
class Hdf5Handle {
public:
using Closer = herr_t (*)(hid_t);
Hdf5Handle() = default;
Hdf5Handle(hid_t value, Closer closer) : value_{value}, closer_{closer} {}
Hdf5Handle(const Hdf5Handle&) = delete;
Hdf5Handle& operator=(const Hdf5Handle&) = delete;
Hdf5Handle(Hdf5Handle&& other) noexcept
: value_{other.value_}, closer_{other.closer_} {
other.value_ = -1;
other.closer_ = nullptr;
}
Hdf5Handle& operator=(Hdf5Handle&& other) noexcept {
if (this != &other) {
Reset();
value_ = other.value_;
closer_ = other.closer_;
other.value_ = -1;
other.closer_ = nullptr;
}
return *this;
}
~Hdf5Handle() { Reset(); }
hid_t Get() const noexcept { return value_; }
herr_t CloseChecked() noexcept {
if (value_ < 0 || closer_ == nullptr) {
return 0;
}
const hid_t value = value_;
const Closer closer = closer_;
value_ = -1;
closer_ = nullptr;
return closer(value);
}
private:
void Reset() noexcept {
if (value_ >= 0 && closer_ != nullptr) {
(void)closer_(value_);
}
value_ = -1;
closer_ = nullptr;
}
hid_t value_{-1};
Closer closer_{nullptr};
};
/// @brief Converts an HDF5 failure into the private exception transport.
class Hdf5Failure final : public std::runtime_error {
public:
explicit Hdf5Failure(const std::string& message)
: std::runtime_error{message} {}
};
/// @brief Requires a successful HDF5 status code.
inline void RequireHdf5(herr_t result, const char* message) {
if (result < 0) {
throw Hdf5Failure{message};
}
}
/// @brief Requires a valid HDF5 identifier.
inline hid_t RequireHdf5Id(hid_t result, const char* message) {
if (result < 0) {
throw Hdf5Failure{message};
}
return result;
}
/// @brief Suppresses backend error-stack output while FESA translates errors.
class Hdf5ErrorSilencer {
public:
Hdf5ErrorSilencer() {
if (H5Eget_auto2(H5E_DEFAULT, &callback_, &client_data_) >= 0 &&
H5Eset_auto2(H5E_DEFAULT, nullptr, nullptr) >= 0) {
active_ = true;
}
}
Hdf5ErrorSilencer(const Hdf5ErrorSilencer&) = delete;
Hdf5ErrorSilencer& operator=(const Hdf5ErrorSilencer&) = delete;
~Hdf5ErrorSilencer() {
if (active_) {
(void)H5Eset_auto2(H5E_DEFAULT, callback_, client_data_);
}
}
private:
H5E_auto2_t callback_{nullptr};
void* client_data_{nullptr};
bool active_{false};
};
} // namespace fesa::hdf5_internal
#endif // FESA_IO_HDF5_HDF5_RAII_H_