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