/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/hdf5lib/group.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/hdf5lib/group.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
group.hh
Go to the documentation of this file.
1#pragma once
2
3#include <hdf5lib/dataset.hh>
5#include <hdf5lib/datatype.hh>
7#include <hdf5lib/handle.hh>
8
9#include <string>
10#include <type_traits>
11#include <vector>
12
13namespace DiFfRG::hdf5
14{
15 class Group
16 {
17 public:
18 Group() = default;
19 explicit Group(hid_t id) : h_(id) {}
20 static Group take(hid_t id) { return Group(Handle::take(id)); }
21
22 hid_t id() const noexcept { return h_.get(); }
23 bool valid() const noexcept { return h_.valid(); }
24
25 // ----------------- subgroups -----------------
26
27 Group create_group(const std::string &name)
28 {
29 hid_t g = H5Gcreate2(h_.get(), name.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
30 throw_if_negative(g, "H5Gcreate2 failed");
31 return Group::take(g);
32 }
33
34 Group open_group(const std::string &name)
35 {
36 hid_t g = H5Gopen2(h_.get(), name.c_str(), H5P_DEFAULT);
37 throw_if_negative(g, "H5Gopen2 failed");
38 return Group::take(g);
39 }
40
41 bool has_group(const std::string &name) const { return child_kind(name) == H5O_TYPE_GROUP; }
42 bool has_dataset(const std::string &name) const { return child_kind(name) == H5O_TYPE_DATASET; }
43
44 // ----------------- datasets -----------------
45
46 Dataset create_dataset(const std::string &name, const Datatype &type, const Dataspace &space)
47 {
48 hid_t d = H5Dcreate2(h_.get(), name.c_str(), type.id(), space.id(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
49 throw_if_negative(d, "H5Dcreate2 failed");
50 return Dataset::take(d);
51 }
52
55 Dataset create_chunked_dataset(const std::string &name, const Datatype &type, const Dataspace &space,
56 const Dims &chunk)
57 {
58 hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE);
59 throw_if_negative(dcpl, "H5Pcreate(H5P_DATASET_CREATE) failed");
60 herr_t e = H5Pset_chunk(dcpl, static_cast<int>(chunk.size()), chunk.data());
61 if (e < 0) {
62 H5Pclose(dcpl);
63 throw std::runtime_error("hdf5lib: H5Pset_chunk failed");
64 }
65 hid_t d = H5Dcreate2(h_.get(), name.c_str(), type.id(), space.id(), H5P_DEFAULT, dcpl, H5P_DEFAULT);
66 H5Pclose(dcpl);
67 throw_if_negative(d, "H5Dcreate2 (chunked) failed");
68 return Dataset::take(d);
69 }
70
71 Dataset open_dataset(const std::string &name)
72 {
73 hid_t d = H5Dopen2(h_.get(), name.c_str(), H5P_DEFAULT);
74 throw_if_negative(d, "H5Dopen2 failed");
75 return Dataset::take(d);
76 }
77
78 // ----------------- soft link -----------------
79
80 void create_soft_link(const std::string &name, const std::string &target_path)
81 {
83 H5Lcreate_soft(target_path.c_str(), h_.get(), name.c_str(), H5P_DEFAULT, H5P_DEFAULT),
84 "H5Lcreate_soft failed");
85 }
86
87 // ----------------- attributes -----------------
88
89 template <class T>
90 requires(!std::is_same_v<std::decay_t<T>, std::string>)
91 void write_attribute(const std::string &name, const T &value)
92 {
93 auto type = type_of<std::decay_t<T>>();
94 auto space = Dataspace::scalar();
95 hid_t a = H5Acreate2(h_.get(), name.c_str(), type.id(), space.id(), H5P_DEFAULT, H5P_DEFAULT);
96 throw_if_negative(a, "H5Acreate2 failed");
97 herr_t e = H5Awrite(a, type.id(), &value);
98 H5Aclose(a);
99 throw_if_negative(e, "H5Awrite failed");
100 }
101
102 void write_attribute(const std::string &name, const std::string &value)
103 {
104 auto type = type_of<std::string>();
105 auto space = Dataspace::scalar();
106 hid_t a = H5Acreate2(h_.get(), name.c_str(), type.id(), space.id(), H5P_DEFAULT, H5P_DEFAULT);
107 throw_if_negative(a, "H5Acreate2 (string) failed");
108 const char *cstr = value.c_str();
109 herr_t e = H5Awrite(a, type.id(), &cstr);
110 H5Aclose(a);
111 throw_if_negative(e, "H5Awrite (string) failed");
112 }
113
114 void write_attribute(const std::string &name, const char *value)
115 {
116 write_attribute(name, std::string(value));
117 }
118
119 bool has_attribute(const std::string &name) const
120 {
121 htri_t e = H5Aexists(h_.get(), name.c_str());
122 throw_if_negative(e, "H5Aexists failed");
123 return e > 0;
124 }
125
126 void delete_attribute(const std::string &name)
127 {
128 throw_if_negative(H5Adelete(h_.get(), name.c_str()), "H5Adelete failed");
129 }
130
136 template <class T> void overwrite_attribute(const std::string &name, const T &value)
137 {
138 if (has_attribute(name)) delete_attribute(name);
139 write_attribute(name, value);
140 }
141
142 template <class T>
143 requires(!std::is_same_v<std::decay_t<T>, std::string>)
144 T read_attribute(const std::string &name) const
145 {
146 hid_t a = H5Aopen(h_.get(), name.c_str(), H5P_DEFAULT);
147 throw_if_negative(a, "H5Aopen failed");
148 auto type = type_of<std::decay_t<T>>();
149 T value{};
150 herr_t e = H5Aread(a, type.id(), &value);
151 H5Aclose(a);
152 throw_if_negative(e, "H5Aread failed");
153 return value;
154 }
155
156 template <class T>
157 requires(std::is_same_v<std::decay_t<T>, std::string>)
158 std::string read_attribute(const std::string &name) const
159 {
160 hid_t a = H5Aopen(h_.get(), name.c_str(), H5P_DEFAULT);
161 throw_if_negative(a, "H5Aopen (string) failed");
162 auto type = type_of<std::string>();
163 char *raw = nullptr;
164 herr_t e = H5Aread(a, type.id(), &raw);
165 if (e < 0) {
166 H5Aclose(a);
167 throw std::runtime_error("hdf5lib: H5Aread (string) failed");
168 }
169 std::string out = raw != nullptr ? std::string(raw) : std::string();
170 // Reclaim the per-element allocation for the variable-length string.
171 hid_t scalar = H5Screate(H5S_SCALAR);
172 H5Treclaim(type.id(), scalar, H5P_DEFAULT, &raw);
173 H5Sclose(scalar);
174 H5Aclose(a);
175 return out;
176 }
177
178 // ----------------- iteration -----------------
179
181 std::vector<std::string> child_names() const
182 {
183 std::vector<std::string> out;
184 auto cb = [](hid_t /*loc*/, const char *name, const H5L_info2_t * /*info*/, void *op_data) -> herr_t {
185 auto &vec = *static_cast<std::vector<std::string> *>(op_data);
186 vec.emplace_back(name);
187 return 0;
188 };
189 hsize_t idx = 0;
190 throw_if_negative(H5Literate2(h_.get(), H5_INDEX_NAME, H5_ITER_NATIVE, &idx, cb, &out),
191 "H5Literate2 failed");
192 return out;
193 }
194
195 bool child_is_group(const std::string &name) const { return child_kind(name) == H5O_TYPE_GROUP; }
196 bool child_is_dataset(const std::string &name) const { return child_kind(name) == H5O_TYPE_DATASET; }
197
198 private:
199 explicit Group(Handle h) : h_(std::move(h)) {}
201
203 H5O_type_t child_kind(const std::string &name) const
204 {
205 if (H5Lexists(h_.get(), name.c_str(), H5P_DEFAULT) <= 0) return H5O_TYPE_UNKNOWN;
206 H5O_info2_t info;
207 if (H5Oget_info_by_name3(h_.get(), name.c_str(), &info, H5O_INFO_BASIC, H5P_DEFAULT) < 0)
208 return H5O_TYPE_UNKNOWN;
209 return info.type;
210 }
211 };
212} // namespace DiFfRG::hdf5
Definition dataset.hh:15
static Dataset take(hid_t id)
Definition dataset.hh:19
Definition dataspace.hh:12
static Dataspace scalar()
Definition dataspace.hh:49
hid_t id() const noexcept
Definition dataspace.hh:18
Definition datatype.hh:12
hid_t id() const noexcept
Definition datatype.hh:18
Definition group.hh:16
void delete_attribute(const std::string &name)
Definition group.hh:126
T read_attribute(const std::string &name) const
Definition group.hh:144
bool child_is_group(const std::string &name) const
Definition group.hh:195
void write_attribute(const std::string &name, const std::string &value)
Definition group.hh:102
static Group take(hid_t id)
Definition group.hh:20
void write_attribute(const std::string &name, const char *value)
Definition group.hh:114
Dataset open_dataset(const std::string &name)
Definition group.hh:71
hid_t id() const noexcept
Definition group.hh:22
bool has_dataset(const std::string &name) const
Definition group.hh:42
Group create_group(const std::string &name)
Definition group.hh:27
Dataset create_chunked_dataset(const std::string &name, const Datatype &type, const Dataspace &space, const Dims &chunk)
Definition group.hh:55
void write_attribute(const std::string &name, const T &value)
Definition group.hh:91
void create_soft_link(const std::string &name, const std::string &target_path)
Definition group.hh:80
Group(hid_t id)
Definition group.hh:19
H5O_type_t child_kind(const std::string &name) const
H5O_TYPE_UNKNOWN if the child does not exist (or is not an object).
Definition group.hh:203
bool has_attribute(const std::string &name) const
Definition group.hh:119
Dataset create_dataset(const std::string &name, const Datatype &type, const Dataspace &space)
Definition group.hh:46
Handle h_
Definition group.hh:200
std::vector< std::string > child_names() const
Names of all immediate children, in link-name order.
Definition group.hh:181
bool valid() const noexcept
Definition group.hh:23
std::string read_attribute(const std::string &name) const
Definition group.hh:158
bool has_group(const std::string &name) const
Definition group.hh:41
Group open_group(const std::string &name)
Definition group.hh:34
void overwrite_attribute(const std::string &name, const T &value)
Definition group.hh:136
Group(Handle h)
Definition group.hh:199
bool child_is_dataset(const std::string &name) const
Definition group.hh:196
Definition handle.hh:25
bool valid() const noexcept
Definition handle.hh:80
hid_t get() const noexcept
Definition handle.hh:79
static Handle take(hid_t id)
Definition handle.hh:37
Definition hdf5.hh:12
std::vector< hsize_t > Dims
Definition dataspace.hh:9
Datatype type_of()
Convenience factory — type_of<T>() returns the HDF5 datatype for T.
Definition datatype.hh:56
void throw_if_negative(hid_t id, const char *what)
Definition handle.hh:11