b56aed6ab28d818b7d2e8a53039a58fcedcd2687
[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     virtual ~H5NamedObjectsList()
49     {
50
51     }
52
53     void setObject(const unsigned int pos, T & obj)
54     {
55
56     }
57
58     T & getObject(const int pos)
59     {
60         return getObject(pos, true);
61     }
62
63     inline static herr_t count(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
64     {
65         OpData & opdata = *(OpData *)op_data;
66
67         if ((opdata.linktype != -1 && info->type == opdata.linktype) || (opdata.linktype == -1 && info->type != H5L_TYPE_ERROR))
68         {
69             H5O_info_t oinfo;
70             herr_t err;
71             if (opdata.basetype != -1)
72             {
73                 hid_t obj = H5Oopen(g_id, name, H5P_DEFAULT);
74
75                 if (obj < 0)
76                 {
77                     return (herr_t) - 1;
78                 }
79
80                 err = H5Oget_info(obj, &oinfo);
81                 H5Oclose(obj);
82
83                 if (err < 0)
84                 {
85                     return (herr_t) - 2;
86                 }
87
88                 if (oinfo.type == opdata.basetype)
89                 {
90                     opdata.u.count++;
91                 }
92             }
93             else
94             {
95                 opdata.u.count++;
96             }
97         }
98
99         return (herr_t)0;
100     }
101
102     inline static herr_t getElement(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
103     {
104         OpData & opdata = *(OpData *)op_data;
105
106         if ((opdata.linktype != -1 && info->type == opdata.linktype) || (opdata.linktype == -1 && info->type != H5L_TYPE_ERROR))
107         {
108             H5O_info_t oinfo;
109             herr_t err;
110             if (opdata.basetype != -1)
111             {
112                 hid_t obj = H5Oopen(g_id, name, H5P_DEFAULT);
113
114                 if (obj < 0)
115                 {
116                     return (herr_t) - 1;
117                 }
118
119                 err = H5Oget_info(obj, &oinfo);
120                 H5Oclose(obj);
121
122                 if (err < 0)
123                 {
124                     return (herr_t) - 2;
125                 }
126
127                 if (oinfo.type == opdata.basetype)
128                 {
129                     opdata.u.count--;
130                 }
131             }
132             else
133             {
134                 opdata.u.count--;
135             }
136
137             if (opdata.u.count == 0)
138             {
139                 opdata.u.name = strdup(name);
140
141                 return (herr_t)1;
142             }
143         }
144
145         return (herr_t)0;
146     }
147
148     const unsigned int getSize() const
149     {
150         hsize_t idx = 0;
151         OpData op_data;
152         herr_t err;
153
154         op_data.u.count = 0;
155         op_data.linktype = linkType;
156         op_data.basetype = baseType;
157
158         err = H5Literate(H5Object::getParent().getH5Id(), H5_INDEX_NAME, H5_ITER_INC, &idx, count, &op_data);
159
160         if (err < 0)
161         {
162             throw H5Exception(__LINE__, __FILE__, _("Cannot get the number of groups %d."));
163         }
164
165         return op_data.u.count;
166     }
167
168     virtual std::string dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
169     {
170         std::ostringstream os;
171         const unsigned int size = getSize();
172
173         for (unsigned int i = 0; i < size; i++)
174         {
175             const T & obj = const_cast<H5NamedObjectsList *>(this)->getObject(i, false);
176             os << obj.dump(alreadyVisited, indentLevel);
177
178             delete &obj;
179         }
180
181         return os.str();
182     }
183
184     virtual void printLsInfo(std::ostringstream & os) const
185     {
186         const unsigned int size = getSize();
187
188         for (unsigned int i = 0; i < size; i++)
189         {
190             const T & obj = const_cast<H5NamedObjectsList *>(this)->getObject(i, false);
191             obj.printLsInfo(os);
192
193             delete &obj;
194         }
195     }
196
197     virtual std::string toString(const unsigned int indentLevel) const
198     {
199         std::ostringstream os;
200         std::string indentString = H5Object::getIndentString(indentLevel);
201         const unsigned int size = getSize();
202
203         os << indentString << _("Filename") << ": " << H5Object::getParent().getFile().getFileName() << std::endl
204            << indentString << _("Parent group name") << ": " << H5Object::getParent().getName() << std::endl
205            << indentString << _("Parent group path") << ": " << H5Object::getParent().getCompletePath() << std::endl
206            << indentString << _("Elements type") << ": " << baseTypeName << std::endl
207            << indentString << _("Size") << ": " << size;
208
209         return os.str();
210     }
211
212 protected :
213
214     const int baseType;
215     const int linkType;
216     const std::string baseTypeName;
217
218 private:
219
220     T & getObject(const int pos, const bool checkPos)
221     {
222         OpData op_data;
223         herr_t err;
224
225         op_data.linktype = linkType;
226         op_data.basetype = baseType;
227
228         if (pos < prevPos)
229         {
230             idx = 0;
231             op_data.u.count = pos + 1;
232         }
233         else
234         {
235             op_data.u.count = pos - prevPos + 1;
236         }
237
238         err = H5Literate(H5Object::getParent().getH5Id(), H5_INDEX_NAME, H5_ITER_INC, &idx, getElement, &op_data);
239
240         if (err > 0)
241         {
242             prevPos = pos + 1;
243             return *new T(H5Object::getParent(), op_data.u.name);
244         }
245         else
246         {
247             idx = 0;
248             prevPos = 0;
249             throw H5Exception(__LINE__, __FILE__, _("Cannot get the number of groups %d %d."), getSize(), pos);
250         }
251     }
252
253     T & getObject(const std::string & name)
254     {
255         H5O_info_t info;
256         herr_t err;
257         H5Object * obj = 0;
258
259         if (H5Lexists(H5Object::getParent().getH5Id(), name.c_str(), H5P_DEFAULT) <= 0)
260         {
261             throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name.c_str());
262         }
263
264         err = H5Oget_info_by_name(H5Object::getParent().getH5Id(), name.c_str(), &info, H5P_DEFAULT);
265         if (err < 0)
266         {
267             throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name.c_str());
268         }
269
270         if (info.type == baseType)
271         {
272             return *new T(H5Object::getParent(), name);
273         }
274
275         throw H5Exception(__LINE__, __FILE__, _("Invalid HDF5 object"));
276     }
277 };
278 }
279
280 #endif // __H5NAMEDOBJECTSLIST_HXX__