HighFive 2.7.1
HighFive - Header-only C++ HDF5 interface
Loading...
Searching...
No Matches
H5Node_traits_misc.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
3 *
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
7 *
8 */
9#pragma once
10
11#include <string>
12#include <vector>
13
14#include <H5Apublic.h>
15#include <H5Dpublic.h>
16#include <H5Fpublic.h>
17#include <H5Gpublic.h>
18#include <H5Ppublic.h>
19#include <H5Tpublic.h>
20
21#include "../H5DataSet.hpp"
22#include "../H5Group.hpp"
23#include "../H5Selection.hpp"
24#include "../H5Utility.hpp"
25#include "H5DataSet_misc.hpp"
26#include "H5Iterables_misc.hpp"
27#include "H5Selection_misc.hpp"
29
30namespace HighFive {
31
32
33template <typename Derivate>
34inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
35 const DataSpace& space,
36 const DataType& dtype,
37 const DataSetCreateProps& createProps,
38 const DataSetAccessProps& accessProps,
39 bool parents) {
41 lcpl.add(CreateIntermediateGroup(parents));
42 const auto hid = H5Dcreate2(static_cast<Derivate*>(this)->getId(),
43 dataset_name.c_str(),
44 dtype.getId(),
45 space.getId(),
46 lcpl.getId(),
47 createProps.getId(),
48 accessProps.getId());
49 if (hid < 0) {
51 std::string("Unable to create the dataset \"") + dataset_name + "\":");
52 }
53 return DataSet(hid);
54}
55
56template <typename Derivate>
57template <typename T,
58 typename std::enable_if<
59 std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
60 int>::type*>
61inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
62 const DataSpace& space,
63 const DataSetCreateProps& createProps,
64 const DataSetAccessProps& accessProps,
65 bool parents) {
66 return createDataSet(dataset_name,
67 space,
68 create_and_check_datatype<typename details::inspector<T>::base_type>(),
69 createProps,
70 accessProps,
71 parents);
72}
73
74template <typename Derivate>
75template <typename T,
76 typename std::enable_if<
77 !std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
78 int>::type*>
79inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
80 const DataSpace& space,
81 const DataSetCreateProps& createProps,
82 const DataSetAccessProps& accessProps,
83 bool parents) {
84 return createDataSet(
85 dataset_name, space, create_and_check_datatype<T>(), createProps, accessProps, parents);
86}
88template <typename Derivate>
89template <typename T>
90inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
91 const T& data,
92 const DataSetCreateProps& createProps,
93 const DataSetAccessProps& accessProps,
94 bool parents) {
96 createDataSet(dataset_name,
97 DataSpace::From(data),
98 create_and_check_datatype<typename details::inspector<T>::base_type>(),
99 createProps,
100 accessProps,
101 parents);
102 ds.write(data);
103 return ds;
104}
105
106template <typename Derivate>
107template <std::size_t N>
108inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
109 const FixedLenStringArray<N>& data,
110 const DataSetCreateProps& createProps,
111 const DataSetAccessProps& accessProps,
112 bool parents) {
113 DataSet ds = createDataSet<char[N]>(
114 dataset_name, DataSpace(data.size()), createProps, accessProps, parents);
115 ds.write(data);
116 return ds;
117}
118
119template <typename Derivate>
120inline DataSet NodeTraits<Derivate>::getDataSet(const std::string& dataset_name,
121 const DataSetAccessProps& accessProps) const {
122 const auto hid = H5Dopen2(static_cast<const Derivate*>(this)->getId(),
123 dataset_name.c_str(),
124 accessProps.getId());
125 if (hid < 0) {
126 HDF5ErrMapper::ToException<DataSetException>(std::string("Unable to open the dataset \"") +
127 dataset_name + "\":");
128 }
129 return DataSet(hid);
131
132template <typename Derivate>
133inline Group NodeTraits<Derivate>::createGroup(const std::string& group_name, bool parents) {
134 LinkCreateProps lcpl;
136 const auto hid = H5Gcreate2(static_cast<Derivate*>(this)->getId(),
137 group_name.c_str(),
138 lcpl.getId(),
139 H5P_DEFAULT,
140 H5P_DEFAULT);
141 if (hid < 0) {
142 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to create the group \"") +
143 group_name + "\":");
144 }
145 return detail::make_group(hid);
146}
147
148template <typename Derivate>
149inline Group NodeTraits<Derivate>::createGroup(const std::string& group_name,
150 const GroupCreateProps& createProps,
151 bool parents) {
152 LinkCreateProps lcpl;
153 lcpl.add(CreateIntermediateGroup(parents));
154 const auto hid = H5Gcreate2(static_cast<Derivate*>(this)->getId(),
155 group_name.c_str(),
156 lcpl.getId(),
157 createProps.getId(),
158 H5P_DEFAULT);
159 if (hid < 0) {
160 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to create the group \"") +
161 group_name + "\":");
162 }
163 return detail::make_group(hid);
165
166template <typename Derivate>
167inline Group NodeTraits<Derivate>::getGroup(const std::string& group_name) const {
168 const auto hid =
169 H5Gopen2(static_cast<const Derivate*>(this)->getId(), group_name.c_str(), H5P_DEFAULT);
170 if (hid < 0) {
171 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to open the group \"") +
172 group_name + "\":");
173 }
174 return detail::make_group(hid);
175}
176
177template <typename Derivate>
179 hsize_t res;
180 if (H5Gget_num_objs(static_cast<const Derivate*>(this)->getId(), &res) < 0) {
182 std::string("Unable to count objects in existing group or file"));
183 }
184 return static_cast<size_t>(res);
185}
186
187template <typename Derivate>
188inline std::string NodeTraits<Derivate>::getObjectName(size_t index) const {
189 return details::get_name([&](char* buffer, size_t length) {
190 return H5Lget_name_by_idx(static_cast<const Derivate*>(this)->getId(),
191 ".",
192 H5_INDEX_NAME,
193 H5_ITER_INC,
194 index,
195 buffer,
196 length,
197 H5P_DEFAULT);
198 });
199}
200
201template <typename Derivate>
202inline bool NodeTraits<Derivate>::rename(const std::string& src_path,
203 const std::string& dst_path,
204 bool parents) const {
205 LinkCreateProps lcpl;
206 lcpl.add(CreateIntermediateGroup(parents));
207 herr_t status = H5Lmove(static_cast<const Derivate*>(this)->getId(),
208 src_path.c_str(),
209 static_cast<const Derivate*>(this)->getId(),
210 dst_path.c_str(),
211 lcpl.getId(),
212 H5P_DEFAULT);
213 if (status < 0) {
214 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to move link to \"") +
215 dst_path + "\":");
216 return false;
217 }
218 return true;
219}
220
221template <typename Derivate>
222inline std::vector<std::string> NodeTraits<Derivate>::listObjectNames(IndexType idx_type) const {
223 std::vector<std::string> names;
224 details::HighFiveIterateData iterateData(names);
225
226 size_t num_objs = getNumberObjects();
227 names.reserve(num_objs);
228
229 if (H5Literate(static_cast<const Derivate*>(this)->getId(),
230 static_cast<H5_index_t>(idx_type),
231 H5_ITER_INC,
232 NULL,
233 &details::internal_high_five_iterate<H5L_info_t>,
234 static_cast<void*>(&iterateData)) < 0) {
235 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to list objects in group"));
236 }
237
238 return names;
239}
240
241template <typename Derivate>
242inline bool NodeTraits<Derivate>::_exist(const std::string& node_name, bool raise_errors) const {
243 SilenceHDF5 silencer{};
244 const auto val =
245 H5Lexists(static_cast<const Derivate*>(this)->getId(), node_name.c_str(), H5P_DEFAULT);
246 if (val < 0) {
247 if (raise_errors) {
248 HDF5ErrMapper::ToException<GroupException>("Invalid link for exist()");
249 } else {
250 return false;
251 }
252 }
253
254 // The root path always exists, but H5Lexists return 0 or 1
255 // depending of the version of HDF5, so always return true for it
256 // We had to call H5Lexists anyway to check that there are no errors
257 return (node_name == "/") ? true : (val > 0);
258}
259
260template <typename Derivate>
261inline bool NodeTraits<Derivate>::exist(const std::string& group_path) const {
262 // When there are slashes, first check everything is fine
263 // so that subsequent errors are only due to missing intermediate groups
264 if (group_path.find('/') != std::string::npos) {
265 _exist("/"); // Shall not throw under normal circumstances
266 // Unless "/" (already checked), verify path exists (not throwing errors)
267 return (group_path == "/") ? true : _exist(group_path, false);
268 }
269 return _exist(group_path);
270}
271
272
273template <typename Derivate>
274inline void NodeTraits<Derivate>::unlink(const std::string& node_name) const {
275 const herr_t val =
276 H5Ldelete(static_cast<const Derivate*>(this)->getId(), node_name.c_str(), H5P_DEFAULT);
277 if (val < 0) {
278 HDF5ErrMapper::ToException<GroupException>(std::string("Invalid name for unlink() "));
279 }
280}
281
282
283// convert internal link types to enum class.
284// This function is internal, so H5L_TYPE_ERROR shall be handled in the calling context
285static inline LinkType _convert_link_type(const H5L_type_t& ltype) noexcept {
286 switch (ltype) {
287 case H5L_TYPE_HARD:
288 return LinkType::Hard;
289 case H5L_TYPE_SOFT:
290 return LinkType::Soft;
291 case H5L_TYPE_EXTERNAL:
292 return LinkType::External;
293 default:
294 // Other link types are possible but are considered strange to HighFive.
295 // see https://support.hdfgroup.org/HDF5/doc/RM/H5L/H5Lregister.htm
296 return LinkType::Other;
297 }
298}
299
300template <typename Derivate>
301inline LinkType NodeTraits<Derivate>::getLinkType(const std::string& node_name) const {
302 H5L_info_t linkinfo;
303 if (H5Lget_info(static_cast<const Derivate*>(this)->getId(),
304 node_name.c_str(),
305 &linkinfo,
306 H5P_DEFAULT) < 0 ||
307 linkinfo.type == H5L_TYPE_ERROR) {
308 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to obtain info for link ") +
309 node_name);
310 }
311 return _convert_link_type(linkinfo.type);
312}
313
314template <typename Derivate>
315inline ObjectType NodeTraits<Derivate>::getObjectType(const std::string& node_name) const {
316 return _open(node_name).getType();
317}
318
319
320template <typename Derivate>
321inline void NodeTraits<Derivate>::createSoftLink(const std::string& link_name,
322 const std::string& obj_path,
323 LinkCreateProps linkCreateProps,
324 const LinkAccessProps& linkAccessProps,
325 const bool parents) {
326 if (parents) {
327 linkCreateProps.add(CreateIntermediateGroup{});
328 }
329 auto status = H5Lcreate_soft(obj_path.c_str(),
330 static_cast<const Derivate*>(this)->getId(),
331 link_name.c_str(),
332 linkCreateProps.getId(),
333 linkAccessProps.getId());
334 if (status < 0) {
335 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to create soft link: "));
336 }
337}
338
339
340template <typename Derivate>
341inline void NodeTraits<Derivate>::createExternalLink(const std::string& link_name,
342 const std::string& h5_file,
343 const std::string& obj_path,
344 LinkCreateProps linkCreateProps,
345 const LinkAccessProps& linkAccessProps,
346 const bool parents) {
347 if (parents) {
348 linkCreateProps.add(CreateIntermediateGroup{});
349 }
350 auto status = H5Lcreate_external(h5_file.c_str(),
351 obj_path.c_str(),
352 static_cast<const Derivate*>(this)->getId(),
353 link_name.c_str(),
354 linkCreateProps.getId(),
355 linkAccessProps.getId());
356 if (status < 0) {
357 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to create external link: "));
358 }
359}
360
361
362template <typename Derivate>
363inline Object NodeTraits<Derivate>::_open(const std::string& node_name,
364 const DataSetAccessProps& accessProps) const {
365 const auto id = H5Oopen(static_cast<const Derivate*>(this)->getId(),
366 node_name.c_str(),
367 accessProps.getId());
368 if (id < 0) {
369 HDF5ErrMapper::ToException<GroupException>(std::string("Unable to open \"") + node_name +
370 "\":");
371 }
372 return detail::make_object(id);
373}
374
375
376} // namespace HighFive
Definition H5PropertyList.hpp:501
Class representing a dataset.
Definition H5DataSet.hpp:30
Class representing the space (dimensions) of a dataset.
Definition H5DataSpace.hpp:25
static DataSpace From(const T &value)
Create a dataspace matching a type accepted by details::inspector.
Definition H5Dataspace_misc.hpp:131
HDF5 Data Type.
Definition H5DataType.hpp:54
A structure representing a set of fixed-length strings.
Definition H5DataType.hpp:284
std::size_t size() const noexcept
Definition H5DataType.hpp:326
Represents an hdf5 group.
Definition H5Group.hpp:46
NodeTraits: Base class for Group and File.
Definition H5Node_traits.hpp:28
Group getGroup(const std::string &group_name) const
open an existing group with the name group_name
Definition H5Node_traits_misc.hpp:167
std::vector< std::string > listObjectNames(IndexType idx_type=IndexType::NAME) const
list all leaf objects name of the node / group
Definition H5Node_traits_misc.hpp:222
void unlink(const std::string &node_name) const
unlink the given dataset or group
Definition H5Node_traits_misc.hpp:274
void createExternalLink(const std::string &link_name, const std::string &h5_file, const std::string &obj_path, LinkCreateProps linkCreateProps=LinkCreateProps(), const LinkAccessProps &linkAccessProps=LinkAccessProps(), const bool parents=true)
Definition H5Node_traits_misc.hpp:341
DataSet getDataSet(const std::string &dataset_name, const DataSetAccessProps &accessProps=DataSetAccessProps::Default()) const
get an existing dataset in the current file
Definition H5Node_traits_misc.hpp:120
void createSoftLink(const std::string &linkName, const T &obj)
A shorthand to create softlink to any object which provides getPath The link will be created with def...
Definition H5Node_traits.hpp:185
Group createGroup(const std::string &group_name, bool parents=true)
create a new group, and eventually intermediate groups
Definition H5Node_traits_misc.hpp:133
DataSet createDataSet(const std::string &dataset_name, const DataSpace &space, const DataType &type, const DataSetCreateProps &createProps=DataSetCreateProps::Default(), const DataSetAccessProps &accessProps=DataSetAccessProps::Default(), bool parents=true)
createDataSet Create a new dataset in the current file of datatype type and of size space
Definition H5Node_traits_misc.hpp:34
bool rename(const std::string &src_path, const std::string &dest_path, bool parents=true) const
moves an object and its content within an HDF5 file.
Definition H5Node_traits_misc.hpp:202
bool exist(const std::string &node_name) const
check a dataset or group exists in the current node / group
Definition H5Node_traits_misc.hpp:261
ObjectType getObjectType(const std::string &node_name) const
A shorthand to get the kind of object pointed to (group, dataset, type...)
Definition H5Node_traits_misc.hpp:315
size_t getNumberObjects() const
return the number of leaf objects of the node / group
Definition H5Node_traits_misc.hpp:178
std::string getObjectName(size_t index) const
return the name of the object with the given index
Definition H5Node_traits_misc.hpp:188
LinkType getLinkType(const std::string &node_name) const
Returns the kind of link of the given name (soft, hard...)
Definition H5Node_traits_misc.hpp:301
Definition H5Object.hpp:54
hid_t getId() const noexcept
getId
Definition H5Object_misc.hpp:65
HDF5 property Lists.
Definition H5PropertyList.hpp:79
void add(const P &property)
Definition H5PropertyList_misc.hpp:74
Utility class to disable HDF5 stack printing inside a scope.
Definition H5Utility.hpp:24
void write(const T &buffer, const DataTransferProps &xfer_props=DataTransferProps())
Definition H5Slice_traits_misc.hpp:241
Definition H5_definitions.hpp:15
DataType create_and_check_datatype()
Create a DataType instance representing type T and perform a sanity check on its size.
Definition H5DataType_misc.hpp:479
LinkType
The possible types of group entries (link concept)
Definition H5Node_traits.hpp:228
ObjectType
Enum of the types of objects (H5O api)
Definition H5Object.hpp:24
IndexType
Definition H5Node_traits.hpp:19
static void ToException(const std::string &prefix_msg)
Definition H5Exception_misc.hpp:42