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