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
32namespace 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 try {
62 reset();
63 }
64 catch(Exception &ex) {
65 std::cerr<<"Error in ScopedHID::dtor: "<<ex.what()<<std::endl;
66 }
67 }
68 operator hid_t() {
69 return id;
70 }
71 void reset() {
72 if(id>=0)
73 if(closeFunc(id)<0)
74 throw Exception("<unknown>", "Close function of ScopedHID failed.");
75 id=-1;
76 closeFunc=nullptr;
77 }
78 void reset(hid_t id_, CloseFunc closeFunc_) {
79 reset();
80 if(id_<0)
81 throw Exception("<unknown>", "Calling the HDF5 function failed (during reset).");
82 if(!closeFunc_)
83 throw Exception("<unknown>", "No close function defined.");
84 id=id_;
85 closeFunc=closeFunc_;
86 }
87 };
88
89 inline void checkCall(herr_t err) {
90 if(err<0)
91 throw Exception("<unknown>", "A HDF5 call failed.");
92 }
93
94 class File;
95 class GroupBase;
96 class Attribute;
97 class Object;
98 template<class Child, class Self> class Container;
99
100 enum ElementType {
101 simpleDatasetScalar,
102 simpleDatasetVector,
103 simpleDatasetMatrix,
104 vectorSerie,
105 simpleAttributeScalar,
106 simpleAttributeVector,
107 simpleAttributeMatrix
108 };
109
110 class Element : virtual public fmatvec::Atom {
111 friend class Container<Attribute, Object>;
112 friend class Container<Object, GroupBase>;
113 protected:
114 ScopedHID id;
115 std::string name;
116 Element(std::string name_);
117 ~Element() override;
118 virtual void close();
119 virtual void refresh();
120 virtual void flush();
121 virtual void enableSWMR();
122 public:
124 hid_t getID() { return id; }
125 std::string getName() { return name; }
126 };
127
128 // a container of objects of type Child which have itself a parent of type Self
129 template<class Child, class Self>
130 class Container {
131 protected:
132 Container() = default;
133 ~Container() {
134 for(auto it=childs.begin(); it!=childs.end(); ++it)
135 delete it->second;
136 }
137 void close() {
138 for(auto it=childs.begin(); it!=childs.end(); ++it)
139 it->second->close();
140 }
141 void refresh() {
142 for(auto it=childs.begin(); it!=childs.end(); ++it)
143 it->second->refresh();
144 }
145 void flush() {
146 for(auto it=childs.begin(); it!=childs.end(); ++it)
147 it->second->flush();
148 }
149 void enableSWMR() {
150 if constexpr (std::is_same_v<Child, Attribute>) {
151 // attributes must be closed if SWMR is enabled
152 for(auto it=childs.begin(); it!=childs.end(); ++it)
153 delete it->second;
154 childs.clear();
155 }
156 else {
157 // for everything else we just call enableSWMR (which usually does just nothing)
158 for(auto it=childs.begin(); it!=childs.end(); ++it)
159 {
160 it->second->enableSWMR();
161 }
162 }
163 }
164 std::map<std::string, Child*> childs;
165
166 // create a objet of class T which is derived from Child
167 template<class T>
168 class Creator {
169 protected:
170 Self *self;
171 std::string name;
172 std::map<std::string, Child*> &childs;
173 public:
174 Creator(Self *self_, std::string name_, std::map<std::string, Child*> &childs_) :
175 self(self_), name(std::move(name_)), childs(childs_) {}
176
177 template<typename... Args>
178 T* operator()(Args&&... args) {
179 auto ret=childs.insert(std::pair<std::string, Child*>(name, NULL));
180 if(!ret.second)
181 throw Exception(self->getPath(), "A element of name "+name+" already exists.");
182 try {
183 auto* r=new T(static_cast<Self*>(self), name, std::forward<Args>(args)...);
184 ret.first->second=r;
185 return r;
186 }
187 catch(...) {
188 childs.erase(name);
189 throw;
190 }
191 }
192 };
193 template<class T>
194 Creator<T> createChild(const std::string &name_) {
195 if(name_.find_first_of('/')!=std::string::npos)
196 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
197 return Creator<T>(static_cast<Self*>(this), name_, childs);
198 }
199
200 template<class T>
201 T* openChild(const std::string &name_) {
202 if(name_.find_first_of('/')!=std::string::npos)
203 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
204 std::pair<typename std::map<std::string, Child*>::iterator, bool> ret=childs.insert(std::pair<std::string, Child*>(name_, NULL));
205 if(!ret.second) {
206 auto *o=dynamic_cast<T*>(ret.first->second);
207 if(!o)
208 std::runtime_error("The element "+name_+" if of other type.");
209 return o;
210 }
211 try {
212 auto* r=new T(0, static_cast<Self*>(this), name_);
213 ret.first->second=r;
214 return r;
215 }
216 catch(...) {
217 childs.erase(name_);
218 throw;
219 }
220 }
221 };
222
223 class Object : public Element, public Container<Attribute, Object> {
224 friend class Container<Object, GroupBase>;
225 protected:
226 Object(GroupBase *parent_, const std::string &name_);
227 ~Object() override;
228 void close() override;
229 void refresh() override;
230 void flush() override;
231 void enableSWMR() override;
232 GroupBase *parent;
233 File *file;
234 Object *getFileAsObject(); // helper function used in openChildAttribute
235 Object *getAttrParent(const std::string &path, size_t pos); // helper function used in openChildAttribute
236 public:
237 template<class T>
238 Creator<T> createChildAttribute(const std::string &path) {
239 if(path[0]=='/') // absolute path -> call openChildAttribute from file
240 return getFileAsObject()->createChildAttribute<T>(path.substr(1));
241 // now its a relative path
242 size_t pos;
243 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
244 return createChild<T>(path);
245 // now its a relative path including at least one /
246 return getAttrParent(path, pos)->createChild<T>(path.substr(pos+1));
247 }
248
249 template<class T>
250 T* openChildAttribute(const std::string &path) {
251 if(path[0]=='/') // absolute path -> call openChildAttribute from file
252 return getFileAsObject()->openChildAttribute<T>(path.substr(1));
253 // now its a relative path
254 size_t pos;
255 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
256 return openChild<T>(path);
257 // now its a relative path including at least one /
258 return getAttrParent(path, pos)->openChild<T>(path.substr(pos+1));
259 }
260 Attribute *openChildAttribute(const std::string &name_, ElementType *attributeType=nullptr, hid_t *type=nullptr);
261 std::set<std::string> getChildAttributeNames();
262 bool hasChildAttribute(const std::string &name_);
263 GroupBase *getParent() { return parent; }
264 File *getFile() { return file; }
265 std::string getPath();
266 };
267
268 class Attribute : public Element {
269 friend class Container<Attribute, Object>;
270 protected:
271 Attribute(Object *parent_, const std::string &name_);
272 ~Attribute() override;
273 Object *parent;
274 File *file;
275 void close() override;
276 void refresh() override;
277 void flush() override;
278 public:
279 Object *getParent() { return parent; }
280 File *getFile() { return file; }
281 std::string getPath();
282 };
283
284 class Dataset : public Object {
285 protected:
286 Dataset(GroupBase *parent_, const std::string &name_);
287 Dataset(int dummy, GroupBase *parent_, const std::string &name_);
288 ~Dataset() override;
289 void close() override;
290 void refresh() override;
291 void flush() override;
292 void enableSWMR() override;
293 public:
294 std::vector<hsize_t> getExtentDims();
295 };
296
297}
298
299#endif
Definition: interface.h:268
Definition: interface.h:168
Definition: interface.h:130
Definition: interface.h:284
Definition: interface.h:110
hid_t getID()
Note: use the returned hid_t only temporarily since it may get invalid, at least when File::enableSWM...
Definition: interface.h:124
Definition: interface.h:36
Definition: file.h:98
Definition: group.h:31
Definition: interface.h:223
Definition: interface.h:47