Fix bugs and it is now possible to read hyperslabs
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5File.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 "HDF5Objects.h"
14 #include "H5Group.hxx"
15 #include "H5File.hxx"
16
17 extern "C"
18 {
19 #include "FileExist.h"
20 }
21
22 namespace org_modules_hdf5
23 {
24
25 void H5File::init()
26 {
27     bool opened;
28
29 #if !defined(__HDF5ERROR_PRINT__)
30     H5Eset_auto2(H5E_DEFAULT, 0, 0);
31 #endif
32
33     switch (flags)
34     {
35         case RDONLY:
36             if (!FileExist(const_cast<char *>(filename.c_str())) || H5Fis_hdf5(filename.c_str()) <= 0)
37             {
38                 throw H5Exception(__LINE__, __FILE__, _("Invalid hdf5 file: %s"), filename.c_str());
39             }
40
41             file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
42             if (file < 0)
43             {
44                 throw H5Exception(__LINE__, __FILE__, _("Cannot open the given hdf5 file: %s"), filename.c_str());
45             }
46
47             opened = true;
48             break;
49         case RDWR:
50             if (!FileExist(const_cast<char *>(filename.c_str())) || H5Fis_hdf5(filename.c_str()) <= 0)
51             {
52                 throw H5Exception(__LINE__, __FILE__, _("Invalid hdf5 file: %s"), filename.c_str());
53             }
54
55             file = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
56             if (file < 0)
57             {
58                 throw H5Exception(__LINE__, __FILE__, _("Cannot open the given hdf5 file: %s"), filename.c_str());
59             }
60
61             opened = true;
62             break;
63         case TRUNC:
64             file = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
65             if (file < 0)
66             {
67                 throw H5Exception(__LINE__, __FILE__, _("Cannot create the given hdf5 file: %s"), filename.c_str());
68             }
69
70             break;
71         case EXCL:
72             file = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
73             if (file < 0)
74             {
75                 throw H5Exception(__LINE__, __FILE__, _("Cannot create the given hdf5 file: %s"), filename.c_str());
76             }
77             break;
78         case APPEND:
79             if (FileExist(const_cast<char *>(filename.c_str())))
80             {
81                 if (H5Fis_hdf5(filename.c_str()) > 0)
82                 {
83                     file = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
84                     if (file < 0)
85                     {
86                         throw H5Exception(__LINE__, __FILE__, _("Cannot open the given hdf5 file: %s"), filename.c_str());
87                     }
88
89                     opened = true;
90                 }
91                 else
92                 {
93                     throw H5Exception(__LINE__, __FILE__, _("Cannot append the file (not HDF5): %s"), filename.c_str());
94                 }
95             }
96             else
97             {
98                 file = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
99                 if (file < 0)
100                 {
101                     throw H5Exception(__LINE__, __FILE__, _("Cannot create the given hdf5 file: %s"), filename.c_str());
102                 }
103             }
104     }
105
106     if (opened && path != "/" && H5Lexists(file, path.c_str(), H5P_DEFAULT) <= 0)
107     {
108         H5Fclose(file);
109         throw H5Exception(__LINE__, __FILE__, _("Invalid path: %s"), path.c_str());
110     }
111 }
112
113 H5File::H5File(const char * _filename, const char * _path, const char * access) : H5Object(H5Object::getRoot()), filename(std::string(_filename)), path(std::string(_path)), flags(getFlags(std::string(access)))
114 {
115     init();
116 }
117
118 H5File::H5File(const std::string & _filename, const std::string & _path, const std::string & access) : H5Object(H5Object::getRoot()), filename(_filename), path(_path), flags(getFlags(access))
119 {
120     init();
121 }
122
123 H5File::~H5File()
124 {
125     if (file >= 0)
126     {
127         H5Fclose(file);
128         H5garbage_collect();
129     }
130 }
131
132 void H5File::flush(const bool local) const
133 {
134     herr_t err = H5Fflush(file, local ? H5F_SCOPE_LOCAL : H5F_SCOPE_GLOBAL);
135     if (err < 0)
136     {
137         throw H5Exception(__LINE__, __FILE__, _("Error in flushing the file."));
138     }
139 }
140
141 H5Object & H5File::getRoot()
142 {
143     hid_t obj = H5Oopen(getH5Id(), path.c_str(), H5P_DEFAULT);
144     if (obj < 0)
145     {
146         throw H5Exception(__LINE__, __FILE__, _("Invalid path: %s"), path.c_str());
147     }
148
149     try
150     {
151         return H5Object::getObject(*this, obj);
152     }
153     catch (const H5Exception & e)
154     {
155         H5Oclose(obj);
156         throw;
157     }
158 }
159
160 std::string H5File::getCompletePath() const
161 {
162     return "";
163 }
164
165 hsize_t H5File::getFileSize() const
166 {
167     herr_t err;
168     hsize_t size = 0;
169
170     err = H5Fget_filesize(file, &size);
171     if (err < 0)
172     {
173         throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve file size: %s"), filename.c_str());
174     }
175
176     return size;
177 }
178
179 void H5File::getFileHDF5Version(unsigned int * out) const
180 {
181     herr_t err = H5get_libversion(out, out + 1, out + 2);
182     if (err < 0)
183     {
184         throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve file version: %s"), filename.c_str());
185     }
186 }
187
188 void H5File::getAccessibleAttribute(const std::string & _name, const int pos, void * pvApiCtx) const
189 {
190     SciErr err;
191     std::string lower(_name);
192
193     /*    try
194         {
195         H5Object & _root = const_cast<H5File *>(this)->getRoot();
196             H5Object & obj = H5Object::getObject(_root, _name);
197             obj.createOnScilabStack(pos, pvApiCtx);
198             return;
199         }
200         catch (const H5Exception & e) { }
201     */
202
203     std::transform(_name.begin(), _name.end(), lower.begin(), tolower);
204
205     if (lower == "name")
206     {
207         const char * _filename = filename.c_str();
208         err = createMatrixOfString(pvApiCtx, pos, 1, 1, &_filename);
209         if (err.iErr)
210         {
211             throw H5Exception(__LINE__, __FILE__, _("Cannot create a string on the stack."));
212         }
213
214         return;
215     }
216     else if (lower == "size")
217     {
218         unsigned int size = (unsigned int)getFileSize();
219         err = createMatrixOfUnsignedInteger32(pvApiCtx, pos, 1, 1, &size);
220         if (err.iErr)
221         {
222             throw H5Exception(__LINE__, __FILE__, _("Cannot create an integer on the stack."));
223         }
224
225         return;
226     }
227     else if (lower == "version")
228     {
229         unsigned int version[3];
230         getFileHDF5Version(version);
231         err = createMatrixOfUnsignedInteger32(pvApiCtx, pos, 1, 3, (unsigned int *)version);
232         if (err.iErr)
233         {
234             throw H5Exception(__LINE__, __FILE__, _("Cannot create an array of integer on the stack."));
235         }
236
237         return;
238     }
239     else if (lower == "root")
240     {
241         H5Object & _root = const_cast<H5File *>(this)->getRoot();
242         _root.createOnScilabStack(pos, pvApiCtx);
243         return;
244     }
245
246     throw H5Exception(__LINE__, __FILE__, _("Invalid field %s."), _name.c_str());
247 }
248
249 std::string H5File::dump(std::map<haddr_t, std::string> & alreadyVisited, const unsigned int indentLevel) const
250 {
251     std::ostringstream os;
252     H5Object & _root = const_cast<H5File *>(this)->getRoot();
253     os << H5Object::getIndentString(indentLevel) << "HDF5 \"" << filename << "\" {" << std::endl
254        << _root.dump(alreadyVisited, indentLevel + 1)
255        << H5Object::getIndentString(indentLevel) << "}" << std::endl;
256
257     delete &_root;
258
259     return os.str();
260 }
261
262 void H5File::ls(std::vector<std::string> & name, std::vector<std::string> & type) const
263 {
264     H5Object & _root = const_cast<H5File *>(this)->getRoot();
265     _root.ls(name, type);
266     delete &_root;
267 }
268
269 std::string H5File::ls() const
270 {
271     H5Object & _root = const_cast<H5File *>(this)->getRoot();
272     std::string str = _root.ls();
273     delete &_root;
274
275     return str;
276 }
277
278 std::string H5File::toString(const unsigned int indentLevel) const
279 {
280     herr_t err;
281     hsize_t size = 0;
282     std::ostringstream os;
283     unsigned int major = 0, minor = 0, release = 0;
284     std::string indentString = H5Object::getIndentString(indentLevel + 1);
285
286     err = H5Fget_filesize(file, &size);
287     if (err < 0)
288     {
289         throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve file size: %s"), filename.c_str());
290     }
291
292     err = H5get_libversion(&major, &minor, &release);
293
294     os << H5Object::getIndentString(indentLevel) << "HDF5 File" << std::endl
295        << indentString << _("Filename") << ": " << filename << std::endl
296        << indentString << _("HDF5 library version") << ": " << major << "." << minor << "." << release << std::endl
297        << indentString << _("File size") << ": " << size << std::endl
298        << indentString << _("Root object") << ": " << path << std::flush;
299
300     return os.str();
301 }
302 }