summaryrefslogtreecommitdiff
path: root/modules/hdf5/src/cpp/H5DataFactory.cpp
blob: d5c620dbe487220f0b8d30ae689f9b5c2c0fb747 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
 *
 * This file must be used under the terms of the CeCILL.
 * This source file is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at
 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
 *
 */

#include "H5DataFactory.hxx"

namespace org_modules_hdf5
{

H5Data & H5DataFactory::getData(H5Object & parent, const hid_t obj, H5Dataspace * space, hsize_t * selectdims, const bool isAttribute)
{
    hsize_t ndims;
    hsize_t * dims = 0;
    hsize_t totalSize;
    hsize_t dataSize;
    void * data = 0;
    const hid_t spaceId = space ? space->getH5Id() : -1;
    const hid_t type = isAttribute ? H5Aget_type(obj) : H5Dget_type(obj);
    const hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
    if (type < 0)
    {
        throw H5Exception(__LINE__, __FILE__, _("Cannot get the data type"));
    }

    try
    {
        getNativeData(obj, spaceId, selectdims, type, &totalSize, &dataSize, &ndims, &dims, &data, isAttribute);
        H5Data & ret = getObjectData(parent, totalSize, dataSize, nativeType, ndims, dims, data, 0, 0, true);
        H5Tclose(type);
        H5Tclose(nativeType);

        return ret;
    }
    catch (const H5Exception & /*e*/)
    {
        H5Tclose(type);
        H5Tclose(nativeType);
        if (dims)
        {
            delete[] dims;
        }

        if (data)
        {
            delete[] static_cast<char *>(data);
        }
        throw;
    }
}

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)
{
    switch (H5Tget_class(type))
    {
        case H5T_INTEGER:
            if (H5Tequal(type, H5T_NATIVE_SCHAR))
            {
                return *new H5CharData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_UCHAR))
            {
                return *new H5UnsignedCharData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_SHORT))
            {
                return *new H5BasicData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_USHORT))
            {
                return *new H5BasicData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_INT))
            {
                return *new H5BasicData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_UINT))
            {
                return *new H5BasicData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data, stride, offset, dataOwner);
            }

#ifdef __SCILAB_INT64__

            else if (H5Tequal(type, H5T_NATIVE_LONG))
            {
                return *new H5BasicData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_ULONG))
            {
                return *new H5BasicData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, stride, offset, dataOwner);
            }
#else

            else if (H5Tequal(type, H5T_NATIVE_LONG))
            {
                return *new H5TransformedData<long long, int>(parent, totalSize, dataSize, ndims, dims, (long long *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_ULONG))
            {
                return *new H5TransformedData<unsigned long long, unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, stride, offset, dataOwner);
            }

