Fix bugs and it is now possible to read hyperslabs
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5Attribute.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 "H5Attribute.hxx"
14 #include "H5DataFactory.hxx"
15
16 namespace org_modules_hdf5
17 {
18
19 H5Attribute::H5Attribute(H5Object & _parent, const std::string & _name) : H5Object(_parent, _name)
20 {
21     if (H5Aexists(getParent().getH5Id(), name.c_str()) <= 0)
22     {
23         throw H5Exception(__LINE__, __FILE__, _("Cannot open attribute: %s"), name.c_str());
24     }
25
26     attr = H5Aopen(getParent().getH5Id(), name.c_str(), H5P_DEFAULT);
27     if (attr < 0)
28     {
29         throw H5Exception(__LINE__, __FILE__, _("Cannot open attribute: %s"), name.c_str());
30     }
31 }
32
33 H5Attribute::H5Attribute(H5Object & _parent, hid_t _attr, const std::string & _name) : H5Object(_parent, _name), attr(_attr)
34 {
35
36 }
37
38 H5Attribute::~H5Attribute()
39 {
40     if (attr >= 0)
41     {
42         H5Aclose(attr);
43     }
44 }
45
46 H5Data & H5Attribute::getData()
47 {
48     return H5DataFactory::getData(*this, attr, 0, 0, true);
49 }
50
51 H5Type & H5Attribute::getDataType()
52 {
53     hid_t type = H5Aget_type(attr);
54     if (type < 0)
55     {
56         throw H5Exception(__LINE__, __FILE__, _("Cannot get the attribute type"));
57     }
58
59     return *new H5Type(*this, type);
60 }
61
62 H5Dataspace & H5Attribute::getSpace()
63 {
64     hid_t space = H5Aget_space(attr);
65     if (space < 0)
66     {
67         throw H5Exception(__LINE__, __FILE__, _("Cannot get the attribute dataspace"));
68     }
69
70     return *new H5Dataspace(*this, space);
71 }
72
73 void H5Attribute::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
74 {
75     SciErr err;
76     std::string lower(_name);
77     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
78
79     if (lower == "type")
80     {
81         const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
82         type.createOnScilabStack(pos, pvApiCtx);
83
84         return;
85     }
86     else if (lower == "dataspace")
87     {
88         const H5Dataspace & space = const_cast<H5Attribute *>(this)->getSpace();
89         space.createOnScilabStack(pos, pvApiCtx);
90
91         return;
92     }
93     else if (lower == "data")
94     {
95         const H5Data & data = const_cast<H5Attribute *>(this)->getData();
96         data.toScilab(pvApiCtx, pos);
97
98         delete &data;
99
100         return;
101     }
102
103     H5Object::getAccessibleAttribute(_name, pos, pvApiCtx);
104 }
105
106 std::string H5Attribute::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
107 {
108     std::ostringstream os;
109     const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
110     const H5Dataspace & space = const_cast<H5Attribute *>(this)->getSpace();
111     const H5Data & data = const_cast<H5Attribute *>(this)->getData();
112
113     os << H5Object::getIndentString(indentLevel) << "ATTRIBUTE \"" << getName() << "\" {" << std::endl
114        << type.dump(alreadyVisited, indentLevel + 1)
115        << space.dump(alreadyVisited, indentLevel + 1)
116        << data.dump(alreadyVisited, indentLevel + 1)
117        << H5Object::getIndentString(indentLevel) << "}" << std::endl;
118
119     delete &type;
120     delete &space;
121     delete &data;
122
123     return os.str();
124 }
125
126 std::string H5Attribute::toString(const unsigned int indentLevel) const
127 {
128     std::ostringstream os;
129     const std::string indentString = H5Object::getIndentString(indentLevel + 1);
130     const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
131
132     os << H5Object::getIndentString(indentLevel) << "HDF5 Attribute" << std::endl
133        << indentString << _("Filename") << ": " << getFile().getFileName() << std::endl
134        << indentString << _("Attribute name") << ": " << getName() << std::endl
135        << indentString << _("Attribute path") << ": " << getCompletePath() << std::endl
136        << indentString << _("Value class") << ": " << type.getClassName();
137
138     delete &type;
139
140     return os.str();
141 }
142
143 void H5Attribute::copy(H5Object & parent, const std::string & name)
144 {
145     H5Attribute::copy(this->getH5Id(), parent.getH5Id(), name);
146 }
147
148 hid_t H5Attribute::create(H5Object & loc, const std::string & name, const hid_t type, const hid_t targettype, const hid_t space, void * data)
149 {
150     return create(loc.getH5Id(), name, type, targettype, space, data);
151 }
152
153 hid_t H5Attribute::create(const hid_t loc, const std::string & name, const hid_t type, const hid_t targettype, const hid_t space, void * data)
154 {
155     herr_t err;
156     hid_t attr = H5Acreate2(loc, name.c_str(), targettype, space, H5P_DEFAULT, H5P_DEFAULT);
157     if (attr < 0)
158     {
159         throw H5Exception(__LINE__, __FILE__, _("Cannot create a new attribute."));
160     }
161
162     err = H5Awrite(attr, type, data);
163     if (err < 0)
164     {
165         H5Aclose(attr);
166         throw H5Exception(__LINE__, __FILE__, _("Cannot write data in the attribute."));
167     }
168
169     return attr;
170 }
171
172 void H5Attribute::copy(const hid_t src, const hid_t dest, const std::string & name)
173 {
174     hid_t type, stype;
175     hid_t space, sspace;
176     char * data = 0;
177     hsize_t size;
178     hsize_t * dims = 0;
179     hsize_t ndims;
180
181     sspace = H5Aget_space(src);
182     if (sspace < 0)
183     {
184         throw H5Exception(__LINE__, __FILE__, _("Cannot copy the attribute"));
185     }
186     space = H5Scopy(sspace);
187     H5Sclose(sspace);
188
189     stype = H5Aget_type(src);
190     if (stype < 0)
191     {
192         H5Sclose(space);
193         throw H5Exception(__LINE__, __FILE__, _("Cannot copy the attribute"));
194     }
195     type = H5Tcopy(stype);
196     H5Tclose(stype);
197
198     size = H5Tget_size(type);
199     dims = new hsize_t[__SCILAB_HDF5_MAX_DIMS__];
200     ndims = H5Sget_simple_extent_dims(space, dims, 0);
201     for (unsigned int i = 0; i < ndims; i++)
202     {
203         size *= dims[i];
204     }
205
206     data = new char[size];
207     if (H5Aread(src, type, data) < 0)
208     {
209         H5Sclose(space);
210         H5Tclose(type);
211         delete[] dims;
212         delete[] data;
213
214         throw H5Exception(__LINE__, __FILE__, _("Cannot read attribute data."));
215     }
216
217     try
218     {
219         hid_t attr = create(dest, name, type, type, space, data);
220         H5Aclose(attr);
221         H5Sclose(space);
222         H5Tclose(type);
223         delete[] dims;
224         delete[] data;
225     }
226     catch (const H5Exception & e)
227     {
228         H5Sclose(space);
229         H5Tclose(type);
230         delete[] dims;
231         delete[] data;
232         throw;
233     }
234 }
235
236 }