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 "H5DataFactory.hxx"
17
18 namespace org_modules_hdf5
19 {
20
getData(H5Object & parent,const hid_t obj,H5Dataspace * space,hsize_t * selectdims,const bool isAttribute)21 H5Data & H5DataFactory::getData(H5Object & parent, const hid_t obj, H5Dataspace * space, hsize_t * selectdims, const bool isAttribute)
22 {
23 hsize_t ndims;
24 hsize_t * dims = 0;
25 hsize_t totalSize;
26 hsize_t dataSize;
27 void * data = 0;
28 const hid_t spaceId = space ? space->getH5Id() : -1;
29 const hid_t type = isAttribute ? H5Aget_type(obj) : H5Dget_type(obj);
30 const hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
31 if (type < 0)
32 {
33 throw H5Exception(__LINE__, __FILE__, _("Cannot get the data type"));
34 }
35
36 try
37 {
38 getNativeData(obj, spaceId, selectdims, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
39 H5Data & ret = getObjectData(parent, totalSize, dataSize, nativeType, ndims, dims, data, 0, 0, true);
40 H5Tclose(type);
41 H5Tclose(nativeType);
42
43 return ret;
44 }
45 catch (const H5Exception & /*e*/)
46 {
47 H5Tclose(type);
48 H5Tclose(nativeType);
49 if (dims)
50 {
51 delete[] dims;
52 }
53
54 if (data)
55 {
56 delete[] static_cast<char *>(data);
57 }
58 throw;
59 }
60 }
61
getObjectData(H5Object & parent,const hsize_t totalSize,const hsize_t dataSize,const hid_t type,const hsize_t ndims,const hsize_t * dims,void * data,const hsize_t stride,const size_t offset,const bool dataOwner)62 H5Data & H5DataFactory::getObjectData(H5Object & parent, const hsize_t totalSize, const hsize_t dataSize, const hid_t type, const hsize_t ndims, const hsize_t * dims, void * data, const hsize_t stride, const size_t offset, const bool dataOwner)
63 {
64 switch (H5Tget_class(type))
65 {
66 case H5T_INTEGER:
67 if (H5Tequal(type, H5T_NATIVE_SCHAR))
68 {
69 return *new H5CharData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
70 }
71 else if (H5Tequal(type, H5T_NATIVE_UCHAR))
72 {
73 return *new H5UnsignedCharData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, stride, offset, dataOwner);
74 }
75 else if (H5Tequal(type, H5T_NATIVE_SHORT))
76 {
77 return *new H5BasicData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data, stride, offset, dataOwner);
78 }
79 else if (H5Tequal(type, H5T_NATIVE_USHORT))
80 {
81 return *new H5BasicData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data, stride, offset, dataOwner);
82 }
83 else if (H5Tequal(type, H5T_NATIVE_INT))
84 {
85 return *new H5BasicData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data, stride, offset, dataOwner);
86 }
87 else if (H5Tequal(type, H5T_NATIVE_UINT))
88 {
89 return *new H5BasicData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data, stride, offset, dataOwner);
90 }
91
92 #ifdef __SCILAB_INT64__
93
94 else if (H5Tequal(type, H5T_NATIVE_LLONG))
95 {
96 return *new H5BasicData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data, stride, offset, dataOwner);
97 }
98 else if (H5Tequal(type, H5T_NATIVE_ULLONG))
99 {
100 return *new H5BasicData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, stride, offset, dataOwner);
101 }
102 #else
103
104 else if (H5Tequal(type, H5T_NATIVE_LONG))
105 {
106 return *new H5TransformedData<long long, int>(parent, totalSize, dataSize, ndims, dims, (long long *)data, stride, offset, dataOwner);
107 }
108 else if (H5Tequal(type, H5T_NATIVE_ULONG))
109 {
110 return *new H5TransformedData<unsigned long long, unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, stride, offset, dataOwner);
111 }
112
113 #endif // __SCILAB_INT64__
114
115 else
116 {
117 throw H5Exception(__LINE__, __FILE__, _("Unknown integer datatype."));
118 }
119 break;
120 case H5T_FLOAT:
121 if (H5Tequal(type, H5T_NATIVE_FLOAT))
122 {
123 return *new H5TransformedData<float, double>(parent, totalSize, dataSize, ndims, dims, (float *)data, stride, offset, dataOwner);
124 }
125 else if (H5Tequal(type, H5T_NATIVE_DOUBLE))
126 {
127 return *new H5BasicData<double>(parent, totalSize, dataSize, ndims, dims, (double *)data, stride, offset, dataOwner);
128 }
129 else
130 {
131 throw H5Exception(__LINE__, __FILE__, _("Unknown floating-point datatype."));
132 }
133 break;
134 case H5T_TIME:
135 return *new H5TimeData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
136 case H5T_STRING:
137 if (H5Tis_variable_str(type))
138 {
139 return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char **)data, stride, offset, dataOwner);
140 }
141 else
142 {
143 return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
144 }
145 case H5T_BITFIELD:
146 switch (dataSize)
147 {
148 case 1:
149 return *new H5Bitfield1Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned char *>(data), stride, offset, dataOwner);
150 case 2:
151 return *new H5Bitfield2Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned short *>(data), stride, offset, dataOwner);
152 case 4:
153 return *new H5Bitfield4Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned int *>(data), stride, offset, dataOwner);
154 case 8:
155 //return *new H5BitfieldData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned long long *>(data), stride, offset, false);
156 default:
157 throw H5Exception(__LINE__, __FILE__, _("Bitfield is too big"));
158 }
159
160 case H5T_OPAQUE:
161 return *new H5OpaqueData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, stride, offset, dataOwner);
162 case H5T_COMPOUND:
163 return *new H5CompoundData(parent, totalSize, dataSize, ndims, dims, (char *)data, H5Tcopy(type), stride, offset, dataOwner);
164 case H5T_REFERENCE:
165 // TODO: virer le false
166 return *new H5ReferenceData(parent, H5Tequal(type, H5T_STD_REF_DSETREG) ? H5R_DATASET_REGION : H5R_OBJECT, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
167 case H5T_ENUM:
168 {
169 int nmembers = H5Tget_nmembers(type);
170 std::string * names = nmembers > 0 ? new std::string[nmembers] : 0;
171
172 for (int i = 0; i < nmembers; i++)
173 {
174 char * mname = H5Tget_member_name(type, i);
175 names[i] = std::string(mname);
176 //HDF5 version > 1.8.13
177 //H5free_memory(mnale);
178
179 //freed memory allocated by H5Tget_member_name trigger a segfault on Windows.
180 //http://lists.hdfgroup.org/pipermail/hdf-forum_lists.hdfgroup.org/2014-September/008061.html
181 //little memory leaks are better then crashs :x
182 #ifndef _MSC_VER
183 free(mname);
184 #endif
185 }
186
187 if (H5Tget_sign(type) == H5T_SGN_NONE)
188 {
189 switch (dataSize)
190 {
191 case 1:
192 return *new H5EnumData<unsigned char>(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, type, H5T_NATIVE_UCHAR, nmembers, names, stride, offset, dataOwner);
193 case 2:
194 return *new H5EnumData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data, type, H5T_NATIVE_USHORT, nmembers, names, stride, offset, dataOwner);
195 case 4:
196 return *new H5EnumData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data, type, H5T_NATIVE_UINT, nmembers, names, stride, offset, dataOwner);
197 #ifdef __SCILAB_INT64__
198 case 8:
199 return *new H5EnumData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, type, H5T_NATIVE_ULLONG, nmembers, names, stride, offset, dataOwner);
200 #endif
201 }
202 }
203 else
204 {
205 switch (dataSize)
206 {
207 case 1:
208 return *new H5EnumData<char>(parent, totalSize, dataSize, ndims, dims, (char *)data, type, H5T_NATIVE_CHAR, nmembers, names, stride, offset, dataOwner);
209 case 2:
210 return *new H5EnumData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data, type, H5T_NATIVE_SHORT, nmembers, names, stride, offset, dataOwner);
211 case 4:
212 return *new H5EnumData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data, type, H5T_NATIVE_INT, nmembers, names, stride, offset, dataOwner);
213 #ifdef __SCILAB_INT64__
214 case 8:
215 return *new H5EnumData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data, type, H5T_NATIVE_LLONG, nmembers, names, stride, offset, dataOwner);
216 #endif
217 }
218 }
219
220 return *new H5EnumData<char>(parent, totalSize, dataSize, ndims, dims, (char *)data, type, H5T_NATIVE_CHAR, nmembers, names, stride, offset, dataOwner);
221 }
222 case H5T_VLEN:
223 return *new H5VlenData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data), type, stride, offset, dataOwner);
224 case H5T_ARRAY:
225 return *new H5ArrayData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data), type, stride, offset, dataOwner);
226 default:
227 throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
228 }
229
230 throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
231 }
232
getNativeData(const hid_t obj,const hid_t space,hsize_t * selectdims,const hid_t type,hsize_t * totalSize,hsize_t * dataSize,hsize_t * ndims,hsize_t ** dims,void ** data,const bool isAttribute)233 void H5DataFactory::getNativeData(const hid_t obj, const hid_t space, hsize_t * selectdims, const hid_t type, hsize_t * totalSize, hsize_t * dataSize, hsize_t * ndims, hsize_t ** dims, void ** data, const bool isAttribute)
234 {
235 hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
236 hid_t _space = space < 0 ? (isAttribute ? H5Aget_space(obj) : H5Dget_space(obj)) : space;
237 hsize_t size = H5Tget_size(nativeType);
238 H5S_sel_type sel;
239 hid_t targetspace;
240 herr_t err;
241 hsize_t * blockbuf = 0;
242 bool hyperslab = false;
243 bool isString = false;
244
245 *totalSize = 1;
246 if (H5Tget_class(nativeType) == H5T_STRING && !H5Tis_variable_str(nativeType))
247 {
248 // We have a C-string so it is null terminated
249 size++;
250 isString = true;
251 }
252
253 *dataSize = size;
254 *ndims = H5Sget_simple_extent_dims(_space, 0, 0);
255 *dims = new hsize_t[*ndims];
256
257 if (isAttribute)
258 {
259 H5Sget_simple_extent_dims(_space, *dims, 0);
260 for (unsigned int i = 0; i < *ndims; i++)
261 {
262 *totalSize *= (*dims)[i];
263 }
264 }
265 else
266 {
267 sel = H5Sget_select_type(_space);
268 switch (sel)
269 {
270 case H5S_SEL_NONE:
271 case H5S_SEL_ALL:
272 H5Sget_simple_extent_dims(_space, *dims, 0);
273 for (unsigned int i = 0; i < *ndims; i++)
274 {
275 *totalSize *= (*dims)[i];
276 }
277 break;
278 case H5S_SEL_POINTS:
279 break;
280 case H5S_SEL_HYPERSLABS:
281 for (unsigned int i = 0; i < *ndims; i++)
282 {
283 (*dims)[i] = selectdims[i];
284 *totalSize *= (*dims)[i];
285 }
286 hyperslab = true;
287 break;
288 default:
289 break;
290 }
291 }
292
293 size *= *totalSize;
294
295 if ((hsize_t)((size_t)size) != size)
296 {
297 H5Tclose(nativeType);
298 if (space < 0)
299 {
300 H5Sclose(_space);
301 }
302 delete[] *dims;
303 throw H5Exception(__LINE__, __FILE__, _("Memory to allocate is too big"));
304 }
305
306 try
307 {
308 if (isString)
309 {
310 *data = static_cast<void *>(new char[(size_t)size]());
311 }
312 else
313 {
314 // No need to initialize the array
315 *data = static_cast<void *>(new char[(size_t)size]);
316 }
317 }
318 catch (const std::bad_alloc & /*e*/)
319 {
320 H5Tclose(nativeType);
321 if (space < 0)
322 {
323 H5Sclose(_space);
324 }
325 *data = 0;
326 delete[] *dims;
327 *dims = 0;
328 throw H5Exception(__LINE__, __FILE__, _("Cannot allocate memory to get the data"));
329 }
330
331 if (!*data)
332 {
333 H5Tclose(nativeType);
334 if (space < 0)
335 {
336 H5Sclose(_space);
337 }
338 delete[] *dims;
339 *dims = 0;
340 throw H5Exception(__LINE__, __FILE__, _("Cannot allocate memory to get the data"));
341 }
342
343 if (hyperslab)
344 {
345 targetspace = H5Screate_simple((int) * ndims, *dims, 0);
346 err = H5Dread(obj, nativeType, targetspace, _space, H5P_DEFAULT, *data);
347 H5Sclose(targetspace);
348 }
349 else
350 {
351 if (isAttribute)
352 {
353 err = H5Aread(obj, nativeType, *data);
354 }
355 else
356 {
357 err = H5Dread(obj, nativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, *data);
358 }
359 }
360
361 if (err < 0)
362 {
363 H5Tclose(nativeType);
364 if (space < 0)
365 {
366 H5Sclose(_space);
367 }
368 delete[] static_cast<char *>(*data);
369 *data = 0;
370 delete[] *dims;
371 *dims = 0;
372 throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve the data from the attribute"));
373 }
374
375 H5Tclose(nativeType);
376 if (space < 0)
377 {
378 H5Sclose(_space);
379 }
380 }
381 }
382