RMF
MutableAttributes.h
Go to the documentation of this file.
1 /**
2  * \file RMF/HDF5/MutableAttributes.h
3  * \brief Handle read/write of Model data from/to files.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef RMF_HDF5_MUTABLE_ATTRIBUTES_H
10 #define RMF_HDF5_MUTABLE_ATTRIBUTES_H
11 
12 #include "RMF/config.h"
13 #include "handle.h"
14 #include "infrastructure_macros.h"
15 #include <hdf5.h>
16 
17 RMF_ENABLE_WARNINGS
18 namespace RMF {
19 namespace HDF5 {
20 /** Wrap a set of HDF5 Attributes. See
21  \external{https://docs.hdfgroup.org/releases/hdf5/v1_14/v1_14_4/documentation/doxygen/group___h5_a.html,
22  the HDF5 manual} for more information.
23  */
24 template <class Base>
25 class MutableAttributes : public Base {
26  typedef Base P;
27 #ifndef SWIG
28  protected:
30  template <class A>
31  MutableAttributes(const A& h)
32  : Base(h) {}
33  template <class A, class B>
34  MutableAttributes(const A& h, const B& i)
35  : Base(h, i) {}
36  template <class A, class B, class C>
37  MutableAttributes(const A& h, const B& i, const C& j)
38  : Base(h, i, j) {}
39  template <class A, class B, class C, class D>
40  MutableAttributes(const A& h, const B& i, const C& j, const D& k)
41  : Base(h, i, j, k) {}
42 #else
43  private:
45 #endif
46  public:
47  /** \name Template attribute methods
48  When manipulating attributes from C++ you can use these
49  templated methods.
50  @{
51  */
52  template <class TypeTraits>
53  void set_attribute(std::string name, typename TypeTraits::Types value) {
54  if (value.empty()) {
55  if (H5Aexists(P::get_handle(), name.c_str())) {
56  RMF_HDF5_CALL(H5Adelete(P::get_handle(), name.c_str()));
57  }
58  } else {
59  bool missing = !H5Aexists(P::get_handle(), name.c_str());
60  if (!missing) {
61  hsize_t dim, maxdim;
62  {
63  RMF_HDF5_HANDLE(a,
64  H5Aopen(P::get_handle(), name.c_str(), H5P_DEFAULT),
65  &H5Aclose);
66  RMF_HDF5_HANDLE(s, H5Aget_space(a), &H5Sclose);
67  RMF_HDF5_CALL(H5Sget_simple_extent_dims(s, &dim, &maxdim));
68  }
69  if (value.size() != dim) {
70  RMF_HDF5_CALL(H5Adelete(P::get_handle(), name.c_str()));
71  missing = true;
72  }
73  }
74  if (missing) {
75  RMF_HDF5_HANDLE(s, H5Screate(H5S_SIMPLE), &H5Sclose);
76  hsize_t dim = std::max(value.size(), size_t(1));
77  hsize_t max = H5S_UNLIMITED;
78  RMF_HDF5_CALL(H5Sset_extent_simple(s, 1, &dim, &max));
79  RMF_HDF5_HANDLE(a, H5Acreate2(P::get_handle(), name.c_str(),
80  TypeTraits::get_hdf5_disk_type(), s,
81  H5P_DEFAULT, H5P_DEFAULT),
82  &H5Aclose);
83  }
84  RMF_HDF5_HANDLE(a, H5Aopen(P::get_handle(), name.c_str(), H5P_DEFAULT),
85  &H5Aclose);
86  TypeTraits::write_values_attribute(a, value);
87  }
88  }
89 
90 /** @} */
91 /** \name Nontemplated attributes
92  When using python, call the non-template versions of the
93  attribute manipulation methods.
94  @{
95  */
96 #define RMF_HDF5_ATTRIBUTE(lcname, UCName, PassValue, ReturnValue, PassValues, \
97  ReturnValues) \
98  void set_##lcname##_attribute(std::string nm, PassValues value) { \
99  set_attribute<UCName##Traits>(nm, value); \
100  }
101 
102  RMF_FOREACH_SIMPLE_TYPE(RMF_HDF5_ATTRIBUTE);
103  RMF_HDF5_ATTRIBUTE(char, Char, char, char, std::string, std::string);
104  /** @} */
105 };
106 
107 } /* namespace HDF5 */
108 } /* namespace RMF */
109 
110 RMF_DISABLE_WARNINGS
111 
112 #endif /* RMF_HDF5_MUTABLE_ATTRIBUTES_H */
char Char
Definition: HDF5/types.h:52
Various general useful macros for IMP.
Handle read/write of Model data from/to files.
#define RMF_HDF5_CALL(v)
Include all non-deprecated headers in RMF.HDF5.
#define RMF_FOREACH_SIMPLE_TYPE(macroname)