ac6bb457090b37345e6cf77f206507e818b8ac61
[scilab.git] / scilab / modules / hdf5 / src / cpp / H5DataFactory.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 "H5DataFactory.hxx"
14
15 namespace org_modules_hdf5
16 {
17
18 H5Data & H5DataFactory::getData(H5Object & parent, const hid_t obj, const bool isAttribute)
19 {
20     const hid_t type = isAttribute ? H5Aget_type(obj) : H5Dget_type(obj);
21     if (type < 0)
22     {
23         throw H5Exception(__LINE__, __FILE__, _("Cannot get the data type"));
24     }
25     H5Data * data = 0;
26     // TODO: le type est ferme dans getNativeData: bonne idee ou pas ??
27
28     switch (H5Tget_class(type))
29     {
30         case H5T_INTEGER:
31             data = &getIntegerData(parent, obj, type, isAttribute);
32             break;
33         case H5T_FLOAT:
34             data = &getFloatingData(parent, obj, type, isAttribute);
35             break;
36         case H5T_TIME:
37             data = &getTimeData(parent, obj, type, isAttribute);
38             break;
39         case H5T_STRING:
40             data = &getStringData(parent, obj, type, isAttribute);
41             break;
42         case H5T_BITFIELD:
43             data = &getBitfieldData(parent, obj, type, isAttribute);
44             break;
45         case H5T_OPAQUE:
46             data = &getOpaqueData(parent, obj, type, isAttribute);
47             break;
48         case H5T_COMPOUND:
49             data = &getCompoundData(parent, obj, type, isAttribute);
50             break;
51         case H5T_REFERENCE:
52             data = &getReferenceData(parent, obj, type, isAttribute);
53             break;
54         case H5T_ENUM:
55             //data = &getEnumData(parent, obj, type, isAttribute);
56             //break;
57         case H5T_VLEN:
58             //data = &getVlenData(parent, obj, type, isAttribute);
59             //break;
60         case H5T_ARRAY:
61             //data = &getArrayData(parent, obj, type, isAttribute);
62             //break;
63         default:
64             H5Tclose(type);
65             throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
66     }
67
68     return *data;
69 }
70
71 H5Data & H5DataFactory::getData(H5Object & parent, const hsize_t totalSize, const hid_t type, hsize_t ndims, hsize_t * dims, void * data, const hsize_t stride, const size_t offset, const bool dataOwner)
72 {
73     hsize_t dataSize = H5Tget_size(type);
74     if (H5Tget_class(type) == H5T_STRING && !H5Tis_variable_str(type))
75     {
76         // We have a C-string so it is null terminated
77         dataSize++;
78     }
79
80     switch (H5Tget_class(type))
81     {
82         case H5T_INTEGER:
83             if (H5Tequal(type, H5T_NATIVE_SCHAR))
84             {
85                 return *new H5CharData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, false);
86             }
87             else if (H5Tequal(type, H5T_NATIVE_UCHAR))
88             {
89                 return *new H5UnsignedCharData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, stride, offset, false);
90             }
91             else if (H5Tequal(type, H5T_NATIVE_SHORT))
92             {
93                 return *new H5BasicData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data, stride, offset, false);
94             }
95             else if (H5Tequal(type, H5T_NATIVE_USHORT))
96             {
97                 return *new H5BasicData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data, stride, offset, false);
98             }
99             else if (H5Tequal(type, H5T_NATIVE_INT))
100             {
101                 return *new H5BasicData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data, stride, offset, false);
102             }
103             else if (H5Tequal(type, H5T_NATIVE_UINT))
104             {
105                 return *new H5BasicData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data, stride, offset, false);
106             }
107
108 #ifdef __SCILAB_INT64__
109
110             else if (H5Tequal(type, H5T_NATIVE_LONG))
111             {
112                 return *new H5BasicData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data, stride, offset, false);
113             }
114             else if (H5Tequal(type, H5T_NATIVE_ULONG))
115             {
116                 return *new H5BasicData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, stride, offset, false);
117             }
118
119 #endif // __SCILAB_INT64__
120
121             else
122             {
123                 H5Tclose(type);
124                 throw H5Exception(__LINE__, __FILE__, _("Unknown integer datatype."));
125             }
126             break;
127         case H5T_FLOAT:
128             if (H5Tequal(type, H5T_NATIVE_FLOAT))
129             {
130                 return *new H5FloatData(parent, totalSize, dataSize, ndims, dims, (float *)data, stride, offset, false);
131             }
132             else if (H5Tequal(type, H5T_NATIVE_DOUBLE))
133             {
134                 return *new H5BasicData<double>(parent, totalSize, dataSize, ndims, dims, (double *)data, stride, offset, false);
135             }
136             else
137             {
138                 throw H5Exception(__LINE__, __FILE__, _("Unknown floating-point datatype."));
139             }
140             break;
141         case H5T_TIME:
142             return *new H5TimeData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, false);
143         case H5T_STRING:
144             if (H5Tis_variable_str(type))
145             {
146                 return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char **)data, stride, offset, false);
147             }
148             else
149             {
150                 return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, false);
151             }
152         case H5T_BITFIELD:
153             return *new H5BitfieldData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, false);
154         case H5T_OPAQUE:
155             return *new H5OpaqueData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, false);
156         case H5T_COMPOUND:
157         {
158             const unsigned int nmembers = (unsigned int)H5Tget_nmembers(type);
159             std::string * names = new std::string[nmembers];
160             size_t offs;
161             H5Data ** fields = new H5Data *[nmembers];
162
163             for (unsigned int i = 0; i < nmembers; i++)
164             {
165                 hid_t mtype = H5Tget_member_type(type, i);
166                 char * mname = H5Tget_member_name(type, i);
167                 size_t offs = H5Tget_member_offset(type, i);
168                 names[i] = std::string(mname);
169                 free(mname);
170                 fields[i] = &getData(parent, totalSize, mtype, ndims, dims, data, stride, offset + offs, false);
171             }
172
173             return *new H5CompoundData(parent, totalSize, dataSize, ndims, dims, nmembers, names, fields, (char *)data, dataOwner);
174         }
175         case H5T_REFERENCE:
176             // TODO: virer le false
177             return *new H5ReferenceData(parent, false, totalSize, dataSize, ndims, dims, (char *)data, offset);
178         case H5T_ENUM:
179         {
180             /*int nmembers = H5Tget_nmembers(type);
181               std::string * names = new std::string[nmembers];
182
183               for (unsigned int i = 0; i < nmembers; i++)
184               {
185               char * mname = H5Tget_member_name(type, i);
186               names[i] = std::string(mname);
187               free(mname);
188               }
189               return *new H5EnumData(parent, totalSize, dataSize, ndims, dims, data, offset, names);*/
190         }
191         case H5T_VLEN:
192             //return *new H5VlenData(parent, totalSize, dataSize, ndims, dims, data, offset);
193         case H5T_ARRAY:
194             //return *new H5ArrayData(parent, totalSize, dataSize, ndims, dims, data, offset);
195         default:
196             throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
197     }
198
199     throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
200 }
201
202 H5Data & H5DataFactory::getIntegerData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
203 {
204     hsize_t ndims;
205     hsize_t * dims = 0;
206     hsize_t totalSize;
207     hsize_t dataSize;
208     void * data = 0;
209     H5Data * dataObj = 0;
210     const hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
211
212     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
213
214     if (H5Tequal(nativeType, H5T_NATIVE_SCHAR))
215     {
216         dataObj = new H5CharData(parent, totalSize, dataSize, ndims, dims, (char *)data);
217     }
218     else if (H5Tequal(nativeType, H5T_NATIVE_UCHAR))
219     {
220         dataObj = new H5UnsignedCharData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data);
221     }
222     else if (H5Tequal(nativeType, H5T_NATIVE_SHORT))
223     {
224         dataObj = new H5BasicData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data);
225     }
226     else if (H5Tequal(nativeType, H5T_NATIVE_USHORT))
227     {
228         dataObj = new H5BasicData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data);
229     }
230     else if (H5Tequal(nativeType, H5T_NATIVE_INT))
231     {
232         dataObj = new H5BasicData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data);
233     }
234     else if (H5Tequal(nativeType, H5T_NATIVE_UINT))
235     {
236         dataObj = new H5BasicData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data);
237     }
238
239 #ifdef __SCILAB_INT64__
240
241     else if (H5Tequal(nativeType, H5T_NATIVE_LONG))
242     {
243         dataObj = new H5BasicData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data);
244     }
245     else if (H5Tequal(nativeType, H5T_NATIVE_ULONG))
246     {
247         dataObj = new H5BasicData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data);
248     }
249
250 #endif // __SCILAB_INT64__
251
252     else
253     {
254         H5Tclose(nativeType);
255         delete[] dims;
256         delete[] static_cast<char *>(data);
257         throw H5Exception(__LINE__, __FILE__, _("Unknown integer datatype."));
258     }
259
260     H5Tclose(nativeType);
261
262     return *dataObj;
263 }
264
265 H5Data & H5DataFactory::getFloatingData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
266 {
267     hsize_t ndims;
268     hsize_t totalSize;
269     hsize_t dataSize;
270     hsize_t * dims = 0;
271     void * data = 0;
272     H5Data * dataObj = 0;
273     const hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
274
275     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
276
277     if (H5Tequal(nativeType, H5T_NATIVE_FLOAT))
278     {
279         dataObj = new H5FloatData(parent, totalSize, dataSize, ndims, dims, (float *)data);
280     }
281     else if (H5Tequal(nativeType, H5T_NATIVE_DOUBLE))
282     {
283         dataObj = new H5BasicData<double>(parent, totalSize, dataSize, ndims, dims, (double *)data);
284     }
285     else
286     {
287         H5Tclose(nativeType);
288         delete[] dims;
289         delete[] static_cast<char *>(data);
290         throw H5Exception(__LINE__, __FILE__, _("Unknown floating-point datatype."));
291     }
292
293     H5Tclose(nativeType);
294
295     return *dataObj;
296 }
297
298 H5StringData & H5DataFactory::getStringData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
299 {
300     hsize_t ndims;
301     hsize_t totalSize;
302     hsize_t dataSize;
303     hsize_t * dims = 0;
304     void * data = 0;
305
306     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
307     if (H5Tis_variable_str(type))
308     {
309         return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char **)data);
310     }
311     else
312     {
313         return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char *)data);
314     }
315 }
316
317 H5TimeData & H5DataFactory::getTimeData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
318 {
319     hsize_t ndims;
320     hsize_t totalSize;
321     hsize_t dataSize;
322     hsize_t * dims = 0;
323     void * data = 0;
324
325     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
326
327     return *new H5TimeData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data));
328 }
329
330 H5BitfieldData & H5DataFactory::getBitfieldData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
331 {
332     hsize_t ndims;
333     hsize_t totalSize;
334     hsize_t dataSize;
335     hsize_t * dims = 0;
336     void * data = 0;
337
338     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
339
340     return *new H5BitfieldData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data));
341 }
342
343 H5OpaqueData & H5DataFactory::getOpaqueData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
344 {
345     hsize_t ndims;
346     hsize_t totalSize;
347     hsize_t dataSize;
348     hsize_t * dims = 0;
349     void * data = 0;
350
351     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
352
353     return *new H5OpaqueData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data));
354 }
355
356 H5Data & H5DataFactory::getCompoundData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
357 {
358     hsize_t ndims;
359     hsize_t totalSize;
360     hsize_t dataSize;
361     hsize_t * dims = 0;
362     void * data = 0;
363     const hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
364     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
365
366     try
367     {
368         return getData(parent, totalSize, nativeType, ndims, dims, data, dataSize, 0, true);
369     }
370     catch (const H5Exception & e)
371     {
372         H5Tclose(nativeType);
373         throw;
374     }
375 }
376
377 H5ReferenceData & H5DataFactory::getReferenceData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
378 {
379     hsize_t ndims;
380     hsize_t totalSize;
381     hsize_t dataSize;
382     hsize_t * dims = 0;
383     void * data = 0;
384
385     getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
386     return *new H5ReferenceData(parent, H5Tequal(type, H5T_STD_REF_DSETREG) > 0, totalSize, dataSize, ndims, dims, (char *)data);
387 }
388
389 /*H5EnumData & H5DataFactory::getEnumData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
390   {
391   hsize_t ndims;
392   hsize_t totalSize;
393   hisze_t dataSize;
394   hsize_t * dims = 0;
395   void * data = 0;
396   int nmembers = H5Tget_nmembers(type);
397   std::string * names = new std::string[nmembers];
398
399   for (unsigned int i = 0; i < nmembers; i++)
400   {
401   char * mname = H5Tget_member_name(type, i);
402   names[i] = std::string(mname);
403   free(mname);
404   }
405
406   getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
407
408   return *new H5EnumData(parent, totalSize, dataSize, ndims, dims, data, names);
409   }
410
411   H5VlenData & H5DataFactory::getVlenData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
412   {
413   hsize_t ndims;
414   hsize_t totalSize;
415   hisze_t dataSize;
416   hsize_t * dims = 0;
417   void * data = 0;
418
419   getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
420
421   return *new H5VlenData(parent, totalSize, dataSize, ndims, dims, data);
422   }
423
424   H5ArrayData & H5DataFactory::getArrayData(H5Object & parent, const hid_t obj, const hid_t type, const bool isAttribute)
425   {
426   hsize_t ndims;
427   hsize_t totalSize;
428   hisze_t dataSize;
429   hsize_t * dims = 0;
430   void * data = 0;
431
432   getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
433
434   return *new H5ArrayData(parent, totalSize, dataSize, ndims, dims, data);
435   }*/
436
437 //  getNativeData(obj, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
438
439 //return *new H5StringData(parent, totalSize, dataSize, ndims, dims, data);
440
441 void H5DataFactory::getNativeData(const hid_t obj, const hid_t type, hsize_t * totalSize, hsize_t * dataSize, hsize_t * ndims, hsize_t ** dims, void ** data, const bool isAttribute)
442 {
443     hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
444     const hid_t space = isAttribute ? H5Aget_space(obj) : H5Dget_space(obj);
445     hsize_t size = H5Tget_size(nativeType);
446     *totalSize = 1;
447     *dims = new hsize_t[__SCILAB_HDF5_MAX_DIMS__ + 1]();
448     *ndims = H5Sget_simple_extent_dims(space, *dims, 0);
449
450     if (H5Tget_class(nativeType) == H5T_STRING && !H5Tis_variable_str(nativeType))
451     {
452         // We have a C-string so it is null terminated
453         size++;
454     }
455
456     *dataSize = size;
457
458     for (int i = 0; i < *ndims; i++)
459     {
460         *totalSize *= (*dims)[i];
461     }
462
463     size *= *totalSize;
464
465     if ((hsize_t)((size_t)size) != size)
466     {
467         H5Tclose(type);
468         H5Tclose(nativeType);
469         H5Sclose(space);
470         delete[] *dims;
471         throw H5Exception(__LINE__, __FILE__, _("Memory to allocate is too big"));
472     }
473
474     *data = static_cast<void *>(new char[(size_t)size]());
475     if (!*data)
476     {
477         H5Tclose(type);
478         H5Tclose(nativeType);
479         H5Sclose(space);
480         delete[] *dims;
481         throw H5Exception(__LINE__, __FILE__, _("Cannot allocate memory to get the data"));
482     }
483
484     if ((isAttribute && H5Aread(obj, nativeType, *data) < 0)
485             || (!isAttribute && H5Dread(obj, nativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, *data) < 0))
486     {
487         H5Tclose(type);
488         H5Tclose(nativeType);
489         H5Sclose(space);
490         delete[] static_cast<char *>(*data);
491         delete[] *dims;
492         throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve the data from the attribute"));
493     }
494
495     H5Tclose(nativeType);
496     H5Sclose(space);
497 }
498 }