Fix bugs and it is now possible to read hyperslabs
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5NamedObjectsList.hxx
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #ifndef __H5NAMEDOBJECTSLIST_HXX__
14 #define __H5NAMEDOBJECTSLIST_HXX__
15
16 #include "H5Object.hxx"
17 #include "H5File.hxx"
18 #include "H5Link.hxx"
19 #include "H5ListObject.hxx"
20
21 namespace org_modules_hdf5
22 {
23
24 class H5Group;
25
26 template <typename T>
27 class H5NamedObjectsList : public H5ListObject<T>
28 {
29
30     typedef struct
31     {
32         union
33         {
34             unsigned int count;
35             const char * name;
36         } u;
37         int linktype;
38         int basetype;
39     } OpData;
40
41     int prevPos;
42     hsize_t idx;
43
44 public :
45
46     H5NamedObjectsList(H5Group & _parent, const int _baseType, const int _linkType, const std::string _baseTypeName) : H5ListObject<T>(_parent), baseType(_baseType), linkType(_linkType), baseTypeName(_baseTypeName), prevPos(0), idx(0) { }
47
48     H5NamedObjectsList(H5Group & _parent, const unsigned int _size, const unsigned int * _index, const int _baseType, const int _linkType, const std::string _baseTypeName) : H5ListObject<T>(_parent, _size, _index), baseType(_baseType), linkType(_linkType), baseTypeName(_baseTypeName), prevPos(0), idx(0)
49     {
50         const unsigned int lsize = getSize(true);
51         for (unsigned int i = 0; i < H5ListObject<T>::indexSize; i++)
52         {
53             if (H5ListObject<T>::indexList[i] >= lsize)
54             {
55                 throw H5Exception(__LINE__, __FILE__, _("Invalid index at position %d"), i);
56             }
57         }
58     }
59
60     virtual ~H5NamedObjectsList()
61     {
62
63     }
64
65     void setObject(const unsigned int pos, T & obj)
66     {
67
68     }
69
70     T & getObject(const int pos)
71     {
72         return getObject(pos, true);
73     }
74
75     inline static herr_t count(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
76     {
77         OpData & opdata = *(OpData *)op_data;
78
79         if ((opdata.linktype != -1 && info->type == opdata.linktype) || (opdata.linktype == -1 && info->type != H5L_TYPE_ERROR))
80         {
81             H5O_info_t oinfo;
82             herr_t err;
83             if (opdata.basetype != -1)
84             {
85                 hid_t obj = H5Oopen(g_id, name, H5P_DEFAULT);
86
87                 if (obj < 0)
88                 {
89                     return (herr_t) - 1;
90                 }
91
92                 err = H5Oget_info(obj, &oinfo);
93                 H5Oclose(obj);
94
95                 if (err < 0)
96                 {
97                     return (herr_t) - 2;
98                 }
99
100                 if (oinfo.type == opdata.basetype)
101                 {
102                     opdata.u.count++;
103                 }
104             }
105             else
106             {
107                 opdata.u.count++;
108             }
109         }
110
111         return (herr_t)0;
112     }
113
114     inline static herr_t getElement(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
115     {
116         OpData & opdata = *(OpData *)op_data;
117
118         if ((opdata.linktype != -1 && info->type == opdata.linktype) || (opdata.linktype == -1 && info->type != H5L_TYPE_ERROR))
119         {
120             H5O_info_t oinfo;
121             herr_t err;
122             if (opdata.basetype != -1)
123             {
124                 hid_t obj = H5Oopen(g_id, name, H5P_DEFAULT);
125
126                 if (obj < 0)
127                 {
128                     return (herr_t) - 1;
129                 }
130
131                 err = H5Oget_info(obj, &oinfo);
132                 H5Oclose(obj);
133
134                 if (err < 0)
135                 {
136                     return (herr_t) - 2;
137                 }
138
139                 if (oinfo.type == opdata.basetype)
140                 {
141                     opdata.u.count--;
142                 }
143             }
144             else
145             {
146                 opdata.u.count--;
147             }
148
149             if (opdata.u.count == 0)
150             {
151                 opdata.u.name = strdup(name);
152
153                 return (herr_t)1;
154             }
155         }
156
157         return (herr_t)0;
158     }
159
160     const unsigned int getSize() const
161     {
162         return getSize(false);
163     }
164
165     const unsigned int getSize(const bool indexChecking) const
166     {
167         if (H5ListObject<T>::indexList && !indexChecking)
168         {
169             return H5ListObject<T>::indexSize;
170         }
171         else
172         {
173             hsize_t idx = 0;
174             OpData op_data;
175             herr_t err;
176
177             op_data.u.count = 0;
178             op_data.linktype = linkType;
179             op_data.basetype = baseType;
180
181             err = H5Literate(H5Object::getParent().getH5Id(), H5_INDEX_NAME, H5_ITER_INC, &idx, count, &op_data);
182
183             if (err < 0)
184             {
185                 throw H5Exception(__LINE__, __FILE__, _("Cannot get the number of objects."));
186             }
187
188             return op_data.u.count;
189         }
190     }
191
192     virtual std::string dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
193     {
194         std::ostringstream os;
195         const unsigned int size = getSize();
196
197         for (unsigned int i = 0; i < size; i++)
198         {
199             const T & obj = const_cast<H5NamedObjectsList *>(this)->getObject(i, false);
200             os << obj.dump(alreadyVisited, indentLevel);
201
202             delete &obj;
203         }
204
205         return os.str();
206     }
207
208     virtual void printLsInfo(std::ostringstream & os) const
209     {
210         const unsigned int size = getSize();
211
212         for (unsigned int i = 0; i < size; i++)
213         {
214             const T & obj = const_cast<H5NamedObjectsList *>(this)->getObject(i, false);
215             obj.printLsInfo(os);
216
217             delete &obj;
218         }
219     }
220
221     virtual std::string toString(const unsigned int indentLevel) const
222     {
223         std::ostringstream os;
224         std::string indentString = H5Object::getIndentString(indentLevel);
225         const unsigned int size = getSize();
226
227         os << indentString << _("Filename") << ": " << H5Object::getParent().getFile().getFileName() << std::endl
228            << indentString << _("Parent group name") << ": " << H5Object::getParent().getName() << std::endl
229            << indentString << _("Parent group path") << ": " << H5Object::getParent().getCompletePath() << std::endl
230            << indentString << _("Elements type") << ": " << baseTypeName << std::endl
231            << indentString << _("Size") << ": " << size;
232
233         return os.str();
234     }
235
236 protected :
237
238     const int baseType;
239     const int linkType;
240     const std::string baseTypeName;
241
242 private:
243
244     T & getObject(const int pos, const bool checkPos)
245     {
246         OpData op_data;
247         herr_t err;
248         int _pos = pos;
249
250         if (H5ListObject<T>::indexList)
251         {
252             if (pos >= 0 && pos < H5ListObject<T>::indexSize)
253             {
254                 _pos = H5ListObject<T>::indexList[pos];
255             }
256             else
257             {
258                 throw H5Exception(__LINE__, __FILE__, _("Invalid index: %d."), pos);
259             }
260         }
261
262         op_data.linktype = linkType;
263         op_data.basetype = baseType;
264
265         if (_pos < prevPos)
266         {
267             idx = 0;
268             op_data.u.count = _pos + 1;
269         }
270         else
271         {
272             op_data.u.count = _pos - prevPos + 1;
273         }
274
275         err = H5Literate(H5Object::getParent().getH5Id(), H5_INDEX_NAME, H5_ITER_INC, &idx, getElement, &op_data);
276
277         if (err > 0)
278         {
279             prevPos = _pos + 1;
280             return *new T(H5Object::getParent(), op_data.u.name);
281         }
282         else
283         {
284             idx = 0;
285             prevPos = 0;
286             throw H5Exception(__LINE__, __FILE__, _("Cannot get object at position %d."), pos);
287         }
288     }
289
290     T & getObject(const std::string & name)
291     {
292         H5O_info_t info;
293         herr_t err;
294         H5Object * obj = 0;
295
296         if (H5Lexists(H5Object::getParent().getH5Id(), name.c_str(), H5P_DEFAULT) <= 0)
297         {
298             throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name.c_str());
299         }
300
301         err = H5Oget_info_by_name(H5Object::getParent().getH5Id(), name.c_str(), &info, H5P_DEFAULT);
302         if (err < 0)
303         {
304             throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name.c_str());
305         }
306
307         if (info.type == baseType)
308         {
309             return *new T(H5Object::getParent(), name);
310         }
311
312         throw H5Exception(__LINE__, __FILE__, _("Invalid HDF5 object"));
313     }
314 };
315 }
316
317 #endif // __H5NAMEDOBJECTSLIST_HXX__