1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /*
15 * Module Info: This module contains the functionality for querying
16 * a "native" datatype for the H5T interface.
17 */
18
19 #include "H5Tmodule.h" /* This source code file is part of the H5T module */
20
21
22 #include "H5private.h" /* Generic Functions */
23 #include "H5CXprivate.h" /* API Contexts */
24 #include "H5Eprivate.h" /* Error handling */
25 #include "H5Iprivate.h" /* IDs */
26 #include "H5Pprivate.h" /* Property lists */
27 #include "H5MMprivate.h" /* Memory management */
28 #include "H5Tpkg.h" /* Datatypes */
29
30 /* Static local functions */
31 static H5T_t *H5T__get_native_type(H5T_t *dt, H5T_direction_t direction,
32 size_t *struct_align, size_t *offset, size_t *comp_size);
33 static H5T_t *H5T__get_native_integer(size_t prec, H5T_sign_t sign,
34 H5T_direction_t direction, size_t *struct_align, size_t *offset,
35 size_t *comp_size);
36 static H5T_t *H5T__get_native_float(size_t size, H5T_direction_t direction,
37 size_t *struct_align, size_t *offset, size_t *comp_size);
38 static H5T_t* H5T__get_native_bitfield(size_t prec, H5T_direction_t direction,
39 size_t *struct_align, size_t *offset, size_t *comp_size);
40 static herr_t H5T__cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size,
41 size_t nelems, size_t align, size_t *struct_align);
42
43
44
45 /*-------------------------------------------------------------------------
46 * Function: H5Tget_native_type
47 *
48 * Purpose: High-level API to return the native type of a datatype.
49 * The native type is chosen by matching the size and class of
50 * querried datatype from the following native premitive
51 * datatypes:
52 * H5T_NATIVE_CHAR H5T_NATIVE_UCHAR
53 * H5T_NATIVE_SHORT H5T_NATIVE_USHORT
54 * H5T_NATIVE_INT H5T_NATIVE_UINT
55 * H5T_NATIVE_LONG H5T_NATIVE_ULONG
56 * H5T_NATIVE_LLONG H5T_NATIVE_ULLONG
57 *
58 * H5T_NATIVE_FLOAT
59 * H5T_NATIVE_DOUBLE
60 * H5T_NATIVE_LDOUBLE
61 *
62 * Compound, array, enum, and VL types all choose among these
63 * types for theire members. Time, Bifield, Opaque, Reference
64 * types are only copy out.
65 *
66 * Return: Success: Returns the native data type if successful.
67 *
68 * Failure: negative
69 *
70 * Programmer: Raymond Lu
71 * Oct 3, 2002
72 *
73 *-------------------------------------------------------------------------
74 */
75 hid_t
H5Tget_native_type(hid_t type_id,H5T_direction_t direction)76 H5Tget_native_type(hid_t type_id, H5T_direction_t direction)
77 {
78 H5T_t *dt; /* Datatype to create native datatype from */
79 H5T_t *new_dt = NULL; /* Datatype for native datatype created */
80 size_t comp_size = 0; /* Compound datatype's size */
81 hid_t ret_value; /* Return value */
82
83 FUNC_ENTER_API(H5I_INVALID_HID)
84 H5TRACE2("i", "iTd", type_id, direction);
85
86 /* Check arguments */
87 if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
88 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a data type")
89 if(direction != H5T_DIR_DEFAULT && direction != H5T_DIR_ASCEND
90 && direction != H5T_DIR_DESCEND)
91 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not valid direction value")
92
93 /* Get the native type */
94 if(NULL == (new_dt = H5T__get_native_type(dt, direction, NULL, NULL, &comp_size)))
95 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "cannot retrieve native type")
96
97 /* Get an ID for the new type */
98 if((ret_value = H5I_register(H5I_DATATYPE, new_dt, TRUE)) < 0)
99 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register data type")
100
101 done:
102 /* Error cleanup */
103 if(ret_value < 0)
104 if(new_dt && H5T_close_real(new_dt) < 0)
105 HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release datatype")
106
107 FUNC_LEAVE_API(ret_value)
108 } /* end H5Tget_native_type() */
109
110
111 /*-------------------------------------------------------------------------
112 * Function: H5T__get_native_type
113 *
114 * Purpose: Returns the native type of a datatype.
115 *
116 * Return: Success: Returns the native data type if successful.
117 *
118 * Failure: negative
119 *
120 * Programmer: Raymond Lu
121 * Oct 3, 2002
122 *
123 *-------------------------------------------------------------------------
124 */
125 static H5T_t *
H5T__get_native_type(H5T_t * dtype,H5T_direction_t direction,size_t * struct_align,size_t * offset,size_t * comp_size)126 H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_align,
127 size_t *offset, size_t *comp_size)
128 {
129 H5T_t *dt; /* Datatype to make native */
130 H5T_t *super_type; /* Super type of VL, array and enum datatypes */
131 H5T_t *nat_super_type; /* Native form of VL, array & enum super datatype */
132 H5T_t *new_type = NULL; /* New native datatype */
133 H5T_t *memb_type = NULL; /* Datatype of member */
134 H5T_t **memb_list = NULL; /* List of compound member IDs */
135 size_t *memb_offset = NULL; /* List of member offsets in compound type, including member size and alignment */
136 char **comp_mname = NULL; /* List of member names in compound type */
137 char *memb_name = NULL; /* Enum's member name */
138 void *memb_value = NULL; /* Enum's member value */
139 void *tmp_memb_value = NULL; /* Enum's member value */
140 hsize_t *dims = NULL; /* Dimension sizes for array */
141 H5T_class_t h5_class; /* Class of datatype to make native */
142 size_t size; /* Size of datatype to make native */
143 size_t prec; /* Precision of datatype to make native */
144 int snmemb; /* Number of members in compound & enum types */
145 unsigned nmemb = 0; /* Number of members in compound & enum types */
146 unsigned u; /* Local index variable */
147 H5T_t *ret_value = NULL; /* Return value */
148
149 FUNC_ENTER_STATIC
150
151 HDassert(dtype);
152
153 if(H5T_NO_CLASS == (h5_class = H5T_get_class(dtype, FALSE)))
154 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class")
155
156 if(0 == (size = H5T_get_size(dtype)))
157 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid size")
158
159 switch(h5_class) {
160 case H5T_INTEGER:
161 {
162 H5T_sign_t sign; /* Signedness of integer type */
163
164 if(H5T_SGN_ERROR == (sign = H5T_get_sign(dtype)))
165 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid signess")
166
167 prec = dtype->shared->u.atomic.prec;
168
169 if(NULL == (ret_value = H5T__get_native_integer(prec, sign, direction, struct_align, offset, comp_size)))
170 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve integer type")
171 } /* end case */
172 break;
173
174 case H5T_FLOAT:
175 if(NULL == (ret_value = H5T__get_native_float(size, direction, struct_align, offset, comp_size)))
176 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
177
178 break;
179
180 case H5T_STRING:
181 if(NULL == (ret_value = H5T_copy(dtype, H5T_COPY_TRANSIENT)))
182 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
183
184 if(H5T_IS_VL_STRING(dtype->shared)) {
185 /* Update size, offset and compound alignment for parent. */
186 if(H5T__cmp_offset(comp_size, offset, sizeof(char *), (size_t)1, H5T_POINTER_COMP_ALIGN_g, struct_align) < 0)
187 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
188 } /* end if */
189 else {
190 /* Update size, offset and compound alignment for parent. */
191 if(H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_COMP_ALIGN_g, struct_align) < 0)
192 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
193 } /* end else */
194 break;
195
196 /* The time type will be supported in the future. Simply return "not supported"
197 * message for now.*/
198 case H5T_TIME:
199 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "time type is not supported yet")
200
201 case H5T_BITFIELD:
202 {
203 prec = dtype->shared->u.atomic.prec;
204
205 if(NULL == (ret_value = H5T__get_native_bitfield(prec, direction, struct_align, offset, comp_size)))
206 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve integer for bitfield type")
207 } /* end case */
208 break;
209
210 case H5T_OPAQUE:
211 if(NULL == (ret_value = H5T_copy(dtype, H5T_COPY_TRANSIENT)))
212 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
213
214 /* Update size, offset and compound alignment for parent. */
215 if(H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_COMP_ALIGN_g, struct_align) < 0)
216 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
217 break;
218
219 case H5T_REFERENCE:
220 {
221 size_t align;
222 size_t ref_size;
223 int not_equal;
224
225 if(NULL == (ret_value = H5T_copy(dtype, H5T_COPY_TRANSIENT)))
226 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
227
228 /* Decide if the data type is object or dataset region reference. */
229 if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_OBJ_g)))
230 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
231 not_equal = H5T_cmp(ret_value, dt, FALSE);
232
233 /* Update size, offset and compound alignment for parent. */
234 if(!not_equal) {
235 align = H5T_HOBJREF_COMP_ALIGN_g;
236 ref_size = sizeof(hobj_ref_t);
237 } /* end if */
238 else {
239 align = H5T_HDSETREGREF_COMP_ALIGN_g;
240 ref_size = sizeof(hdset_reg_ref_t);
241 } /* end else */
242
243 if(H5T__cmp_offset(comp_size, offset, ref_size, (size_t)1, align, struct_align) < 0)
244 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
245 } /* end case */
246 break;
247
248 case H5T_COMPOUND:
249 {
250 size_t children_size = 0;/* Total size of compound members */
251 size_t children_st_align = 0; /* The max alignment among compound members. This'll be the compound alignment */
252
253 if((snmemb = H5T_get_nmembers(dtype)) <= 0)
254 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "compound data type doesn't have any member")
255 H5_CHECKED_ASSIGN(nmemb, unsigned, snmemb, int);
256
257 if(NULL == (memb_list = (H5T_t **)H5MM_calloc(nmemb * sizeof(H5T_t *))))
258 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
259 if(NULL == (memb_offset = (size_t *)H5MM_calloc(nmemb * sizeof(size_t))))
260 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
261 if(NULL == (comp_mname = (char **)H5MM_calloc(nmemb * sizeof(char *))))
262 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
263
264 /* Construct child compound type and retrieve a list of their IDs, offsets, total size, and alignment for compound type. */
265 for(u = 0; u < nmemb; u++) {
266 if(NULL == (memb_type = H5T_get_member_type(dtype, u, H5T_COPY_TRANSIENT)))
267 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "member type retrieval failed")
268
269 if(NULL == (comp_mname[u] = H5T__get_member_name(dtype, u)))
270 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "member type retrieval failed")
271
272 if(NULL == (memb_list[u] = H5T__get_native_type(memb_type, direction, &children_st_align, &(memb_offset[u]), &children_size)))
273 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "member identifier retrieval failed")
274
275 if(H5T_close_real(memb_type) < 0)
276 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot close datatype")
277 } /* end for */
278
279 /* The alignment for whole compound type */
280 if(children_st_align && children_size % children_st_align)
281 children_size += children_st_align - (children_size % children_st_align);
282
283 /* Construct new compound type based on native type */
284 if(NULL == (new_type = H5T__create(H5T_COMPOUND, children_size)))
285 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot create a compound type")
286
287 /* Insert members for the new compound type */
288 for(u = 0; u < nmemb; u++)
289 if(H5T__insert(new_type, comp_mname[u], memb_offset[u], memb_list[u]) < 0)
290 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot insert member to compound datatype")
291
292 /* Update size, offset and compound alignment for parent in the case of
293 * nested compound type. The alignment for a compound type as one field in
294 * a compound type is the biggest compound alignment among all its members.
295 * e.g. in the structure
296 * typedef struct s1 {
297 * char c;
298 * int i;
299 * s2 st;
300 * unsigned long long l;
301 * } s1;
302 * typedef struct s2 {
303 * short c2;
304 * long l2;
305 * long long ll2;
306 * } s2;
307 * The alignment for ST in S1 is the biggest structure alignment of all the
308 * members of S2, which is probably the LL2 of 'long long'. -SLU 2010/4/28
309 */
310 if(H5T__cmp_offset(comp_size, offset, children_size, (size_t)1, children_st_align, struct_align) < 0)
311 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
312
313 /* Close member data type */
314 for(u = 0; u < nmemb; u++) {
315 if(H5T_close_real(memb_list[u]) < 0)
316 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot close datatype")
317
318 /* Free member names in list */
319 comp_mname[u] = (char *)H5MM_xfree(comp_mname[u]);
320 } /* end for */
321
322 /* Free lists for members */
323 memb_list = (H5T_t **)H5MM_xfree(memb_list);
324 memb_offset = (size_t *)H5MM_xfree(memb_offset);
325 comp_mname = (char **)H5MM_xfree(comp_mname);
326
327 ret_value = new_type;
328 } /* end case */
329 break;
330
331 case H5T_ENUM:
332 {
333 H5T_path_t *tpath; /* Type conversion info */
334 hid_t super_type_id, nat_super_type_id;
335
336 /* Don't need to do anything special for alignment, offset since the ENUM type usually is integer. */
337
338 /* Retrieve base type for enumerated type */
339 if(NULL == (super_type = H5T_get_super(dtype)))
340 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to get base type for enumerate type")
341 if(NULL == (nat_super_type = H5T__get_native_type(super_type, direction, struct_align, offset, comp_size)))
342 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "base native type retrieval failed")
343
344 if((super_type_id = H5I_register(H5I_DATATYPE, super_type, FALSE)) < 0)
345 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot register datatype")
346 if((nat_super_type_id = H5I_register(H5I_DATATYPE, nat_super_type, FALSE)) < 0)
347 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot register datatype")
348
349 /* Allocate room for the enum values */
350 if(NULL == (tmp_memb_value = H5MM_calloc(H5T_get_size(super_type))))
351 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
352 if(NULL == (memb_value = H5MM_calloc(H5T_get_size(nat_super_type))))
353 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
354
355 /* Construct new enum type based on native type */
356 if(NULL == (new_type = H5T__enum_create(nat_super_type)))
357 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to create enum type")
358
359 /* Find the conversion function */
360 if(NULL == (tpath = H5T_path_find(super_type, nat_super_type)))
361 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and dst data types")
362
363 /* Retrieve member info and insert members into new enum type */
364 if((snmemb = H5T_get_nmembers(dtype)) <= 0)
365 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "enumerate data type doesn't have any member")
366 H5_CHECKED_ASSIGN(nmemb, unsigned, snmemb, int);
367 for(u = 0; u < nmemb; u++) {
368 if(NULL == (memb_name = H5T__get_member_name(dtype, u)))
369 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member name")
370 if(H5T__get_member_value(dtype, u, tmp_memb_value) < 0)
371 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member value")
372 HDmemcpy(memb_value, tmp_memb_value, H5T_get_size(super_type));
373
374 if(H5T_convert(tpath, super_type_id, nat_super_type_id, (size_t)1, (size_t)0, (size_t)0, memb_value, NULL) < 0)
375 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get member value")
376
377 if(H5T__enum_insert(new_type, memb_name, memb_value) < 0)
378 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot insert member")
379 memb_name = (char *)H5MM_xfree(memb_name);
380 }
381 memb_value = H5MM_xfree(memb_value);
382 tmp_memb_value = H5MM_xfree(tmp_memb_value);
383
384 /* Close base type */
385 if(H5I_dec_app_ref(nat_super_type_id) < 0)
386 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot close datatype")
387 /* Close super type */
388 if(H5I_dec_app_ref(super_type_id) < 0)
389 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot close datatype")
390
391 ret_value = new_type;
392 } /* end case */
393 break;
394
395 case H5T_ARRAY:
396 {
397 int sarray_rank; /* Array's rank */
398 unsigned array_rank; /* Array's rank */
399 hsize_t nelems = 1;
400 size_t super_offset = 0;
401 size_t super_size = 0;
402 size_t super_align = 0;
403
404 /* Retrieve dimension information for array data type */
405 if((sarray_rank = H5T__get_array_ndims(dtype)) <= 0)
406 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get dimension rank")
407 H5_CHECKED_ASSIGN(array_rank, unsigned, sarray_rank, int);
408 if(NULL == (dims = (hsize_t*)H5MM_malloc(array_rank * sizeof(hsize_t))))
409 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory")
410 if(H5T__get_array_dims(dtype, dims) < 0)
411 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot get dimension size")
412
413 /* Retrieve base type for array type */
414 if(NULL == (super_type = H5T_get_super(dtype)))
415 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to get parent type for array type")
416 if(NULL == (nat_super_type = H5T__get_native_type(super_type, direction, &super_align,
417 &super_offset, &super_size)))
418 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "parent native type retrieval failed")
419
420 /* Close super type */
421 if(H5T_close_real(super_type) < 0)
422 HGOTO_ERROR(H5E_ARGS, H5E_CLOSEERROR, NULL, "cannot close datatype")
423
424 /* Create a new array type based on native type */
425 if(NULL == (new_type = H5T__array_create(nat_super_type, array_rank, dims)))
426 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to create array type")
427
428 /* Close base type */
429 if(H5T_close_real(nat_super_type) < 0)
430 HGOTO_ERROR(H5E_ARGS, H5E_CLOSEERROR, NULL, "cannot close datatype")
431
432 for(u = 0; u < array_rank; u++)
433 nelems *= dims[u];
434 H5_CHECK_OVERFLOW(nelems, hsize_t, size_t);
435 if(H5T__cmp_offset(comp_size, offset, super_size, (size_t)nelems, super_align, struct_align) < 0)
436 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
437
438 dims = (hsize_t *)H5MM_xfree(dims);
439
440 ret_value = new_type;
441 } /* end case */
442 break;
443
444 case H5T_VLEN:
445 {
446 size_t vl_align = 0;
447 size_t vl_size = 0;
448 size_t super_size = 0;
449
450 /* Retrieve base type for array type */
451 if(NULL == (super_type = H5T_get_super(dtype)))
452 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to get parent type for VL type")
453 /* Don't need alignment, offset information if this VL isn't a field of compound type. If it
454 * is, go to a few steps below to compute the information directly. */
455 if(NULL == (nat_super_type = H5T__get_native_type(super_type, direction, NULL, NULL, &super_size)))
456 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "parent native type retrieval failed")
457
458 /* Close super type */
459 if(H5T_close_real(super_type) < 0)
460 HGOTO_ERROR(H5E_ARGS, H5E_CLOSEERROR, NULL, "cannot close datatype")
461
462 /* Create a new array type based on native type */
463 if(NULL == (new_type = H5T__vlen_create(nat_super_type)))
464 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to create VL type")
465
466 /* Close base type */
467 if(H5T_close_real(nat_super_type) < 0)
468 HGOTO_ERROR(H5E_ARGS, H5E_CLOSEERROR, NULL, "cannot close datatype")
469
470 /* Update size, offset and compound alignment for parent compound type directly. */
471 vl_align = H5T_HVL_COMP_ALIGN_g;
472 vl_size = sizeof(hvl_t);
473
474 if(H5T__cmp_offset(comp_size, offset, vl_size, (size_t)1, vl_align, struct_align) < 0)
475 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
476
477 ret_value = new_type;
478 } /* end case */
479 break;
480
481 case H5T_NO_CLASS:
482 case H5T_NCLASSES:
483 default:
484 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "data type doesn't match any native type")
485 } /* end switch */
486
487 done:
488 /* Error cleanup */
489 if(NULL == ret_value) {
490 if(new_type)
491 if(H5T_close_real(new_type) < 0)
492 HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, NULL, "unable to release datatype")
493
494 /* Free lists for members */
495 if(memb_list) {
496 for(u = 0; u < nmemb; u++)
497 if(memb_list[u] && H5T_close_real(memb_list[u]) < 0)
498 HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot close datatype")
499
500 memb_list = (H5T_t **)H5MM_xfree(memb_list);
501 } /* end if */
502 memb_offset = (size_t *)H5MM_xfree(memb_offset);
503 if(comp_mname) {
504 for(u = 0; u < nmemb; u++)
505 if(comp_mname[u])
506 H5MM_xfree(comp_mname[u]);
507 comp_mname = (char **)H5MM_xfree(comp_mname);
508 } /* end if */
509 memb_name = (char *)H5MM_xfree(memb_name);
510 memb_value = H5MM_xfree(memb_value);
511 tmp_memb_value = H5MM_xfree(tmp_memb_value);
512 dims = (hsize_t *)H5MM_xfree(dims);
513 } /* end if */
514
515 FUNC_LEAVE_NOAPI(ret_value)
516 } /* end H5T__get_native_type() */
517
518
519 /*-------------------------------------------------------------------------
520 * Function: H5T__get_native_integer
521 *
522 * Purpose: Returns the native integer type of a datatype.
523 *
524 * Return: Success: Returns the native data type if successful.
525 *
526 * Failure: negative
527 *
528 * Programmer: Raymond Lu
529 * Oct 3, 2002
530 *
531 *-------------------------------------------------------------------------
532 */
533 static H5T_t *
H5T__get_native_integer(size_t prec,H5T_sign_t sign,H5T_direction_t direction,size_t * struct_align,size_t * offset,size_t * comp_size)534 H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction,
535 size_t *struct_align, size_t *offset, size_t *comp_size)
536 {
537 H5T_t *dt; /* Appropriate native datatype to copy */
538 hid_t tid = (-1); /* Datatype ID of appropriate native datatype */
539 size_t align = 0; /* Alignment necessary for native datatype */
540 size_t native_size = 0; /* Datatype size of the native type */
541 enum match_type { /* The different kinds of integers we can match */
542 H5T_NATIVE_INT_MATCH_CHAR,
543 H5T_NATIVE_INT_MATCH_SHORT,
544 H5T_NATIVE_INT_MATCH_INT,
545 H5T_NATIVE_INT_MATCH_LONG,
546 H5T_NATIVE_INT_MATCH_LLONG,
547 H5T_NATIVE_INT_MATCH_UNKNOWN
548 } match = H5T_NATIVE_INT_MATCH_UNKNOWN;
549 H5T_t *ret_value = NULL; /* Return value */
550
551 FUNC_ENTER_STATIC
552
553 if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) {
554 if(prec <= H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g))) {
555 match = H5T_NATIVE_INT_MATCH_CHAR;
556 native_size = sizeof(char);
557 } else if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_SHORT_g))) {
558 match = H5T_NATIVE_INT_MATCH_SHORT;
559 native_size = sizeof(short);
560 } else if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_INT_g))) {
561 match = H5T_NATIVE_INT_MATCH_INT;
562 native_size = sizeof(int);
563 } else if(prec <= H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_LONG_g))) {
564 match = H5T_NATIVE_INT_MATCH_LONG;
565 native_size = sizeof(long);
566 } else if(prec <= H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_LLONG_g))) {
567 match = H5T_NATIVE_INT_MATCH_LLONG;
568 native_size = sizeof(long long);
569 } else { /* If no native type matches the querried datatype, simply choose the type of biggest size. */
570 match = H5T_NATIVE_INT_MATCH_LLONG;
571 native_size = sizeof(long long);
572 }
573 } else if(direction == H5T_DIR_DESCEND) {
574 if(prec > H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_LONG_g))) {
575 match = H5T_NATIVE_INT_MATCH_LLONG;
576 native_size = sizeof(long long);
577 } else if(prec > H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_INT_g))) {
578 match = H5T_NATIVE_INT_MATCH_LONG;
579 native_size = sizeof(long);
580 } else if(prec > H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_SHORT_g))) {
581 match = H5T_NATIVE_INT_MATCH_INT;
582 native_size = sizeof(int);
583 } else if(prec > H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g))) {
584 match = H5T_NATIVE_INT_MATCH_SHORT;
585 native_size = sizeof(short);
586 } else {
587 match = H5T_NATIVE_INT_MATCH_CHAR;
588 native_size = sizeof(char);
589 }
590 }
591
592 /* Set the appropriate native datatype information */
593 switch(match) {
594 case H5T_NATIVE_INT_MATCH_CHAR:
595 if(sign == H5T_SGN_2)
596 tid = H5T_NATIVE_SCHAR;
597 else
598 tid = H5T_NATIVE_UCHAR;
599
600 align = H5T_NATIVE_SCHAR_COMP_ALIGN_g;
601 break;
602
603 case H5T_NATIVE_INT_MATCH_SHORT:
604 if(sign == H5T_SGN_2)
605 tid = H5T_NATIVE_SHORT;
606 else
607 tid = H5T_NATIVE_USHORT;
608 align = H5T_NATIVE_SHORT_COMP_ALIGN_g;
609 break;
610
611 case H5T_NATIVE_INT_MATCH_INT:
612 if(sign == H5T_SGN_2)
613 tid = H5T_NATIVE_INT;
614 else
615 tid = H5T_NATIVE_UINT;
616
617 align = H5T_NATIVE_INT_COMP_ALIGN_g;
618 break;
619
620 case H5T_NATIVE_INT_MATCH_LONG:
621 if(sign == H5T_SGN_2)
622 tid = H5T_NATIVE_LONG;
623 else
624 tid = H5T_NATIVE_ULONG;
625
626 align = H5T_NATIVE_LONG_COMP_ALIGN_g;
627 break;
628
629 case H5T_NATIVE_INT_MATCH_LLONG:
630 if(sign == H5T_SGN_2)
631 tid = H5T_NATIVE_LLONG;
632 else
633 tid = H5T_NATIVE_ULLONG;
634
635 align = H5T_NATIVE_LLONG_COMP_ALIGN_g;
636 break;
637
638 case H5T_NATIVE_INT_MATCH_UNKNOWN:
639 default:
640 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "Unknown native integer match")
641 } /* end switch */
642
643 /* Create new native type */
644 HDassert(tid >= 0);
645 if(NULL == (dt = (H5T_t *)H5I_object(tid)))
646 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
647
648 if(NULL == (ret_value = H5T_copy(dt, H5T_COPY_TRANSIENT)))
649 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot copy type")
650
651 /* compute size and offset of compound type member. */
652 if(H5T__cmp_offset(comp_size, offset, native_size, (size_t)1, align, struct_align) < 0)
653 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
654
655 done:
656 FUNC_LEAVE_NOAPI(ret_value)
657 } /* end H5T__get_native_integer() */
658
659
660 /*-------------------------------------------------------------------------
661 * Function: H5T__get_native_float
662 *
663 * Purpose: Returns the native floatt type of a datatype.
664 *
665 * Return: Success: Returns the native data type if successful.
666 *
667 * Failure: negative
668 *
669 * Programmer: Raymond Lu
670 * Oct 3, 2002
671 *
672 *-------------------------------------------------------------------------
673 */
674 static H5T_t*
H5T__get_native_float(size_t size,H5T_direction_t direction,size_t * struct_align,size_t * offset,size_t * comp_size)675 H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_align,
676 size_t *offset, size_t *comp_size)
677 {
678 H5T_t *dt=NULL; /* Appropriate native datatype to copy */
679 hid_t tid=(-1); /* Datatype ID of appropriate native datatype */
680 size_t align=0; /* Alignment necessary for native datatype */
681 size_t native_size=0; /* Datatype size of the native type */
682 enum match_type { /* The different kinds of floating point types we can match */
683 H5T_NATIVE_FLOAT_MATCH_FLOAT,
684 H5T_NATIVE_FLOAT_MATCH_DOUBLE,
685 #if H5_SIZEOF_LONG_DOUBLE !=0
686 H5T_NATIVE_FLOAT_MATCH_LDOUBLE,
687 #endif
688 H5T_NATIVE_FLOAT_MATCH_UNKNOWN
689 } match=H5T_NATIVE_FLOAT_MATCH_UNKNOWN;
690 H5T_t *ret_value = NULL; /* Return value */
691
692 FUNC_ENTER_STATIC
693
694 HDassert(size>0);
695
696 if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) {
697 if(size<=sizeof(float)) {
698 match=H5T_NATIVE_FLOAT_MATCH_FLOAT;
699 native_size = sizeof(float);
700 }
701 else if(size<=sizeof(double)) {
702 match=H5T_NATIVE_FLOAT_MATCH_DOUBLE;
703 native_size = sizeof(double);
704 }
705 #if H5_SIZEOF_LONG_DOUBLE !=0
706 else if(size<=sizeof(long double)) {
707 match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE;
708 native_size = sizeof(long double);
709 }
710 #endif
711 else { /* If not match, return the biggest datatype */
712 #if H5_SIZEOF_LONG_DOUBLE !=0
713 match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE;
714 native_size = sizeof(long double);
715 #else
716 match=H5T_NATIVE_FLOAT_MATCH_DOUBLE;
717 native_size = sizeof(double);
718 #endif
719 }
720 } else {
721 #if H5_SIZEOF_LONG_DOUBLE !=0
722 if(size>sizeof(double)) {
723 match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE;
724 native_size = sizeof(long double);
725 }
726 else if(size>sizeof(float)) {
727 match=H5T_NATIVE_FLOAT_MATCH_DOUBLE;
728 native_size = sizeof(double);
729 }
730 else {
731 match=H5T_NATIVE_FLOAT_MATCH_FLOAT;
732 native_size = sizeof(float);
733 }
734 #else
735 if(size>sizeof(float)) {
736 match=H5T_NATIVE_FLOAT_MATCH_DOUBLE;
737 native_size = sizeof(double);
738 }
739 else {
740 match=H5T_NATIVE_FLOAT_MATCH_FLOAT;
741 native_size = sizeof(float);
742 }
743 #endif
744 }
745
746 /* Set the appropriate native floating point information */
747 switch(match) {
748 case H5T_NATIVE_FLOAT_MATCH_FLOAT:
749 tid = H5T_NATIVE_FLOAT;
750 align = H5T_NATIVE_FLOAT_COMP_ALIGN_g;
751 break;
752
753 case H5T_NATIVE_FLOAT_MATCH_DOUBLE:
754 tid = H5T_NATIVE_DOUBLE;
755 align = H5T_NATIVE_DOUBLE_COMP_ALIGN_g;
756 break;
757
758 #if H5_SIZEOF_LONG_DOUBLE !=0
759 case H5T_NATIVE_FLOAT_MATCH_LDOUBLE:
760 tid = H5T_NATIVE_LDOUBLE;
761 align = H5T_NATIVE_LDOUBLE_COMP_ALIGN_g;
762 break;
763 #endif
764 case H5T_NATIVE_FLOAT_MATCH_UNKNOWN:
765 default:
766 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "Unknown native floating-point match")
767 } /* end switch */
768
769 /* Create new native type */
770 HDassert(tid>=0);
771 if(NULL==(dt=(H5T_t *)H5I_object(tid)))
772 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
773 if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL)
774 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type")
775
776 /* compute offset of compound type member. */
777 if(H5T__cmp_offset(comp_size, offset, native_size, (size_t)1, align, struct_align)<0)
778 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
779
780 done:
781 FUNC_LEAVE_NOAPI(ret_value)
782 } /* end H5T__get_native_float() */
783
784
785 /*-------------------------------------------------------------------------
786 * Function: H5T__get_native_bitfield
787 *
788 * Purpose: Returns the native bitfield type of a datatype. Bitfield
789 * is similar to unsigned integer.
790 *
791 * Return: Success: Returns the native data type if successful.
792 *
793 * Failure: negative
794 *
795 * Programmer: Raymond Lu
796 * 1 December 2009
797 *
798 *-------------------------------------------------------------------------
799 */
800 static H5T_t*
H5T__get_native_bitfield(size_t prec,H5T_direction_t direction,size_t * struct_align,size_t * offset,size_t * comp_size)801 H5T__get_native_bitfield(size_t prec, H5T_direction_t direction,
802 size_t *struct_align, size_t *offset, size_t *comp_size)
803 {
804 H5T_t *dt; /* Appropriate native datatype to copy */
805 hid_t tid=(-1); /* Datatype ID of appropriate native datatype */
806 size_t align=0; /* Alignment necessary for native datatype */
807 size_t native_size=0; /* Datatype size of the native type */
808 H5T_t *ret_value = NULL; /* Return value */
809
810 FUNC_ENTER_STATIC
811
812 if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) {
813 if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B8_g))) {
814 tid = H5T_NATIVE_B8;
815 native_size = 1;
816 align = H5T_NATIVE_UINT8_ALIGN_g;
817 } else if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B16_g))) {
818 tid = H5T_NATIVE_B16;
819 native_size = 2;
820 align = H5T_NATIVE_UINT16_ALIGN_g;
821 } else if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B32_g))) {
822 tid = H5T_NATIVE_B32;
823 native_size = 4;
824 align = H5T_NATIVE_UINT32_ALIGN_g;
825 } else if(prec<=H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B64_g))) {
826 tid = H5T_NATIVE_B64;
827 native_size = 8;
828 align = H5T_NATIVE_UINT64_ALIGN_g;
829 } else { /* If no native type matches the querried datatype, simply choose the type of biggest size. */
830 tid = H5T_NATIVE_B64;
831 native_size = 8;
832 align = H5T_NATIVE_UINT64_ALIGN_g;
833 }
834 } else if(direction == H5T_DIR_DESCEND) {
835 if(prec>H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B32_g))) {
836 tid = H5T_NATIVE_B64;
837 native_size = 8;
838 align = H5T_NATIVE_UINT64_ALIGN_g;
839 } else if(prec>H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B16_g))) {
840 tid = H5T_NATIVE_B32;
841 native_size = 4;
842 align = H5T_NATIVE_UINT32_ALIGN_g;
843 } else if(prec>H5T_get_precision((H5T_t *)H5I_object(H5T_NATIVE_B8_g))) {
844 tid = H5T_NATIVE_B16;
845 native_size = 2;
846 align = H5T_NATIVE_UINT16_ALIGN_g;
847 } else {
848 tid = H5T_NATIVE_B8;
849 native_size = 1;
850 align = H5T_NATIVE_UINT8_ALIGN_g;
851 }
852 }
853
854 /* Create new native type */
855 HDassert(tid>=0);
856 if(NULL==(dt=(H5T_t *)H5I_object(tid)))
857 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type")
858
859 if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL)
860 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot copy type")
861
862 /* compute size and offset of compound type member. */
863 if(H5T__cmp_offset(comp_size, offset, native_size, (size_t)1, align, struct_align)<0)
864 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset")
865
866 done:
867 FUNC_LEAVE_NOAPI(ret_value)
868 } /* end H5T__get_native_bitfield() */
869
870
871 /*-------------------------------------------------------------------------
872 * Function: H5T__cmp_offset
873 *
874 * Purpose: This function is only for convenience. It computes the
875 * compound type size, offset of the member being considered
876 * and the alignment for the whole compound type.
877 *
878 * Return: Success: Non-negative value.
879 *
880 * Failure: Negative value.
881 *
882 * Programmer: Raymond Lu
883 * December 10, 2002
884 *
885 *-------------------------------------------------------------------------
886 */
887 static herr_t
H5T__cmp_offset(size_t * comp_size,size_t * offset,size_t elem_size,size_t nelems,size_t align,size_t * struct_align)888 H5T__cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size,
889 size_t nelems, size_t align, size_t *struct_align)
890 {
891 FUNC_ENTER_STATIC_NOERR
892
893 if(offset && comp_size) {
894 if(align > 1 && *comp_size % align) {
895 /* Add alignment value */
896 *offset = *comp_size + (align - *comp_size % align);
897 *comp_size += (align - *comp_size % align);
898 } /* end if */
899 else
900 *offset = *comp_size;
901
902 /* compute size of compound type member. */
903 *comp_size += nelems* elem_size;
904 } /* end if */
905
906 if(struct_align && *struct_align < align)
907 *struct_align = align;
908
909 FUNC_LEAVE_NOAPI(SUCCEED)
910 } /* end H5T__cmp_offset() */
911
912