#endif // __SCILAB_INT64__

            else
            {
                throw H5Exception(__LINE__, __FILE__, _("Unknown integer datatype."));
            }
            break;
        case H5T_FLOAT:
            if (H5Tequal(type, H5T_NATIVE_FLOAT))
            {
                return *new H5TransformedData<float, double>(parent, totalSize, dataSize, ndims, dims, (float *)data, stride, offset, dataOwner);
            }
            else if (H5Tequal(type, H5T_NATIVE_DOUBLE))
            {
                return *new H5BasicData<double>(parent, totalSize, dataSize, ndims, dims, (double *)data, stride, offset, dataOwner);
            }
            else
            {
                throw H5Exception(__LINE__, __FILE__, _("Unknown floating-point datatype."));
            }
            break;
        case H5T_TIME:
            return *new H5TimeData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
        case H5T_STRING:
            if (H5Tis_variable_str(type))
            {
                return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char **)data, stride, offset, dataOwner);
            }
            else
            {
                return *new H5StringData(parent, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
            }
        case H5T_BITFIELD:
            switch (dataSize)
            {
                case 1:
                    return *new H5Bitfield1Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned char *>(data), stride, offset, dataOwner);
                case 2:
                    return *new H5Bitfield2Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned short *>(data), stride, offset, dataOwner);
                case 4:
                    return *new H5Bitfield4Data(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned int *>(data), stride, offset, dataOwner);
                case 8:
                //return *new H5BitfieldData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, static_cast<unsigned long long *>(data), stride, offset, false);
                default:
                    throw H5Exception(__LINE__, __FILE__, _("Bitfield is too big"));
            }

        case H5T_OPAQUE:
            return *new H5OpaqueData(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, stride, offset, dataOwner);
        case H5T_COMPOUND:
            return *new H5CompoundData(parent, totalSize, dataSize, ndims, dims, (char *)data, H5Tcopy(type), stride, offset, dataOwner);
        case H5T_REFERENCE:
            // TODO: virer le false
            return *new H5ReferenceData(parent, H5Tequal(type, H5T_STD_REF_DSETREG) ? H5R_DATASET_REGION : H5R_OBJECT, totalSize, dataSize, ndims, dims, (char *)data, stride, offset, dataOwner);
        case H5T_ENUM:
        {
            int nmembers = H5Tget_nmembers(type);
            std::string * names = nmembers > 0 ? new std::string[nmembers] : 0;

            for (int i = 0; i < nmembers; i++)
            {
                char * mname = H5Tget_member_name(type, i);
                names[i] = std::string(mname);
                //HDF5 version > 1.8.13
                //H5free_memory(mnale);

                //freed memory allocated by H5Tget_member_name trigger a segfault on Windows.
                //http://lists.hdfgroup.org/pipermail/hdf-forum_lists.hdfgroup.org/2014-September/008061.html
                //little memory leaks are better then crashs :x
#ifndef _MSC_VER
                free(mname);
#endif
            }

            if (H5Tget_sign(type) == H5T_SGN_NONE)
            {
                switch (dataSize)
                {
                    case 1:
                        return *new H5EnumData<unsigned char>(parent, totalSize, dataSize, ndims, dims, (unsigned char *)data, type, H5T_NATIVE_UCHAR, nmembers, names, stride, offset, dataOwner);
                    case 2:
                        return *new H5EnumData<unsigned short>(parent, totalSize, dataSize, ndims, dims, (unsigned short *)data, type, H5T_NATIVE_USHORT, nmembers, names, stride, offset, dataOwner);
                    case 4:
                        return *new H5EnumData<unsigned int>(parent, totalSize, dataSize, ndims, dims, (unsigned int *)data, type, H5T_NATIVE_UINT, nmembers, names, stride, offset, dataOwner);
#ifdef __SCILAB_INT64__
                    case 8:
                        return *new H5EnumData<unsigned long long>(parent, totalSize, dataSize, ndims, dims, (unsigned long long *)data, type, H5T_NATIVE_ULLONG, nmembers, names, stride, offset, dataOwner);
#endif
                }
            }
            else
            {
                switch (dataSize)
                {
                    case 1:
                        return *new H5EnumData<char>(parent, totalSize, dataSize, ndims, dims, (char *)data, type, H5T_NATIVE_CHAR, nmembers, names, stride, offset, dataOwner);
                    case 2:
                        return *new H5EnumData<short>(parent, totalSize, dataSize, ndims, dims, (short *)data, type, H5T_NATIVE_SHORT, nmembers, names, stride, offset, dataOwner);
                    case 4:
                        return *new H5EnumData<int>(parent, totalSize, dataSize, ndims, dims, (int *)data, type, H5T_NATIVE_INT, nmembers, names, stride, offset, dataOwner);
#ifdef __SCILAB_INT64__
                    case 8:
                        return *new H5EnumData<long long>(parent, totalSize, dataSize, ndims, dims, (long long *)data, type, H5T_NATIVE_LLONG, nmembers, names, stride, offset, dataOwner);
#endif
                }
            }

            return *new H5EnumData<char>(parent, totalSize, dataSize, ndims, dims, (char *)data, type, H5T_NATIVE_CHAR, nmembers, names, stride, offset, dataOwner);
        }
        case H5T_VLEN:
            return *new H5VlenData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data), type, stride, offset, dataOwner);
        case H5T_ARRAY:
            return *new H5ArrayData(parent, totalSize, dataSize, ndims, dims, static_cast<char *>(data), type, stride, offset, dataOwner);
        default:
            throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
    }

    throw H5Exception(__LINE__, __FILE__, _("Cannot get data from an unknown data type."));
}

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)
{
    hid_t nativeType = H5Tget_native_type(type, H5T_DIR_DEFAULT);
    hid_t _space = space < 0 ? (isAttribute ? H5Aget_space(obj) : H5Dget_space(obj)) : space;
    hsize_t size = H5Tget_size(nativeType);
    H5S_sel_type sel;
    hid_t targetspace;
    herr_t err;
    hsize_t * blockbuf = 0;
    bool hyperslab = false;
    bool isString = false;

    *totalSize = 1;
    if (H5Tget_class(nativeType) == H5T_STRING && !H5Tis_variable_str(nativeType))
    {
        // We have a C-string so it is null terminated
        size++;
        isString = true;
    }

    *dataSize = size;
    *ndims = H5Sget_simple_extent_dims(_space, 0, 0);
    *dims = new hsize_t[*ndims];

    if (isAttribute)
    {
        H5Sget_simple_extent_dims(_space, *dims, 0);
        for (unsigned int i = 0; i < *ndims; i++)
        {
            *totalSize *= (*dims)[i];
        }
    }
    else
    {
        sel = H5Sget_select_type(_space);
        switch (sel)
        {
            case H5S_SEL_NONE:
            case H5S_SEL_ALL:
                H5Sget_simple_extent_dims(_space, *dims, 0);
                for (unsigned int i = 0; i < *ndims; i++)
                {
                    *totalSize *= (*dims)[i];
                }
                break;
            case H5S_SEL_POINTS:
                break;
            case H5S_SEL_HYPERSLABS:
                for (unsigned int i = 0; i < *ndims; i++)
                {
                    (*dims)[i] = selectdims[i];
                    *totalSize *= (*dims)[i];
                }
                hyperslab = true;
        }
    }

    size *= *totalSize;

    if ((hsize_t)((size_t)size) != size)
    {
        H5Tclose(nativeType);
        if (space < 0)
        {
            H5Sclose(_space);
        }
        delete[] *dims;
        throw H5Exception(__LINE__, __FILE__, _("Memory to allocate is too big"));
    }

    try
    {
        if (isString)
        {
            *data = static_cast<void *>(new char[(size_t)size]());
        }
        else
        {
            // No need to initialize the array
            *data = static_cast<void *>(new char[(size_t)size]);
        }
    }
    catch (const std::bad_alloc & /*e*/)
    {
        H5Tclose(nativeType);
        if (space < 0)
        {
            H5Sclose(_space);
        }
        *data = 0;
        delete[] *dims;
        *dims = 0;
        throw H5Exception(__LINE__, __FILE__, _("Cannot allocate memory to get the data"));
    }

    if (!*data)
    {
        H5Tclose(nativeType);
        if (space < 0)
        {
            H5Sclose(_space);
        }
        delete[] *dims;
        *dims = 0;
        throw H5Exception(__LINE__, __FILE__, _("Cannot allocate memory to get the data"));
    }

    if (hyperslab)
    {
        targetspace =  H5Screate_simple((int) * ndims, *dims, 0);
        err = H5Dread(obj, nativeType, targetspace, _space, H5P_DEFAULT, *data);
        H5Sclose(targetspace);
    }
    else
    {
        if (isAttribute)
        {
            err = H5Aread(obj, nativeType, *data);
        }
        else
        {
            err = H5Dread(obj, nativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, *data);
        }
    }

    if (err < 0)
    {
        H5Tclose(nativeType);
        if (space < 0)
        {
            H5Sclose(_space);
        }
        delete[] static_cast<char *>(*data);
        *data = 0;
        delete[] *dims;
        *dims = 0;
        throw H5Exception(__LINE__, __FILE__, _("Cannot retrieve the data from the attribute"));
    }

    H5Tclose(nativeType);
    if (space < 0)
    {
        H5Sclose(_space);
    }
}
}