1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 
16 #include "H5Options.hxx"
17 #include "H5Attribute.hxx"
18 #include "H5DataFactory.hxx"
19 
20 namespace org_modules_hdf5
21 {
22 
H5Attribute(H5Object & _parent,const std::string & _name)23 H5Attribute::H5Attribute(H5Object & _parent, const std::string & _name) : H5Object(_parent, _name)
24 {
25     if (H5Aexists(getParent().getH5Id(), name.c_str()) <= 0)
26     {
27         throw H5Exception(__LINE__, __FILE__, _("Cannot open attribute: %s"), name.c_str());
28     }
29 
30     attr = H5Aopen(getParent().getH5Id(), name.c_str(), H5P_DEFAULT);
31     if (attr < 0)
32     {
33         throw H5Exception(__LINE__, __FILE__, _("Cannot open attribute: %s"), name.c_str());
34     }
35 }
36 
H5Attribute(H5Object & _parent,hid_t _attr,const std::string & _name)37 H5Attribute::H5Attribute(H5Object & _parent, hid_t _attr, const std::string & _name) : H5Object(_parent, _name), attr(_attr)
38 {
39 
40 }
41 
~H5Attribute()42 H5Attribute::~H5Attribute()
43 {
44     if (attr >= 0)
45     {
46         H5Aclose(attr);
47     }
48 }
49 
getData()50 H5Data & H5Attribute::getData()
51 {
52     return H5DataFactory::getData(*this, attr, 0, 0, true);
53 }
54 
getDataType()55 H5Type & H5Attribute::getDataType()
56 {
57     hid_t type = H5Aget_type(attr);
58     if (type < 0)
59     {
60         throw H5Exception(__LINE__, __FILE__, _("Cannot get the attribute type"));
61     }
62 
63     return *new H5Type(*this, type);
64 }
65 
getSpace()66 H5Dataspace & H5Attribute::getSpace()
67 {
68     hid_t space = H5Aget_space(attr);
69     if (space < 0)
70     {
71         throw H5Exception(__LINE__, __FILE__, _("Cannot get the attribute dataspace"));
72     }
73 
74     return *new H5Dataspace(*this, space);
75 }
76 
getAccessibleAttribute(const std::string & _name,const int pos,void * pvApiCtx) const77 void H5Attribute::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
78 {
79     std::string lower(_name);
80     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
81 
82     if (lower == "type")
83     {
84         const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
85         type.createOnScilabStack(pos, pvApiCtx);
86 
87         return;
88     }
89     else if (lower == "dataspace")
90     {
91         const H5Dataspace & space = const_cast<H5Attribute *>(this)->getSpace();
92         space.createOnScilabStack(pos, pvApiCtx);
93 
94         return;
95     }
96     else if (lower == "data")
97     {
98         const H5Data & data = const_cast<H5Attribute *>(this)->getData();
99         data.toScilab(pvApiCtx, pos, 0, 0, H5Options::isReadFlip());
100 
101         delete &data;
102 
103         return;
104     }
105 
106     H5Object::getAccessibleAttribute(_name, pos, pvApiCtx);
107 }
108 
dump(std::map<haddr_t,std::string> & alreadyVisited,const unsigned int indentLevel) const109 std::string H5Attribute::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
110 {
111     std::ostringstream os;
112     const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
113     const H5Dataspace & space = const_cast<H5Attribute *>(this)->getSpace();
114     H5Data * data = 0;
115 
116     try
117     {
118         data = &const_cast<H5Attribute *>(this)->getData();
119     }
120     catch (const H5Exception & /*e*/)
121     {
122 
123     }
124 
125     os << H5Object::getIndentString(indentLevel) << "ATTRIBUTE \"" << getName() << "\" {" << std::endl
126        << type.dump(alreadyVisited, indentLevel + 1)
127        << space.dump(alreadyVisited, indentLevel + 1);
128 
129     if (data)
130     {
131         os << data->dump(alreadyVisited, indentLevel + 1);
132     }
133     else
134     {
135         os << H5Object::getIndentString(indentLevel + 1) << _("Error in retrieving data.") << std::endl;
136     }
137 
138     os << H5Object::getIndentString(indentLevel) << "}" << std::endl;
139 
140     delete &type;
141     delete &space;
142     if (data)
143     {
144         delete data;
145     }
146 
147     return os.str();
148 }
149 
toString(const unsigned int indentLevel) const150 std::string H5Attribute::toString(const unsigned int indentLevel) const
151 {
152     std::ostringstream os;
153     const std::string indentString = H5Object::getIndentString(indentLevel + 1);
154     const H5Type & type = const_cast<H5Attribute *>(this)->getDataType();
155     const H5Dataspace & space = const_cast<H5Attribute *>(this)->getSpace();
156 
157     os << H5Object::getIndentString(indentLevel) << "HDF5 Attribute" << std::endl
158        << indentString << "Filename" << ": " << getFile().getFileName() << std::endl
159        << indentString << "Name" << ": " << getName() << std::endl
160        << indentString << "Parent path" << ": " << getParent().getCompletePath() << std::endl
161        << indentString << "Type" << ": " << type.getTypeName() << std::endl
162        << indentString << "Dataspace" << ": " << space.getTypeName() << std::endl
163        << indentString << "Data" << ": " << space.getStringDims() << std::endl;
164 
165     delete &type;
166     delete &space;
167 
168     return os.str();
169 }
170 
copy(H5Object & parent,const std::string & name)171 void H5Attribute::copy(H5Object & parent, const std::string & name)
172 {
173     H5Attribute::copy(this->getH5Id(), parent.getH5Id(), name);
174 }
175 
create(H5Object & loc,const std::string & name,const hid_t type,const hid_t targettype,const hid_t srcspace,const hid_t targetspace,void * data,const bool chunked)176 hid_t H5Attribute::create(H5Object & loc, const std::string & name, const hid_t type, const hid_t targettype, const hid_t srcspace, const hid_t targetspace, void * data, const bool chunked)
177 {
178     return create(loc.getH5Id(), name, type, targettype, srcspace, targetspace, data);
179 }
180 
create(const hid_t loc,const std::string & name,const hid_t type,const hid_t targettype,const hid_t srcspace,const hid_t targetspace,void * data)181 hid_t H5Attribute::create(const hid_t loc, const std::string & name, const hid_t type, const hid_t targettype, const hid_t srcspace, const hid_t targetspace, void * data)
182 {
183     herr_t err;
184     if (H5Aexists(loc, name.c_str()) > 0)
185     {
186         throw H5Exception(__LINE__, __FILE__, _("Attribute %s already exists."), name.c_str());
187     }
188 
189     hid_t attr = H5Acreate(loc, name.c_str(), targettype, targetspace == -1 ? srcspace : targetspace, H5P_DEFAULT, H5P_DEFAULT);
190     if (attr < 0)
191     {
192         throw H5Exception(__LINE__, __FILE__, _("Cannot create a new attribute."));
193     }
194 
195     err = H5Awrite(attr, type, data);
196     if (err < 0)
197     {
198         H5Aclose(attr);
199         throw H5Exception(__LINE__, __FILE__, _("Cannot write data in the attribute."));
200     }
201 
202     return attr;
203 }
204 
copy(const hid_t src,const hid_t dest,const std::string & name)205 void H5Attribute::copy(const hid_t src, const hid_t dest, const std::string & name)
206 {
207     hid_t type, stype;
208     hid_t space, sspace;
209     char * data = 0;
210     hsize_t size;
211     hsize_t * dims = 0;
212     hsize_t ndims;
213 
214     sspace = H5Aget_space(src);
215     if (sspace < 0)
216     {
217         throw H5Exception(__LINE__, __FILE__, _("Cannot copy the attribute"));
218     }
219     space = H5Scopy(sspace);
220     H5Sclose(sspace);
221 
222     stype = H5Aget_type(src);
223     if (stype < 0)
224     {
225         H5Sclose(space);
226         throw H5Exception(__LINE__, __FILE__, _("Cannot copy the attribute"));
227     }
228     type = H5Tcopy(stype);
229     H5Tclose(stype);
230 
231     size = H5Tget_size(type);
232     dims = new hsize_t[__SCILAB_HDF5_MAX_DIMS__];
233     ndims = H5Sget_simple_extent_dims(space, dims, 0);
234     for (unsigned int i = 0; i < ndims; i++)
235     {
236         size *= dims[i];
237     }
238 
239     data = new char[size];
240     if (H5Aread(src, type, data) < 0)
241     {
242         H5Sclose(space);
243         H5Tclose(type);
244         delete[] dims;
245         delete[] data;
246 
247         throw H5Exception(__LINE__, __FILE__, _("Cannot read attribute data."));
248     }
249 
250     try
251     {
252         hid_t attr = create(dest, name, type, type, space, space, data);
253         H5Aclose(attr);
254         H5Sclose(space);
255         H5Tclose(type);
256         delete[] dims;
257         delete[] data;
258     }
259     catch (const H5Exception & /*e*/)
260     {
261         H5Sclose(space);
262         H5Tclose(type);
263         delete[] dims;
264         delete[] data;
265         throw;
266     }
267 }
268 
269 }
270