feat(cpp-object-oriented-modular-refactoring): step 23 - hdf5-writer-modules
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
#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_
|
||||
Reference in New Issue
Block a user