File indexing completed on 2026-09-15 09:12:33
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <H5Ipublic.h>
0012 #include <algorithm>
0013 #include <functional>
0014 #include <numeric>
0015 #include <sstream>
0016 #include <string>
0017
0018 #include <H5Ppublic.h>
0019
0020 #include "../H5DataSpace.hpp"
0021 #include "H5Converter_misc.hpp"
0022 #include "H5Inspector_misc.hpp"
0023 #include "H5ReadWrite_misc.hpp"
0024 #include "H5Utils.hpp"
0025 #include "h5a_wrapper.hpp"
0026 #include "h5d_wrapper.hpp"
0027 #include "squeeze.hpp"
0028 #include "assert_compatible_spaces.hpp"
0029
0030 namespace HighFive {
0031
0032 inline std::string Attribute::getName() const {
0033 return details::get_name(
0034 [&](char* buffer, size_t length) { return detail::h5a_get_name(_hid, length, buffer); });
0035 }
0036
0037 inline size_t Attribute::getStorageSize() const {
0038 if (!this->isValid()) {
0039 throw AttributeException("Invalid call to `DataSet::getFile` for invalid object");
0040 }
0041
0042 return static_cast<size_t>(detail::h5a_get_storage_size(_hid));
0043 }
0044
0045 inline DataType Attribute::getDataType() const {
0046 DataType res;
0047 res._hid = detail::h5a_get_type(_hid);
0048 return res;
0049 }
0050
0051 inline DataSpace Attribute::getSpace() const {
0052 DataSpace space;
0053 space._hid = detail::h5a_get_space(_hid);
0054 return space;
0055 }
0056
0057 inline DataSpace Attribute::getMemSpace() const {
0058 return _mem_space.getId() == H5I_INVALID_HID ? getSpace() : _mem_space;
0059 }
0060
0061 template <typename T>
0062 inline T Attribute::read() const {
0063 T array;
0064 read(array);
0065 return array;
0066 }
0067
0068 template <typename T>
0069 inline void Attribute::read(T& array) const {
0070 const DataSpace& mem_space = getMemSpace();
0071 auto file_datatype = getDataType();
0072 const details::BufferInfo<T> buffer_info(
0073 file_datatype,
0074 [this]() -> std::string { return this->getName(); },
0075 details::BufferInfo<T>::Operation::read);
0076
0077 if (!details::checkDimensions(mem_space, buffer_info.getMinRank(), buffer_info.getMaxRank())) {
0078 std::ostringstream ss;
0079 ss << "Impossible to read attribute of dimensions " << mem_space.getNumberDimensions()
0080 << " into arrays of dimensions: " << buffer_info.getMinRank() << "(min) to "
0081 << buffer_info.getMaxRank() << "(max)";
0082 throw DataSpaceException(ss.str());
0083 }
0084 auto dims = mem_space.getDimensions();
0085
0086 if (mem_space.getElementCount() == 0) {
0087 details::inspector<T>::prepare(array, dims);
0088 return;
0089 }
0090
0091 auto r = details::data_converter::get_reader<T>(dims, array, file_datatype);
0092 read_raw(r.getPointer(), buffer_info.data_type);
0093
0094 r.unserialize(array);
0095
0096 auto t = buffer_info.data_type;
0097 auto c = t.getClass();
0098
0099 if (c == DataTypeClass::VarLen || t.isVariableStr()) {
0100 #if H5_VERSION_GE(1, 12, 0)
0101
0102 (void) detail::h5t_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
0103 #else
0104
0105 (void) detail::h5d_vlen_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
0106 #endif
0107 }
0108 }
0109
0110 template <typename T>
0111 inline void Attribute::read_raw(T* array, const DataType& mem_datatype) const {
0112 static_assert(!std::is_const<T>::value,
0113 "read() requires a non-const structure to read data into");
0114
0115 detail::h5a_read(getId(), mem_datatype.getId(), static_cast<void*>(array));
0116 }
0117
0118 template <typename T>
0119 inline void Attribute::read_raw(T* array) const {
0120 using element_type = typename details::inspector<T>::base_type;
0121 const DataType& mem_datatype = create_and_check_datatype<element_type>();
0122
0123 read_raw(array, mem_datatype);
0124 }
0125
0126 template <typename T>
0127 inline void Attribute::write(const T& buffer) {
0128 const DataSpace& mem_space = getMemSpace();
0129 auto dims = mem_space.getDimensions();
0130
0131 if (mem_space.getElementCount() == 0) {
0132 return;
0133 }
0134
0135 auto file_datatype = getDataType();
0136
0137 const details::BufferInfo<T> buffer_info(
0138 file_datatype,
0139 [this]() -> std::string { return this->getName(); },
0140 details::BufferInfo<T>::Operation::write);
0141
0142 if (!details::checkDimensions(mem_space, buffer_info.getMinRank(), buffer_info.getMaxRank())) {
0143 std::ostringstream ss;
0144 ss << "Impossible to write attribute of dimensions " << mem_space.getNumberDimensions()
0145 << " into arrays of dimensions: " << buffer_info.getMinRank() << "(min) to "
0146 << buffer_info.getMaxRank() << "(max)";
0147 throw DataSpaceException(ss.str());
0148 }
0149 auto w = details::data_converter::serialize<T>(buffer, dims, file_datatype);
0150 write_raw(w.getPointer(), buffer_info.data_type);
0151 }
0152
0153 template <typename T>
0154 inline void Attribute::write_raw(const T* buffer, const DataType& mem_datatype) {
0155 detail::h5a_write(getId(), mem_datatype.getId(), buffer);
0156 }
0157
0158 template <typename T>
0159 inline void Attribute::write_raw(const T* buffer) {
0160 using element_type = typename details::inspector<T>::base_type;
0161 const auto& mem_datatype = create_and_check_datatype<element_type>();
0162
0163 write_raw(buffer, mem_datatype);
0164 }
0165
0166 inline Attribute Attribute::squeezeMemSpace(const std::vector<size_t>& axes) const {
0167 auto mem_dims = this->getMemSpace().getDimensions();
0168 auto squeezed_dims = detail::squeeze(mem_dims, axes);
0169
0170 auto attr = *this;
0171 attr._mem_space = DataSpace(squeezed_dims);
0172 return attr;
0173 }
0174
0175 inline Attribute Attribute::reshapeMemSpace(const std::vector<size_t>& new_dims) const {
0176 detail::assert_compatible_spaces(this->getMemSpace(), new_dims);
0177
0178 auto attr = *this;
0179 attr._mem_space = DataSpace(new_dims);
0180 return attr;
0181 }
0182
0183 }