Fix bugs and it is now possible to read hyperslabs
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5Dataset.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 "H5Dataset.hxx"
14 #include "H5DataFactory.hxx"
15 #include "H5Attribute.hxx"
16 #include "H5HardLink.hxx"
17
18 namespace org_modules_hdf5
19 {
20
21 void H5Dataset::init()
22 {
23     dataset = H5Dopen2(getParent().getH5Id(), name.c_str(), H5P_DEFAULT);
24     if (dataset < 0)
25     {
26         throw H5Exception(__LINE__, __FILE__, _("Cannot open the given dataset %s."), name.c_str());
27     }
28 }
29
30 H5Dataset::H5Dataset(H5Object & _parent, const std::string & _name) : H5Object(_parent, _name), dataset((hid_t) - 1)
31 {
32     init();
33 }
34
35 H5Dataset::H5Dataset(H5Object & _parent, hid_t _dataset, const std::string & _name) : H5Object(_parent, _name), dataset(_dataset)
36 {
37
38 }
39
40 H5Dataset::~H5Dataset()
41 {
42     if (dataset >= 0)
43     {
44         H5Dclose(dataset);
45     }
46 }
47
48 H5Data & H5Dataset::getData()
49 {
50     return H5DataFactory::getData(*this, dataset, 0, 0, false);
51 }
52
53 H5Data & H5Dataset::getData(H5Dataspace & space, hsize_t * dims)
54 {
55     return H5DataFactory::getData(*this, dataset, &space, dims, false);
56 }
57
58 H5Dataspace & H5Dataset::getSpace()
59 {
60     hid_t space = H5Dget_space(dataset);
61     if (space < 0)
62     {
63         throw H5Exception(__LINE__, __FILE__, _("Cannot get the dataspace associated with dataset named %s."), name.c_str());
64     }
65
66     return *new H5Dataspace(*this, space);
67 }
68
69 H5Type & H5Dataset::getDataType()
70 {
71     hid_t type = H5Dget_type(dataset);
72     if (type < 0)
73     {
74         throw H5Exception(__LINE__, __FILE__, _("Cannot get the dataspace associated with dataset named %s."), name.c_str());
75     }
76
77     return *new H5Type(*this, type);
78 }
79
80 H5Dataset::H5Layout & H5Dataset::getLayout()
81 {
82     hid_t plist = H5Dget_create_plist(dataset);
83     H5D_layout_t layout = H5Pget_layout(plist);
84     H5Dataset::H5Layout * obj = 0;
85
86     switch (layout)
87     {
88         case H5D_COMPACT:
89             obj = new H5Dataset::H5CompactLayout(*this);
90             break;
91         case H5D_CONTIGUOUS:
92             obj = new H5Dataset::H5ContiguousLayout(*this);
93             break;
94         case H5D_CHUNKED:
95             obj = new H5Dataset::H5ChunkedLayout(*this);
96             break;
97         default:
98             H5Pclose(plist);
99             throw H5Exception(__LINE__, __FILE__, _("Invalid layout"));
100     }
101
102     H5Pclose(plist);
103
104     return *obj;
105 }
106
107 void H5Dataset::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
108 {
109     SciErr err;
110     std::string lower(_name);
111
112     try
113     {
114         H5Attribute * attr = new H5Attribute(*const_cast<H5Dataset *>(this), _name);
115         attr->createOnScilabStack(pos, pvApiCtx);
116
117         return;
118     }
119     catch (const H5Exception & e) { }
120
121     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
122
123     if (lower == "attributes")
124     {
125         const H5AttributesList & attrs = const_cast<H5Dataset *>(this)->getAttributes();
126         attrs.createOnScilabStack(pos, pvApiCtx);
127
128         return;
129     }
130     else if (lower == "type")
131     {
132         const H5Type & type = const_cast<H5Dataset *>(this)->getDataType();
133         type.createOnScilabStack(pos, pvApiCtx);
134
135         return;
136     }
137     else if (lower == "dataspace")
138     {
139         const H5Dataspace & space = const_cast<H5Dataset *>(this)->getSpace();
140         space.createOnScilabStack(pos, pvApiCtx);
141
142         return;
143     }
144     else if (lower == "data")
145     {
146         const H5Data & data = const_cast<H5Dataset *>(this)->getData();
147         data.toScilab(pvApiCtx, pos);
148
149         if (!data.isReference())
150         {
151             delete &data;
152         }
153
154         return;
155     }
156     else if (lower == "layout")
157     {
158         const H5Dataset::H5Layout & layout = const_cast<H5Dataset *>(this)->getLayout();
159         layout.createOnScilabStack(pos, pvApiCtx);
160
161         return;
162     }
163
164     H5Object::getAccessibleAttribute(_name, pos, pvApiCtx);
165 }
166
167 std::string H5Dataset::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
168 {
169     std::ostringstream os;
170     haddr_t addr = this->getAddr();
171     std::map<haddr_t, std::string>::iterator it = alreadyVisited.find(addr);
172     if (it != alreadyVisited.end())
173     {
174         os << H5Object::getIndentString(indentLevel) << "DATASET \"" << getName() << "\" {" << std::endl
175            << H5Object::getIndentString(indentLevel + 1) << "HARDLINK \"" << it->second << "\"" << std::endl
176            << H5Object::getIndentString(indentLevel) << "}" << std::endl;
177
178         return os.str();
179     }
180     else
181     {
182         alreadyVisited.insert(std::pair<haddr_t, std::string>(addr, getCompletePath()));
183     }
184
185     const H5Type & type = const_cast<H5Dataset *>(this)->getDataType();
186     const H5Dataspace & space = const_cast<H5Dataset *>(this)->getSpace();
187     const H5AttributesList & attrs = const_cast<H5Dataset *>(this)->getAttributes();
188     const H5Data & data = const_cast<H5Dataset *>(this)->getData();
189     const H5Dataset::H5Layout & layout = const_cast<H5Dataset *>(this)->getLayout();
190
191     os << H5Object::getIndentString(indentLevel) << "DATASET \"" << getName() << "\" {" << std::endl
192        << type.dump(alreadyVisited, indentLevel + 1)
193        << space.dump(alreadyVisited, indentLevel + 1)
194        << layout.dump(alreadyVisited, indentLevel + 1)
195        << data.dump(alreadyVisited, indentLevel + 1)
196        << attrs.dump(alreadyVisited, indentLevel + 1)
197        << H5Object::getIndentString(indentLevel) << "}" << std::endl;
198
199     delete &type;
200     delete &space;
201     delete &data;
202     delete &attrs;
203     delete &layout;
204
205     return os.str();
206 }
207
208 void H5Dataset::printLsInfo(std::ostringstream & os) const
209 {
210     const H5Dataspace & space = const_cast<H5Dataset *>(this)->getSpace();
211     std::vector<unsigned int> dims = space.getDims();
212     std::string str(getName());
213     H5Object::getResizedString(str);
214
215     os << str << "Dataset {";
216
217     if (dims.size() == 0)
218     {
219         os << "}";
220     }
221     else
222     {
223         for (unsigned int i = 0; i < dims.size() - 1; i++)
224         {
225             os << dims[i] << ", ";
226         }
227         os << dims[dims.size() - 1] << "}";
228     }
229
230     delete &space;
231
232     os << std::endl;
233 }
234
235 std::string H5Dataset::ls() const
236 {
237     std::ostringstream os;
238     printLsInfo(os);
239
240     return os.str();
241 }
242
243 void H5Dataset::ls(std::vector<std::string> & name, std::vector<std::string> & type) const
244 {
245     herr_t err;
246     OpDataGetLs opdata;
247     opdata.parent = const_cast<H5Dataset *>(this);
248     opdata.name = &name;
249     opdata.type = &type;
250     hsize_t idx = 0;
251
252     err = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, H5Object::getLsAttributes, &opdata);
253     if (err < 0)
254     {
255         throw H5Exception(__LINE__, __FILE__, _("Cannot list dataset attributes."));
256     }
257 }
258
259 std::string H5Dataset::toString(const unsigned int indentLevel) const
260 {
261     std::ostringstream os;
262     std::string indentString = H5Object::getIndentString(indentLevel + 1);
263     const H5Type & type = const_cast<H5Dataset *>(this)->getDataType();
264     const H5AttributesList & attrs = const_cast<H5Dataset *>(this)->getAttributes();
265
266     os << H5Object::getIndentString(indentLevel) << "HDF5 Dataset" << std::endl
267        << indentString << _("Filename") << ": " << getParent().getFile().getFileName() << std::endl
268        << indentString << _("Name") << ": " << getName() << std::endl
269        << indentString << _("Path") << ": " << getCompletePath() << std::endl
270        << indentString << _("Elements type") << ": " << type.getTypeName() << std::endl
271        << indentString << _("Attributes") << ": [1 x " << attrs.getSize() << "]";
272
273     delete &type;
274     delete &attrs;
275
276     return os.str();
277 }
278
279 hid_t H5Dataset::create(H5Object & loc, const std::string & name, const hid_t type, const hid_t targettype, const hid_t space, void * data)
280 {
281     herr_t err;
282     hid_t dataset = H5Dcreate2(loc.getH5Id(), name.c_str(), targettype, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
283     if (dataset < 0)
284     {
285         throw H5Exception(__LINE__, __FILE__, _("Cannot create a new dataset."));
286     }
287
288     err = H5Dwrite(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
289     if (err < 0)
290     {
291         throw H5Exception(__LINE__, __FILE__, _("Cannot write data in the dataset."));
292     }
293
294     return dataset;
295 }
296 }