4c8f4a7ff7ce8b3468bee1d640e0232ad774ec49
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5Object.cpp
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 #include "H5Object.hxx"
14 #include "H5File.hxx"
15 #include "H5Group.hxx"
16 #include "H5Dataset.hxx"
17 #include "H5Type.hxx"
18 #include "H5AttributesList.hxx"
19
20 namespace org_modules_hdf5
21 {
22
23 H5Object & H5Object::root = *new H5Object();
24
25 H5Object::H5Object(H5Object & _parent) : parent(_parent), children(std::set<H5Object *>()), locked(false), scilabId(-1)
26 {
27     parent.registerChild(this);
28 }
29
30 H5Object::~H5Object()
31 {
32     locked = true;
33     for (std::set<H5Object *>::iterator it = children.begin(); it != children.end(); it++)
34     {
35         delete *it;
36     }
37     locked = false;
38     parent.unregisterChild(this);
39
40     H5VariableScope::removeId(scilabId);
41 }
42
43 hid_t H5Object::getH5Id() const
44 {
45     return (hid_t) - 1;
46 }
47
48 /*std::string H5Object::getName() const
49   {
50   herr_t err;
51   hid_t obj = getH5Id();
52   ssize_t size;
53   char * name = 0;
54   std::string ret;
55
56   size = H5Iget_name(obj, 0, 0);
57   if (size < 0)
58   {
59   throw H5Exception(__LINE__, __FILE__, _("Cannot get object name."));
60   }
61
62   name = new char[size + 1];
63   if (H5Iget_name(obj, name, size + 1) < 0)
64   {
65   delete[] name;
66   throw H5Exception(__LINE__, __FILE__, _("Cannot get object name."));
67   }
68
69   ret = std::string(name);
70   delete[] name;
71
72   return ret;
73   }*/
74
75 H5File & H5Object::getFile() const
76 {
77     const H5Object * sobj = this;
78     const H5Object * obj = &parent;
79     while (obj != &root)
80     {
81         sobj = obj;
82         obj = &(obj->parent);
83     }
84
85     return *reinterpret_cast<H5File *>(const_cast<H5Object *>(sobj));
86 }
87
88 void H5Object::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
89 {
90     SciErr err;
91     std::string lower(_name);
92     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
93
94     if (lower == "name")
95     {
96         const char * name = getName().c_str();
97         err = createMatrixOfString(pvApiCtx, pos, 1, 1, &name);
98         if (err.iErr)
99         {
100             throw H5Exception(__LINE__, __FILE__, _("Cannot create a string on the stack."));
101         }
102
103         return;
104     }
105     else if (lower == "path")
106     {
107         const char * path = getCompletePath().c_str();
108         err = createMatrixOfString(pvApiCtx, pos, 1, 1, &path);
109         if (err.iErr)
110         {
111             throw H5Exception(__LINE__, __FILE__, _("Cannot create a string on the stack."));
112         }
113
114         return;
115     }
116
117     throw H5Exception(__LINE__, __FILE__, _("Invalid field: %s"), _name.c_str());
118 }
119
120 void H5Object::createOnScilabStack(int pos, void * pvApiCtx) const
121 {
122     static const char * fields[] = {"H5Object", "_id"};
123     int * mlistaddr = 0;
124     SciErr err;
125     int id = H5VariableScope::getVariableId(*const_cast<H5Object *>(this));
126     const_cast<H5Object *>(this)->setScilabId(id);
127
128     err = createMList(pvApiCtx, pos, 2, &mlistaddr);
129     if (err.iErr)
130     {
131         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
132     }
133
134     err = createMatrixOfStringInList(pvApiCtx, pos, mlistaddr, 1, 1, 2, fields);
135     if (err.iErr)
136     {
137         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
138     }
139
140     err = createMatrixOfInteger32InList(pvApiCtx, pos, mlistaddr, 2, 1, 1, &id);
141     if (err.iErr)
142     {
143         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
144     }
145 }
146
147 void H5Object::createInScilabList(int * list, int stackPos, int pos, void * pvApiCtx) const
148 {
149     static const char * fields[] = {"H5Object", "_id"};
150     int * mlistaddr = 0;
151     SciErr err;
152     int id = H5VariableScope::getVariableId(*const_cast<H5Object *>(this));
153     const_cast<H5Object *>(this)->setScilabId(id);
154
155     err = createMListInList(pvApiCtx, stackPos, list, pos, 2, &mlistaddr);
156     if (err.iErr)
157     {
158         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
159     }
160
161     err = createMatrixOfStringInList(pvApiCtx, stackPos, mlistaddr, 1, 1, 2, fields);
162     if (err.iErr)
163     {
164         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
165     }
166
167     err = createMatrixOfInteger32InList(pvApiCtx, stackPos, mlistaddr, 2, 1, 1, &id);
168     if (err.iErr)
169     {
170         throw H5Exception(__LINE__, __FILE__, _("Cannot create a mlist on the stack."));
171     }
172 }
173
174 H5AttributesList & H5Object::getAttributes()
175 {
176     return *new H5AttributesList(*this);
177 }
178
179 H5Object & H5Object::getObject(H5Object & parent, hid_t obj)
180 {
181     H5O_info_t info;
182     herr_t err = H5Oget_info(obj, &info);
183     ssize_t size;
184     char * name = 0;
185     std::string _name;
186     //TODO: voir pr utiliser getName().
187
188     if (err < 0)
189     {
190         throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve informations about the object"));
191     }
192
193     size = H5Iget_name(obj, 0, 0);
194     name = new char[size + 1];
195     H5Iget_name(obj, name, size + 1);
196     _name = std::string(name);
197     delete[] name;
198
199     switch (info.type)
200     {
201         case H5O_TYPE_GROUP:
202             return *new H5Group(parent, obj, _name);
203         case H5O_TYPE_DATASET:
204             return *new H5Dataset(parent, obj, _name);
205         case H5O_TYPE_NAMED_DATATYPE:
206             return *new H5Type(parent, obj, _name);
207         case H5O_TYPE_UNKNOWN:
208         default:
209             throw H5Exception(__LINE__, __FILE__, _("Unknown HDF5 object"));
210     }
211 }
212
213 H5Object & H5Object::getObject(H5Object & parent, const std::string & name)
214 {
215     return getObject(parent, name.c_str());
216 }
217
218 H5Object & H5Object::getObject(H5Object & parent, const char * name)
219 {
220     hid_t loc = parent.getH5Id();
221     H5O_info_t info;
222     herr_t err;
223     H5Object * obj = 0;
224
225     if (H5Lexists(loc, name, H5P_DEFAULT) <= 0)
226     {
227         throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name);
228     }
229
230     err = H5Oget_info_by_name(loc, name, &info, H5P_DEFAULT);
231     if (err < 0)
232     {
233         throw H5Exception(__LINE__, __FILE__, _("Invalid name: %s."), name);
234     }
235
236     switch (info.type)
237     {
238         case H5O_TYPE_GROUP:
239             obj = new H5Group(parent, name);
240             break;
241         case H5O_TYPE_DATASET:
242             obj = new H5Dataset(parent, name);
243             break;
244         case H5O_TYPE_NAMED_DATATYPE:
245             obj = new H5Type(parent, name);
246             break;
247         default:
248             throw H5Exception(__LINE__, __FILE__, _("Invalid HDF5 object"));
249     }
250
251     return *obj;
252 }
253
254 /*    std::string H5Object::getCompletePath() const
255       {
256       std::string name = getName();
257       if (this != &root && name != "")
258       {
259       std::string path = parent.getCompletePath();
260       if (path == "/")
261       {
262       return "/" + name;
263       }
264       else
265       {
266       return path + "/" + name;
267       }
268       }
269       return "";
270       }*/
271
272 std::string H5Object::getCompletePath() const
273 {
274     std::string name = getName();
275     if (name.empty())
276     {
277         return parent.getCompletePath();
278     }
279
280     std::string path = parent.getCompletePath();
281     if (path.empty())
282     {
283         return name;
284     }
285
286     if (path.at(path.length() - 1) == '/' && name.at(0) == '/')
287     {
288         return path + name.substr(1);
289     }
290     else if (path.at(path.length() - 1) == '/' || name.at(0) == '/')
291     {
292         return path + name;
293     }
294
295     return path + "/" + name;
296 }
297
298 void H5Object::getLinksInfo(const H5Object & obj, std::vector<std::string> & linksName, std::vector<std::string> & type, std::vector<std::string> & linksType)
299 {
300     hsize_t idx = 0;
301     LinksInfo_ info;
302
303     info.name = &linksName;
304     info.type = &type;
305     info.linktype = &linksType;
306
307     H5Literate(obj.getH5Id(), H5_INDEX_NAME, H5_ITER_INC, &idx, iterateGetInfo, &info);
308 }
309
310 herr_t H5Object::iterateGetInfo(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
311 {
312     H5O_info_t oinfo;
313     herr_t err;
314     LinksInfo_ & linfo = *(LinksInfo_ *)op_data;
315     hid_t obj = H5Oopen(g_id, name, H5P_DEFAULT);
316
317     if (obj < 0)
318     {
319         return (herr_t) - 1;
320     }
321
322     err = H5Oget_info(obj, &oinfo);
323     H5Oclose(obj);
324
325     if (err < 0)
326     {
327         return (herr_t) - 2;
328     }
329
330     linfo.name->push_back(std::string(name));
331
332     switch (info->type)
333     {
334         case H5L_TYPE_HARD:
335             linfo.linktype->push_back("hard");
336             break;
337         case H5L_TYPE_SOFT:
338             linfo.linktype->push_back("soft");
339             break;
340         case H5L_TYPE_EXTERNAL:
341             linfo.linktype->push_back("external");
342             break;
343         default:
344             linfo.linktype->push_back("error");
345     }
346
347     switch (oinfo.type)
348     {
349         case H5O_TYPE_GROUP:
350             linfo.type->push_back("group");
351             break;
352         case H5O_TYPE_DATASET:
353             linfo.type->push_back("dataset");
354             break;
355         case H5O_TYPE_NAMED_DATATYPE:
356             linfo.type->push_back("datatype");
357             break;
358         default:
359             linfo.type->push_back("unknown");
360     }
361
362     return (herr_t)0;
363 }
364 }