hdf5serie 2.0.0 HDF5 Serie

interface.h
1 /* Copyright (C) 2009 Markus Friedrich
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * Contact:
18 * friedrich.at.gc@googlemail.com
19 *
20 */
21
22 #ifndef _HDF5SERIE_INTERFACE_H_
23 #define _HDF5SERIE_INTERFACE_H_
24
25 #include <fmatvec/atom.h>
26 #include <hdf5.h>
27 #include <map>
28 #include <set>
29 #include <utility>
30 #include <vector>
31
32 namespace H5 {
33
34 #define HDF5SERIE_MAXCTORPARAMETERS 5
35
36 class Exception : public std::exception {
37 protected:
38 std::string path;
39 std::string msg;
40 mutable std::string whatMsg;
41 public:
42 explicit Exception(std::string path_, std::string msg_);
43 ~Exception() noexcept override;
44 const char* what() const noexcept override;
45 };
46
47 class ScopedHID {
48 protected:
49 using CloseFunc = herr_t (*)(hid_t);
50 hid_t id{-1};
51 CloseFunc closeFunc{nullptr};
52 public:
53 ScopedHID() = default;
54 ScopedHID(hid_t id_, CloseFunc closeFunc_) : id(id_), closeFunc(closeFunc_) {
55 if(id<0)
56 throw Exception("<unknown>", "Calling the HDF5 function failed.");
57 if(!closeFunc)
58 throw Exception("<unknown>", "No close function defined.");
59 }
60 ~ScopedHID() {
61 reset();
62 }
63 operator hid_t() {
64 return id;
65 }
66 void reset() {
67 if(id>=0)
68 closeFunc(id);
69 id=-1;
70 closeFunc=nullptr;
71 }
72 void reset(hid_t id_, CloseFunc closeFunc_) {
73 reset();
74 if(id_<0)
75 throw Exception("<unknown>", "Calling the HDF5 function failed (during reset).");
76 if(!closeFunc_)
77 throw Exception("<unknown>", "No close function defined.");
78 id=id_;
79 closeFunc=closeFunc_;
80 }
81 };
82
83 class File;
84 class GroupBase;
85 class Attribute;
86 class Object;
87 template<class Child, class Self> class Container;
88
89 enum ElementType {
90 simpleDatasetScalar,
91 simpleDatasetVector,
92 simpleDatasetMatrix,
93 vectorSerie,
94 simpleAttributeScalar,
95 simpleAttributeVector,
96 simpleAttributeMatrix
97 };
98
99 class Element : virtual public fmatvec::Atom {
100 friend class Container<Attribute, Object>;
101 friend class Container<Object, GroupBase>;
102 protected:
103 ScopedHID id;
104 std::string name;
105 Element(std::string name_);
106 ~Element() override;
107 virtual void close();
108 virtual void refresh();
109 virtual void flush();
110 virtual void enableSWMR();
111 public:
113 hid_t getID() { return id; }
114 std::string getName() { return name; }
115 };
116
117 // a container of objects of type Child which have itself a parent of type Self
118 template<class Child, class Self>
119 class Container {
120 protected:
121 Container() = default;
122 ~Container() {
123 for(auto it=childs.begin(); it!=childs.end(); ++it)
124 delete it->second;
125 }
126 void close() {
127 for(auto it=childs.begin(); it!=childs.end(); ++it)
128 it->second->close();
129 }
130 void refresh() {
131 for(auto it=childs.begin(); it!=childs.end(); ++it)
132 it->second->refresh();
133 }
134 void flush() {
135 for(auto it=childs.begin(); it!=childs.end(); ++it)
136 it->second->flush();
137 }
138 void enableSWMR() {
139 if constexpr (std::is_same_v<Child, Attribute>) {
140 // attributes must be closed if SWMR is enabled
141 for(auto it=childs.begin(); it!=childs.end(); ++it)
142 delete it->second;
143 childs.clear();
144 }
145 else {
146 // for everything else we just call enableSWMR (which usually does just nothing)
147 for(auto it=childs.begin(); it!=childs.end(); ++it)
148 {
149 it->second->enableSWMR();
150 }
151 }
152 }
153 std::map<std::string, Child*> childs;
154
155 // create a objet of class T which is derived from Child
156 template<class T>
157 class Creator {
158 protected:
159 Self *self;
160 std::string name;
161 std::map<std::string, Child*> &childs;
162 public:
163 Creator(Self *self_, std::string name_, std::map<std::string, Child*> &childs_) :
164 self(self_), name(std::move(name_)), childs(childs_) {}
165
166 template<typename... Args>
167 T* operator()(Args&&... args) {
168 auto ret=childs.insert(std::pair<std::string, Child*>(name, NULL));
169 if(!ret.second)
170 throw Exception(self->getPath(), "A element of name "+name+" already exists.");
171 try {
172 auto* r=new T(static_cast<Self*>(self), name, std::forward<Args>(args)...);
173 ret.first->second=r;
174 return r;
175 }
176 catch(...) {
177 childs.erase(name);
178 throw;
179 }
180 }
181 };
182 template<class T>
183 Creator<T> createChild(const std::string &name_) {
184 if(name_.find_first_of('/')!=std::string::npos)
185 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
186 return Creator<T>(static_cast<Self*>(this), name_, childs);
187 }
188
189 template<class T>
190 T* openChild(const std::string &name_) {
191 if(name_.find_first_of('/')!=std::string::npos)
192 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
193 std::pair<typename std::map<std::string, Child*>::iterator, bool> ret=childs.insert(std::pair<std::string, Child*>(name_, NULL));
194 if(!ret.second) {
195 auto *o=dynamic_cast<T*>(ret.first->second);
196 if(!o)
197 std::runtime_error("The element "+name_+" if of other type.");
198 return o;
199 }
200 try {
201 auto* r=new T(0, static_cast<Self*>(this), name_);
202 ret.first->second=r;
203 return r;
204 }
205 catch(...) {
206 childs.erase(name_);
207 throw;
208 }
209 }
210 };
211
212 class Object : public Element, public Container<Attribute, Object> {
213 friend class Container<Object, GroupBase>;
214 protected:
215 Object(GroupBase *parent_, const std::string &name_);
216 ~Object() override;
217 void close() override;
218 void refresh() override;
219 void flush() override;
220 void enableSWMR() override;
221 GroupBase *parent;
222 File *file;
223 Object *getFileAsObject(); // helper function used in openChildAttribute
224 Object *getAttrParent(const std::string &path, size_t pos); // helper function used in openChildAttribute
225 public:
226 template<class T>
227 Creator<T> createChildAttribute(const std::string &path) {
228 if(path[0]=='/') // absolute path -> call openChildAttribute from file
229 return getFileAsObject()->createChildAttribute<T>(path.substr(1));
230 // now its a relative path
231 size_t pos;
232 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
233 return createChild<T>(path);
234 // now its a relative path including at least one /
235 return getAttrParent(path, pos)->createChild<T>(path.substr(pos+1));
236 }
237
238 template<class T>
239 T* openChildAttribute(const std::string &path) {
240 if(path[0]=='/') // absolute path -> call openChildAttribute from file
241 return getFileAsObject()->openChildAttribute<T>(path.substr(1));
242 // now its a relative path
243 size_t pos;
244 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
245 return openChild<T>(path);
246 // now its a relative path including at least one /
247 return getAttrParent(path, pos)->openChild<T>(path.substr(pos+1));
248 }
249 Attribute *openChildAttribute(const std::string &name_, ElementType *attributeType=nullptr, hid_t *type=nullptr);
250 std::set<std::string> getChildAttributeNames();
251 bool hasChildAttribute(const std::string &name_);
252 GroupBase *getParent() { return parent; }
253 File *getFile() { return file; }
254 std::string getPath();
255 };
256
257 class Attribute : public Element {
258 friend class Container<Attribute, Object>;
259 protected:
260 Attribute(Object *parent_, const std::string &name_);
261 ~Attribute() override;
262 Object *parent;
263 File *file;
264 void close() override;
265 void refresh() override;
266 void flush() override;
267 public:
268 Object *getParent() { return parent; }
269 File *getFile() { return file; }
270 std::string getPath();
271 };
272
273 class Dataset : public Object {
274 protected:
275 Dataset(GroupBase *parent_, const std::string &name_);
276 Dataset(int dummy, GroupBase *parent_, const std::string &name_);
277 ~Dataset() override;
278 void close() override;
279 void refresh() override;
280 void flush() override;
281 void enableSWMR() override;
282 public:
283 std::vector<hsize_t> getExtentDims();
284 };
285
286 }
287
288 #endif
H5::Attribute
Definition: interface.h:257
H5::Exception
Definition: interface.h:36
H5::Container::Creator
Definition: interface.h:157
H5::Object
Definition: interface.h:212
H5::Element
Definition: interface.h:99
H5::ScopedHID
Definition: interface.h:47
H5::GroupBase
Definition: group.h:31
H5::Container
Definition: interface.h:87
H5::Dataset
Definition: interface.h:273
H5::Element::getID
hid_t getID()
Note: use the returned hid_t only temporarily since it may get invalid, at least when File::enableSWM...
Definition: interface.h:113
H5::File
Definition: file.h:98