Utopia  2
Framework for studying models of complex & adaptive systems.
hdftype.hh
Go to the documentation of this file.
1 
7 #ifndef UTOPIA_DATAIO_HDFTYPEFACTORY_HH
8 #define UTOPIA_DATAIO_HDFTYPEFACTORY_HH
9 
10 #include <variant>
11 
12 #include <hdf5.h>
13 #include <hdf5_hl.h>
14 
16 
17 #include "hdfobject.hh"
18 #include "hdfutilities.hh"
19 
20 namespace Utopia
21 {
22 namespace DataIO
23 {
24 
35 namespace Detail
36 {
37 
38 template < typename T >
39 hid_t inline get_type()
40 {
41  return 0;
42 }
43 // bunch of overloads of get_type for getting hdf5 types for different c++
44 // types
45 template <>
46 hid_t
48 {
49  return H5T_NATIVE_FLOAT;
50 }
51 
52 template <>
53 hid_t
55 {
56  return H5T_NATIVE_DOUBLE;
57 }
58 template <>
59 hid_t
61 {
62  return H5T_NATIVE_LDOUBLE;
63 }
64 template <>
65 hid_t
67 {
68  return H5T_NATIVE_INT;
69 }
70 
71 template <>
72 hid_t
74 {
75  return H5T_NATIVE_SHORT;
76 }
77 template <>
78 hid_t
80 {
81  return H5T_NATIVE_LONG;
82 }
83 template <>
84 hid_t
86 {
87  return H5T_NATIVE_LLONG;
88 }
89 template <>
90 hid_t
92 {
93  return H5T_NATIVE_UINT;
94 }
95 template <>
96 hid_t
98 {
99  return H5T_NATIVE_UINT16;
100 }
101 template <>
102 hid_t
104 {
105  return H5T_NATIVE_ULLONG;
106 }
107 
108 template <>
109 hid_t
111 {
112  return H5T_NATIVE_ULLONG;
113 }
114 
115 template <>
116 hid_t
118 {
119  return H5T_NATIVE_HBOOL;
120 }
121 template <>
122 hid_t
124 {
125  return H5T_NATIVE_CHAR;
126 }
127 
128 }
129 
135 class HDFType final : public HDFObject< HDFCategory::datatype >
136 {
137  private:
138  // identify if the type is mutable or not. Unfortunatelly there is no
139  // HDF5-intrinsic way to check this...
140  bool _mutable = false;
141 
142  // enumeration telling what class the type belongs to
143  H5T_class_t _classid;
144 
145  public:
147 
148  // typedef for variant type to store attributes in
149  // all supported types are assembled into one variant here
150  using Variant = std::variant< float,
151  double,
152  long double,
153  int,
154  short int,
155  long int,
156  long long int,
157  unsigned int,
158  unsigned short int,
159  std::size_t,
160  unsigned long long,
161  bool,
162  char,
163  std::vector< float >,
164  std::vector< double >,
165  std::vector< long double >,
166  std::vector< int >,
167  std::vector< short int >,
168  std::vector< long int >,
169  std::vector< long long int >,
170  std::vector< unsigned int >,
171  std::vector< unsigned short int >,
172  std::vector< std::size_t >,
173  std::vector< unsigned long long >,
174  // std::vector<bool>,
175  std::vector< char >,
176  std::vector< std::string >,
177  std::string,
178  const char* >;
179 
186  inline bool
187  is_mutable() const
188  {
189  return _mutable;
190  }
191 
198  inline auto
200  {
201  return _classid;
202  }
203 
209  inline std::size_t
210  size() const
211  {
212  return H5Tget_size(get_C_id());
213  }
214 
222  template < typename T >
223  void
224  open(T&& object)
225  {
226  this->_log->debug("Opening HDFType from existing object {}",
227  object.get_path());
228 
229  if (is_valid())
230  {
231  throw std::runtime_error(
232  "Error, cannot open HDFType while it's still bound to another "
233  "valid type object, close it first");
234  }
235 
236  bind_to(open_type(object),
237  &H5Tclose, // we lock the type, hence no H5Tclose needed
238  "datatype of " + object.get_path());
239 
240  _mutable = true;
241  _classid = H5Tget_class(get_C_id());
242  }
243 
253  template < typename T >
254  void
255  open(std::string name, hsize_t typesize)
256  {
257  this->_log->debug("Opening HDFType from scratch");
258 
259  if (is_valid())
260  {
261  throw std::runtime_error(
262  "Error, cannot open HDFType '" + name + "' while it's still bound "
263  "to another valid type object! Close it first.");
264  }
265 
266  // include const char* which is a c-string
267  if constexpr (Utils::is_container_v< T >)
268  {
269  if (typesize == 0ul)
270  {
271  bind_to(H5Tvlen_create(
272  Detail::get_type< typename T::value_type >()),
273  &H5Tclose,
274  name);
275  }
276  else
277  {
278  hsize_t dim[1] = { typesize };
279  bind_to(
280  H5Tarray_create(
281  Detail::get_type< typename T::value_type >(), 1, dim),
282  &H5Tclose,
283  name);
284  }
285  _mutable = true;
286  }
287  else if constexpr (Utils::is_string_v< T >)
288  {
289  hid_t type = H5Tcopy(H5T_C_S1);
290 
291  if (typesize == 0)
292  {
293  H5Tset_size(type, H5T_VARIABLE);
294  }
295  else
296  {
297  H5Tset_size(type, typesize);
298  }
299  bind_to(std::move(type), &H5Tclose, name);
300 
301  _mutable = true;
302  }
303  else
304  {
305  // native type objects like H5T_NATIVE_INT are interpreted as
306  // invalid by H5Iis_valid, hence at this point the `bind_to`
307  // function is not used, because it checks validity
308  _id.open(Detail::get_type< T >(),
309  [](hid_t) -> herr_t { return 0; });
310  _path = name;
311  _mutable = false;
312  }
313 
314  _classid = H5Tget_class(get_C_id());
315  }
316 
321  void
322  close()
323  {
324 
325  // everything that is obtained via H5Tcopy, H5Topen or H5Tcreate
326  // needs to be released explicitly. This is given by the _mutable
327  // flag
328  Base::close();
329  _mutable = false;
330  _classid = H5T_NO_CLASS;
331  }
332 
341  virtual bool
342  is_valid() const override
343  {
344  // this distinction is important because identifiers are not always
345  // checkable via H5Iis_valid
346  if (not(_classid == H5T_VLEN or _classid == H5T_ARRAY or
347  _classid == H5T_STRING) and
348  not(get_C_id() == -1))
349  {
350  return true;
351  }
352  else
353  {
354  return Base::is_valid();
355  }
356  }
357 
363  HDFType(HDFType&& other) : Base(static_cast< Base&& >(other))
364  {
365  _mutable = std::move(other._mutable);
366  _classid = std::move(other._classid);
367 
368  other._mutable = false;
369  other._classid = H5T_NO_CLASS;
370  }
371 
377  HDFType&
379  {
380  static_cast<Base&>(*this) = static_cast< Base&& >(other);
381  _mutable = std::move(other._mutable);
382  _classid = std::move(other._classid);
383 
384  other._mutable = false;
385  other._classid = H5T_NO_CLASS;
386 
387  return *this;
388  }
389 
394  HDFType(const HDFType& other) = default;
395 
401  HDFType&
402  operator=(const HDFType& other) = default;
403 
408  virtual ~HDFType()
409  {
410  close();
411  }
412 
417  HDFType() : Base(), _mutable(false), _classid(H5T_NO_CLASS)
418  {
419  }
420 
427  template < typename T >
428  HDFType(T&& object_or_size,
429  std::enable_if_t< not std::is_same_v< HDFType, std::decay_t< T > >, int > = 0):
430  HDFType()
431  {
432  open(object_or_size);
433  }
434 };
435 
448 bool
449 operator==(const HDFType& lhs, const HDFType& rhs)
450 {
451  auto equal = H5Tequal(lhs.get_C_id(), rhs.get_C_id()) &&
452  lhs.type_category() == rhs.type_category();
453  if (equal > 0)
454  {
455  return true;
456  }
457  else if (equal == 0)
458  {
459  return false;
460  }
461  else
462  {
463  throw std::runtime_error("Error when comparing dataspaces");
464  return false;
465  }
466 }
467 
476 bool
477 operator!=(const HDFType& lhs, const HDFType& rhs)
478 {
479  return not(lhs == rhs);
480 }
481  // end of group HDF5 // end of group DataIO
484 
485 } // namespace DataIO
486 } // namespace Utopia
487 
488 #endif
void open(hid_t id, std::function< herr_t(hid_t) > closing_func)
Open the object and bind it to another C-Level id.
Definition: hdfidentifier.hh:156
Common base class for all HDF5 classes in the DATAIO Module i.e., for all classes that wrap HDF5-C-Li...
Definition: hdfobject.hh:37
std::string _path
Name of the object.
Definition: hdfobject.hh:50
std::string get_path() const
Get the name or path object.
Definition: hdfobject.hh:88
void close()
Close function which takes care of correctly closing the object and managing the reference counter.
Definition: hdfobject.hh:161
virtual bool is_valid() const
Check if the object is still valid.
Definition: hdfobject.hh:143
std::shared_ptr< spdlog::logger > _log
pointer to the logger for dataio
Definition: hdfobject.hh:56
HDFIdentifier _id
Identifier object that binds an instance of this class to an HDF5 object.
Definition: hdfobject.hh:44
hid_t get_C_id() const
Get the C id object.
Definition: hdfobject.hh:120
void bind_to(hid_t id, std::function< herr_t(hid_t) > closing_func, std::string path={})
Open the object and bind it to a HDF5 object identified by 'id' with name 'path'. Object should be cr...
Definition: hdfobject.hh:186
Class which handles the conversion of C-types into hdf5types.
Definition: hdftype.hh:136
HDFType & operator=(const HDFType &other)=default
Copy assign type.
void open(T &&object)
Open the HDF5 type associated with an HDFObject, i.e., a dataset or an attribute.
Definition: hdftype.hh:224
void open(std::string name, hsize_t typesize)
Create an HDF datatype corresponding to the C datatype given as template argument.
Definition: hdftype.hh:255
HDFType(HDFType &&other)
Construct HDFType from the given arguments by move, deleted, because apparently incompatible with HDF...
Definition: hdftype.hh:363
virtual ~HDFType()
Destroy the HDFType object.
Definition: hdftype.hh:408
HDFType()
Construct HDFType from by default.
Definition: hdftype.hh:417
void close()
Construct close from the given arguments.
Definition: hdftype.hh:322
auto type_category() const
Get the type category of the held type, i.e., scala, string, varlen,...
Definition: hdftype.hh:199
HDFType(T &&object_or_size, std::enable_if_t< not std::is_same_v< HDFType, std::decay_t< T > >, int >=0)
Construct HDFType from the given arguments.
Definition: hdftype.hh:428
H5T_class_t _classid
Definition: hdftype.hh:143
std::size_t size() const
Size of the type held in bytes.
Definition: hdftype.hh:210
bool _mutable
Definition: hdftype.hh:140
bool is_mutable() const
Get if the type is mutable or not.
Definition: hdftype.hh:187
HDFType & operator=(HDFType &&other)
Move assign the type.
Definition: hdftype.hh:378
virtual bool is_valid() const override
Check if the held type identifier is still valid. Primitive types are valid by definition,...
Definition: hdftype.hh:342
std::variant< float, double, long double, int, short int, long int, long long int, unsigned int, unsigned short int, std::size_t, unsigned long long, bool, char, std::vector< float >, std::vector< double >, std::vector< long double >, std::vector< int >, std::vector< short int >, std::vector< long int >, std::vector< long long int >, std::vector< unsigned int >, std::vector< unsigned short int >, std::vector< std::size_t >, std::vector< unsigned long long >, std::vector< char >, std::vector< std::string >, std::string, const char * > Variant
Definition: hdftype.hh:178
HDFType(const HDFType &other)=default
Construct HDFType from the given arguments by copy.
bool operator!=(const HDFIdentifier &lhs, const HDFIdentifier &rhs)
Comparsion operator for inequality.
Definition: hdfidentifier.hh:275
bool operator==(const HDFIdentifier &lhs, const HDFIdentifier &rhs)
Comparsion operator for equality.
Definition: hdfidentifier.hh:262
hid_t open_type(Object &&object)
Depending on object category, invokes H5Dget_type or H5Aget_type.
Definition: hdfutilities.hh:261
This file provides metafunctions for automatically determining the nature of a C/C++ types at compile...
hid_t get_type< double >()
Definition: hdftype.hh:54
hid_t get_type< std::size_t >()
Definition: hdftype.hh:103
hid_t get_type< char >()
Definition: hdftype.hh:123
hid_t get_type< float >()
Definition: hdftype.hh:47
hid_t get_type< long long int >()
Definition: hdftype.hh:85
hid_t get_type()
Definition: hdftype.hh:39
hid_t get_type< unsigned short int >()
Definition: hdftype.hh:97
hid_t get_type< bool >()
Definition: hdftype.hh:117
hid_t get_type< short int >()
Definition: hdftype.hh:73
hid_t get_type< int >()
Definition: hdftype.hh:66
hid_t get_type< unsigned long long >()
Definition: hdftype.hh:110
hid_t get_type< unsigned int >()
Definition: hdftype.hh:91
hid_t get_type< long int >()
Definition: hdftype.hh:79
hid_t get_type< long double >()
Definition: hdftype.hh:60
Definition: agent.hh:11