1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#ifndef RITSUKO_HDF5_LOAD_ATTRIBUTE_HPP
#define RITSUKO_HDF5_LOAD_ATTRIBUTE_HPP
#include "H5Cpp.h"
#include <vector>
#include <string>
#include "get_1d_length.hpp"
#include "as_numeric_datatype.hpp"
#include "_strings.hpp"
/**
* @file load_attribute.hpp
* @brief Load HDF5 attributes.
*/
namespace ritsuko {
namespace hdf5 {
/**
* @param attr Handle to a scalar string attribute.
* Callers are responsible for checking that `attr` contains a string datatype class.
* @return The attribute as a string.
*/
inline std::string load_scalar_string_attribute(const H5::Attribute& attr) {
auto dtype = attr.getDataType();
// Unfortunately, we can't just do 'std::string output; attr.read(dtype, output);',
// as we need to catch NULL pointers in the variable case.
if (dtype.isVariableStr()) {
auto mspace = attr.getSpace();
char* buffer;
attr.read(dtype, &buffer);
[[maybe_unused]] VariableStringCleaner deletor(dtype.getId(), mspace.getId(), &buffer);
if (buffer == NULL) {
throw std::runtime_error("detected a NULL pointer for a variable length string attribute");
}
return std::string(buffer);
} else {
size_t len = dtype.getSize();
std::vector<char> buffer(len);
attr.read(dtype, buffer.data());
auto ptr = buffer.data();
return std::string(ptr, ptr + find_string_length(ptr, len));
}
}
/**
* @tparam check_ Whether to check that `attr` is a 1-dimensional string attribute.
* @param attr Handle to a 1-dimensional string attribute.
* Callers are responsible for checking that `attr` contains a string datatype class.
* @param full_length Length of the attribute in `attr`, usually obtained by `get_1d_length()`.
* @return Vector of strings.
*/
inline std::vector<std::string> load_1d_string_attribute(const H5::Attribute& attr, hsize_t full_length) {
auto dtype = attr.getDataType();
auto mspace = attr.getSpace();
std::vector<std::string> output;
output.reserve(full_length);
if (dtype.isVariableStr()) {
std::vector<char*> buffer(full_length);
attr.read(dtype, buffer.data());
[[maybe_unused]] VariableStringCleaner deletor(dtype.getId(), mspace.getId(), buffer.data());
for (hsize_t i = 0; i < full_length; ++i) {
if (buffer[i] == NULL) {
throw std::runtime_error("detected a NULL pointer for a variable length string attribute");
}
output.emplace_back(buffer[i]);
}
} else {
size_t len = dtype.getSize();
std::vector<char> buffer(len * full_length);
attr.read(dtype, buffer.data());
auto ptr = buffer.data();
for (size_t i = 0; i < full_length; ++i, ptr += len) {
output.emplace_back(ptr, ptr + find_string_length(ptr, len));
}
}
return output;
}
/**
* Overload of `load_1d_string_attribute()` that determines the length of the attribute via `get_1d_length()`.
* @param attr Handle to a 1-dimensional string attribute.
* Callers are responsible for checking that `attr` contains a string datatype class.
* @return Vector of strings.
*/
inline std::vector<std::string> load_1d_string_attribute(const H5::Attribute& attr) {
return load_1d_string_attribute(attr, get_1d_length(attr.getSpace(), false));
}
/**
* @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
* @param attr Handle to a scalar numeric attribute.
* Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
* @return The value of the attribute.
*/
template<typename Type_>
Type_ load_scalar_numeric_attribute(const H5::Attribute& attr) {
Type_ val;
const auto& mtype = as_numeric_datatype<Type_>();
attr.read(mtype, &val);
return val;
}
/**
* @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
* @param attr Handle to a numeric attribute.
* Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
* @param full_length Length of the attribute in `attr`, usually obtained by `get_1d_length()`.
* @return Vector containing the contents of the attribute.
*/
template<typename Type_>
std::vector<Type_> load_1d_numeric_attribute(const H5::Attribute& attr, hsize_t full_length) {
const auto& mtype = as_numeric_datatype<Type_>();
std::vector<Type_> buffer(full_length);
attr.read(mtype, buffer.data());
return buffer;
}
/**
* Overload of `load_1d_numeric_attribute()` that determines the length of the attribute via `get_1d_length()`.
* @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
* @param attr Handle to a numeric attribute.
* Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
* @return Vector containing the contents of the attribute.
*/
template<typename Type_>
std::vector<Type_> load_1d_numeric_attribute(const H5::Attribute& attr) {
return load_1d_numeric_attribute<Type_>(attr, get_1d_length(attr.getSpace(), false));
}
}
}
#endif
|