Fix bugs and it is now possible to read hyperslabs
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5Group.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 "H5Group.hxx"
14 #include "H5File.hxx"
15 #include "H5SoftLinksList.hxx"
16 #include "H5LinksList.hxx"
17 #include "H5GroupsList.hxx"
18 #include "H5DatasetsList.hxx"
19 #include "H5TypesList.hxx"
20 #include "H5Link.hxx"
21
22 namespace org_modules_hdf5
23 {
24
25 void H5Group::init()
26 {
27     group = H5Gopen(getParent().getH5Id(), name.c_str(), H5P_DEFAULT);
28     if (group < 0)
29     {
30         throw H5Exception(__LINE__, __FILE__, _("Cannot open the group %s."), name.c_str());
31     }
32 }
33
34 H5Group::H5Group(H5Object & _parent, const std::string & _name) : H5Object(_parent, _name)
35 {
36     init();
37 }
38
39 H5Group::H5Group(H5Object & _parent, hid_t _group, const std::string & _name) : H5Object(_parent, _name), group(_group)
40 {
41
42 }
43
44 H5Group::~H5Group()
45 {
46     if (group >= 0)
47     {
48         H5Gclose(group);
49     }
50 }
51
52 H5LinksList & H5Group::getLinks()
53 {
54     return *new H5LinksList(*this);
55 }
56
57 H5NamedObjectsList<H5SoftLink> & H5Group::getSoftLinks()
58 {
59     return *new H5NamedObjectsList<H5SoftLink>(*this, -1, H5L_TYPE_SOFT, "Soft Link");
60 }
61
62 H5NamedObjectsList<H5ExternalLink> & H5Group::getExternalLinks()
63 {
64     return *new H5NamedObjectsList<H5ExternalLink>(*this, -1, H5L_TYPE_EXTERNAL, "External Link");
65 }
66
67 H5GroupsList & H5Group::getGroups()
68 {
69     return *new H5GroupsList(*this);
70 }
71
72 H5NamedObjectsList<H5Group> & H5Group::getHardGroups()
73 {
74     return *new H5NamedObjectsList<H5Group>(*this, H5O_TYPE_GROUP, H5L_TYPE_HARD, "Group");
75 }
76
77 H5NamedObjectsList<H5Type> & H5Group::getHardTypes()
78 {
79     return *new H5NamedObjectsList<H5Type>(*this, H5O_TYPE_NAMED_DATATYPE, H5L_TYPE_HARD, "Type");
80 }
81
82 H5NamedObjectsList<H5Dataset> & H5Group::getHardDatasets()
83 {
84     return *new H5NamedObjectsList<H5Dataset>(*this, H5O_TYPE_DATASET, H5L_TYPE_HARD, "Dataset");
85 }
86
87 H5DatasetsList & H5Group::getDatasets()
88 {
89     return *new H5DatasetsList(*this);
90 }
91
92 H5TypesList & H5Group::getTypes()
93 {
94     return *new H5TypesList(*this);
95 }
96
97 const unsigned int H5Group::getLinksSize() const
98 {
99     herr_t err;
100     H5G_info_t info;
101
102     err = H5Gget_info(group, &info);
103     if (err < 0)
104     {
105         throw H5Exception(__LINE__, __FILE__, _("Cannot get the links number"));
106     }
107
108     return (unsigned int)info.nlinks;
109 }
110
111 std::string H5Group::getCompletePath() const
112 {
113     std::string name = getName();
114     if (name == "/")
115     {
116         return "/";
117     }
118
119     return H5Object::getCompletePath();
120 }
121
122 void H5Group::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
123 {
124     SciErr err;
125     std::string lower(_name);
126
127     try
128     {
129         H5Object & obj = H5Object::getObject(*const_cast<H5Group *>(this), _name);
130         obj.createOnScilabStack(pos, pvApiCtx);
131         return;
132     }
133     catch (const H5Exception & e) { }
134
135     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
136
137     if (lower == "attributes")
138     {
139         const H5AttributesList & attrs = const_cast<H5Group *>(this)->getAttributes();
140         attrs.createOnScilabStack(pos, pvApiCtx);
141
142         return;
143     }
144     else if (lower == "groups")
145     {
146         const H5GroupsList & groups = const_cast<H5Group *>(this)->getGroups();
147         groups.createOnScilabStack(pos, pvApiCtx);
148
149         return;
150     }
151     else if (lower == "datasets")
152     {
153         const H5DatasetsList & sets = const_cast<H5Group *>(this)->getDatasets();
154         sets.createOnScilabStack(pos, pvApiCtx);
155
156         return;
157     }
158     else if (lower == "types")
159     {
160         const H5TypesList & types = const_cast<H5Group *>(this)->getTypes();
161         types.createOnScilabStack(pos, pvApiCtx);
162
163         return;
164     }
165     else if (lower == "links")
166     {
167         std::vector<std::string> names;
168         std::vector<std::string> types;
169         std::vector<std::string> linkstype;
170         std::vector<const char *> _str;
171         H5Object::getLinksInfo(*this, names, types, linkstype);
172         _str.reserve(names.size() * 3);
173
174         for (unsigned int i = 0; i < names.size(); i++)
175         {
176             _str.push_back(names[i].c_str());
177         }
178         for (unsigned int i = 0; i < names.size(); i++)
179         {
180             _str.push_back(linkstype[i].c_str());
181         }
182         for (unsigned int i = 0; i < names.size(); i++)
183         {
184             _str.push_back(types[i].c_str());
185         }
186
187         err = createMatrixOfString(pvApiCtx, pos, names.size(), 3, &(_str[0]));
188         if (err.iErr)
189         {
190             throw H5Exception(__LINE__, __FILE__, _("Cannot create a column of strings on the stack."));
191         }
192
193         return;
194     }
195
196     H5Object::getAccessibleAttribute(_name, pos, pvApiCtx);
197 }
198
199 void H5Group::ls(std::vector<std::string> & name, std::vector<std::string> & type) const
200 {
201     herr_t err;
202     OpDataGetLs opdata;
203     opdata.parent = const_cast<H5Group *>(this);
204     opdata.name = &name;
205     opdata.type = &type;
206     hsize_t idx = 0;
207
208     err = H5Literate(group, H5_INDEX_NAME, H5_ITER_INC, &idx, getLsInfo, &opdata);
209     if (err < 0)
210     {
211         throw H5Exception(__LINE__, __FILE__, _("Cannot list group links."));
212     }
213
214     idx = 0;
215     err = H5Aiterate2(group, H5_INDEX_NAME, H5_ITER_INC, &idx, H5Object::getLsAttributes, &opdata);
216     if (err < 0)
217     {
218         throw H5Exception(__LINE__, __FILE__, _("Cannot list group attributes."));
219     }
220 }
221
222 herr_t H5Group::getLsInfo(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
223 {
224     H5O_info_t oinfo;
225     herr_t err;
226     H5Object * hobj = 0;
227     hid_t obj;
228     OpDataGetLs & opdata = *(OpDataGetLs *)op_data;
229
230     if (obj < 0)
231     {
232         return (herr_t) - 1;
233     }
234
235     switch (info->type)
236     {
237         case H5L_TYPE_SOFT:
238             opdata.name->push_back(name);
239             opdata.type->push_back("soft");
240             break;
241         case H5L_TYPE_EXTERNAL:
242             opdata.name->push_back(name);
243             opdata.type->push_back("external");
244             break;
245         case H5L_TYPE_HARD:
246             obj = H5Oopen(g_id, name, H5P_DEFAULT);
247             err = H5Oget_info(obj, &oinfo);
248             H5Oclose(obj);
249
250             if (err < 0)
251             {
252                 return (herr_t) - 1;
253             }
254
255             switch (oinfo.type)
256             {
257                 case H5O_TYPE_GROUP:
258                     opdata.name->push_back(name);
259                     opdata.type->push_back("group");
260                     break;
261                 case H5O_TYPE_DATASET:
262                     opdata.name->push_back(name);
263                     opdata.type->push_back("dataset");
264                     break;
265                 case H5O_TYPE_NAMED_DATATYPE:
266                     opdata.name->push_back(name);
267                     opdata.type->push_back("type");
268                     break;
269                 default:
270                     return (herr_t) - 1;
271             }
272             break;
273         default:
274             return (herr_t) - 1;
275     }
276
277     return (herr_t)0;
278 }
279
280 std::string H5Group::ls() const
281 {
282     std::ostringstream os;
283     herr_t err;
284     OpDataPrintLs opdata;
285     opdata.parent = const_cast<H5Group *>(this);
286     opdata.os = &os;
287     hsize_t idx = 0;
288
289     err = H5Literate(group, H5_INDEX_NAME, H5_ITER_INC, &idx, printLsInfo, &opdata);
290     if (err < 0)
291     {
292         throw H5Exception(__LINE__, __FILE__, _("Cannot list group contents"));
293     }
294
295     return os.str();
296 }
297
298 herr_t H5Group::printLsInfo(hid_t g_id, const char * name, const H5L_info_t * info, void * op_data)
299 {
300     H5O_info_t oinfo;
301     herr_t err;
302     H5Object * hobj = 0;
303     hid_t obj;
304     OpDataPrintLs & opdata = *(OpDataPrintLs *)op_data;
305
306     if (obj < 0)
307     {
308         return (herr_t) - 1;
309     }
310
311     switch (info->type)
312     {
313         case H5L_TYPE_SOFT:
314             hobj = new H5SoftLink(*opdata.parent, name);
315             break;
316         case H5L_TYPE_EXTERNAL:
317             hobj = new H5ExternalLink(*opdata.parent, name);
318             break;
319         case H5L_TYPE_HARD:
320             obj = H5Oopen(g_id, name, H5P_DEFAULT);
321             err = H5Oget_info(obj, &oinfo);
322             H5Oclose(obj);
323
324             if (err < 0)
325             {
326                 return (herr_t) - 1;
327             }
328
329             switch (oinfo.type)
330             {
331                 case H5O_TYPE_GROUP:
332                     hobj = new H5Group(*opdata.parent, name);
333                     break;
334                 case H5O_TYPE_DATASET:
335                     hobj = new H5Dataset(*opdata.parent, name);
336                     break;
337                 case H5O_TYPE_NAMED_DATATYPE:
338                     hobj = new H5Type(*opdata.parent, name);
339                     break;
340                 default:
341                     return (herr_t) - 1;
342             }
343             break;
344         default:
345             return (herr_t) - 1;
346     }
347
348     hobj->printLsInfo(*opdata.os);
349     delete hobj;
350
351     return (herr_t)0;
352 }
353
354 void H5Group::printLsInfo(std::ostringstream & os) const
355 {
356     std::string str(getName());
357     H5Object::getResizedString(str);
358
359     os << str << "Group" << std::endl;
360 }
361
362 std::string H5Group::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
363 {
364     std::ostringstream os;
365     haddr_t addr = this->getAddr();
366     std::map<haddr_t, std::string>::iterator it = alreadyVisited.find(addr);
367     if (it != alreadyVisited.end())
368     {
369         os << H5Object::getIndentString(indentLevel) << "GROUP \"" << getName() << "\" {" << std::endl
370            << H5Object::getIndentString(indentLevel + 1) << "HARDLINK \"" << it->second << "\"" << std::endl
371            << H5Object::getIndentString(indentLevel) << "}" << std::endl;
372
373         return os.str();
374     }
375     else
376     {
377         alreadyVisited.insert(std::pair<haddr_t, std::string>(addr, getCompletePath()));
378     }
379
380     H5AttributesList & attrs = const_cast<H5Group *>(this)->getAttributes();
381     H5NamedObjectsList<H5SoftLink> & softlinks = const_cast<H5Group *>(this)->getSoftLinks();
382     H5NamedObjectsList<H5ExternalLink> & externallinks = const_cast<H5Group *>(this)->getExternalLinks();
383     H5NamedObjectsList<H5Group> & hardgroups = const_cast<H5Group *>(this)->getHardGroups();
384     H5NamedObjectsList<H5Type> & hardtypes = const_cast<H5Group *>(this)->getHardTypes();
385     H5NamedObjectsList<H5Dataset> & harddatasets = const_cast<H5Group *>(this)->getHardDatasets();
386
387     os << H5Object::getIndentString(indentLevel) << "GROUP \"" << name << "\" {" << std::endl;
388     os << attrs.dump(alreadyVisited, indentLevel + 1);
389     os << hardgroups.dump(alreadyVisited, indentLevel + 1);
390     os << hardtypes.dump(alreadyVisited, indentLevel + 1);
391     os << harddatasets.dump(alreadyVisited, indentLevel + 1);
392     os << softlinks.dump(alreadyVisited, indentLevel + 1);
393     os << externallinks.dump(alreadyVisited, indentLevel + 1);
394     os << H5Object::getIndentString(indentLevel) << "}" << std::endl;
395
396     delete &attrs;
397     delete &softlinks;
398     delete &externallinks;
399     delete &hardgroups;
400     delete &hardtypes;
401     delete &harddatasets;
402
403     return os.str();
404 }
405
406 std::string H5Group::toString(const unsigned int indentLevel) const
407 {
408     std::ostringstream os;
409     std::string indentString = H5Object::getIndentString(indentLevel + 1);
410     const H5GroupsList & groups = const_cast<H5Group *>(this)->getGroups();
411     const H5DatasetsList & datasets = const_cast<H5Group *>(this)->getDatasets();
412     const H5TypesList & types = const_cast<H5Group *>(this)->getTypes();
413     const H5AttributesList & attrs = const_cast<H5Group *>(this)->getAttributes();
414
415     os << H5Object::getIndentString(indentLevel) << "HDF5 Group" << std::endl
416        << indentString << _("Filename") << ": " << getFile().getFileName() << std::endl
417        << indentString << _("Name") << ": " << getName() << std::endl
418        << indentString << _("Path") << ": " << getCompletePath() << std::endl
419        << indentString << _("Attributes") << ": [1 x " << attrs.getSize() << "]" << std::endl
420        << indentString << _("Groups") << ": [1 x " << groups.getSize() << "]" << std::endl
421        << indentString << _("Datasets") << ": [1 x " << datasets.getSize() << "]" << std::endl
422        << indentString << _("Types") << ": [1 x " << types.getSize() << "]" << std::endl
423        << indentString << _("Links") << ": [" << getLinksSize() << " x 3]";
424
425     delete &groups;
426     delete &datasets;
427     delete &types;
428     delete &attrs;
429
430     return os.str();
431 }
432
433 H5Group & H5Group::createGroup(H5Object & parent, const std::string & name)
434 {
435     hid_t obj;
436     hid_t lcpl;
437     H5Object * loc = 0;
438
439     if (H5Lexists(parent.getH5Id(), name.c_str(), H5P_DEFAULT) > 0)
440     {
441         throw H5Exception(__LINE__, __FILE__, _("The group already exists: %s."), name.c_str());
442     }
443
444     if (parent.isFile())
445     {
446         loc = &reinterpret_cast<H5File *>(&parent)->getRoot();
447     }
448     else
449     {
450         loc = &parent;
451     }
452
453     lcpl = H5Pcreate(H5P_LINK_CREATE);
454     H5Pset_create_intermediate_group(lcpl, 1);
455
456     obj = H5Gcreate2(loc->getH5Id(), name.c_str(), lcpl, H5P_DEFAULT, H5P_DEFAULT);
457     H5Pclose(lcpl);
458     if (obj < 0)
459     {
460         throw H5Exception(__LINE__, __FILE__, _("Cannot create the group: %s."), name.c_str());
461     }
462
463     return *new H5Group(*loc, obj, name);
464 }
465 }