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