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