Coverage Report

Created: 2026-03-04 00:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5T.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Module Info: This module contains most of the "core" functionality of
15
 *      the H5T interface, including the API initialization code, etc.
16
 *      Many routines that are infrequently used, or are specialized for
17
 *      one particular datatype class are in another module.
18
 */
19
20
/****************/
21
/* Module Setup */
22
/****************/
23
24
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
25
26
/***********/
27
/* Headers */
28
/***********/
29
#include "H5private.h"   /* Generic Functions                        */
30
#include "H5ACprivate.h" /* Metadata cache                           */
31
#include "H5CXprivate.h" /* API Contexts                             */
32
#include "H5Dprivate.h"  /* Datasets                                 */
33
#include "H5Eprivate.h"  /* Error handling                           */
34
#include "H5ESprivate.h" /* Event Sets                               */
35
#include "H5Fprivate.h"  /* Files                                    */
36
#include "H5FLprivate.h" /* Free Lists                               */
37
#include "H5FOprivate.h" /* File objects                             */
38
#include "H5Gprivate.h"  /* Groups                                   */
39
#include "H5Iprivate.h"  /* IDs                                      */
40
#include "H5MMprivate.h" /* Memory management                        */
41
#include "H5Pprivate.h"  /* Property lists                           */
42
#include "H5Tpkg.h"      /* Datatypes                                */
43
#include "H5VLprivate.h" /* Virtual Object Layer                     */
44
#include "H5VMprivate.h" /* Vectors and arrays                       */
45
46
/* Datatype conversion functions */
47
#include "H5Tconv_integer.h"
48
#include "H5Tconv_float.h"
49
#include "H5Tconv_string.h"
50
#include "H5Tconv_bitfield.h"
51
#include "H5Tconv_compound.h"
52
#include "H5Tconv_reference.h"
53
#include "H5Tconv_enum.h"
54
#include "H5Tconv_vlen.h"
55
#include "H5Tconv_array.h"
56
#include "H5Tconv_complex.h"
57
58
/****************/
59
/* Local Macros */
60
/****************/
61
62
2
#define H5T_ENCODE_VERSION 0
63
64
/*
65
 * The default number of slots allocated in the
66
 * datatype conversion path table.
67
 */
68
1
#define H5T_DEF_CONV_TABLE_SLOTS 128
69
70
/*
71
 * Type initialization macros
72
 *
73
 * These use the "template macro" technique to reduce the amount of gratuitous
74
 * duplicated code when initializing the datatypes for the library.  The main
75
 * template macro is the H5T_INIT_TYPE() macro below.
76
 *
77
 */
78
79
/* Define the code template for bitfields for the "GUTS" in the H5T_INIT_TYPE macro */
80
#define H5T_INIT_TYPE_BITFIELD_CORE                                                                          \
81
12
    {                                                                                                        \
82
12
        dt->shared->type = H5T_BITFIELD;                                                                     \
83
12
    }
84
85
#define H5T_INIT_TYPE_BITFIELD_COMMON(ENDIANNESS)                                                            \
86
8
    {                                                                                                        \
87
8
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
88
8
        H5T_INIT_TYPE_BITFIELD_CORE;                                                                         \
89
8
    }
90
91
#define H5T_INIT_TYPE_BITFIELDLE_CORE                                                                        \
92
4
    {                                                                                                        \
93
4
        H5T_INIT_TYPE_BITFIELD_COMMON(H5T_ORDER_LE)                                                          \
94
4
    }
95
96
#define H5T_INIT_TYPE_BITFIELDBE_CORE                                                                        \
97
4
    {                                                                                                        \
98
4
        H5T_INIT_TYPE_BITFIELD_COMMON(H5T_ORDER_BE)                                                          \
99
4
    }
100
101
/* Define the code template for times for the "GUTS" in the H5T_INIT_TYPE macro */
102
#define H5T_INIT_TYPE_TIME_CORE                                                                              \
103
4
    {                                                                                                        \
104
4
        dt->shared->type = H5T_TIME;                                                                         \
105
4
    }
106
107
/* Define the code template for types which reset the offset for the "GUTS" in the H5T_INIT_TYPE macro */
108
#define H5T_INIT_TYPE_OFFSET_CORE                                                                            \
109
5
    {                                                                                                        \
110
5
        dt->shared->u.atomic.offset = 0;                                                                     \
111
5
    }
112
113
/* Define common code for all numeric types (floating-point & int, signed & unsigned) */
114
#define H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
115
41
    {                                                                                                        \
116
41
        dt->shared->u.atomic.order   = ENDIANNESS;                                                           \
117
41
        dt->shared->u.atomic.offset  = 0;                                                                    \
118
41
        dt->shared->u.atomic.lsb_pad = H5T_PAD_ZERO;                                                         \
119
41
        dt->shared->u.atomic.msb_pad = H5T_PAD_ZERO;                                                         \
120
41
    }
121
122
/* Define the code templates for standard 16-bit floats for the "GUTS" in the H5T_INIT_TYPE macro */
123
#define H5T_INIT_TYPE_FLOAT16_COMMON(ENDIANNESS)                                                             \
124
2
    {                                                                                                        \
125
2
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
126
2
        dt->shared->u.atomic.u.f.sign  = 15;                                                                 \
127
2
        dt->shared->u.atomic.u.f.epos  = 10;                                                                 \
128
2
        dt->shared->u.atomic.u.f.esize = 5;                                                                  \
129
2
        dt->shared->u.atomic.u.f.ebias = 0xf;                                                                \
130
2
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
131
2
        dt->shared->u.atomic.u.f.msize = 10;                                                                 \
132
2
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
133
2
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
134
2
    }
135
136
#define H5T_INIT_TYPE_FLOAT16LE_CORE                                                                         \
137
1
    {                                                                                                        \
138
1
        H5T_INIT_TYPE_FLOAT16_COMMON(H5T_ORDER_LE)                                                           \
139
1
    }
140
141
#define H5T_INIT_TYPE_FLOAT16BE_CORE                                                                         \
142
1
    {                                                                                                        \
143
1
        H5T_INIT_TYPE_FLOAT16_COMMON(H5T_ORDER_BE)                                                           \
144
1
    }
145
146
/* Define the code templates for standard 16-bit bfloat16 floats for the "GUTS" in the H5T_INIT_TYPE macro */
147
#define H5T_INIT_TYPE_BFLOAT16_COMMON(ENDIANNESS)                                                            \
148
2
    {                                                                                                        \
149
2
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
150
2
        dt->shared->u.atomic.u.f.sign  = 15;                                                                 \
151
2
        dt->shared->u.atomic.u.f.epos  = 7;                                                                  \
152
2
        dt->shared->u.atomic.u.f.esize = 8;                                                                  \
153
2
        dt->shared->u.atomic.u.f.ebias = 0x7f;                                                               \
154
2
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
155
2
        dt->shared->u.atomic.u.f.msize = 7;                                                                  \
156
2
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
157
2
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
158
2
    }
159
160
#define H5T_INIT_TYPE_BFLOAT16LE_CORE                                                                        \
161
1
    {                                                                                                        \
162
1
        H5T_INIT_TYPE_BFLOAT16_COMMON(H5T_ORDER_LE)                                                          \
163
1
    }
164
165
#define H5T_INIT_TYPE_BFLOAT16BE_CORE                                                                        \
166
1
    {                                                                                                        \
167
1
        H5T_INIT_TYPE_BFLOAT16_COMMON(H5T_ORDER_BE)                                                          \
168
1
    }
169
170
/* Define the code templates for standard FP8 E4M3 8-bit floats for the "GUTS" in the H5T_INIT_TYPE macro */
171
#define H5T_INIT_TYPE_FLOAT8E4M3_CORE                                                                        \
172
1
    {                                                                                                        \
173
1
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_LE) /* Simply pick LE here */                                     \
174
1
        dt->shared->u.atomic.u.f.sign  = 7;                                                                  \
175
1
        dt->shared->u.atomic.u.f.epos  = 3;                                                                  \
176
1
        dt->shared->u.atomic.u.f.esize = 4;                                                                  \
177
1
        dt->shared->u.atomic.u.f.ebias = 0x7;                                                                \
178
1
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
179
1
        dt->shared->u.atomic.u.f.msize = 3;                                                                  \
180
1
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
181
1
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
182
1
    }
183
184
/* Define the code templates for standard FP8 E5M2 8-bit floats for the "GUTS" in the H5T_INIT_TYPE macro */
185
#define H5T_INIT_TYPE_FLOAT8E5M2_CORE                                                                        \
186
1
    {                                                                                                        \
187
1
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_LE) /* Simply pick LE here */                                     \
188
1
        dt->shared->u.atomic.u.f.sign  = 7;                                                                  \
189
1
        dt->shared->u.atomic.u.f.epos  = 2;                                                                  \
190
1
        dt->shared->u.atomic.u.f.esize = 5;                                                                  \
191
1
        dt->shared->u.atomic.u.f.ebias = 0xf;                                                                \
192
1
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
193
1
        dt->shared->u.atomic.u.f.msize = 2;                                                                  \
194
1
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
195
1
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
196
1
    }
197
198
/* Define the code templates for standard floats for the "GUTS" in the H5T_INIT_TYPE macro */
199
#define H5T_INIT_TYPE_FLOAT_COMMON(ENDIANNESS)                                                               \
200
2
    {                                                                                                        \
201
2
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
202
2
        dt->shared->u.atomic.u.f.sign  = 31;                                                                 \
203
2
        dt->shared->u.atomic.u.f.epos  = 23;                                                                 \
204
2
        dt->shared->u.atomic.u.f.esize = 8;                                                                  \
205
2
        dt->shared->u.atomic.u.f.ebias = 0x7f;                                                               \
206
2
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
207
2
        dt->shared->u.atomic.u.f.msize = 23;                                                                 \
208
2
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
209
2
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
210
2
    }
211
212
#define H5T_INIT_TYPE_FLOATLE_CORE                                                                           \
213
1
    {                                                                                                        \
214
1
        H5T_INIT_TYPE_FLOAT_COMMON(H5T_ORDER_LE)                                                             \
215
1
    }
216
217
#define H5T_INIT_TYPE_FLOATBE_CORE                                                                           \
218
1
    {                                                                                                        \
219
1
        H5T_INIT_TYPE_FLOAT_COMMON(H5T_ORDER_BE)                                                             \
220
1
    }
221
222
/* Define the code templates for standard doubles for the "GUTS" in the H5T_INIT_TYPE macro */
223
#define H5T_INIT_TYPE_DOUBLE_COMMON(ENDIANNESS)                                                              \
224
2
    {                                                                                                        \
225
2
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
226
2
        dt->shared->u.atomic.u.f.sign  = 63;                                                                 \
227
2
        dt->shared->u.atomic.u.f.epos  = 52;                                                                 \
228
2
        dt->shared->u.atomic.u.f.esize = 11;                                                                 \
229
2
        dt->shared->u.atomic.u.f.ebias = 0x03ff;                                                             \
230
2
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
231
2
        dt->shared->u.atomic.u.f.msize = 52;                                                                 \
232
2
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
233
2
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
234
2
    }
235
236
#define H5T_INIT_TYPE_DOUBLELE_CORE                                                                          \
237
1
    {                                                                                                        \
238
1
        H5T_INIT_TYPE_DOUBLE_COMMON(H5T_ORDER_LE)                                                            \
239
1
    }
240
241
#define H5T_INIT_TYPE_DOUBLEBE_CORE                                                                          \
242
1
    {                                                                                                        \
243
1
        H5T_INIT_TYPE_DOUBLE_COMMON(H5T_ORDER_BE)                                                            \
244
1
    }
245
246
/* Define the code templates for VAX float for the "GUTS" in the H5T_INIT_TYPE macro */
247
#define H5T_INIT_TYPE_FLOATVAX_CORE                                                                          \
248
1
    {                                                                                                        \
249
1
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_VAX)                                                              \
250
1
        dt->shared->u.atomic.u.f.sign  = 31;                                                                 \
251
1
        dt->shared->u.atomic.u.f.epos  = 23;                                                                 \
252
1
        dt->shared->u.atomic.u.f.esize = 8;                                                                  \
253
1
        dt->shared->u.atomic.u.f.ebias = 0x81;                                                               \
254
1
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
255
1
        dt->shared->u.atomic.u.f.msize = 23;                                                                 \
256
1
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
257
1
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
258
1
        dt->shared->version            = H5O_DTYPE_VERSION_3;                                                \
259
1
    }
260
261
/* Define the code templates for VAX double for the "GUTS" in the H5T_INIT_TYPE macro */
262
#define H5T_INIT_TYPE_DOUBLEVAX_CORE                                                                         \
263
1
    {                                                                                                        \
264
1
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_VAX)                                                              \
265
1
        dt->shared->u.atomic.u.f.sign  = 63;                                                                 \
266
1
        dt->shared->u.atomic.u.f.epos  = 52;                                                                 \
267
1
        dt->shared->u.atomic.u.f.esize = 11;                                                                 \
268
1
        dt->shared->u.atomic.u.f.ebias = 0x0401;                                                             \
269
1
        dt->shared->u.atomic.u.f.mpos  = 0;                                                                  \
270
1
        dt->shared->u.atomic.u.f.msize = 52;                                                                 \
271
1
        dt->shared->u.atomic.u.f.norm  = H5T_NORM_IMPLIED;                                                   \
272
1
        dt->shared->u.atomic.u.f.pad   = H5T_PAD_ZERO;                                                       \
273
1
        dt->shared->version            = H5O_DTYPE_VERSION_3;                                                \
274
1
    }
275
276
/* Define the code templates for standard signed integers for the "GUTS" in the H5T_INIT_TYPE macro */
277
#define H5T_INIT_TYPE_SINT_COMMON(ENDIANNESS)                                                                \
278
8
    {                                                                                                        \
279
8
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
280
8
        dt->shared->u.atomic.u.i.sign = H5T_SGN_2;                                                           \
281
8
    }
282
283
#define H5T_INIT_TYPE_SINTLE_CORE                                                                            \
284
4
    {                                                                                                        \
285
4
        H5T_INIT_TYPE_SINT_COMMON(H5T_ORDER_LE)                                                              \
286
4
    }
287
288
#define H5T_INIT_TYPE_SINTBE_CORE                                                                            \
289
4
    {                                                                                                        \
290
4
        H5T_INIT_TYPE_SINT_COMMON(H5T_ORDER_BE)                                                              \
291
4
    }
292
293
/* Define the code templates for standard unsigned integers for the "GUTS" in the H5T_INIT_TYPE macro */
294
#define H5T_INIT_TYPE_UINT_COMMON(ENDIANNESS)                                                                \
295
8
    {                                                                                                        \
296
8
        H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS)                                                                 \
297
8
        dt->shared->u.atomic.u.i.sign = H5T_SGN_NONE;                                                        \
298
8
    }
299
300
#define H5T_INIT_TYPE_UINTLE_CORE                                                                            \
301
4
    {                                                                                                        \
302
4
        H5T_INIT_TYPE_UINT_COMMON(H5T_ORDER_LE)                                                              \
303
4
    }
304
305
#define H5T_INIT_TYPE_UINTBE_CORE                                                                            \
306
4
    {                                                                                                        \
307
4
        H5T_INIT_TYPE_UINT_COMMON(H5T_ORDER_BE)                                                              \
308
4
    }
309
310
/* Define a macro for common code for all newly allocate datatypes */
311
#define H5T_INIT_TYPE_ALLOC_COMMON(TYPE)                                                                     \
312
6
    {                                                                                                        \
313
6
        dt->sh_loc.type  = H5O_SHARE_TYPE_UNSHARED;                                                          \
314
6
        dt->shared->type = TYPE;                                                                             \
315
6
    }
316
317
/* Define the code templates for opaque for the "GUTS" in the H5T_INIT_TYPE macro */
318
#define H5T_INIT_TYPE_OPAQ_CORE                                                                              \
319
1
    {                                                                                                        \
320
1
        H5T_INIT_TYPE_ALLOC_COMMON(H5T_OPAQUE)                                                               \
321
1
        dt->shared->u.opaque.tag = H5MM_xstrdup("");                                                         \
322
1
    }
323
324
/* Define the code templates for strings for the "GUTS" in the H5T_INIT_TYPE macro */
325
#define H5T_INIT_TYPE_STRING_COMMON                                                                          \
326
2
    {                                                                                                        \
327
2
        H5T_INIT_TYPE_ALLOC_COMMON(H5T_STRING)                                                               \
328
2
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE)                                                             \
329
2
        dt->shared->u.atomic.u.s.cset = H5F_DEFAULT_CSET;                                                    \
330
2
    }
331
332
#define H5T_INIT_TYPE_CSTRING_CORE                                                                           \
333
1
    {                                                                                                        \
334
1
        H5T_INIT_TYPE_STRING_COMMON                                                                          \
335
1
        dt->shared->u.atomic.u.s.pad = H5T_STR_NULLTERM;                                                     \
336
1
    }
337
338
#define H5T_INIT_TYPE_FORSTRING_CORE                                                                         \
339
1
    {                                                                                                        \
340
1
        H5T_INIT_TYPE_STRING_COMMON                                                                          \
341
1
        dt->shared->u.atomic.u.s.pad = H5T_STR_SPACEPAD;                                                     \
342
1
    }
343
344
/* Define the code templates for references for the "GUTS" in the H5T_INIT_TYPE macro */
345
#define H5T_INIT_TYPE_REF_COMMON                                                                             \
346
3
    {                                                                                                        \
347
3
        H5T_INIT_TYPE_ALLOC_COMMON(H5T_REFERENCE)                                                            \
348
3
        H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE)                                                             \
349
3
        dt->shared->force_conv        = true;                                                                \
350
3
        dt->shared->u.atomic.u.r.file = NULL;                                                                \
351
3
        dt->shared->u.atomic.u.r.loc  = H5T_LOC_BADLOC;                                                      \
352
3
        dt->shared->u.atomic.u.r.cls  = NULL;                                                                \
353
3
    }
354
355
#define H5T_INIT_TYPE_OBJREF_CORE                                                                            \
356
1
    {                                                                                                        \
357
1
        H5T_INIT_TYPE_REF_COMMON                                                                             \
358
1
        dt->shared->u.atomic.u.r.rtype   = H5R_OBJECT1;                                                      \
359
1
        dt->shared->u.atomic.u.r.opaque  = false;                                                            \
360
1
        dt->shared->u.atomic.u.r.version = 0;                                                                \
361
1
    }
362
363
#define H5T_INIT_TYPE_REGREF_CORE                                                                            \
364
1
    {                                                                                                        \
365
1
        H5T_INIT_TYPE_REF_COMMON                                                                             \
366
1
        dt->shared->u.atomic.u.r.rtype   = H5R_DATASET_REGION1;                                              \
367
1
        dt->shared->u.atomic.u.r.opaque  = false;                                                            \
368
1
        dt->shared->u.atomic.u.r.version = 0;                                                                \
369
1
    }
370
371
/* rtype value is only used as a placeholder to differentiate the type from
372
 * other types, any opaque (i.e. "new") reference type could be used.
373
 */
374
#define H5T_INIT_TYPE_REF_CORE                                                                               \
375
1
    {                                                                                                        \
376
1
        H5T_INIT_TYPE_REF_COMMON                                                                             \
377
1
        dt->shared->u.atomic.u.r.rtype   = H5R_OBJECT2;                                                      \
378
1
        dt->shared->u.atomic.u.r.opaque  = true;                                                             \
379
1
        dt->shared->u.atomic.u.r.version = H5R_ENCODE_VERSION;                                               \
380
1
        dt->shared->version              = H5O_DTYPE_VERSION_4;                                              \
381
1
    }
382
383
/* Define the code templates for the "SIZE_TMPL" in the H5T_INIT_TYPE macro */
384
#define H5T_INIT_TYPE_SET_SIZE(SIZE)                                                                         \
385
40
    {                                                                                                        \
386
40
        dt->shared->size          = SIZE;                                                                    \
387
40
        dt->shared->u.atomic.prec = 8 * (SIZE);                                                              \
388
40
    }
389
390
#define H5T_INIT_TYPE_NOSET_SIZE(SIZE)                                                                       \
391
15
    {                                                                                                        \
392
15
    }
393
394
/* Define the code templates for the "CRT_TMPL" in the H5T_INIT_TYPE macro */
395
#define H5T_INIT_TYPE_COPY_CREATE(BASE)                                                                      \
396
49
    {                                                                                                        \
397
49
        /* Base off of existing datatype */                                                                  \
398
49
        if (NULL == (dt = H5T_copy(BASE, H5T_COPY_TRANSIENT)))                                               \
399
49
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "duplicating base type failed");                   \
400
49
    }
401
402
#define H5T_INIT_TYPE_ALLOC_CREATE(BASE)                                                                     \
403
6
    {                                                                                                        \
404
6
        /* Allocate new datatype info */                                                                     \
405
6
        if (NULL == (dt = H5T__alloc()))                                                                     \
406
6
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed");                      \
407
6
    }
408
409
#define H5T_INIT_TYPE(GUTS, GLOBAL, CRT_TMPL, BASE, SIZE_TMPL, SIZE)                                         \
410
55
    {                                                                                                        \
411
55
        /* Get new datatype struct */                                                                        \
412
55
        H5_GLUE3(H5T_INIT_TYPE_, CRT_TMPL, _CREATE)                                                          \
413
55
        (BASE)                                                                                               \
414
55
                                                                                                             \
415
55
            /* Adjust information for all types */                                                           \
416
55
            dt->shared->state = H5T_STATE_IMMUTABLE;                                                         \
417
55
        H5_GLUE3(H5T_INIT_TYPE_, SIZE_TMPL, _SIZE)                                                           \
418
55
        (SIZE)                                                                                               \
419
55
                                                                                                             \
420
55
            /* Adjust information for this type */                                                           \
421
55
            H5_GLUE3(H5T_INIT_TYPE_, GUTS, _CORE)                                                            \
422
55
                                                                                                             \
423
55
            /* Register result */                                                                            \
424
55
            if (((GLOBAL) = H5I_register(H5I_DATATYPE, dt, false)) < 0)                                      \
425
55
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");       \
426
55
    }
427
428
/******************/
429
/* Local Typedefs */
430
/******************/
431
432
/* Typedef for recursive const-correct datatype copying routines */
433
typedef H5T_t *(*H5T_copy_func_t)(H5T_t *old_dt);
434
435
/********************/
436
/* Local Prototypes */
437
/********************/
438
static herr_t H5T__register_int(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
439
                                H5T_lib_conv_t func);
440
static herr_t H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_func_t *conv);
441
static htri_t H5T__compiler_conv(H5T_t *src, H5T_t *dst);
442
static herr_t H5T__set_size(H5T_t *dt, size_t size);
443
static herr_t H5T__close_cb(H5T_t *dt, void **request);
444
static herr_t H5T__init_path_table(void);
445
static bool   H5T__path_table_search(const H5T_t *src, const H5T_t *dst, int *idx, int *last_cmp);
446
static H5T_path_t *H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name,
447
                                       H5T_conv_func_t *conv);
448
static herr_t      H5T__path_find_init_new_path(H5T_path_t *path, const H5T_t *src, const H5T_t *dst,
449
                                                H5T_conv_func_t *conv, H5T_conv_ctx_t *conv_ctx);
450
static herr_t      H5T__path_free(H5T_path_t *path, H5T_conv_ctx_t *conv_ctx);
451
static bool        H5T_path_match(H5T_path_t *path, H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
452
                                  H5VL_object_t *owned_vol_obj, H5T_conv_t func);
453
static bool   H5T_path_match_find_type_with_volobj(const H5T_t *datatype, const H5VL_object_t *owned_vol_obj);
454
static bool   H5T__detect_vlen_ref(const H5T_t *dt);
455
static H5T_t *H5T__initiate_copy(const H5T_t *old_dt);
456
static H5T_t *H5T__copy_transient(H5T_t *old_dt);
457
static H5T_t *H5T__copy_all(H5T_t *old_dt);
458
static herr_t H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo,
459
                                 bool set_memory_type, H5T_copy_func_t copyfn);
460
461
/*****************************/
462
/* Library Private Variables */
463
/*****************************/
464
465
/* The native endianness of the platform */
466
H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR;
467
468
/*********************/
469
/* Package Variables */
470
/*********************/
471
472
/* Package initialization variable */
473
bool H5_PKG_INIT_VAR = false;
474
475
/*
476
 * Predefined data types. These are initialized at runtime by H5T__init_package().
477
 *
478
 * If more of these are added, the new ones must be added to the list of
479
 * types to reset in H5T_term_package().
480
 */
481
hid_t H5T_IEEE_F16BE_g = H5I_INVALID_HID;
482
hid_t H5T_IEEE_F16LE_g = H5I_INVALID_HID;
483
hid_t H5T_IEEE_F32BE_g = H5I_INVALID_HID;
484
hid_t H5T_IEEE_F32LE_g = H5I_INVALID_HID;
485
hid_t H5T_IEEE_F64BE_g = H5I_INVALID_HID;
486
hid_t H5T_IEEE_F64LE_g = H5I_INVALID_HID;
487
488
hid_t H5T_FLOAT_BFLOAT16BE_g = H5I_INVALID_HID;
489
hid_t H5T_FLOAT_BFLOAT16LE_g = H5I_INVALID_HID;
490
hid_t H5T_FLOAT_F8E4M3_g     = H5I_INVALID_HID;
491
hid_t H5T_FLOAT_F8E5M2_g     = H5I_INVALID_HID;
492
493
hid_t H5T_COMPLEX_IEEE_F16BE_g = H5I_INVALID_HID;
494
hid_t H5T_COMPLEX_IEEE_F16LE_g = H5I_INVALID_HID;
495
hid_t H5T_COMPLEX_IEEE_F32BE_g = H5I_INVALID_HID;
496
hid_t H5T_COMPLEX_IEEE_F32LE_g = H5I_INVALID_HID;
497
hid_t H5T_COMPLEX_IEEE_F64BE_g = H5I_INVALID_HID;
498
hid_t H5T_COMPLEX_IEEE_F64LE_g = H5I_INVALID_HID;
499
500
hid_t H5T_VAX_F32_g = H5I_INVALID_HID;
501
hid_t H5T_VAX_F64_g = H5I_INVALID_HID;
502
503
hid_t H5T_STD_I8BE_g        = H5I_INVALID_HID;
504
hid_t H5T_STD_I8LE_g        = H5I_INVALID_HID;
505
hid_t H5T_STD_I16BE_g       = H5I_INVALID_HID;
506
hid_t H5T_STD_I16LE_g       = H5I_INVALID_HID;
507
hid_t H5T_STD_I32BE_g       = H5I_INVALID_HID;
508
hid_t H5T_STD_I32LE_g       = H5I_INVALID_HID;
509
hid_t H5T_STD_I64BE_g       = H5I_INVALID_HID;
510
hid_t H5T_STD_I64LE_g       = H5I_INVALID_HID;
511
hid_t H5T_STD_U8BE_g        = H5I_INVALID_HID;
512
hid_t H5T_STD_U8LE_g        = H5I_INVALID_HID;
513
hid_t H5T_STD_U16BE_g       = H5I_INVALID_HID;
514
hid_t H5T_STD_U16LE_g       = H5I_INVALID_HID;
515
hid_t H5T_STD_U32BE_g       = H5I_INVALID_HID;
516
hid_t H5T_STD_U32LE_g       = H5I_INVALID_HID;
517
hid_t H5T_STD_U64BE_g       = H5I_INVALID_HID;
518
hid_t H5T_STD_U64LE_g       = H5I_INVALID_HID;
519
hid_t H5T_STD_B8BE_g        = H5I_INVALID_HID;
520
hid_t H5T_STD_B8LE_g        = H5I_INVALID_HID;
521
hid_t H5T_STD_B16BE_g       = H5I_INVALID_HID;
522
hid_t H5T_STD_B16LE_g       = H5I_INVALID_HID;
523
hid_t H5T_STD_B32BE_g       = H5I_INVALID_HID;
524
hid_t H5T_STD_B32LE_g       = H5I_INVALID_HID;
525
hid_t H5T_STD_B64BE_g       = H5I_INVALID_HID;
526
hid_t H5T_STD_B64LE_g       = H5I_INVALID_HID;
527
hid_t H5T_STD_REF_OBJ_g     = H5I_INVALID_HID;
528
hid_t H5T_STD_REF_DSETREG_g = H5I_INVALID_HID;
529
hid_t H5T_STD_REF_g         = H5I_INVALID_HID;
530
531
hid_t H5T_UNIX_D32BE_g = H5I_INVALID_HID;
532
hid_t H5T_UNIX_D32LE_g = H5I_INVALID_HID;
533
hid_t H5T_UNIX_D64BE_g = H5I_INVALID_HID;
534
hid_t H5T_UNIX_D64LE_g = H5I_INVALID_HID;
535
536
hid_t H5T_C_S1_g = H5I_INVALID_HID;
537
538
hid_t H5T_FORTRAN_S1_g = H5I_INVALID_HID;
539
540
hid_t H5T_NATIVE_SCHAR_g           = H5I_INVALID_HID;
541
hid_t H5T_NATIVE_UCHAR_g           = H5I_INVALID_HID;
542
hid_t H5T_NATIVE_SHORT_g           = H5I_INVALID_HID;
543
hid_t H5T_NATIVE_USHORT_g          = H5I_INVALID_HID;
544
hid_t H5T_NATIVE_INT_g             = H5I_INVALID_HID;
545
hid_t H5T_NATIVE_UINT_g            = H5I_INVALID_HID;
546
hid_t H5T_NATIVE_LONG_g            = H5I_INVALID_HID;
547
hid_t H5T_NATIVE_ULONG_g           = H5I_INVALID_HID;
548
hid_t H5T_NATIVE_LLONG_g           = H5I_INVALID_HID;
549
hid_t H5T_NATIVE_ULLONG_g          = H5I_INVALID_HID;
550
hid_t H5T_NATIVE_FLOAT16_g         = H5I_INVALID_HID;
551
hid_t H5T_NATIVE_FLOAT_g           = H5I_INVALID_HID;
552
hid_t H5T_NATIVE_DOUBLE_g          = H5I_INVALID_HID;
553
hid_t H5T_NATIVE_LDOUBLE_g         = H5I_INVALID_HID;
554
hid_t H5T_NATIVE_FLOAT_COMPLEX_g   = H5I_INVALID_HID;
555
hid_t H5T_NATIVE_DOUBLE_COMPLEX_g  = H5I_INVALID_HID;
556
hid_t H5T_NATIVE_LDOUBLE_COMPLEX_g = H5I_INVALID_HID;
557
hid_t H5T_NATIVE_B8_g              = H5I_INVALID_HID;
558
hid_t H5T_NATIVE_B16_g             = H5I_INVALID_HID;
559
hid_t H5T_NATIVE_B32_g             = H5I_INVALID_HID;
560
hid_t H5T_NATIVE_B64_g             = H5I_INVALID_HID;
561
hid_t H5T_NATIVE_OPAQUE_g          = H5I_INVALID_HID;
562
hid_t H5T_NATIVE_HADDR_g           = H5I_INVALID_HID;
563
hid_t H5T_NATIVE_HSIZE_g           = H5I_INVALID_HID;
564
hid_t H5T_NATIVE_HSSIZE_g          = H5I_INVALID_HID;
565
hid_t H5T_NATIVE_HERR_g            = H5I_INVALID_HID;
566
hid_t H5T_NATIVE_HBOOL_g           = H5I_INVALID_HID;
567
568
hid_t H5T_NATIVE_INT8_g        = H5I_INVALID_HID;
569
hid_t H5T_NATIVE_UINT8_g       = H5I_INVALID_HID;
570
hid_t H5T_NATIVE_INT_LEAST8_g  = H5I_INVALID_HID;
571
hid_t H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID;
572
hid_t H5T_NATIVE_INT_FAST8_g   = H5I_INVALID_HID;
573
hid_t H5T_NATIVE_UINT_FAST8_g  = H5I_INVALID_HID;
574
575
hid_t H5T_NATIVE_INT16_g        = H5I_INVALID_HID;
576
hid_t H5T_NATIVE_UINT16_g       = H5I_INVALID_HID;
577
hid_t H5T_NATIVE_INT_LEAST16_g  = H5I_INVALID_HID;
578
hid_t H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID;
579
hid_t H5T_NATIVE_INT_FAST16_g   = H5I_INVALID_HID;
580
hid_t H5T_NATIVE_UINT_FAST16_g  = H5I_INVALID_HID;
581
582
hid_t H5T_NATIVE_INT32_g        = H5I_INVALID_HID;
583
hid_t H5T_NATIVE_UINT32_g       = H5I_INVALID_HID;
584
hid_t H5T_NATIVE_INT_LEAST32_g  = H5I_INVALID_HID;
585
hid_t H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID;
586
hid_t H5T_NATIVE_INT_FAST32_g   = H5I_INVALID_HID;
587
hid_t H5T_NATIVE_UINT_FAST32_g  = H5I_INVALID_HID;
588
589
hid_t H5T_NATIVE_INT64_g        = H5I_INVALID_HID;
590
hid_t H5T_NATIVE_UINT64_g       = H5I_INVALID_HID;
591
hid_t H5T_NATIVE_INT_LEAST64_g  = H5I_INVALID_HID;
592
hid_t H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID;
593
hid_t H5T_NATIVE_INT_FAST64_g   = H5I_INVALID_HID;
594
hid_t H5T_NATIVE_UINT_FAST64_g  = H5I_INVALID_HID;
595
596
/*
597
 * Alignment constraints for HDF5 types.  Accessing objects of these
598
 * types with improper alignment invokes C undefined behavior, so the
599
 * library lays out objects with correct alignment, always.
600
 *
601
 * A value of N indicates that the data must be aligned on an address
602
 * ADDR such that 0 == ADDR mod N. When N=1 no alignment is required;
603
 * N=0 implies that alignment constraints were not calculated.  These
604
 * values are used for structure alignment.
605
 */
606
size_t H5T_POINTER_ALIGN_g     = 0;
607
size_t H5T_HVL_ALIGN_g         = 0;
608
size_t H5T_HOBJREF_ALIGN_g     = 0;
609
size_t H5T_HDSETREGREF_ALIGN_g = 0;
610
size_t H5T_REF_ALIGN_g         = 0;
611
612
size_t H5T_NATIVE_SCHAR_ALIGN_g           = 0;
613
size_t H5T_NATIVE_UCHAR_ALIGN_g           = 0;
614
size_t H5T_NATIVE_SHORT_ALIGN_g           = 0;
615
size_t H5T_NATIVE_USHORT_ALIGN_g          = 0;
616
size_t H5T_NATIVE_INT_ALIGN_g             = 0;
617
size_t H5T_NATIVE_UINT_ALIGN_g            = 0;
618
size_t H5T_NATIVE_LONG_ALIGN_g            = 0;
619
size_t H5T_NATIVE_ULONG_ALIGN_g           = 0;
620
size_t H5T_NATIVE_LLONG_ALIGN_g           = 0;
621
size_t H5T_NATIVE_ULLONG_ALIGN_g          = 0;
622
size_t H5T_NATIVE_FLOAT16_ALIGN_g         = 0;
623
size_t H5T_NATIVE_FLOAT_ALIGN_g           = 0;
624
size_t H5T_NATIVE_DOUBLE_ALIGN_g          = 0;
625
size_t H5T_NATIVE_LDOUBLE_ALIGN_g         = 0;
626
size_t H5T_NATIVE_FLOAT_COMPLEX_ALIGN_g   = 0;
627
size_t H5T_NATIVE_DOUBLE_COMPLEX_ALIGN_g  = 0;
628
size_t H5T_NATIVE_LDOUBLE_COMPLEX_ALIGN_g = 0;
629
630
/* Alignment constraints for C99 types */
631
size_t H5T_NATIVE_INT8_ALIGN_g        = 0;
632
size_t H5T_NATIVE_UINT8_ALIGN_g       = 0;
633
size_t H5T_NATIVE_INT_LEAST8_ALIGN_g  = 0;
634
size_t H5T_NATIVE_UINT_LEAST8_ALIGN_g = 0;
635
size_t H5T_NATIVE_INT_FAST8_ALIGN_g   = 0;
636
size_t H5T_NATIVE_UINT_FAST8_ALIGN_g  = 0;
637
638
size_t H5T_NATIVE_INT16_ALIGN_g        = 0;
639
size_t H5T_NATIVE_UINT16_ALIGN_g       = 0;
640
size_t H5T_NATIVE_INT_LEAST16_ALIGN_g  = 0;
641
size_t H5T_NATIVE_UINT_LEAST16_ALIGN_g = 0;
642
size_t H5T_NATIVE_INT_FAST16_ALIGN_g   = 0;
643
size_t H5T_NATIVE_UINT_FAST16_ALIGN_g  = 0;
644
645
size_t H5T_NATIVE_INT32_ALIGN_g        = 0;
646
size_t H5T_NATIVE_UINT32_ALIGN_g       = 0;
647
size_t H5T_NATIVE_INT_LEAST32_ALIGN_g  = 0;
648
size_t H5T_NATIVE_UINT_LEAST32_ALIGN_g = 0;
649
size_t H5T_NATIVE_INT_FAST32_ALIGN_g   = 0;
650
size_t H5T_NATIVE_UINT_FAST32_ALIGN_g  = 0;
651
652
size_t H5T_NATIVE_INT64_ALIGN_g        = 0;
653
size_t H5T_NATIVE_UINT64_ALIGN_g       = 0;
654
size_t H5T_NATIVE_INT_LEAST64_ALIGN_g  = 0;
655
size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g = 0;
656
size_t H5T_NATIVE_INT_FAST64_ALIGN_g   = 0;
657
size_t H5T_NATIVE_UINT_FAST64_ALIGN_g  = 0;
658
659
/* Useful floating-point values for conversion routines */
660
/* (+/- Inf for all floating-point types) */
661
#ifdef H5_HAVE__FLOAT16
662
/* Initialize these with a float literal since the f16 suffix
663
 * is non-standard C and gives warnings when compiling the
664
 * library with the -pedantic flag. These values will be
665
 * overwritten anyway.
666
 */
667
H5__Float16 H5T_NATIVE_FLOAT16_POS_INF_g = 0.0f;
668
H5__Float16 H5T_NATIVE_FLOAT16_NEG_INF_g = 0.0f;
669
#endif
670
float       H5T_NATIVE_FLOAT_POS_INF_g   = 0.0F;
671
float       H5T_NATIVE_FLOAT_NEG_INF_g   = 0.0F;
672
double      H5T_NATIVE_DOUBLE_POS_INF_g  = 0.0;
673
double      H5T_NATIVE_DOUBLE_NEG_INF_g  = 0.0;
674
long double H5T_NATIVE_LDOUBLE_POS_INF_g = 0.0L;
675
long double H5T_NATIVE_LDOUBLE_NEG_INF_g = 0.0L;
676
#ifdef H5_HAVE_COMPLEX_NUMBERS
677
H5_float_complex   H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g;
678
H5_float_complex   H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g;
679
H5_double_complex  H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g;
680
H5_double_complex  H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g;
681
H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g;
682
H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g;
683
#endif
684
685
/* Declare the free list for H5T_t's and H5T_shared_t's */
686
H5FL_DEFINE(H5T_t);
687
H5FL_DEFINE(H5T_shared_t);
688
689
/* Format version bounds for datatype */
690
const unsigned H5O_dtype_ver_bounds[] = {
691
    H5O_DTYPE_VERSION_1,     /* H5F_LIBVER_EARLIEST */
692
    H5O_DTYPE_VERSION_3,     /* H5F_LIBVER_V18 */
693
    H5O_DTYPE_VERSION_3,     /* H5F_LIBVER_V110 */
694
    H5O_DTYPE_VERSION_4,     /* H5F_LIBVER_V112 */
695
    H5O_DTYPE_VERSION_4,     /* H5F_LIBVER_V114 */
696
    H5O_DTYPE_VERSION_5,     /* H5F_LIBVER_V200 */
697
    H5O_DTYPE_VERSION_LATEST /* H5F_LIBVER_LATEST */
698
};
699
700
/*******************/
701
/* Local Variables */
702
/*******************/
703
704
/*
705
 * The path database. Each path has a source and destination data type pair
706
 * which is used as the key by which the `entries' array is sorted.
707
 */
708
static struct {
709
    int          npaths; /*number of paths defined               */
710
    size_t       apaths; /*number of paths allocated             */
711
    H5T_path_t **path;   /*sorted array of path pointers         */
712
    int          nsoft;  /*number of soft conversions defined    */
713
    size_t       asoft;  /*number of soft conversions allocated  */
714
    H5T_soft_t  *soft;   /*unsorted array of soft conversions    */
715
} H5T_g;
716
717
/* Declare the free list for H5T_path_t's */
718
H5FL_DEFINE_STATIC(H5T_path_t);
719
720
/* Datatype ID class */
721
static const H5I_class_t H5I_DATATYPE_CLS[1] = {{
722
    H5I_DATATYPE,             /* ID class value */
723
    0,                        /* Class flags    */
724
    8,                        /* # of reserved IDs for class */
725
    (H5I_free_t)H5T__close_cb /* Callback routine for closing objects of this class */
726
}};
727
728
/* Flag indicating "top" of interface has been initialized */
729
static bool H5T_top_package_initialize_s = false;
730
731
/*-------------------------------------------------------------------------
732
 * Function:    H5T_init
733
 *
734
 * Purpose:    Initialize the interface from some other package.
735
 *
736
 * Return:    Success:    non-negative
737
 *            Failure:    negative
738
 *
739
 * Programmer:    Robb Matzke
740
 *              Wednesday, December 16, 1998
741
 *
742
 *-------------------------------------------------------------------------
743
 */
744
herr_t
745
H5T_init(void)
746
2
{
747
2
    herr_t ret_value = SUCCEED; /* Return value */
748
749
2
    FUNC_ENTER_NOAPI(FAIL)
750
    /* FUNC_ENTER() does all the work */
751
752
2
done:
753
2
    FUNC_LEAVE_NOAPI(ret_value)
754
2
} /* end H5T_init() */
755
756
/*-------------------------------------------------------------------------
757
 * Function:    H5T__init_inf
758
 *
759
 * Purpose:    Initialize the +/- Infinity floating-poing values for type
760
 *              conversion.
761
 *
762
 * Return:    Success:    non-negative
763
 *            Failure:    negative
764
 *
765
 *-------------------------------------------------------------------------
766
 */
767
static herr_t
768
H5T__init_inf(void)
769
1
{
770
1
    H5T_t        *dst_p;               /* Datatype type operate on */
771
1
    H5T_atomic_t *dst;                 /* Datatype's atomic info   */
772
1
    uint8_t      *d;                   /* Pointer to value to set  */
773
1
    size_t        half_size;           /* Half the type size       */
774
1
    size_t        u;                   /* Local index value        */
775
1
    herr_t        ret_value = SUCCEED; /* Return value             */
776
777
1
    FUNC_ENTER_PACKAGE
778
779
    /* Get the float datatype */
780
1
    if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g)))
781
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
782
1
    dst = &dst_p->shared->u.atomic;
783
784
    /* Check that we can re-order the bytes correctly */
785
1
    if (H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g)
786
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
787
788
    /* +Inf */
789
1
    d = (uint8_t *)&H5T_NATIVE_FLOAT_POS_INF_g;
790
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, false);
791
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
792
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
793
794
    /* Swap the bytes if the machine architecture is big-endian */
795
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
796
0
        half_size = dst_p->shared->size / 2;
797
0
        for (u = 0; u < half_size; u++) {
798
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
799
0
            d[dst_p->shared->size - (u + 1)] = d[u];
800
0
            d[u]                             = tmp;
801
0
        } /* end for */
802
0
    }     /* end if */
803
804
    /* -Inf */
805
1
    d = (uint8_t *)&H5T_NATIVE_FLOAT_NEG_INF_g;
806
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, true);
807
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
808
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
809
810
    /* Swap the bytes if the machine architecture is big-endian */
811
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
812
0
        half_size = dst_p->shared->size / 2;
813
0
        for (u = 0; u < half_size; u++) {
814
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
815
0
            d[dst_p->shared->size - (u + 1)] = d[u];
816
0
            d[u]                             = tmp;
817
0
        } /* end for */
818
0
    }     /* end if */
819
820
    /* Get the double datatype */
821
1
    if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g)))
822
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
823
1
    dst = &dst_p->shared->u.atomic;
824
825
    /* Check that we can re-order the bytes correctly */
826
1
    if (H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g)
827
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
828
829
    /* +Inf */
830
1
    d = (uint8_t *)&H5T_NATIVE_DOUBLE_POS_INF_g;
831
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, false);
832
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
833
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
834
835
    /* Swap the bytes if the machine architecture is big-endian */
836
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
837
0
        half_size = dst_p->shared->size / 2;
838
0
        for (u = 0; u < half_size; u++) {
839
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
840
0
            d[dst_p->shared->size - (u + 1)] = d[u];
841
0
            d[u]                             = tmp;
842
0
        } /* end for */
843
0
    }     /* end if */
844
845
    /* -Inf */
846
1
    d = (uint8_t *)&H5T_NATIVE_DOUBLE_NEG_INF_g;
847
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, true);
848
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
849
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
850
851
    /* Swap the bytes if the machine architecture is big-endian */
852
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
853
0
        half_size = dst_p->shared->size / 2;
854
0
        for (u = 0; u < half_size; u++) {
855
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
856
0
            d[dst_p->shared->size - (u + 1)] = d[u];
857
0
            d[u]                             = tmp;
858
0
        } /* end for */
859
0
    }     /* end if */
860
861
    /* Get the long double datatype */
862
1
    if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g)))
863
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
864
1
    dst = &dst_p->shared->u.atomic;
865
866
    /* Check that we can re-order the bytes correctly */
867
1
    if (H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g)
868
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
869
870
    /* +Inf */
871
1
    d = (uint8_t *)&H5T_NATIVE_LDOUBLE_POS_INF_g;
872
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, false);
873
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
874
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
875
876
    /* Swap the bytes if the machine architecture is big-endian */
877
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
878
0
        half_size = dst_p->shared->size / 2;
879
0
        for (u = 0; u < half_size; u++) {
880
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
881
0
            d[dst_p->shared->size - (u + 1)] = d[u];
882
0
            d[u]                             = tmp;
883
0
        } /* end for */
884
0
    }     /* end if */
885
886
    /* -Inf */
887
1
    d = (uint8_t *)&H5T_NATIVE_LDOUBLE_NEG_INF_g;
888
1
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, true);
889
1
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
890
1
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
891
892
    /* Swap the bytes if the machine architecture is big-endian */
893
1
    if (H5T_ORDER_BE == H5T_native_order_g) {
894
0
        half_size = dst_p->shared->size / 2;
895
0
        for (u = 0; u < half_size; u++) {
896
0
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
897
0
            d[dst_p->shared->size - (u + 1)] = d[u];
898
0
            d[u]                             = tmp;
899
0
        } /* end for */
900
0
    }     /* end if */
901
902
#ifdef H5_HAVE__FLOAT16
903
    /* Get the _Float16 datatype */
904
    if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT16_g)))
905
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
906
    dst = &dst_p->shared->u.atomic;
907
908
    /* Check that we can re-order the bytes correctly */
909
    if (H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g)
910
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
911
912
    /* +Inf */
913
    d = (uint8_t *)&H5T_NATIVE_FLOAT16_POS_INF_g;
914
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, false);
915
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
916
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
917
918
    /* Swap the bytes if the machine architecture is big-endian */
919
    if (H5T_ORDER_BE == H5T_native_order_g) {
920
        half_size = dst_p->shared->size / 2;
921
        for (u = 0; u < half_size; u++) {
922
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
923
            d[dst_p->shared->size - (u + 1)] = d[u];
924
            d[u]                             = tmp;
925
        } /* end for */
926
    }     /* end if */
927
928
    /* -Inf */
929
    d = (uint8_t *)&H5T_NATIVE_FLOAT16_NEG_INF_g;
930
    H5T__bit_set(d, dst->u.f.sign, (size_t)1, true);
931
    H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true);
932
    H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false);
933
934
    /* Swap the bytes if the machine architecture is big-endian */
935
    if (H5T_ORDER_BE == H5T_native_order_g) {
936
        half_size = dst_p->shared->size / 2;
937
        for (u = 0; u < half_size; u++) {
938
            uint8_t tmp                      = d[dst_p->shared->size - (u + 1)];
939
            d[dst_p->shared->size - (u + 1)] = d[u];
940
            d[u]                             = tmp;
941
        } /* end for */
942
    }     /* end if */
943
#endif
944
945
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
946
    /*
947
     * A complex number is considered to be infinite if any of its parts
948
     * (real or imaginary) is infinite, so simply set the real part of
949
     * the complex number positive/negative infinity values to the
950
     * positive/negative infinity value for the base floating-point type.
951
     * The imaginary part should be zeroed-out bits.
952
     */
953
1
    memcpy(&H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g, &H5T_NATIVE_FLOAT_POS_INF_g, sizeof(float));
954
1
    memcpy(&H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g, &H5T_NATIVE_FLOAT_NEG_INF_g, sizeof(float));
955
1
    memcpy(&H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g, &H5T_NATIVE_DOUBLE_POS_INF_g, sizeof(double));
956
1
    memcpy(&H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g, &H5T_NATIVE_DOUBLE_NEG_INF_g, sizeof(double));
957
1
    memcpy(&H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g, &H5T_NATIVE_LDOUBLE_POS_INF_g, sizeof(long double));
958
1
    memcpy(&H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g, &H5T_NATIVE_LDOUBLE_NEG_INF_g, sizeof(long double));
959
1
#endif
960
961
1
done:
962
1
    FUNC_LEAVE_NOAPI(ret_value)
963
1
} /* end H5T__init_inf() */
964
965
/*--------------------------------------------------------------------------
966
NAME
967
   H5T__init_package -- Initialize interface-specific information
968
USAGE
969
    herr__t H5T_init_package()
970
RETURNS
971
    Non-negative on success/Negative on failure
972
DESCRIPTION
973
    Initializes any interface-specific data or routines.
974
--------------------------------------------------------------------------*/
975
herr_t
976
H5T__init_package(void)
977
1
{
978
1
    H5T_t  *native_schar   = NULL; /* Datatype structure for native signed char */
979
1
    H5T_t  *native_uchar   = NULL; /* Datatype structure for native unsigned char */
980
1
    H5T_t  *native_short   = NULL; /* Datatype structure for native short */
981
1
    H5T_t  *native_ushort  = NULL; /* Datatype structure for native unsigned short */
982
1
    H5T_t  *native_int     = NULL; /* Datatype structure for native int */
983
1
    H5T_t  *native_uint    = NULL; /* Datatype structure for native unsigned int */
984
1
    H5T_t  *native_long    = NULL; /* Datatype structure for native long */
985
1
    H5T_t  *native_ulong   = NULL; /* Datatype structure for native unsigned long */
986
1
    H5T_t  *native_llong   = NULL; /* Datatype structure for native long long */
987
1
    H5T_t  *native_ullong  = NULL; /* Datatype structure for native unsigned long long */
988
1
    H5T_t  *native_float   = NULL; /* Datatype structure for native float */
989
1
    H5T_t  *native_double  = NULL; /* Datatype structure for native double */
990
1
    H5T_t  *native_ldouble = NULL; /* Datatype structure for native long double */
991
1
    H5T_t  *std_u8le       = NULL; /* Datatype structure for unsigned 8-bit little-endian integer */
992
1
    H5T_t  *std_u8be       = NULL; /* Datatype structure for unsigned 8-bit big-endian integer */
993
1
    H5T_t  *std_u16le      = NULL; /* Datatype structure for unsigned 16-bit little-endian integer */
994
1
    H5T_t  *std_u16be      = NULL; /* Datatype structure for unsigned 16-bit big-endian integer */
995
1
    H5T_t  *std_u32le      = NULL; /* Datatype structure for unsigned 32-bit little-endian integer */
996
1
    H5T_t  *std_u32be      = NULL; /* Datatype structure for unsigned 32-bit big-endian integer */
997
1
    H5T_t  *std_u64le      = NULL; /* Datatype structure for unsigned 64-bit little-endian integer */
998
1
    H5T_t  *std_u64be      = NULL; /* Datatype structure for unsigned 64-bit big-endian integer */
999
1
    H5T_t  *dt             = NULL;
1000
1
    H5T_t  *tmp_float      = NULL;
1001
1
    H5T_t  *fixedpt        = NULL; /* Datatype structure for native int */
1002
1
    H5T_t  *floatpt        = NULL; /* Datatype structure for native float */
1003
1
    H5T_t  *string         = NULL; /* Datatype structure for C string */
1004
1
    H5T_t  *bitfield       = NULL; /* Datatype structure for bitfield */
1005
1
    H5T_t  *compound       = NULL; /* Datatype structure for compound objects */
1006
1
    H5T_t  *enum_type      = NULL; /* Datatype structure for enum objects */
1007
1
    H5T_t  *vlen           = NULL; /* Datatype structure for vlen objects */
1008
1
    H5T_t  *array          = NULL; /* Datatype structure for array objects */
1009
1
    H5T_t  *cplx           = NULL; /* Datatype structure for complex number objects */
1010
1
    H5T_t  *objref         = NULL; /* Datatype structure for deprecated reference objects */
1011
1
    H5T_t  *regref         = NULL; /* Datatype structure for deprecated region references */
1012
1
    H5T_t  *ref            = NULL; /* Datatype structure for opaque references */
1013
1
    hsize_t dim[1]         = {1};  /* Dimension info for array datatype */
1014
1
    herr_t  status;
1015
1
    bool    copied_dtype =
1016
1
        true; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
1017
#ifdef H5_HAVE__FLOAT16
1018
    H5T_t *native_float16 = NULL; /* Datatype structure for native _Float16 type */
1019
#endif
1020
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1021
1
    H5T_t *native_float_complex  = NULL; /* Datatype structure for native float _Complex / _Fcomplex type */
1022
1
    H5T_t *native_double_complex = NULL; /* Datatype structure for native double _Complex / _Dcomplex type */
1023
1
    H5T_t *native_ldouble_complex =
1024
1
        NULL; /* Datatype structure for native long double _Complex / _Lcomplex type */
1025
1
#endif
1026
1
    herr_t ret_value = SUCCEED; /* Return value */
1027
1028
1
    FUNC_ENTER_PACKAGE
1029
1030
    /* Initialize the ID group for the file IDs */
1031
1
    if (H5I_register_type(H5I_DATATYPE_CLS) < 0)
1032
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface");
1033
1034
    /* Make certain there aren't too many classes of datatypes defined */
1035
    /* Only 16 (numbered 0-15) are supported in the current file format */
1036
1
    HDcompile_assert(H5T_NCLASSES < 16);
1037
1038
    /* Initialize native floating-point datatypes */
1039
1
    if (H5T__init_native_float_types() < 0)
1040
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize floating-point types");
1041
1042
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1043
    /* Initialize native complex number datatypes */
1044
1
    if (H5T__init_native_complex_types() < 0)
1045
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize complex number types");
1046
1
#endif
1047
1048
    /* Initialize all other native types */
1049
1
    if (H5T__init_native_internal() < 0)
1050
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize integers");
1051
1052
    /* Get the atomic datatype structures needed by the initialization code below */
1053
1
    if (NULL == (native_schar = (H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g)))
1054
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1055
1
    if (NULL == (native_uchar = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR_g)))
1056
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1057
1
    if (NULL == (native_short = (H5T_t *)H5I_object(H5T_NATIVE_SHORT_g)))
1058
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1059
1
    if (NULL == (native_ushort = (H5T_t *)H5I_object(H5T_NATIVE_USHORT_g)))
1060
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1061
1
    if (NULL == (native_int = (H5T_t *)H5I_object(H5T_NATIVE_INT_g)))
1062
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1063
1
    if (NULL == (native_uint = (H5T_t *)H5I_object(H5T_NATIVE_UINT_g)))
1064
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1065
1
    if (NULL == (native_long = (H5T_t *)H5I_object(H5T_NATIVE_LONG_g)))
1066
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1067
1
    if (NULL == (native_ulong = (H5T_t *)H5I_object(H5T_NATIVE_ULONG_g)))
1068
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1069
1
    if (NULL == (native_llong = (H5T_t *)H5I_object(H5T_NATIVE_LLONG_g)))
1070
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1071
1
    if (NULL == (native_ullong = (H5T_t *)H5I_object(H5T_NATIVE_ULLONG_g)))
1072
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1073
#ifdef H5_HAVE__FLOAT16
1074
    if (NULL == (native_float16 = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT16_g)))
1075
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1076
#endif
1077
1
    if (NULL == (native_float = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g)))
1078
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1079
1
    if (NULL == (native_double = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g)))
1080
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1081
1
    if (NULL == (native_ldouble = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g)))
1082
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1083
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1084
1
    if (NULL == (native_float_complex = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_COMPLEX_g)))
1085
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1086
1
    if (NULL == (native_double_complex = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_COMPLEX_g)))
1087
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1088
1
    if (NULL == (native_ldouble_complex = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_COMPLEX_g)))
1089
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1090
1
#endif
1091
1092
    /*------------------------------------------------------------
1093
     * Derived native types
1094
     *------------------------------------------------------------
1095
     */
1096
1097
    /* 1-byte bit field */
1098
2
    H5T_INIT_TYPE(BITFIELD, H5T_NATIVE_B8_g, COPY, native_uint, SET, 1)
1099
1100
    /* 2-byte bit field */
1101
2
    H5T_INIT_TYPE(BITFIELD, H5T_NATIVE_B16_g, COPY, native_uint, SET, 2)
1102
1103
    /* 4-byte bit field */
1104
2
    H5T_INIT_TYPE(BITFIELD, H5T_NATIVE_B32_g, COPY, native_uint, SET, 4)
1105
1106
    /* 8-byte bit field */
1107
2
    H5T_INIT_TYPE(BITFIELD, H5T_NATIVE_B64_g, COPY, native_uint, SET, 8)
1108
1109
    /* haddr_t */
1110
2
    H5T_INIT_TYPE(OFFSET, H5T_NATIVE_HADDR_g, COPY, native_uint, SET, sizeof(haddr_t))
1111
1112
    /* hsize_t */
1113
2
    H5T_INIT_TYPE(OFFSET, H5T_NATIVE_HSIZE_g, COPY, native_uint, SET, sizeof(hsize_t))
1114
1115
    /* hssize_t */
1116
2
    H5T_INIT_TYPE(OFFSET, H5T_NATIVE_HSSIZE_g, COPY, native_int, SET, sizeof(hssize_t))
1117
1118
    /* herr_t */
1119
2
    H5T_INIT_TYPE(OFFSET, H5T_NATIVE_HERR_g, COPY, native_int, SET, sizeof(herr_t))
1120
1121
    /* bool */
1122
2
    H5T_INIT_TYPE(OFFSET, H5T_NATIVE_HBOOL_g, COPY, native_uint, SET, sizeof(bool))
1123
1124
    /*------------------------------------------------------------
1125
     * IEEE Types
1126
     *------------------------------------------------------------
1127
     */
1128
1129
    /* IEEE 2-byte little-endian float */
1130
2
    H5T_INIT_TYPE(FLOAT16LE, H5T_IEEE_F16LE_g, COPY, native_double, SET, 2)
1131
1132
    /* IEEE 2-byte big-endian float */
1133
2
    H5T_INIT_TYPE(FLOAT16BE, H5T_IEEE_F16BE_g, COPY, native_double, SET, 2)
1134
1135
    /* IEEE 4-byte little-endian float */
1136
2
    H5T_INIT_TYPE(FLOATLE, H5T_IEEE_F32LE_g, COPY, native_double, SET, 4)
1137
1138
    /* IEEE 4-byte big-endian float */
1139
2
    H5T_INIT_TYPE(FLOATBE, H5T_IEEE_F32BE_g, COPY, native_double, SET, 4)
1140
1141
    /* IEEE 8-byte little-endian float */
1142
2
    H5T_INIT_TYPE(DOUBLELE, H5T_IEEE_F64LE_g, COPY, native_double, SET, 8)
1143
1144
    /* IEEE 8-byte big-endian float */
1145
2
    H5T_INIT_TYPE(DOUBLEBE, H5T_IEEE_F64BE_g, COPY, native_double, SET, 8)
1146
1147
    /*------------------------------------------------------------
1148
     * Alternative floating-point types
1149
     *------------------------------------------------------------
1150
     */
1151
1152
    /* 2-byte little-endian bfloat16 float type */
1153
2
    H5T_INIT_TYPE(BFLOAT16LE, H5T_FLOAT_BFLOAT16LE_g, COPY, native_double, SET, 2)
1154
1155
    /* 2-byte big-endian bfloat16 float type */
1156
2
    H5T_INIT_TYPE(BFLOAT16BE, H5T_FLOAT_BFLOAT16BE_g, COPY, native_double, SET, 2)
1157
1158
    /* 8-bit FP8 E4M3 float type */
1159
2
    H5T_INIT_TYPE(FLOAT8E4M3, H5T_FLOAT_F8E4M3_g, COPY, native_double, SET, 1)
1160
1161
    /* 8-bit FP8 E5M2 float type */
1162
2
    H5T_INIT_TYPE(FLOAT8E5M2, H5T_FLOAT_F8E5M2_g, COPY, native_double, SET, 1)
1163
1164
    /*------------------------------------------------------------
1165
     * VAX Types
1166
     *------------------------------------------------------------
1167
     */
1168
1169
    /* VAX 4-byte float */
1170
2
    H5T_INIT_TYPE(FLOATVAX, H5T_VAX_F32_g, COPY, native_double, SET, 4)
1171
1172
    /* VAX 8-byte double */
1173
2
    H5T_INIT_TYPE(DOUBLEVAX, H5T_VAX_F64_g, COPY, native_double, SET, 8)
1174
1175
    /*------------------------------------------------------------
1176
     * C99 types
1177
     *------------------------------------------------------------
1178
     */
1179
1180
    /* 1-byte little-endian (endianness is irrelevant) signed integer */
1181
2
    H5T_INIT_TYPE(SINTLE, H5T_STD_I8LE_g, COPY, native_int, SET, 1)
1182
1183
    /* 1-byte big-endian (endianness is irrelevant) signed integer */
1184
2
    H5T_INIT_TYPE(SINTBE, H5T_STD_I8BE_g, COPY, native_int, SET, 1)
1185
1186
    /* 2-byte little-endian signed integer */
1187
2
    H5T_INIT_TYPE(SINTLE, H5T_STD_I16LE_g, COPY, native_int, SET, 2)
1188
1189
    /* 2-byte big-endian signed integer */
1190
2
    H5T_INIT_TYPE(SINTBE, H5T_STD_I16BE_g, COPY, native_int, SET, 2)
1191
1192
    /* 4-byte little-endian signed integer */
1193
2
    H5T_INIT_TYPE(SINTLE, H5T_STD_I32LE_g, COPY, native_int, SET, 4)
1194
1195
    /* 4-byte big-endian signed integer */
1196
2
    H5T_INIT_TYPE(SINTBE, H5T_STD_I32BE_g, COPY, native_int, SET, 4)
1197
1198
    /* 8-byte little-endian signed integer */
1199
2
    H5T_INIT_TYPE(SINTLE, H5T_STD_I64LE_g, COPY, native_int, SET, 8)
1200
1201
    /* 8-byte big-endian signed integer */
1202
2
    H5T_INIT_TYPE(SINTBE, H5T_STD_I64BE_g, COPY, native_int, SET, 8)
1203
1204
    /* 1-byte little-endian (endianness is irrelevant) unsigned integer */
1205
2
    H5T_INIT_TYPE(UINTLE, H5T_STD_U8LE_g, COPY, native_uint, SET, 1)
1206
1
    std_u8le = dt; /* Keep type for later */
1207
1208
    /* 1-byte big-endian (endianness is irrelevant) unsigned integer */
1209
1
    H5T_INIT_TYPE(UINTBE, H5T_STD_U8BE_g, COPY, native_uint, SET, 1)
1210
1
    std_u8be = dt; /* Keep type for later */
1211
1212
    /* 2-byte little-endian unsigned integer */
1213
1
    H5T_INIT_TYPE(UINTLE, H5T_STD_U16LE_g, COPY, native_uint, SET, 2)
1214
1
    std_u16le = dt; /* Keep type for later */
1215
1216
    /* 2-byte big-endian unsigned integer */
1217
1
    H5T_INIT_TYPE(UINTBE, H5T_STD_U16BE_g, COPY, native_uint, SET, 2)
1218
1
    std_u16be = dt; /* Keep type for later */
1219
1220
    /* 4-byte little-endian unsigned integer */
1221
1
    H5T_INIT_TYPE(UINTLE, H5T_STD_U32LE_g, COPY, native_uint, SET, 4)
1222
1
    std_u32le = dt; /* Keep type for later */
1223
1224
    /* 4-byte big-endian unsigned integer */
1225
1
    H5T_INIT_TYPE(UINTBE, H5T_STD_U32BE_g, COPY, native_uint, SET, 4)
1226
1
    std_u32be = dt; /* Keep type for later */
1227
1228
    /* 8-byte little-endian unsigned integer */
1229
1
    H5T_INIT_TYPE(UINTLE, H5T_STD_U64LE_g, COPY, native_uint, SET, 8)
1230
1
    std_u64le = dt; /* Keep type for later */
1231
1232
    /* 8-byte big-endian unsigned integer */
1233
1
    H5T_INIT_TYPE(UINTBE, H5T_STD_U64BE_g, COPY, native_uint, SET, 8)
1234
1
    std_u64be = dt; /* Keep type for later */
1235
1236
    /*------------------------------------------------------------
1237
     * Native, Little- & Big-endian bitfields
1238
     *------------------------------------------------------------
1239
     */
1240
1241
    /* little-endian (order is irrelevant) 8-bit bitfield */
1242
1
    H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B8LE_g, COPY, std_u8le, NOSET, -)
1243
1
    bitfield = dt; /* Keep type for later */
1244
1245
    /* big-endian (order is irrelevant) 8-bit bitfield */
1246
1
    H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B8BE_g, COPY, std_u8be, NOSET, -)
1247
1248
    /* Little-endian 16-bit bitfield */
1249
2
    H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B16LE_g, COPY, std_u16le, NOSET, -)
1250
1251
    /* Big-endian 16-bit bitfield */
1252
2
    H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B16BE_g, COPY, std_u16be, NOSET, -)
1253
1254
    /* Little-endian 32-bit bitfield */
1255
2
    H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B32LE_g, COPY, std_u32le, NOSET, -)
1256
1257
    /* Big-endian 32-bit bitfield */
1258
2
    H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B32BE_g, COPY, std_u32be, NOSET, -)
1259
1260
    /* Little-endian 64-bit bitfield */
1261
2
    H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B64LE_g, COPY, std_u64le, NOSET, -)
1262
1263
    /* Big-endian 64-bit bitfield */
1264
2
    H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B64BE_g, COPY, std_u64be, NOSET, -)
1265
1266
    /*------------------------------------------------------------
1267
     * The Unix architecture for dates and times.
1268
     *------------------------------------------------------------
1269
     */
1270
1271
    /* Little-endian 32-bit UNIX time_t */
1272
2
    H5T_INIT_TYPE(TIME, H5T_UNIX_D32LE_g, COPY, std_u32le, NOSET, -)
1273
1274
    /* Big-endian 32-bit UNIX time_t */
1275
2
    H5T_INIT_TYPE(TIME, H5T_UNIX_D32BE_g, COPY, std_u32be, NOSET, -)
1276
1277
    /* Little-endian 64-bit UNIX time_t */
1278
2
    H5T_INIT_TYPE(TIME, H5T_UNIX_D64LE_g, COPY, std_u64le, NOSET, -)
1279
1280
    /* Big-endian 64-bit UNIX time_t */
1281
2
    H5T_INIT_TYPE(TIME, H5T_UNIX_D64BE_g, COPY, std_u64be, NOSET, -)
1282
1283
    /* Indicate that the types that are created from here down are allocated
1284
     * H5FL_ALLOC(), not copied with H5T_copy()
1285
     */
1286
1
    copied_dtype = false;
1287
1288
    /* Opaque data */
1289
1
    H5T_INIT_TYPE(OPAQ, H5T_NATIVE_OPAQUE_g, ALLOC, -, SET, 1)
1290
1291
    /*------------------------------------------------------------
1292
     * The `C' architecture
1293
     *------------------------------------------------------------
1294
     */
1295
1296
    /* One-byte character string */
1297
2
    H5T_INIT_TYPE(CSTRING, H5T_C_S1_g, ALLOC, -, SET, 1)
1298
1
    string = dt; /* Keep type for later */
1299
1300
    /*------------------------------------------------------------
1301
     * The `Fortran' architecture
1302
     *------------------------------------------------------------
1303
     */
1304
1305
    /* One-byte character string */
1306
1
    H5T_INIT_TYPE(FORSTRING, H5T_FORTRAN_S1_g, ALLOC, -, SET, 1)
1307
1308
    /*------------------------------------------------------------
1309
     * Reference types
1310
     *------------------------------------------------------------
1311
     */
1312
1313
    /* Deprecated object reference type */
1314
2
    H5T_INIT_TYPE(OBJREF, H5T_STD_REF_OBJ_g, ALLOC, -, NOSET, -)
1315
1
    if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
1316
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
1317
1
    objref = dt; /* Keep type for later */
1318
1319
    /* Deprecated region reference type */
1320
1
    H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, NOSET, -)
1321
1
    if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
1322
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
1323
1
    regref = dt; /* Keep type for later */
1324
1325
    /* Opaque reference type */
1326
1
    H5T_INIT_TYPE(REF, H5T_STD_REF_g, ALLOC, -, NOSET, -)
1327
1
    if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
1328
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
1329
1
    ref = dt; /* Keep type for later */
1330
1331
    /*------------------------------------------------------------
1332
     * Complex Number Types
1333
     *------------------------------------------------------------
1334
     */
1335
1336
    /* Complex number of 2 IEEE 2-byte little-endian floats */
1337
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F16LE)))
1338
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1339
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1340
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1341
1
    if ((H5T_COMPLEX_IEEE_F16LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1342
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1343
1344
    /* Complex number of 2 IEEE 2-byte big-endian floats */
1345
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F16BE)))
1346
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1347
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1348
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1349
1
    if ((H5T_COMPLEX_IEEE_F16BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1350
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1351
1352
    /* Complex number of 2 IEEE 4-byte little-endian floats */
1353
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F32LE)))
1354
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1355
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1356
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1357
1
    if ((H5T_COMPLEX_IEEE_F32LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1358
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1359
1360
    /* Complex number of 2 IEEE 4-byte big-endian floats */
1361
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F32BE)))
1362
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1363
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1364
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1365
1
    if ((H5T_COMPLEX_IEEE_F32BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1366
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1367
1368
    /* Complex number of 2 IEEE 8-byte little-endian floats */
1369
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F64LE)))
1370
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1371
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1372
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1373
1
    if ((H5T_COMPLEX_IEEE_F64LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1374
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1375
1376
    /* Complex number of 2 IEEE 8-byte big-endian floats */
1377
1
    if (NULL == (tmp_float = H5I_object(H5T_IEEE_F64BE)))
1378
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
1379
1
    if (NULL == (dt = H5T__complex_create(tmp_float)))
1380
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype");
1381
1
    if ((H5T_COMPLEX_IEEE_F64BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0)
1382
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom");
1383
1384
    /*
1385
     * Register conversion functions beginning with the most general and
1386
     * ending with the most specific.
1387
     */
1388
1
    fixedpt = native_int;
1389
1
    floatpt = native_float;
1390
1
    if (NULL == (compound = H5T__create(H5T_COMPOUND, (size_t)1)))
1391
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
1392
1
    if (NULL == (enum_type = H5T__create(H5T_ENUM, (size_t)1)))
1393
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
1394
1
    if (NULL == (vlen = H5T__vlen_create(native_int)))
1395
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
1396
1
    if (NULL == (array = H5T__array_create(native_int, 1, dim)))
1397
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
1398
1
    if (NULL == (cplx = H5T__complex_create(native_float)))
1399
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
1400
1
    status = 0;
1401
1402
1
    status |= H5T__register_int(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T__conv_i_i);
1403
1
    status |= H5T__register_int(H5T_PERS_SOFT, "i_f", fixedpt, floatpt, H5T__conv_i_f);
1404
1
    status |= H5T__register_int(H5T_PERS_SOFT, "i_complex", fixedpt, cplx, H5T__conv_i_complex);
1405
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complex_i", cplx, fixedpt, H5T__conv_complex_i);
1406
1
    status |= H5T__register_int(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T__conv_f_f);
1407
1
    status |= H5T__register_int(H5T_PERS_SOFT, "f_i", floatpt, fixedpt, H5T__conv_f_i);
1408
1
    status |= H5T__register_int(H5T_PERS_SOFT, "f_complex", floatpt, cplx, H5T__conv_f_complex);
1409
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complex_f", cplx, floatpt, H5T__conv_complex_f);
1410
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complex_complex", cplx, cplx, H5T__conv_complex);
1411
1
    status |= H5T__register_int(H5T_PERS_SOFT, "s_s", string, string, H5T__conv_s_s);
1412
1
    status |= H5T__register_int(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T__conv_b_b);
1413
1
    status |= H5T__register_int(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T__conv_order);
1414
1
    status |= H5T__register_int(H5T_PERS_SOFT, "ibo(opt)", fixedpt, fixedpt, H5T__conv_order_opt);
1415
1
    status |= H5T__register_int(H5T_PERS_SOFT, "fbo", floatpt, floatpt, H5T__conv_order);
1416
1
    status |= H5T__register_int(H5T_PERS_SOFT, "fbo(opt)", floatpt, floatpt, H5T__conv_order_opt);
1417
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complexbo", cplx, cplx, H5T__conv_order);
1418
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complexbo(opt)", cplx, cplx, H5T__conv_order_opt);
1419
1
    status |= H5T__register_int(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T__conv_struct);
1420
1
    status |= H5T__register_int(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T__conv_struct_opt);
1421
1
    status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum);
1422
1
    status |= H5T__register_int(H5T_PERS_SOFT, "enum_i", enum_type, fixedpt, H5T__conv_enum_numeric);
1423
1
    status |= H5T__register_int(H5T_PERS_SOFT, "enum_f", enum_type, floatpt, H5T__conv_enum_numeric);
1424
1
    status |= H5T__register_int(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T__conv_vlen);
1425
1
    status |= H5T__register_int(H5T_PERS_SOFT, "array", array, array, H5T__conv_array);
1426
1
    status |= H5T__register_int(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_noop);
1427
1
    status |= H5T__register_int(H5T_PERS_SOFT, "regref", regref, regref, H5T__conv_noop);
1428
1
    status |= H5T__register_int(H5T_PERS_SOFT, "ref", ref, ref, H5T__conv_ref);
1429
1
    status |= H5T__register_int(H5T_PERS_SOFT, "objref_ref", objref, ref, H5T__conv_ref);
1430
1
    status |= H5T__register_int(H5T_PERS_SOFT, "regref_ref", regref, ref, H5T__conv_ref);
1431
1
    status |= H5T__register_int(H5T_PERS_SOFT, "complex_array_compat", cplx, array, H5T__conv_complex_compat);
1432
1
    status |= H5T__register_int(H5T_PERS_SOFT, "array_complex_compat", array, cplx, H5T__conv_complex_compat);
1433
1
    status |=
1434
1
        H5T__register_int(H5T_PERS_SOFT, "complex_compound_compat", cplx, compound, H5T__conv_complex_compat);
1435
1
    status |=
1436
1
        H5T__register_int(H5T_PERS_SOFT, "compound_complex_compat", compound, cplx, H5T__conv_complex_compat);
1437
1438
    /*
1439
     * Native conversions should be listed last since we can use hardware to
1440
     * perform the conversion.  We list the odd types like `llong', `long',
1441
     * and `short' before the usual types like `int' and `char' so that when
1442
     * diagnostics are printed we favor the usual names over the odd names
1443
     * when two or more types are the same size.
1444
     */
1445
1446
    /* floating point */
1447
1
    status |=
1448
1
        H5T__register_int(H5T_PERS_HARD, "flt_dbl", native_float, native_double, H5T__conv_float_double);
1449
1
    status |=
1450
1
        H5T__register_int(H5T_PERS_HARD, "dbl_flt", native_double, native_float, H5T__conv_double_float);
1451
1
    status |=
1452
1
        H5T__register_int(H5T_PERS_HARD, "flt_ldbl", native_float, native_ldouble, H5T__conv_float_ldouble);
1453
1
    status |=
1454
1
        H5T__register_int(H5T_PERS_HARD, "dbl_ldbl", native_double, native_ldouble, H5T__conv_double_ldouble);
1455
1
    status |=
1456
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_flt", native_ldouble, native_float, H5T__conv_ldouble_float);
1457
1
    status |=
1458
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_dbl", native_ldouble, native_double, H5T__conv_ldouble_double);
1459
#ifdef H5_HAVE__FLOAT16
1460
    status |=
1461
        H5T__register_int(H5T_PERS_HARD, "flt16_flt", native_float16, native_float, H5T__conv__Float16_float);
1462
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_dbl", native_float16, native_double,
1463
                                H5T__conv__Float16_double);
1464
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_ldbl", native_float16, native_ldouble,
1465
                                H5T__conv__Float16_ldouble);
1466
    status |=
1467
        H5T__register_int(H5T_PERS_HARD, "flt_flt16", native_float, native_float16, H5T__conv_float__Float16);
1468
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_flt16", native_double, native_float16,
1469
                                H5T__conv_double__Float16);
1470
#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16
1471
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_flt16", native_ldouble, native_float16,
1472
                                H5T__conv_ldouble__Float16);
1473
#endif
1474
#endif
1475
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1476
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_fcomplex", native_float, native_float_complex,
1477
1
                                H5T__conv_float_fcomplex);
1478
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_dcomplex", native_float, native_double_complex,
1479
1
                                H5T__conv_float_dcomplex);
1480
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_lcomplex", native_float, native_ldouble_complex,
1481
1
                                H5T__conv_float_lcomplex);
1482
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_fcomplex", native_double, native_float_complex,
1483
1
                                H5T__conv_double_fcomplex);
1484
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_dcomplex", native_double, native_double_complex,
1485
1
                                H5T__conv_double_dcomplex);
1486
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_lcomplex", native_double, native_ldouble_complex,
1487
1
                                H5T__conv_double_lcomplex);
1488
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_fcomplex", native_ldouble, native_float_complex,
1489
1
                                H5T__conv_ldouble_fcomplex);
1490
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_dcomplex", native_ldouble, native_double_complex,
1491
1
                                H5T__conv_ldouble_dcomplex);
1492
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_lcomplex", native_ldouble, native_ldouble_complex,
1493
1
                                H5T__conv_ldouble_lcomplex);
1494
#ifdef H5_HAVE__FLOAT16
1495
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_fcomplex", native_float16, native_float_complex,
1496
                                H5T__conv__Float16_fcomplex);
1497
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_dcomplex", native_float16, native_double_complex,
1498
                                H5T__conv__Float16_dcomplex);
1499
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_lcomplex", native_float16, native_ldouble_complex,
1500
                                H5T__conv__Float16_lcomplex);
1501
#endif
1502
1
#endif
1503
1504
    /* from long long */
1505
1
    status |=
1506
1
        H5T__register_int(H5T_PERS_HARD, "llong_ullong", native_llong, native_ullong, H5T__conv_llong_ullong);
1507
1
    status |=
1508
1
        H5T__register_int(H5T_PERS_HARD, "ullong_llong", native_ullong, native_llong, H5T__conv_ullong_llong);
1509
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_long", native_llong, native_long, H5T__conv_llong_long);
1510
1
    status |=
1511
1
        H5T__register_int(H5T_PERS_HARD, "llong_ulong", native_llong, native_ulong, H5T__conv_llong_ulong);
1512
1
    status |=
1513
1
        H5T__register_int(H5T_PERS_HARD, "ullong_long", native_ullong, native_long, H5T__conv_ullong_long);
1514
1
    status |=
1515
1
        H5T__register_int(H5T_PERS_HARD, "ullong_ulong", native_ullong, native_ulong, H5T__conv_ullong_ulong);
1516
1
    status |=
1517
1
        H5T__register_int(H5T_PERS_HARD, "llong_short", native_llong, native_short, H5T__conv_llong_short);
1518
1
    status |=
1519
1
        H5T__register_int(H5T_PERS_HARD, "llong_ushort", native_llong, native_ushort, H5T__conv_llong_ushort);
1520
1
    status |=
1521
1
        H5T__register_int(H5T_PERS_HARD, "ullong_short", native_ullong, native_short, H5T__conv_ullong_short);
1522
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_ushort", native_ullong, native_ushort,
1523
1
                                H5T__conv_ullong_ushort);
1524
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_int", native_llong, native_int, H5T__conv_llong_int);
1525
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_uint", native_llong, native_uint, H5T__conv_llong_uint);
1526
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_int", native_ullong, native_int, H5T__conv_ullong_int);
1527
1
    status |=
1528
1
        H5T__register_int(H5T_PERS_HARD, "ullong_uint", native_ullong, native_uint, H5T__conv_ullong_uint);
1529
1
    status |=
1530
1
        H5T__register_int(H5T_PERS_HARD, "llong_schar", native_llong, native_schar, H5T__conv_llong_schar);
1531
1
    status |=
1532
1
        H5T__register_int(H5T_PERS_HARD, "llong_uchar", native_llong, native_uchar, H5T__conv_llong_uchar);
1533
1
    status |=
1534
1
        H5T__register_int(H5T_PERS_HARD, "ullong_schar", native_ullong, native_schar, H5T__conv_ullong_schar);
1535
1
    status |=
1536
1
        H5T__register_int(H5T_PERS_HARD, "ullong_uchar", native_ullong, native_uchar, H5T__conv_ullong_uchar);
1537
1538
    /* From long */
1539
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_llong", native_long, native_llong, H5T__conv_long_llong);
1540
1
    status |=
1541
1
        H5T__register_int(H5T_PERS_HARD, "long_ullong", native_long, native_ullong, H5T__conv_long_ullong);
1542
1
    status |=
1543
1
        H5T__register_int(H5T_PERS_HARD, "ulong_llong", native_ulong, native_llong, H5T__conv_ulong_llong);
1544
1
    status |=
1545
1
        H5T__register_int(H5T_PERS_HARD, "ulong_ullong", native_ulong, native_ullong, H5T__conv_ulong_ullong);
1546
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_ulong", native_long, native_ulong, H5T__conv_long_ulong);
1547
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_long", native_ulong, native_long, H5T__conv_ulong_long);
1548
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_short", native_long, native_short, H5T__conv_long_short);
1549
1
    status |=
1550
1
        H5T__register_int(H5T_PERS_HARD, "long_ushort", native_long, native_ushort, H5T__conv_long_ushort);
1551
1
    status |=
1552
1
        H5T__register_int(H5T_PERS_HARD, "ulong_short", native_ulong, native_short, H5T__conv_ulong_short);
1553
1
    status |=
1554
1
        H5T__register_int(H5T_PERS_HARD, "ulong_ushort", native_ulong, native_ushort, H5T__conv_ulong_ushort);
1555
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_int", native_long, native_int, H5T__conv_long_int);
1556
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_uint", native_long, native_uint, H5T__conv_long_uint);
1557
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_int", native_ulong, native_int, H5T__conv_ulong_int);
1558
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_uint", native_ulong, native_uint, H5T__conv_ulong_uint);
1559
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_schar", native_long, native_schar, H5T__conv_long_schar);
1560
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_uchar", native_long, native_uchar, H5T__conv_long_uchar);
1561
1
    status |=
1562
1
        H5T__register_int(H5T_PERS_HARD, "ulong_schar", native_ulong, native_schar, H5T__conv_ulong_schar);
1563
1
    status |=
1564
1
        H5T__register_int(H5T_PERS_HARD, "ulong_uchar", native_ulong, native_uchar, H5T__conv_ulong_uchar);
1565
1566
    /* From short */
1567
1
    status |=
1568
1
        H5T__register_int(H5T_PERS_HARD, "short_llong", native_short, native_llong, H5T__conv_short_llong);
1569
1
    status |=
1570
1
        H5T__register_int(H5T_PERS_HARD, "short_ullong", native_short, native_ullong, H5T__conv_short_ullong);
1571
1
    status |=
1572
1
        H5T__register_int(H5T_PERS_HARD, "ushort_llong", native_ushort, native_llong, H5T__conv_ushort_llong);
1573
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_ullong", native_ushort, native_ullong,
1574
1
                                H5T__conv_ushort_ullong);
1575
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_long", native_short, native_long, H5T__conv_short_long);
1576
1
    status |=
1577
1
        H5T__register_int(H5T_PERS_HARD, "short_ulong", native_short, native_ulong, H5T__conv_short_ulong);
1578
1
    status |=
1579
1
        H5T__register_int(H5T_PERS_HARD, "ushort_long", native_ushort, native_long, H5T__conv_ushort_long);
1580
1
    status |=
1581
1
        H5T__register_int(H5T_PERS_HARD, "ushort_ulong", native_ushort, native_ulong, H5T__conv_ushort_ulong);
1582
1
    status |=
1583
1
        H5T__register_int(H5T_PERS_HARD, "short_ushort", native_short, native_ushort, H5T__conv_short_ushort);
1584
1
    status |=
1585
1
        H5T__register_int(H5T_PERS_HARD, "ushort_short", native_ushort, native_short, H5T__conv_ushort_short);
1586
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_int", native_short, native_int, H5T__conv_short_int);
1587
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_uint", native_short, native_uint, H5T__conv_short_uint);
1588
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_int", native_ushort, native_int, H5T__conv_ushort_int);
1589
1
    status |=
1590
1
        H5T__register_int(H5T_PERS_HARD, "ushort_uint", native_ushort, native_uint, H5T__conv_ushort_uint);
1591
1
    status |=
1592
1
        H5T__register_int(H5T_PERS_HARD, "short_schar", native_short, native_schar, H5T__conv_short_schar);
1593
1
    status |=
1594
1
        H5T__register_int(H5T_PERS_HARD, "short_uchar", native_short, native_uchar, H5T__conv_short_uchar);
1595
1
    status |=
1596
1
        H5T__register_int(H5T_PERS_HARD, "ushort_schar", native_ushort, native_schar, H5T__conv_ushort_schar);
1597
1
    status |=
1598
1
        H5T__register_int(H5T_PERS_HARD, "ushort_uchar", native_ushort, native_uchar, H5T__conv_ushort_uchar);
1599
1600
    /* From int */
1601
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_llong", native_int, native_llong, H5T__conv_int_llong);
1602
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_ullong", native_int, native_ullong, H5T__conv_int_ullong);
1603
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_llong", native_uint, native_llong, H5T__conv_uint_llong);
1604
1
    status |=
1605
1
        H5T__register_int(H5T_PERS_HARD, "uint_ullong", native_uint, native_ullong, H5T__conv_uint_ullong);
1606
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_long", native_int, native_long, H5T__conv_int_long);
1607
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_ulong", native_int, native_ulong, H5T__conv_int_ulong);
1608
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_long", native_uint, native_long, H5T__conv_uint_long);
1609
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_ulong", native_uint, native_ulong, H5T__conv_uint_ulong);
1610
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_short", native_int, native_short, H5T__conv_int_short);
1611
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_ushort", native_int, native_ushort, H5T__conv_int_ushort);
1612
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_short", native_uint, native_short, H5T__conv_uint_short);
1613
1
    status |=
1614
1
        H5T__register_int(H5T_PERS_HARD, "uint_ushort", native_uint, native_ushort, H5T__conv_uint_ushort);
1615
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_uint", native_int, native_uint, H5T__conv_int_uint);
1616
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_int", native_uint, native_int, H5T__conv_uint_int);
1617
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_schar", native_int, native_schar, H5T__conv_int_schar);
1618
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_uchar", native_int, native_uchar, H5T__conv_int_uchar);
1619
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_schar", native_uint, native_schar, H5T__conv_uint_schar);
1620
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_uchar", native_uint, native_uchar, H5T__conv_uint_uchar);
1621
1622
    /* From char */
1623
1
    status |=
1624
1
        H5T__register_int(H5T_PERS_HARD, "schar_llong", native_schar, native_llong, H5T__conv_schar_llong);
1625
1
    status |=
1626
1
        H5T__register_int(H5T_PERS_HARD, "schar_ullong", native_schar, native_ullong, H5T__conv_schar_ullong);
1627
1
    status |=
1628
1
        H5T__register_int(H5T_PERS_HARD, "uchar_llong", native_uchar, native_llong, H5T__conv_uchar_llong);
1629
1
    status |=
1630
1
        H5T__register_int(H5T_PERS_HARD, "uchar_ullong", native_uchar, native_ullong, H5T__conv_uchar_ullong);
1631
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_long", native_schar, native_long, H5T__conv_schar_long);
1632
1
    status |=
1633
1
        H5T__register_int(H5T_PERS_HARD, "schar_ulong", native_schar, native_ulong, H5T__conv_schar_ulong);
1634
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_long", native_uchar, native_long, H5T__conv_uchar_long);
1635
1
    status |=
1636
1
        H5T__register_int(H5T_PERS_HARD, "uchar_ulong", native_uchar, native_ulong, H5T__conv_uchar_ulong);
1637
1
    status |=
1638
1
        H5T__register_int(H5T_PERS_HARD, "schar_short", native_schar, native_short, H5T__conv_schar_short);
1639
1
    status |=
1640
1
        H5T__register_int(H5T_PERS_HARD, "schar_ushort", native_schar, native_ushort, H5T__conv_schar_ushort);
1641
1
    status |=
1642
1
        H5T__register_int(H5T_PERS_HARD, "uchar_short", native_uchar, native_short, H5T__conv_uchar_short);
1643
1
    status |=
1644
1
        H5T__register_int(H5T_PERS_HARD, "uchar_ushort", native_uchar, native_ushort, H5T__conv_uchar_ushort);
1645
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_int", native_schar, native_int, H5T__conv_schar_int);
1646
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_uint", native_schar, native_uint, H5T__conv_schar_uint);
1647
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_int", native_uchar, native_int, H5T__conv_uchar_int);
1648
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_uint", native_uchar, native_uint, H5T__conv_uchar_uint);
1649
1
    status |=
1650
1
        H5T__register_int(H5T_PERS_HARD, "schar_uchar", native_schar, native_uchar, H5T__conv_schar_uchar);
1651
1
    status |=
1652
1
        H5T__register_int(H5T_PERS_HARD, "uchar_schar", native_uchar, native_schar, H5T__conv_uchar_schar);
1653
1654
    /* From char to floats */
1655
1
    status |=
1656
1
        H5T__register_int(H5T_PERS_HARD, "schar_flt", native_schar, native_float, H5T__conv_schar_float);
1657
1
    status |=
1658
1
        H5T__register_int(H5T_PERS_HARD, "schar_dbl", native_schar, native_double, H5T__conv_schar_double);
1659
1
    status |=
1660
1
        H5T__register_int(H5T_PERS_HARD, "schar_ldbl", native_schar, native_ldouble, H5T__conv_schar_ldouble);
1661
#ifdef H5_HAVE__FLOAT16
1662
    status |= H5T__register_int(H5T_PERS_HARD, "schar_flt16", native_schar, native_float16,
1663
                                H5T__conv_schar__Float16);
1664
#endif
1665
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1666
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_fcomplex", native_schar, native_float_complex,
1667
1
                                H5T__conv_schar_fcomplex);
1668
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_dcomplex", native_schar, native_double_complex,
1669
1
                                H5T__conv_schar_dcomplex);
1670
1
    status |= H5T__register_int(H5T_PERS_HARD, "schar_lcomplex", native_schar, native_ldouble_complex,
1671
1
                                H5T__conv_schar_lcomplex);
1672
1
#endif
1673
1674
    /* From unsigned char to floats */
1675
1
    status |=
1676
1
        H5T__register_int(H5T_PERS_HARD, "uchar_flt", native_uchar, native_float, H5T__conv_uchar_float);
1677
1
    status |=
1678
1
        H5T__register_int(H5T_PERS_HARD, "uchar_dbl", native_uchar, native_double, H5T__conv_uchar_double);
1679
1
    status |=
1680
1
        H5T__register_int(H5T_PERS_HARD, "uchar_ldbl", native_uchar, native_ldouble, H5T__conv_uchar_ldouble);
1681
#ifdef H5_HAVE__FLOAT16
1682
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_flt16", native_uchar, native_float16,
1683
                                H5T__conv_uchar__Float16);
1684
#endif
1685
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1686
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_fcomplex", native_uchar, native_float_complex,
1687
1
                                H5T__conv_uchar_fcomplex);
1688
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_dcomplex", native_uchar, native_double_complex,
1689
1
                                H5T__conv_uchar_dcomplex);
1690
1
    status |= H5T__register_int(H5T_PERS_HARD, "uchar_lcomplex", native_uchar, native_ldouble_complex,
1691
1
                                H5T__conv_uchar_lcomplex);
1692
1
#endif
1693
1694
    /* From short to floats */
1695
1
    status |=
1696
1
        H5T__register_int(H5T_PERS_HARD, "short_flt", native_short, native_float, H5T__conv_short_float);
1697
1
    status |=
1698
1
        H5T__register_int(H5T_PERS_HARD, "short_dbl", native_short, native_double, H5T__conv_short_double);
1699
1
    status |=
1700
1
        H5T__register_int(H5T_PERS_HARD, "short_ldbl", native_short, native_ldouble, H5T__conv_short_ldouble);
1701
#ifdef H5_HAVE__FLOAT16
1702
    status |= H5T__register_int(H5T_PERS_HARD, "short_flt16", native_short, native_float16,
1703
                                H5T__conv_short__Float16);
1704
#endif
1705
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1706
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_fcomplex", native_short, native_float_complex,
1707
1
                                H5T__conv_short_fcomplex);
1708
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_dcomplex", native_short, native_double_complex,
1709
1
                                H5T__conv_short_dcomplex);
1710
1
    status |= H5T__register_int(H5T_PERS_HARD, "short_lcomplex", native_short, native_ldouble_complex,
1711
1
                                H5T__conv_short_lcomplex);
1712
1
#endif
1713
1714
    /* From unsigned short to floats */
1715
1
    status |=
1716
1
        H5T__register_int(H5T_PERS_HARD, "ushort_flt", native_ushort, native_float, H5T__conv_ushort_float);
1717
1
    status |=
1718
1
        H5T__register_int(H5T_PERS_HARD, "ushort_dbl", native_ushort, native_double, H5T__conv_ushort_double);
1719
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_ldbl", native_ushort, native_ldouble,
1720
1
                                H5T__conv_ushort_ldouble);
1721
#ifdef H5_HAVE__FLOAT16
1722
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_flt16", native_ushort, native_float16,
1723
                                H5T__conv_ushort__Float16);
1724
#endif
1725
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1726
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_fcomplex", native_ushort, native_float_complex,
1727
1
                                H5T__conv_ushort_fcomplex);
1728
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_dcomplex", native_ushort, native_double_complex,
1729
1
                                H5T__conv_ushort_dcomplex);
1730
1
    status |= H5T__register_int(H5T_PERS_HARD, "ushort_lcomplex", native_ushort, native_ldouble_complex,
1731
1
                                H5T__conv_ushort_lcomplex);
1732
1
#endif
1733
1734
    /* From int to floats */
1735
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_flt", native_int, native_float, H5T__conv_int_float);
1736
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_dbl", native_int, native_double, H5T__conv_int_double);
1737
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_ldbl", native_int, native_ldouble, H5T__conv_int_ldouble);
1738
#ifdef H5_HAVE__FLOAT16
1739
    status |=
1740
        H5T__register_int(H5T_PERS_HARD, "int_flt16", native_int, native_float16, H5T__conv_int__Float16);
1741
#endif
1742
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1743
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_fcomplex", native_int, native_float_complex,
1744
1
                                H5T__conv_int_fcomplex);
1745
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_dcomplex", native_int, native_double_complex,
1746
1
                                H5T__conv_int_dcomplex);
1747
1
    status |= H5T__register_int(H5T_PERS_HARD, "int_lcomplex", native_int, native_ldouble_complex,
1748
1
                                H5T__conv_int_lcomplex);
1749
1
#endif
1750
1751
    /* From unsigned int to floats */
1752
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_flt", native_uint, native_float, H5T__conv_uint_float);
1753
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_dbl", native_uint, native_double, H5T__conv_uint_double);
1754
1
    status |=
1755
1
        H5T__register_int(H5T_PERS_HARD, "uint_ldbl", native_uint, native_ldouble, H5T__conv_uint_ldouble);
1756
#ifdef H5_HAVE__FLOAT16
1757
    status |=
1758
        H5T__register_int(H5T_PERS_HARD, "uint_flt16", native_uint, native_float16, H5T__conv_uint__Float16);
1759
#endif
1760
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1761
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_fcomplex", native_uint, native_float_complex,
1762
1
                                H5T__conv_uint_fcomplex);
1763
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_dcomplex", native_uint, native_double_complex,
1764
1
                                H5T__conv_uint_dcomplex);
1765
1
    status |= H5T__register_int(H5T_PERS_HARD, "uint_lcomplex", native_uint, native_ldouble_complex,
1766
1
                                H5T__conv_uint_lcomplex);
1767
1
#endif
1768
1769
    /* From long to floats */
1770
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_flt", native_long, native_float, H5T__conv_long_float);
1771
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_dbl", native_long, native_double, H5T__conv_long_double);
1772
1
    status |=
1773
1
        H5T__register_int(H5T_PERS_HARD, "long_ldbl", native_long, native_ldouble, H5T__conv_long_ldouble);
1774
#ifdef H5_HAVE__FLOAT16
1775
    status |=
1776
        H5T__register_int(H5T_PERS_HARD, "long_flt16", native_long, native_float16, H5T__conv_long__Float16);
1777
#endif
1778
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1779
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_fcomplex", native_long, native_float_complex,
1780
1
                                H5T__conv_long_fcomplex);
1781
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_dcomplex", native_long, native_double_complex,
1782
1
                                H5T__conv_long_dcomplex);
1783
1
    status |= H5T__register_int(H5T_PERS_HARD, "long_lcomplex", native_long, native_ldouble_complex,
1784
1
                                H5T__conv_long_lcomplex);
1785
1
#endif
1786
1787
    /* From unsigned long to floats */
1788
1
    status |=
1789
1
        H5T__register_int(H5T_PERS_HARD, "ulong_flt", native_ulong, native_float, H5T__conv_ulong_float);
1790
1
    status |=
1791
1
        H5T__register_int(H5T_PERS_HARD, "ulong_dbl", native_ulong, native_double, H5T__conv_ulong_double);
1792
1
    status |=
1793
1
        H5T__register_int(H5T_PERS_HARD, "ulong_ldbl", native_ulong, native_ldouble, H5T__conv_ulong_ldouble);
1794
#ifdef H5_HAVE__FLOAT16
1795
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_flt16", native_ulong, native_float16,
1796
                                H5T__conv_ulong__Float16);
1797
#endif
1798
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1799
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_fcomplex", native_ulong, native_float_complex,
1800
1
                                H5T__conv_ulong_fcomplex);
1801
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_dcomplex", native_ulong, native_double_complex,
1802
1
                                H5T__conv_ulong_dcomplex);
1803
1
    status |= H5T__register_int(H5T_PERS_HARD, "ulong_lcomplex", native_ulong, native_ldouble_complex,
1804
1
                                H5T__conv_ulong_lcomplex);
1805
1
#endif
1806
1807
    /* From long long to floats */
1808
1
    status |=
1809
1
        H5T__register_int(H5T_PERS_HARD, "llong_flt", native_llong, native_float, H5T__conv_llong_float);
1810
1
    status |=
1811
1
        H5T__register_int(H5T_PERS_HARD, "llong_dbl", native_llong, native_double, H5T__conv_llong_double);
1812
1
#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE
1813
1
    status |=
1814
1
        H5T__register_int(H5T_PERS_HARD, "llong_ldbl", native_llong, native_ldouble, H5T__conv_llong_ldouble);
1815
1
#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */
1816
#ifdef H5_HAVE__FLOAT16
1817
    status |= H5T__register_int(H5T_PERS_HARD, "llong_flt16", native_llong, native_float16,
1818
                                H5T__conv_llong__Float16);
1819
#endif
1820
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1821
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_fcomplex", native_llong, native_float_complex,
1822
1
                                H5T__conv_llong_fcomplex);
1823
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_dcomplex", native_llong, native_double_complex,
1824
1
                                H5T__conv_llong_dcomplex);
1825
1
#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE
1826
1
    status |= H5T__register_int(H5T_PERS_HARD, "llong_lcomplex", native_llong, native_ldouble_complex,
1827
1
                                H5T__conv_llong_lcomplex);
1828
1
#endif
1829
1
#endif
1830
1831
    /* From unsigned long long to floats */
1832
1
    status |=
1833
1
        H5T__register_int(H5T_PERS_HARD, "ullong_flt", native_ullong, native_float, H5T__conv_ullong_float);
1834
1
    status |=
1835
1
        H5T__register_int(H5T_PERS_HARD, "ullong_dbl", native_ullong, native_double, H5T__conv_ullong_double);
1836
1
#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE
1837
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_ldbl", native_ullong, native_ldouble,
1838
1
                                H5T__conv_ullong_ldouble);
1839
1
#endif /* H5T_CONV_INTERNAL_ULLONG_LDOUBLE */
1840
#ifdef H5_HAVE__FLOAT16
1841
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_flt16", native_ullong, native_float16,
1842
                                H5T__conv_ullong__Float16);
1843
#endif
1844
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1845
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_fcomplex", native_ullong, native_float_complex,
1846
1
                                H5T__conv_ullong_fcomplex);
1847
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_dcomplex", native_ullong, native_double_complex,
1848
1
                                H5T__conv_ullong_dcomplex);
1849
1
#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE
1850
1
    status |= H5T__register_int(H5T_PERS_HARD, "ullong_lcomplex", native_ullong, native_ldouble_complex,
1851
1
                                H5T__conv_ullong_lcomplex);
1852
1
#endif
1853
1
#endif
1854
1855
    /* From floats to char */
1856
1
    status |=
1857
1
        H5T__register_int(H5T_PERS_HARD, "flt_schar", native_float, native_schar, H5T__conv_float_schar);
1858
1
    status |=
1859
1
        H5T__register_int(H5T_PERS_HARD, "dbl_schar", native_double, native_schar, H5T__conv_double_schar);
1860
1
    status |=
1861
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_schar", native_ldouble, native_schar, H5T__conv_ldouble_schar);
1862
#ifdef H5_HAVE__FLOAT16
1863
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_schar", native_float16, native_schar,
1864
                                H5T__conv__Float16_schar);
1865
#endif
1866
1867
    /* From floats to unsigned char */
1868
1
    status |=
1869
1
        H5T__register_int(H5T_PERS_HARD, "flt_uchar", native_float, native_uchar, H5T__conv_float_uchar);
1870
1
    status |=
1871
1
        H5T__register_int(H5T_PERS_HARD, "dbl_uchar", native_double, native_uchar, H5T__conv_double_uchar);
1872
1
    status |=
1873
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_uchar", native_ldouble, native_uchar, H5T__conv_ldouble_uchar);
1874
#ifdef H5_HAVE__FLOAT16
1875
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_uchar", native_float16, native_uchar,
1876
                                H5T__conv__Float16_uchar);
1877
#endif
1878
1879
    /* From floats to short */
1880
1
    status |=
1881
1
        H5T__register_int(H5T_PERS_HARD, "flt_short", native_float, native_short, H5T__conv_float_short);
1882
1
    status |=
1883
1
        H5T__register_int(H5T_PERS_HARD, "dbl_short", native_double, native_short, H5T__conv_double_short);
1884
1
    status |=
1885
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_short", native_ldouble, native_short, H5T__conv_ldouble_short);
1886
#ifdef H5_HAVE__FLOAT16
1887
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_short", native_float16, native_short,
1888
                                H5T__conv__Float16_short);
1889
#endif
1890
1891
    /* From floats to unsigned short */
1892
1
    status |=
1893
1
        H5T__register_int(H5T_PERS_HARD, "flt_ushort", native_float, native_ushort, H5T__conv_float_ushort);
1894
1
    status |=
1895
1
        H5T__register_int(H5T_PERS_HARD, "dbl_ushort", native_double, native_ushort, H5T__conv_double_ushort);
1896
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ushort", native_ldouble, native_ushort,
1897
1
                                H5T__conv_ldouble_ushort);
1898
#ifdef H5_HAVE__FLOAT16
1899
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_ushort", native_float16, native_ushort,
1900
                                H5T__conv__Float16_ushort);
1901
#endif
1902
1903
    /* From floats to int */
1904
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_int", native_float, native_int, H5T__conv_float_int);
1905
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_int", native_double, native_int, H5T__conv_double_int);
1906
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_int", native_ldouble, native_int, H5T__conv_ldouble_int);
1907
#ifdef H5_HAVE__FLOAT16
1908
    status |=
1909
        H5T__register_int(H5T_PERS_HARD, "flt16_int", native_float16, native_int, H5T__conv__Float16_int);
1910
#endif
1911
1912
    /* From floats to unsigned int */
1913
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_uint", native_float, native_uint, H5T__conv_float_uint);
1914
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_uint", native_double, native_uint, H5T__conv_double_uint);
1915
1
    status |=
1916
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_uint", native_ldouble, native_uint, H5T__conv_ldouble_uint);
1917
#ifdef H5_HAVE__FLOAT16
1918
    status |=
1919
        H5T__register_int(H5T_PERS_HARD, "flt16_uint", native_float16, native_uint, H5T__conv__Float16_uint);
1920
#endif
1921
1922
    /* From floats to long */
1923
1
    status |= H5T__register_int(H5T_PERS_HARD, "flt_long", native_float, native_long, H5T__conv_float_long);
1924
1
    status |= H5T__register_int(H5T_PERS_HARD, "dbl_long", native_double, native_long, H5T__conv_double_long);
1925
1
    status |=
1926
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_long", native_ldouble, native_long, H5T__conv_ldouble_long);
1927
#ifdef H5_HAVE__FLOAT16
1928
    status |=
1929
        H5T__register_int(H5T_PERS_HARD, "flt16_long", native_float16, native_long, H5T__conv__Float16_long);
1930
#endif
1931
1932
    /* From floats to unsigned long */
1933
1
    status |=
1934
1
        H5T__register_int(H5T_PERS_HARD, "flt_ulong", native_float, native_ulong, H5T__conv_float_ulong);
1935
1
    status |=
1936
1
        H5T__register_int(H5T_PERS_HARD, "dbl_ulong", native_double, native_ulong, H5T__conv_double_ulong);
1937
1
    status |=
1938
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_ulong", native_ldouble, native_ulong, H5T__conv_ldouble_ulong);
1939
#ifdef H5_HAVE__FLOAT16
1940
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_ulong", native_float16, native_ulong,
1941
                                H5T__conv__Float16_ulong);
1942
#endif
1943
1944
    /* From floats to long long */
1945
1
    status |=
1946
1
        H5T__register_int(H5T_PERS_HARD, "flt_llong", native_float, native_llong, H5T__conv_float_llong);
1947
1
    status |=
1948
1
        H5T__register_int(H5T_PERS_HARD, "dbl_llong", native_double, native_llong, H5T__conv_double_llong);
1949
1
#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
1950
1
    status |=
1951
1
        H5T__register_int(H5T_PERS_HARD, "ldbl_llong", native_ldouble, native_llong, H5T__conv_ldouble_llong);
1952
1
#endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */
1953
#ifdef H5_HAVE__FLOAT16
1954
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_llong", native_float16, native_llong,
1955
                                H5T__conv__Float16_llong);
1956
#endif
1957
1958
    /* From floats to unsigned long long */
1959
1
    status |=
1960
1
        H5T__register_int(H5T_PERS_HARD, "flt_ullong", native_float, native_ullong, H5T__conv_float_ullong);
1961
1
    status |=
1962
1
        H5T__register_int(H5T_PERS_HARD, "dbl_ullong", native_double, native_ullong, H5T__conv_double_ullong);
1963
1
#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG
1964
1
    status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ullong", native_ldouble, native_ullong,
1965
1
                                H5T__conv_ldouble_ullong);
1966
1
#endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */
1967
#ifdef H5_HAVE__FLOAT16
1968
    status |= H5T__register_int(H5T_PERS_HARD, "flt16_ullong", native_float16, native_ullong,
1969
                                H5T__conv__Float16_ullong);
1970
#endif
1971
1972
1
#ifdef H5_HAVE_COMPLEX_NUMBERS
1973
    /* From complex numbers to char */
1974
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_schar", native_float_complex, native_schar,
1975
1
                                H5T__conv_fcomplex_schar);
1976
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_schar", native_double_complex, native_schar,
1977
1
                                H5T__conv_dcomplex_schar);
1978
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_schar", native_ldouble_complex, native_schar,
1979
1
                                H5T__conv_lcomplex_schar);
1980
1981
    /* From complex numbers to unsigned char */
1982
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uchar", native_float_complex, native_uchar,
1983
1
                                H5T__conv_fcomplex_uchar);
1984
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uchar", native_double_complex, native_uchar,
1985
1
                                H5T__conv_dcomplex_uchar);
1986
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uchar", native_ldouble_complex, native_uchar,
1987
1
                                H5T__conv_lcomplex_uchar);
1988
1989
    /* From complex numbers to short */
1990
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_short", native_float_complex, native_short,
1991
1
                                H5T__conv_fcomplex_short);
1992
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_short", native_double_complex, native_short,
1993
1
                                H5T__conv_dcomplex_short);
1994
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_short", native_ldouble_complex, native_short,
1995
1
                                H5T__conv_lcomplex_short);
1996
1997
    /* From complex numbers to unsigned short */
1998
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ushort", native_float_complex, native_ushort,
1999
1
                                H5T__conv_fcomplex_ushort);
2000
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ushort", native_double_complex, native_ushort,
2001
1
                                H5T__conv_dcomplex_ushort);
2002
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ushort", native_ldouble_complex, native_ushort,
2003
1
                                H5T__conv_lcomplex_ushort);
2004
2005
    /* From complex numbers to int */
2006
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_int", native_float_complex, native_int,
2007
1
                                H5T__conv_fcomplex_int);
2008
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_int", native_double_complex, native_int,
2009
1
                                H5T__conv_dcomplex_int);
2010
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_int", native_ldouble_complex, native_int,
2011
1
                                H5T__conv_lcomplex_int);
2012
2013
    /* From complex numbers to unsigned int */
2014
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uint", native_float_complex, native_uint,
2015
1
                                H5T__conv_fcomplex_uint);
2016
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uint", native_double_complex, native_uint,
2017
1
                                H5T__conv_dcomplex_uint);
2018
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uint", native_ldouble_complex, native_uint,
2019
1
                                H5T__conv_lcomplex_uint);
2020
2021
    /* From complex numbers to long */
2022
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_long", native_float_complex, native_long,
2023
1
                                H5T__conv_fcomplex_long);
2024
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_long", native_double_complex, native_long,
2025
1
                                H5T__conv_dcomplex_long);
2026
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_long", native_ldouble_complex, native_long,
2027
1
                                H5T__conv_lcomplex_long);
2028
2029
    /* From complex numbers to unsigned long */
2030
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ulong", native_float_complex, native_ulong,
2031
1
                                H5T__conv_fcomplex_ulong);
2032
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ulong", native_double_complex, native_ulong,
2033
1
                                H5T__conv_dcomplex_ulong);
2034
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ulong", native_ldouble_complex, native_ulong,
2035
1
                                H5T__conv_lcomplex_ulong);
2036
2037
    /* From complex numbers to long long */
2038
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_llong", native_float_complex, native_llong,
2039
1
                                H5T__conv_fcomplex_llong);
2040
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_llong", native_double_complex, native_llong,
2041
1
                                H5T__conv_dcomplex_llong);
2042
1
#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
2043
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_llong", native_ldouble_complex, native_llong,
2044
1
                                H5T__conv_lcomplex_llong);
2045
1
#endif
2046
2047
    /* From complex numbers to unsigned long long */
2048
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ullong", native_float_complex, native_ullong,
2049
1
                                H5T__conv_fcomplex_ullong);
2050
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ullong", native_double_complex, native_ullong,
2051
1
                                H5T__conv_dcomplex_ullong);
2052
1
#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG
2053
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ullong", native_ldouble_complex, native_ullong,
2054
1
                                H5T__conv_lcomplex_ullong);
2055
1
#endif
2056
2057
    /* From complex numbers to floats */
2058
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_flt", native_float_complex, native_float,
2059
1
                                H5T__conv_fcomplex_float);
2060
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_dbl", native_float_complex, native_double,
2061
1
                                H5T__conv_fcomplex_double);
2062
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ldbl", native_float_complex, native_ldouble,
2063
1
                                H5T__conv_fcomplex_ldouble);
2064
#ifdef H5_HAVE__FLOAT16
2065
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_flt16", native_float_complex, native_float16,
2066
                                H5T__conv_fcomplex__Float16);
2067
#endif
2068
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_flt", native_double_complex, native_float,
2069
1
                                H5T__conv_dcomplex_float);
2070
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_dbl", native_double_complex, native_double,
2071
1
                                H5T__conv_dcomplex_double);
2072
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ldbl", native_double_complex, native_ldouble,
2073
1
                                H5T__conv_dcomplex_ldouble);
2074
#ifdef H5_HAVE__FLOAT16
2075
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_flt16", native_double_complex, native_float16,
2076
                                H5T__conv_dcomplex__Float16);
2077
#endif
2078
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_flt", native_ldouble_complex, native_float,
2079
1
                                H5T__conv_lcomplex_float);
2080
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_dbl", native_ldouble_complex, native_double,
2081
1
                                H5T__conv_lcomplex_double);
2082
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ldbl", native_ldouble_complex, native_ldouble,
2083
1
                                H5T__conv_lcomplex_ldouble);
2084
#if defined(H5_HAVE__FLOAT16) && defined(H5T_CONV_INTERNAL_LDOUBLE_FLOAT16)
2085
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_flt16", native_ldouble_complex, native_float16,
2086
                                H5T__conv_lcomplex__Float16);
2087
#endif
2088
2089
    /* From complex numbers to complex numbers */
2090
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_dcomplex", native_float_complex,
2091
1
                                native_double_complex, H5T__conv_fcomplex_dcomplex);
2092
1
    status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_lcomplex", native_float_complex,
2093
1
                                native_ldouble_complex, H5T__conv_fcomplex_lcomplex);
2094
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_fcomplex", native_double_complex,
2095
1
                                native_float_complex, H5T__conv_dcomplex_fcomplex);
2096
1
    status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_lcomplex", native_double_complex,
2097
1
                                native_ldouble_complex, H5T__conv_dcomplex_lcomplex);
2098
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_fcomplex", native_ldouble_complex,
2099
1
                                native_float_complex, H5T__conv_lcomplex_fcomplex);
2100
1
    status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_dcomplex", native_ldouble_complex,
2101
1
                                native_double_complex, H5T__conv_lcomplex_dcomplex);
2102
1
#endif
2103
2104
    /*
2105
     * The special no-op conversion is the fastest, so we list it last. The
2106
     * data types we use are not important as long as the source and
2107
     * destination are equal.
2108
     */
2109
1
    status |= H5T__register_int(H5T_PERS_HARD, "no-op", native_int, native_int, H5T__conv_noop);
2110
2111
    /* Initialize the +/- Infinity values for floating-point types */
2112
1
    status |= H5T__init_inf();
2113
2114
1
    if (status < 0)
2115
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function(s)");
2116
2117
    /* Register datatype creation property class properties here.  See similar
2118
     * code in H5D__init_package(), etc. for example.
2119
     */
2120
2121
    /* Only register the default property list if it hasn't been created yet */
2122
1
    if (H5P_LST_DATATYPE_CREATE_ID_g == (-1)) {
2123
        /* ========== Datatype Creation Property Class Initialization ============*/
2124
0
        assert(H5P_CLS_DATATYPE_CREATE_g != NULL);
2125
2126
        /* Register the default datatype creation property list */
2127
0
        if ((H5P_LST_DATATYPE_CREATE_ID_g = H5P_create_id(H5P_CLS_DATATYPE_CREATE_g, false)) < 0)
2128
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class");
2129
0
    } /* end if */
2130
2131
    /* Mark "top" of interface as initialized, too */
2132
1
    H5T_top_package_initialize_s = true;
2133
2134
1
done:
2135
    /* General cleanup */
2136
1
    if (compound != NULL)
2137
1
        (void)H5T_close_real(compound);
2138
1
    if (enum_type != NULL)
2139
1
        (void)H5T_close_real(enum_type);
2140
1
    if (vlen != NULL)
2141
1
        (void)H5T_close_real(vlen);
2142
1
    if (array != NULL)
2143
1
        (void)H5T_close_real(array);
2144
1
    if (cplx != NULL)
2145
1
        (void)H5T_close_real(cplx);
2146
2147
    /* Error cleanup */
2148
1
    if (ret_value < 0) {
2149
0
        if (dt) {
2150
            /* Check if we should call H5T_close_real or H5FL_FREE */
2151
0
            if (copied_dtype)
2152
0
                (void)H5T_close_real(dt);
2153
0
            else {
2154
0
                if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
2155
0
                    HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object");
2156
0
                dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
2157
0
                dt         = H5FL_FREE(H5T_t, dt);
2158
0
            } /* end else */
2159
0
        }     /* end if */
2160
0
    }         /* end if */
2161
2162
1
    FUNC_LEAVE_NOAPI(ret_value)
2163
1
} /* end H5T__init_package() */
2164
2165
/*-------------------------------------------------------------------------
2166
 * Function:   H5T__unlock_cb
2167
 *
2168
 * Purpose:    Clear the immutable flag for a datatype.  This function is
2169
 *             called when the library is closing in order to unlock all
2170
 *             registered datatypes and thus make them free-able.
2171
 *
2172
 * Return:     Non-negative on success/Negative on failure
2173
 *
2174
 *-------------------------------------------------------------------------
2175
 */
2176
static int
2177
H5T__unlock_cb(void *_dt, hid_t H5_ATTR_UNUSED id, void *_udata)
2178
217
{
2179
217
    H5T_t *dt = (H5T_t *)_dt;
2180
217
    int   *n  = (int *)_udata;
2181
2182
217
    FUNC_ENTER_PACKAGE_NOERR
2183
2184
217
    assert(dt);
2185
2186
217
    if (dt->shared && (H5T_STATE_IMMUTABLE == dt->shared->state)) {
2187
97
        dt->shared->state = H5T_STATE_RDONLY;
2188
97
        (*n)++;
2189
97
    }
2190
2191
217
    FUNC_LEAVE_NOAPI(SUCCEED)
2192
217
} /* end H5T__unlock_cb() */
2193
2194
/*-------------------------------------------------------------------------
2195
 * Function:   H5T_top_term_package
2196
 *
2197
 * Purpose:    Close the "top" of the interface, releasing IDs, etc.
2198
 *
2199
 * Return:     Success:    Positive if any action might have caused a
2200
 *                            change in some other interface; zero otherwise.
2201
 *             Failure:    Negative
2202
 *
2203
 *-------------------------------------------------------------------------
2204
 */
2205
int
2206
H5T_top_term_package(void)
2207
9
{
2208
9
    int n = 0;
2209
2210
9
    FUNC_ENTER_NOAPI_NOINIT_NOERR
2211
2212
4
    if (H5T_top_package_initialize_s) {
2213
        /* Unregister all conversion functions */
2214
2
        if (H5T_g.path) {
2215
1
            H5T_conv_ctx_t conv_ctx = {0};
2216
2217
1
            conv_ctx.u.free.src_type_id = H5I_INVALID_HID;
2218
1
            conv_ctx.u.free.dst_type_id = H5I_INVALID_HID;
2219
2220
196
            for (int i = 0; i < H5T_g.npaths; i++) {
2221
195
                H5T_path_t *path = H5T_g.path[i];
2222
2223
195
                (void)H5T__path_free(path, &conv_ctx);
2224
2225
195
                H5T_g.path[i] = NULL;
2226
195
            } /* end for */
2227
2228
            /* Clear conversion tables */
2229
1
            H5T_g.path   = (H5T_path_t **)H5MM_xfree(H5T_g.path);
2230
1
            H5T_g.npaths = 0;
2231
1
            H5T_g.apaths = 0;
2232
1
            H5T_g.soft   = (H5T_soft_t *)H5MM_xfree(H5T_g.soft);
2233
1
            H5T_g.nsoft  = 0;
2234
1
            H5T_g.asoft  = 0;
2235
2236
1
            n++;
2237
1
        } /* end if */
2238
2239
        /* Unlock all datatypes, then free them */
2240
        /* note that we are ignoring the return value from H5I_iterate() */
2241
        /* Also note that we are incrementing 'n' in the callback */
2242
2
        H5I_iterate(H5I_DATATYPE, H5T__unlock_cb, &n, false);
2243
2244
        /* Release all datatype IDs */
2245
2
        if (H5I_nmembers(H5I_DATATYPE) > 0) {
2246
1
            (void)H5I_clear_type(H5I_DATATYPE, false, false);
2247
1
            n++; /*H5I*/
2248
1
        }        /* end if */
2249
2250
        /* Reset all the datatype IDs */
2251
2
        if (H5T_IEEE_F32BE_g > 0) {
2252
1
            H5T_IEEE_F16BE_g = H5I_INVALID_HID;
2253
1
            H5T_IEEE_F16LE_g = H5I_INVALID_HID;
2254
1
            H5T_IEEE_F32BE_g = H5I_INVALID_HID;
2255
1
            H5T_IEEE_F32LE_g = H5I_INVALID_HID;
2256
1
            H5T_IEEE_F64BE_g = H5I_INVALID_HID;
2257
1
            H5T_IEEE_F64LE_g = H5I_INVALID_HID;
2258
2259
1
            H5T_FLOAT_BFLOAT16BE_g = H5I_INVALID_HID;
2260
1
            H5T_FLOAT_BFLOAT16LE_g = H5I_INVALID_HID;
2261
1
            H5T_FLOAT_F8E4M3_g     = H5I_INVALID_HID;
2262
1
            H5T_FLOAT_F8E5M2_g     = H5I_INVALID_HID;
2263
2264
1
            H5T_COMPLEX_IEEE_F16BE_g = H5I_INVALID_HID;
2265
1
            H5T_COMPLEX_IEEE_F16LE_g = H5I_INVALID_HID;
2266
1
            H5T_COMPLEX_IEEE_F32BE_g = H5I_INVALID_HID;
2267
1
            H5T_COMPLEX_IEEE_F32LE_g = H5I_INVALID_HID;
2268
1
            H5T_COMPLEX_IEEE_F64BE_g = H5I_INVALID_HID;
2269
1
            H5T_COMPLEX_IEEE_F64LE_g = H5I_INVALID_HID;
2270
2271
1
            H5T_STD_I8BE_g        = H5I_INVALID_HID;
2272
1
            H5T_STD_I8LE_g        = H5I_INVALID_HID;
2273
1
            H5T_STD_I16BE_g       = H5I_INVALID_HID;
2274
1
            H5T_STD_I16LE_g       = H5I_INVALID_HID;
2275
1
            H5T_STD_I32BE_g       = H5I_INVALID_HID;
2276
1
            H5T_STD_I32LE_g       = H5I_INVALID_HID;
2277
1
            H5T_STD_I64BE_g       = H5I_INVALID_HID;
2278
1
            H5T_STD_I64LE_g       = H5I_INVALID_HID;
2279
1
            H5T_STD_U8BE_g        = H5I_INVALID_HID;
2280
1
            H5T_STD_U8LE_g        = H5I_INVALID_HID;
2281
1
            H5T_STD_U16BE_g       = H5I_INVALID_HID;
2282
1
            H5T_STD_U16LE_g       = H5I_INVALID_HID;
2283
1
            H5T_STD_U32BE_g       = H5I_INVALID_HID;
2284
1
            H5T_STD_U32LE_g       = H5I_INVALID_HID;
2285
1
            H5T_STD_U64BE_g       = H5I_INVALID_HID;
2286
1
            H5T_STD_U64LE_g       = H5I_INVALID_HID;
2287
1
            H5T_STD_B8BE_g        = H5I_INVALID_HID;
2288
1
            H5T_STD_B8LE_g        = H5I_INVALID_HID;
2289
1
            H5T_STD_B16BE_g       = H5I_INVALID_HID;
2290
1
            H5T_STD_B16LE_g       = H5I_INVALID_HID;
2291
1
            H5T_STD_B32BE_g       = H5I_INVALID_HID;
2292
1
            H5T_STD_B32LE_g       = H5I_INVALID_HID;
2293
1
            H5T_STD_B64BE_g       = H5I_INVALID_HID;
2294
1
            H5T_STD_B64LE_g       = H5I_INVALID_HID;
2295
1
            H5T_STD_REF_OBJ_g     = H5I_INVALID_HID;
2296
1
            H5T_STD_REF_DSETREG_g = H5I_INVALID_HID;
2297
1
            H5T_STD_REF_g         = H5I_INVALID_HID;
2298
2299
1
            H5T_UNIX_D32BE_g = H5I_INVALID_HID;
2300
1
            H5T_UNIX_D32LE_g = H5I_INVALID_HID;
2301
1
            H5T_UNIX_D64BE_g = H5I_INVALID_HID;
2302
1
            H5T_UNIX_D64LE_g = H5I_INVALID_HID;
2303
2304
1
            H5T_C_S1_g = H5I_INVALID_HID;
2305
2306
1
            H5T_FORTRAN_S1_g = H5I_INVALID_HID;
2307
2308
1
            H5T_NATIVE_SCHAR_g           = H5I_INVALID_HID;
2309
1
            H5T_NATIVE_UCHAR_g           = H5I_INVALID_HID;
2310
1
            H5T_NATIVE_SHORT_g           = H5I_INVALID_HID;
2311
1
            H5T_NATIVE_USHORT_g          = H5I_INVALID_HID;
2312
1
            H5T_NATIVE_INT_g             = H5I_INVALID_HID;
2313
1
            H5T_NATIVE_UINT_g            = H5I_INVALID_HID;
2314
1
            H5T_NATIVE_LONG_g            = H5I_INVALID_HID;
2315
1
            H5T_NATIVE_ULONG_g           = H5I_INVALID_HID;
2316
1
            H5T_NATIVE_LLONG_g           = H5I_INVALID_HID;
2317
1
            H5T_NATIVE_ULLONG_g          = H5I_INVALID_HID;
2318
1
            H5T_NATIVE_FLOAT16_g         = H5I_INVALID_HID;
2319
1
            H5T_NATIVE_FLOAT_g           = H5I_INVALID_HID;
2320
1
            H5T_NATIVE_DOUBLE_g          = H5I_INVALID_HID;
2321
1
            H5T_NATIVE_LDOUBLE_g         = H5I_INVALID_HID;
2322
1
            H5T_NATIVE_FLOAT_COMPLEX_g   = H5I_INVALID_HID;
2323
1
            H5T_NATIVE_DOUBLE_COMPLEX_g  = H5I_INVALID_HID;
2324
1
            H5T_NATIVE_LDOUBLE_COMPLEX_g = H5I_INVALID_HID;
2325
1
            H5T_NATIVE_B8_g              = H5I_INVALID_HID;
2326
1
            H5T_NATIVE_B16_g             = H5I_INVALID_HID;
2327
1
            H5T_NATIVE_B32_g             = H5I_INVALID_HID;
2328
1
            H5T_NATIVE_B64_g             = H5I_INVALID_HID;
2329
1
            H5T_NATIVE_OPAQUE_g          = H5I_INVALID_HID;
2330
1
            H5T_NATIVE_HADDR_g           = H5I_INVALID_HID;
2331
1
            H5T_NATIVE_HSIZE_g           = H5I_INVALID_HID;
2332
1
            H5T_NATIVE_HSSIZE_g          = H5I_INVALID_HID;
2333
1
            H5T_NATIVE_HERR_g            = H5I_INVALID_HID;
2334
1
            H5T_NATIVE_HBOOL_g           = H5I_INVALID_HID;
2335
2336
1
            H5T_NATIVE_INT8_g        = H5I_INVALID_HID;
2337
1
            H5T_NATIVE_UINT8_g       = H5I_INVALID_HID;
2338
1
            H5T_NATIVE_INT_LEAST8_g  = H5I_INVALID_HID;
2339
1
            H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID;
2340
1
            H5T_NATIVE_INT_FAST8_g   = H5I_INVALID_HID;
2341
1
            H5T_NATIVE_UINT_FAST8_g  = H5I_INVALID_HID;
2342
2343
1
            H5T_NATIVE_INT16_g        = H5I_INVALID_HID;
2344
1
            H5T_NATIVE_UINT16_g       = H5I_INVALID_HID;
2345
1
            H5T_NATIVE_INT_LEAST16_g  = H5I_INVALID_HID;
2346
1
            H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID;
2347
1
            H5T_NATIVE_INT_FAST16_g   = H5I_INVALID_HID;
2348
1
            H5T_NATIVE_UINT_FAST16_g  = H5I_INVALID_HID;
2349
2350
1
            H5T_NATIVE_INT32_g        = H5I_INVALID_HID;
2351
1
            H5T_NATIVE_UINT32_g       = H5I_INVALID_HID;
2352
1
            H5T_NATIVE_INT_LEAST32_g  = H5I_INVALID_HID;
2353
1
            H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID;
2354
1
            H5T_NATIVE_INT_FAST32_g   = H5I_INVALID_HID;
2355
1
            H5T_NATIVE_UINT_FAST32_g  = H5I_INVALID_HID;
2356
2357
1
            H5T_NATIVE_INT64_g        = H5I_INVALID_HID;
2358
1
            H5T_NATIVE_UINT64_g       = H5I_INVALID_HID;
2359
1
            H5T_NATIVE_INT_LEAST64_g  = H5I_INVALID_HID;
2360
1
            H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID;
2361
1
            H5T_NATIVE_INT_FAST64_g   = H5I_INVALID_HID;
2362
1
            H5T_NATIVE_UINT_FAST64_g  = H5I_INVALID_HID;
2363
2364
1
            n++;
2365
1
        } /* end if */
2366
2367
        /* Mark "top" of interface as closed */
2368
2
        if (0 == n)
2369
1
            H5T_top_package_initialize_s = false;
2370
2
    } /* end if */
2371
2372
4
    FUNC_LEAVE_NOAPI(n)
2373
9
} /* end H5T_top_term_package() */
2374
2375
/*-------------------------------------------------------------------------
2376
 * Function:   H5T_term_package
2377
 *
2378
 * Purpose:    Close this interface.
2379
 *
2380
 * Note:    Finishes shutting down the interface, after
2381
 *          H5T_top_term_package() is called
2382
 *
2383
 * Return:   Success:    Positive if any action might have caused a
2384
 *                change in some other interface; zero
2385
 *                otherwise.
2386
 *           Failure:    Negative
2387
 *
2388
 *-------------------------------------------------------------------------
2389
 */
2390
int
2391
H5T_term_package(void)
2392
6
{
2393
6
    int n = 0;
2394
2395
6
    FUNC_ENTER_NOAPI_NOINIT_NOERR
2396
2397
1
    if (H5_PKG_INIT_VAR) {
2398
        /* Sanity check */
2399
1
        assert(0 == H5I_nmembers(H5I_DATATYPE));
2400
1
        assert(false == H5T_top_package_initialize_s);
2401
2402
        /* Destroy the datatype object id group */
2403
1
        n += (H5I_dec_type_ref(H5I_DATATYPE) > 0);
2404
2405
        /* Mark interface as closed */
2406
1
        if (0 == n)
2407
1
            H5_PKG_INIT_VAR = false;
2408
1
    } /* end if */
2409
2410
1
    FUNC_LEAVE_NOAPI(n)
2411
6
} /* end H5T_term_package() */
2412
2413
/*-------------------------------------------------------------------------
2414
 * Function:    H5T__close_cb
2415
 *
2416
 * Purpose:     Called when the ref count reaches zero on the datatype's ID
2417
 *
2418
 * Return:      SUCCEED/FAIL
2419
 *
2420
 *-------------------------------------------------------------------------
2421
 */
2422
static herr_t
2423
H5T__close_cb(H5T_t *dt, void **request)
2424
17.5k
{
2425
17.5k
    herr_t ret_value = SUCCEED; /* Return value */
2426
2427
17.5k
    FUNC_ENTER_PACKAGE
2428
2429
    /* Sanity check */
2430
17.5k
    assert(dt);
2431
2432
    /* If this datatype is VOL-managed (i.e.: has a VOL object),
2433
     * close it through the VOL connector.
2434
     */
2435
17.5k
    if (NULL != dt->vol_obj) {
2436
        /* Close the connector-managed datatype data */
2437
1
        if (H5VL_datatype_close(dt->vol_obj, H5P_DATASET_XFER_DEFAULT, request) < 0)
2438
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype");
2439
2440
        /* Free the VOL object */
2441
1
        if (H5VL_free_object(dt->vol_obj) < 0)
2442
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object");
2443
1
        dt->vol_obj = NULL;
2444
1
    } /* end if */
2445
2446
    /* Close the datatype */
2447
17.5k
    if (H5T_close(dt) < 0)
2448
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype");
2449
2450
17.5k
done:
2451
17.5k
    FUNC_LEAVE_NOAPI(ret_value)
2452
17.5k
} /* end H5T__close_cb() */
2453
2454
/*-------------------------------------------------------------------------
2455
 * Function:   H5Tcreate
2456
 *
2457
 * Purpose:    Create a new type and initialize it to reasonable values.
2458
 *             The type is a member of type class TYPE and is SIZE bytes.
2459
 *
2460
 * Return:    Success:    A new type identifier.
2461
 *
2462
 *            Failure:    Negative
2463
 *
2464
 * Errors:
2465
 *        ARGS      BADVALUE    Invalid size.
2466
 *        DATATYPE  CANTINIT    Can't create type.
2467
 *        DATATYPE  CANTREGISTER    Can't register datatype ID.
2468
 *
2469
 *-------------------------------------------------------------------------
2470
 */
2471
hid_t
2472
H5Tcreate(H5T_class_t type, size_t size)
2473
0
{
2474
0
    H5T_t *dt = NULL; /* New datatype constructed */
2475
0
    hid_t  ret_value; /* Return value */
2476
2477
0
    FUNC_ENTER_API(H5I_INVALID_HID)
2478
2479
    /* check args. We support string (fixed-size or variable-length) now. */
2480
0
    if (size <= 0 && size != H5T_VARIABLE)
2481
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "size must be positive");
2482
2483
    /* create the type */
2484
0
    if (NULL == (dt = H5T__create(type, size)))
2485
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create type");
2486
2487
    /* Get an ID for the datatype */
2488
0
    if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0)
2489
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype ID");
2490
2491
0
done:
2492
0
    FUNC_LEAVE_API(ret_value)
2493
0
} /* end H5Tcreate() */
2494
2495
/*-------------------------------------------------------------------------
2496
 * Function:    H5Tcopy
2497
 *
2498
 * Purpose:     Copies a datatype.  The resulting datatype is not locked.
2499
 *              The datatype should be closed when no longer needed by
2500
 *              calling H5Tclose().
2501
 *
2502
 * Return:      Success:    The ID of a new datatype
2503
 *
2504
 *              Failure:    H5I_INVALID_HID
2505
 *
2506
 * Note:        The returned type is always transient and unlocked. If the
2507
 *              TYPE_ID argument is a dataset instead of a datatype then
2508
 *              this function returns a transient, modifiable datatype
2509
 *              which is a copy of the dataset's datatype.
2510
 *
2511
 *-------------------------------------------------------------------------
2512
 */
2513
hid_t
2514
H5Tcopy(hid_t obj_id)
2515
0
{
2516
0
    H5T_t *dt        = NULL;            /* Pointer to the datatype to copy */
2517
0
    H5T_t *new_dt    = NULL;            /* Pointer to the new datatype */
2518
0
    hid_t  dset_tid  = H5I_INVALID_HID; /* Datatype ID from dataset */
2519
0
    hid_t  ret_value = H5I_INVALID_HID; /* Return value */
2520
2521
0
    FUNC_ENTER_API(H5I_INVALID_HID)
2522
2523
0
    switch (H5I_get_type(obj_id)) {
2524
0
        case H5I_DATATYPE:
2525
            /* The argument is a datatype handle */
2526
0
            if (NULL == (dt = (H5T_t *)H5I_object(obj_id)))
2527
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "obj_id is not a datatype ID");
2528
0
            break;
2529
2530
0
        case H5I_DATASET: {
2531
0
            H5VL_object_t          *vol_obj;     /* Object for obj_id */
2532
0
            H5VL_dataset_get_args_t vol_cb_args; /* Arguments to VOL callback */
2533
2534
            /* The argument is a dataset handle */
2535
0
            if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(obj_id, H5I_DATASET)))
2536
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "type_id is not a dataset ID");
2537
2538
            /* Set up VOL callback arguments */
2539
0
            vol_cb_args.op_type               = H5VL_DATASET_GET_TYPE;
2540
0
            vol_cb_args.args.get_type.type_id = H5I_INVALID_HID;
2541
2542
            /* Get the datatype from the dataset
2543
             * NOTE: This will have to be closed after we're done with it.
2544
             */
2545
0
            if (H5VL_dataset_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
2546
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5I_INVALID_HID,
2547
0
                            "unable to get datatype from the dataset");
2548
0
            dset_tid = vol_cb_args.args.get_type.type_id;
2549
2550
            /* Unwrap the type ID */
2551
0
            if (NULL == (dt = (H5T_t *)H5I_object(dset_tid)))
2552
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, H5I_INVALID_HID,
2553
0
                            "received invalid datatype from the dataset");
2554
0
        } break;
2555
2556
0
        case H5I_UNINIT:
2557
0
        case H5I_BADID:
2558
0
        case H5I_FILE:
2559
0
        case H5I_GROUP:
2560
0
        case H5I_DATASPACE:
2561
0
        case H5I_ATTR:
2562
0
        case H5I_MAP:
2563
0
        case H5I_VFL:
2564
0
        case H5I_VOL:
2565
0
        case H5I_GENPROP_CLS:
2566
0
        case H5I_GENPROP_LST:
2567
0
        case H5I_ERROR_CLASS:
2568
0
        case H5I_ERROR_MSG:
2569
0
        case H5I_ERROR_STACK:
2570
0
        case H5I_SPACE_SEL_ITER:
2571
0
        case H5I_EVENTSET:
2572
0
        case H5I_NTYPES:
2573
0
        default:
2574
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype or dataset");
2575
0
    } /* end switch */
2576
2577
    /* Copy datatype */
2578
0
    if (NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
2579
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy");
2580
2581
    /* Get an ID for the copied datatype */
2582
0
    if ((ret_value = H5I_register(H5I_DATATYPE, new_dt, true)) < 0)
2583
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype atom");
2584
2585
0
done:
2586
2587
    /* If we got a type ID from a passed-in dataset, we need to close that */
2588
0
    if (dset_tid != H5I_INVALID_HID)
2589
0
        if (H5I_dec_app_ref(dset_tid) < 0)
2590
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADID, FAIL, "problem freeing temporary dataset type ID");
2591
2592
    /* Close the new datatype on errors */
2593
0
    if (H5I_INVALID_HID == ret_value)
2594
0
        if (new_dt && H5T_close_real(new_dt) < 0)
2595
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release datatype info");
2596
2597
0
    FUNC_LEAVE_API(ret_value)
2598
0
} /* end H5Tcopy() */
2599
2600
/*-------------------------------------------------------------------------
2601
 * Function:    H5Tclose
2602
 *
2603
 * Purpose:     Frees a datatype and all associated memory.
2604
 *
2605
 * Return:      Non-negative on success/Negative on failure
2606
 *
2607
 *-------------------------------------------------------------------------
2608
 */
2609
herr_t
2610
H5Tclose(hid_t type_id)
2611
11.3k
{
2612
11.3k
    H5T_t *dt;                  /* Pointer to datatype to close */
2613
11.3k
    herr_t ret_value = SUCCEED; /* Return value */
2614
2615
22.7k
    FUNC_ENTER_API(FAIL)
2616
2617
    /* Check args */
2618
22.7k
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
2619
91
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2620
11.2k
    if (H5T_STATE_IMMUTABLE == dt->shared->state)
2621
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype");
2622
2623
    /* When the reference count reaches zero the resources are freed */
2624
11.2k
    if (H5I_dec_app_ref(type_id) < 0)
2625
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "problem freeing id");
2626
2627
11.3k
done:
2628
11.3k
    FUNC_LEAVE_API(ret_value)
2629
11.2k
} /* end H5Tclose() */
2630
2631
/*-------------------------------------------------------------------------
2632
 * Function:    H5Tclose_async
2633
 *
2634
 * Purpose:     Asynchronous version of H5Tclose.
2635
 *
2636
 * Return:      Non-negative on success/Negative on failure
2637
 *
2638
 *-------------------------------------------------------------------------
2639
 */
2640
herr_t
2641
H5Tclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t type_id, hid_t es_id)
2642
0
{
2643
0
    H5T_t            *dt;                          /* Pointer to datatype to close */
2644
0
    void             *token     = NULL;            /* Request token for async operation        */
2645
0
    void            **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
2646
0
    H5VL_object_t    *vol_obj   = NULL;            /* VOL object of dset_id */
2647
0
    H5VL_connector_t *connector = NULL;            /* VOL connector */
2648
0
    herr_t            ret_value = SUCCEED;         /* Return value */
2649
2650
0
    FUNC_ENTER_API(FAIL)
2651
2652
    /* Check args */
2653
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
2654
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2655
0
    if (H5T_STATE_IMMUTABLE == dt->shared->state)
2656
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype");
2657
2658
    /* Get dataset object's connector */
2659
0
    if (NULL == (vol_obj = H5VL_vol_object(type_id)))
2660
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get VOL object for dataset");
2661
2662
    /* Prepare for possible asynchronous operation */
2663
0
    if (H5ES_NONE != es_id) {
2664
        /* Increase connector's refcount, so it doesn't get closed if closing
2665
         * the dataset closes the file */
2666
0
        connector = H5VL_OBJ_CONNECTOR(vol_obj);
2667
0
        H5VL_conn_inc_rc(connector);
2668
2669
        /* Point at token for operation to set up */
2670
0
        token_ptr = &token;
2671
0
    } /* end if */
2672
2673
    /* When the reference count reaches zero the resources are freed */
2674
0
    if (H5I_dec_app_ref_async(type_id, token_ptr) < 0)
2675
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "problem freeing id");
2676
2677
    /* If a token was created, add the token to the event set */
2678
0
    if (NULL != token)
2679
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
2680
0
                        H5ARG_TRACE5(__func__, "*s*sIuii", app_file, app_func, app_line, type_id, es_id)) < 0)
2681
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert token into event set");
2682
2683
0
done:
2684
0
    if (connector && H5VL_conn_dec_rc(connector) < 0)
2685
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement ref count on connector");
2686
2687
0
    FUNC_LEAVE_API(ret_value)
2688
0
} /* end H5Tclose_async() */
2689
2690
/*-------------------------------------------------------------------------
2691
 * Function:  H5Tequal
2692
 *
2693
 * Purpose:   Determines if two datatypes are equal.
2694
 *
2695
 * Return:    Success:    true if equal, false if unequal
2696
 *
2697
 *            Failure:    Negative
2698
 *
2699
 *-------------------------------------------------------------------------
2700
 */
2701
htri_t
2702
H5Tequal(hid_t type1_id, hid_t type2_id)
2703
0
{
2704
0
    const H5T_t *dt1;       /* Pointer to first datatype */
2705
0
    const H5T_t *dt2;       /* Pointer to second datatype */
2706
0
    htri_t       ret_value; /* Return value */
2707
2708
0
    FUNC_ENTER_API(FAIL)
2709
2710
    /* check args */
2711
0
    if (NULL == (dt1 = (H5T_t *)H5I_object_verify(type1_id, H5I_DATATYPE)))
2712
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2713
0
    if (NULL == (dt2 = (H5T_t *)H5I_object_verify(type2_id, H5I_DATATYPE)))
2714
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2715
2716
0
    ret_value = (0 == H5T_cmp(dt1, dt2, false)) ? true : false;
2717
2718
0
done:
2719
0
    FUNC_LEAVE_API(ret_value)
2720
0
} /* end H5Tequal() */
2721
2722
/*-------------------------------------------------------------------------
2723
 * Function:    H5Tlock
2724
 *
2725
 * Purpose:    Locks a type, making it read only and non-destructable.
2726
 *        This is normally done by the library for predefined datatypes so
2727
 *        the application doesn't inadvertently change or delete a
2728
 *        predefined type.
2729
 *
2730
 *        Once a datatype is locked it can never be unlocked unless
2731
 *        the entire library is closed.
2732
 *
2733
 * Return:    Non-negative on success/Negative on failure
2734
 *
2735
 *-------------------------------------------------------------------------
2736
 */
2737
herr_t
2738
H5Tlock(hid_t type_id)
2739
0
{
2740
0
    H5T_t *dt;                  /* Datatype to operate on */
2741
0
    herr_t ret_value = SUCCEED; /* Return value */
2742
2743
0
    FUNC_ENTER_API(FAIL)
2744
2745
    /* Check args */
2746
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
2747
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2748
0
    if (H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state)
2749
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to lock named datatype");
2750
2751
0
    if (H5T_lock(dt, true) < 0)
2752
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype");
2753
2754
0
done:
2755
0
    FUNC_LEAVE_API(ret_value)
2756
0
} /* end H5Tlock() */
2757
2758
/*-------------------------------------------------------------------------
2759
 * Function:  H5Tget_class
2760
 *
2761
 * Purpose:   Returns the datatype class identifier for datatype TYPE_ID.
2762
 *
2763
 * Return:    Success:    One of the non-negative datatype class constants.
2764
 *
2765
 *            Failure:    H5T_NO_CLASS (Negative)
2766
 *
2767
 *-------------------------------------------------------------------------
2768
 */
2769
H5T_class_t
2770
H5Tget_class(hid_t type_id)
2771
6.07k
{
2772
6.07k
    H5T_t      *dt;        /* Pointer to datatype */
2773
6.07k
    H5T_class_t ret_value; /* Return value */
2774
2775
12.1k
    FUNC_ENTER_API(H5T_NO_CLASS)
2776
2777
    /* Check args */
2778
12.1k
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
2779
91
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype");
2780
2781
    /* Set return value */
2782
5.98k
    ret_value = H5T_get_class(dt, false);
2783
2784
6.07k
done:
2785
6.07k
    FUNC_LEAVE_API(ret_value)
2786
5.98k
} /* end H5Tget_class() */
2787
2788
/*-------------------------------------------------------------------------
2789
 * Function:  H5T_get_class
2790
 *
2791
 * Purpose:   Returns the data type class identifier for a datatype ptr.
2792
 *
2793
 * Return:    Success:    One of the non-negative data type class constants.
2794
 *
2795
 *            Failure:    H5T_NO_CLASS (Negative)
2796
 *
2797
 *-------------------------------------------------------------------------
2798
 */
2799
H5T_class_t
2800
H5T_get_class(const H5T_t *dt, htri_t internal)
2801
5.98k
{
2802
5.98k
    H5T_class_t ret_value = H5T_NO_CLASS; /* Return value */
2803
2804
5.98k
    FUNC_ENTER_NOAPI(H5T_NO_CLASS)
2805
2806
5.98k
    assert(dt);
2807
2808
    /* Externally, a VL string is a string; internally, a VL string is a VL. */
2809
5.98k
    if (internal) {
2810
0
        ret_value = dt->shared->type;
2811
0
    }
2812
5.98k
    else {
2813
5.98k
        if (H5T_IS_VL_STRING(dt->shared))
2814
1
            ret_value = H5T_STRING;
2815
5.98k
        else
2816
5.98k
            ret_value = dt->shared->type;
2817
5.98k
    }
2818
2819
5.98k
done:
2820
5.98k
    FUNC_LEAVE_NOAPI(ret_value)
2821
5.98k
} /* end H5T_get_class() */
2822
2823
/*-------------------------------------------------------------------------
2824
 * Function:   H5Tdetect_class
2825
 *
2826
 * Purpose:    Check whether a datatype contains (or is) a certain type of
2827
 *             datatype.
2828
 *
2829
 * Return:     true (1) or false (0) on success/Negative on failure
2830
 *
2831
 *-------------------------------------------------------------------------
2832
 */
2833
htri_t
2834
H5Tdetect_class(hid_t type, H5T_class_t cls)
2835
0
{
2836
0
    H5T_t *dt;        /* Datatype to query */
2837
0
    htri_t ret_value; /* Return value */
2838
2839
0
    FUNC_ENTER_API(FAIL)
2840
2841
    /* Check args */
2842
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE)))
2843
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype");
2844
0
    if (!(cls > H5T_NO_CLASS && cls < H5T_NCLASSES))
2845
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype class");
2846
2847
    /* Set return value */
2848
0
    if ((ret_value = H5T_detect_class(dt, cls, true)) < 0)
2849
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5T_NO_CLASS, "can't get datatype class");
2850
2851
0
done:
2852
0
    FUNC_LEAVE_API(ret_value)
2853
0
} /* end H5Tdetect_class() */
2854
2855
/*-------------------------------------------------------------------------
2856
 * Function:   H5T_detect_class
2857
 *
2858
 * Purpose:    Check whether a datatype contains (or is) a certain type of
2859
 *             datatype.
2860
 *
2861
 * Return:     true (1) or false (0) on success/Negative on failure
2862
 *
2863
 *-------------------------------------------------------------------------
2864
 */
2865
htri_t
2866
H5T_detect_class(const H5T_t *dt, H5T_class_t cls, bool from_api)
2867
1.56k
{
2868
1.56k
    unsigned i;
2869
1.56k
    htri_t   ret_value = false; /* Return value */
2870
2871
1.56k
    FUNC_ENTER_NOAPI(FAIL)
2872
2873
1.56k
    assert(dt);
2874
1.56k
    assert(cls > H5T_NO_CLASS && cls < H5T_NCLASSES);
2875
2876
    /* Consider VL string as a string for API, as a VL for internal use. */
2877
    /* (note that this check must be performed before checking if the VL
2878
     *  string belongs to the H5T_VLEN class, which would otherwise return
2879
     *  true. -QAK)
2880
     */
2881
1.56k
    if (from_api && H5T_IS_VL_STRING(dt->shared))
2882
0
        HGOTO_DONE(H5T_STRING == cls);
2883
2884
    /* Check if this type is the correct type */
2885
1.56k
    if (dt->shared->type == cls)
2886
376
        HGOTO_DONE(true);
2887
2888
    /* check for types that might have the correct type as a component */
2889
1.18k
    switch (dt->shared->type) {
2890
0
        case H5T_COMPOUND:
2891
0
            for (i = 0; i < dt->shared->u.compnd.nmembs; i++) {
2892
0
                htri_t nested_ret; /* Return value from nested call */
2893
2894
                /* Check if this field's type is the correct type */
2895
0
                if (dt->shared->u.compnd.memb[i].type->shared->type == cls)
2896
0
                    HGOTO_DONE(true);
2897
2898
                /* Recurse if it's VL, compound, enum or array */
2899
0
                if (H5T_IS_COMPOSITE(dt->shared->u.compnd.memb[i].type->shared->type))
2900
0
                    if ((nested_ret = H5T_detect_class(dt->shared->u.compnd.memb[i].type, cls, from_api)) !=
2901
0
                        false)
2902
0
                        HGOTO_DONE(nested_ret);
2903
0
            } /* end for */
2904
0
            break;
2905
2906
0
        case H5T_ARRAY:
2907
0
        case H5T_VLEN:
2908
0
        case H5T_ENUM:
2909
0
            HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api));
2910
0
            break;
2911
0
        case H5T_COMPLEX:
2912
0
            HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api));
2913
0
            break;
2914
0
        case H5T_NO_CLASS:
2915
0
        case H5T_INTEGER:
2916
0
        case H5T_FLOAT:
2917
0
        case H5T_TIME:
2918
435
        case H5T_STRING:
2919
435
        case H5T_BITFIELD:
2920
435
        case H5T_OPAQUE:
2921
1.18k
        case H5T_REFERENCE:
2922
1.18k
        case H5T_NCLASSES:
2923
1.18k
        default:
2924
1.18k
            break;
2925
1.18k
    } /* end if */
2926
2927
1.56k
done:
2928
1.56k
    FUNC_LEAVE_NOAPI(ret_value)
2929
1.56k
} /* end H5T_detect_class() */
2930
2931
/*-------------------------------------------------------------------------
2932
 * Function:  H5Tis_variable_str
2933
 *
2934
 * Purpose:   Check whether a datatype is a variable-length string
2935
 *
2936
 * Return:    true (1) or false (0) on success/Negative on failure
2937
 *
2938
 *-------------------------------------------------------------------------
2939
 */
2940
htri_t
2941
H5Tis_variable_str(hid_t dtype_id)
2942
0
{
2943
0
    H5T_t *dt;        /* Datatype to query */
2944
0
    htri_t ret_value; /* Return value */
2945
2946
0
    FUNC_ENTER_API(FAIL)
2947
2948
    /* Check args */
2949
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
2950
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
2951
2952
    /* Set return value */
2953
0
    if ((ret_value = H5T_is_variable_str(dt)) < 0)
2954
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "can't determine if datatype is VL-string");
2955
2956
0
done:
2957
0
    FUNC_LEAVE_API(ret_value)
2958
0
} /* end H5Tis_variable_str() */
2959
2960
/*-------------------------------------------------------------------------
2961
 * Function:  H5T_is_variable_str
2962
 *
2963
 * Purpose:   Check whether a datatype is a variable-length string
2964
 *
2965
 * Return:    true (1) or false (0) on success/Negative on failure
2966
 *
2967
 *-------------------------------------------------------------------------
2968
 */
2969
htri_t
2970
H5T_is_variable_str(const H5T_t *dt)
2971
0
{
2972
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
2973
2974
0
    FUNC_LEAVE_NOAPI(H5T_IS_VL_STRING(dt->shared))
2975
0
} /* end H5T_is_variable_str() */
2976
2977
/*-------------------------------------------------------------------------
2978
 * Function:  H5Tget_size
2979
 *
2980
 * Purpose:   Determines the total size of a datatype in bytes.
2981
 *
2982
 * Return:    Success:    Size of the datatype in bytes.     The size of
2983
 *                datatype is the size of an instance of that
2984
 *                datatype.
2985
 *
2986
 *            Failure:    0 (valid datatypes are never zero size)
2987
 *
2988
 *-------------------------------------------------------------------------
2989
 */
2990
size_t
2991
H5Tget_size(hid_t type_id)
2992
5.41k
{
2993
5.41k
    H5T_t *dt;        /* Datatype to query */
2994
5.41k
    size_t ret_value; /* Return value */
2995
2996
10.8k
    FUNC_ENTER_API(0)
2997
2998
    /* Check args */
2999
10.8k
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
3000
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype");
3001
3002
    /* size */
3003
5.41k
    ret_value = H5T_GET_SIZE(dt);
3004
3005
5.41k
done:
3006
5.41k
    FUNC_LEAVE_API(ret_value)
3007
5.41k
} /* end H5Tget_size() */
3008
3009
/*-------------------------------------------------------------------------
3010
 * Function:    H5Tset_size
3011
 *
3012
 * Purpose:    Sets the total size in bytes for a datatype (this operation
3013
 *        is not permitted on reference datatypes).  If the size is
3014
 *        decreased so that the significant bits of the datatype
3015
 *        extend beyond the edge of the new size, then the `offset'
3016
 *        property is decreased toward zero.  If the `offset' becomes
3017
 *        zero and the significant bits of the datatype still hang
3018
 *        over the edge of the new size, then the number of significant
3019
 *        bits is decreased.
3020
 *
3021
 *        Adjusting the size of an H5T_STRING automatically sets the
3022
 *        precision to 8*size.
3023
 *
3024
 *        All datatypes have a positive size.
3025
 *
3026
 * Return:    Non-negative on success/Negative on failure
3027
 *
3028
 *-------------------------------------------------------------------------
3029
 */
3030
herr_t
3031
H5Tset_size(hid_t type_id, size_t size)
3032
0
{
3033
0
    H5T_t *dt;                  /* Datatype to modify */
3034
0
    herr_t ret_value = SUCCEED; /* Return value */
3035
3036
0
    FUNC_ENTER_API(FAIL)
3037
3038
    /* Check args */
3039
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
3040
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
3041
0
    if (H5T_STATE_TRANSIENT != dt->shared->state)
3042
0
        HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "datatype is read-only");
3043
0
    if (size <= 0 && size != H5T_VARIABLE)
3044
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive");
3045
0
    if (size == H5T_VARIABLE && !H5T_IS_STRING(dt->shared))
3046
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length");
3047
0
    if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0)
3048
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined");
3049
0
    if (H5T_ARRAY == dt->shared->type || H5T_REFERENCE == dt->shared->type || H5T_COMPLEX == dt->shared->type)
3050
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
3051
0
    if (H5T_VLEN == dt->shared->type && H5T_VLEN_STRING != dt->shared->u.vlen.type)
3052
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
3053
3054
    /* Modify the datatype */
3055
0
    if (H5T__set_size(dt, size) < 0)
3056
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for datatype");
3057
3058
0
done:
3059
0
    FUNC_LEAVE_API(ret_value)
3060
0
} /* end H5Tset_size() */
3061
3062
/*-------------------------------------------------------------------------
3063
 * Function:  H5Tget_super
3064
 *
3065
 * Purpose:   Returns the type from which TYPE is derived. In the case of
3066
 *            an enumeration type the return value is an integer type.
3067
 *
3068
 * Return:    Success:    Type ID for base datatype.
3069
 *
3070
 *            Failure:    negative
3071
 *
3072
 *-------------------------------------------------------------------------
3073
 */
3074
hid_t
3075
H5Tget_super(hid_t type)
3076
435
{
3077
435
    H5T_t *dt;                          /* Datatype to query */
3078
435
    H5T_t *super     = NULL;            /* Supertype */
3079
435
    hid_t  ret_value = H5I_INVALID_HID; /* Return value */
3080
3081
870
    FUNC_ENTER_API(H5I_INVALID_HID)
3082
3083
870
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE)))
3084
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype");
3085
435
    if (NULL == (super = H5T_get_super(dt)))
3086
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "not a datatype");
3087
435
    if ((ret_value = H5I_register(H5I_DATATYPE, super, true)) < 0)
3088
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register parent datatype");
3089
3090
435
done:
3091
435
    if (H5I_INVALID_HID == ret_value)
3092
0
        if (super && H5T_close_real(super) < 0)
3093
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, H5I_INVALID_HID,
3094
435
                        "unable to release super datatype info")
3095
3096
435
    FUNC_LEAVE_API(ret_value)
3097
435
} /* end H5Tget_super() */
3098
3099
/*-------------------------------------------------------------------------
3100
 * Function:  H5T_get_super
3101
 *
3102
 * Purpose:   Private function for H5Tget_super.  Returns the type from
3103
 *            which TYPE is derived. In the case of an enumeration type
3104
 *            the return value is an integer type.
3105
 *
3106
 * Return:    Success:    Data type for base data type.
3107
 *            Failure:        NULL
3108
 *
3109
 *-------------------------------------------------------------------------
3110
 */
3111
H5T_t *
3112
H5T_get_super(const H5T_t *dt)
3113
435
{
3114
435
    H5T_t *ret_value = NULL;
3115
3116
435
    FUNC_ENTER_NOAPI(NULL)
3117
3118
435
    assert(dt);
3119
3120
435
    if (!dt->shared->parent)
3121
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type");
3122
435
    if (NULL == (ret_value = H5T_copy(dt->shared->parent, H5T_COPY_ALL)))
3123
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type");
3124
3125
435
done:
3126
435
    FUNC_LEAVE_NOAPI(ret_value)
3127
435
} /* end H5T_get_super() */
3128
3129
/*-------------------------------------------------------------------------
3130
 * Function:    H5T__register_int
3131
 *
3132
 * Purpose:    Register a library internal datatype conversion routine.
3133
 *
3134
 * Return:    Non-negative on success/Negative on failure
3135
 *
3136
 *-------------------------------------------------------------------------
3137
 */
3138
static herr_t
3139
H5T__register_int(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_lib_conv_t func)
3140
274
{
3141
274
    H5T_conv_func_t conv_func;           /* Conversion function wrapper */
3142
274
    herr_t          ret_value = SUCCEED; /* Return value */
3143
3144
274
    FUNC_ENTER_PACKAGE
3145
3146
    /* Check args */
3147
274
    assert(H5T_PERS_HARD == pers || H5T_PERS_SOFT == pers);
3148
274
    assert(name && *name);
3149
274
    assert(src);
3150
274
    assert(dst);
3151
274
    assert(func);
3152
3153
    /* Set up conversion function wrapper */
3154
274
    conv_func.is_app     = false;
3155
274
    conv_func.u.lib_func = func;
3156
3157
    /* Register conversion */
3158
274
    if (H5T__register(pers, name, src, dst, &conv_func) < 0)
3159
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
3160
274
                    "unable to register internal datatype conversion routine");
3161
3162
274
done:
3163
274
    FUNC_LEAVE_NOAPI(ret_value)
3164
274
} /* end H5T__register_int() */
3165
3166
/*-------------------------------------------------------------------------
3167
 * Function:    H5T__register
3168
 *
3169
 * Purpose:    Register a hard or soft conversion function for a data type
3170
 *        conversion path.  The path is specified by the source and
3171
 *        destination data types SRC and DST (for soft functions only the
3172
 *        class of these types is important). If FUNC is a hard function
3173
 *        then it replaces any previous path; if it's a soft function then
3174
 *        it replaces all existing paths to which it applies and is used
3175
 *        for any new path to which it applies as long as that path doesn't
3176
 *        have a hard function.
3177
 *
3178
 * Return:    Non-negative on success/Negative on failure
3179
 *
3180
 *-------------------------------------------------------------------------
3181
 */
3182
static herr_t
3183
H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_func_t *conv)
3184
274
{
3185
274
    H5T_path_t *old_path = NULL;             /*existing conversion path   */
3186
274
    H5T_path_t *new_path = NULL;             /*new conversion path        */
3187
274
    H5T_cdata_t cdata;                       /*temporary conversion data  */
3188
274
    H5T_t      *tmp_stype = NULL;            /*temporary source datatype */
3189
274
    H5T_t      *tmp_dtype = NULL;            /*temporary destination datatype */
3190
274
    hid_t       tmp_sid   = H5I_INVALID_HID; /*temporary datatype ID */
3191
274
    hid_t       tmp_did   = H5I_INVALID_HID; /*temporary datatype ID */
3192
274
    int         i;                           /*counter                    */
3193
274
    herr_t      ret_value = SUCCEED;         /*return value               */
3194
3195
274
    FUNC_ENTER_PACKAGE
3196
3197
    /* Check args */
3198
274
    assert(src);
3199
274
    assert(dst);
3200
274
    assert(conv);
3201
274
    assert(H5T_PERS_HARD == pers || H5T_PERS_SOFT == pers);
3202
274
    assert(name && *name);
3203
3204
274
    if (H5T_PERS_HARD == pers) {
3205
        /* Only bother to register the path if it's not a no-op path (for this machine) */
3206
241
        if (H5T_cmp(src, dst, false)) {
3207
            /* Locate or create a new conversion path */
3208
236
            if (NULL == (new_path = H5T__path_find_real(src, dst, name, conv)))
3209
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to locate/allocate conversion path");
3210
3211
            /* Notify all other functions to recalculate private data since some
3212
             * functions might cache a list of conversion functions.  For
3213
             * instance, the compound type converter caches a list of conversion
3214
             * functions for the members, so adding a new function should cause
3215
             * the list to be recalculated to use the new function.
3216
             */
3217
21.4k
            for (i = 0; i < H5T_g.npaths; i++)
3218
21.2k
                if (new_path != H5T_g.path[i])
3219
21.0k
                    H5T_g.path[i]->cdata.recalc = true;
3220
236
        } /* end if */
3221
241
    }     /* end if */
3222
33
    else {
3223
33
        H5T_conv_ctx_t conv_ctx = {0};
3224
3225
        /*
3226
         * Get the datatype conversion exception callback structure.
3227
         * Note that we have to first check if an API context has been
3228
         * pushed, since we could have arrived here during library
3229
         * initialization of the H5T package.
3230
         */
3231
33
        if (!conv->is_app && H5CX_pushed() && (H5CX_get_dt_conv_cb(&conv_ctx.u.init.cb_struct) < 0))
3232
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
3233
3234
        /* Add function to end of soft list */
3235
33
        if ((size_t)H5T_g.nsoft >= H5T_g.asoft) {
3236
2
            size_t      na = MAX(32, 2 * H5T_g.asoft);
3237
2
            H5T_soft_t *x;
3238
3239
2
            if (NULL == (x = (H5T_soft_t *)H5MM_realloc(H5T_g.soft, na * sizeof(H5T_soft_t))))
3240
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
3241
2
            H5T_g.asoft = na;
3242
2
            H5T_g.soft  = x;
3243
2
        } /* end if */
3244
33
        strncpy(H5T_g.soft[H5T_g.nsoft].name, name, (size_t)H5T_NAMELEN - 1);
3245
33
        H5T_g.soft[H5T_g.nsoft].name[H5T_NAMELEN - 1] = '\0';
3246
33
        H5T_g.soft[H5T_g.nsoft].src                   = src->shared->type;
3247
33
        H5T_g.soft[H5T_g.nsoft].dst                   = dst->shared->type;
3248
33
        H5T_g.soft[H5T_g.nsoft].conv                  = *conv;
3249
33
        H5T_g.nsoft++;
3250
3251
        /*
3252
         * Any existing path (except the no-op path) to which this new soft
3253
         * conversion function applies should be replaced by a new path that
3254
         * uses this function.
3255
         */
3256
33
        for (i = 1; i < H5T_g.npaths; i++) {
3257
0
            old_path = H5T_g.path[i];
3258
0
            assert(old_path);
3259
3260
            /* Does the new soft conversion function apply to this path? */
3261
0
            if (old_path->is_hard || old_path->src->shared->type != src->shared->type ||
3262
0
                old_path->dst->shared->type != dst->shared->type)
3263
0
                continue;
3264
3265
0
            memset(&cdata, 0, sizeof cdata);
3266
0
            cdata.command = H5T_CONV_INIT;
3267
0
            if (conv->is_app) {
3268
0
                if (NULL == (tmp_stype = H5T_copy(old_path->src, H5T_COPY_ALL)))
3269
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy src datatype");
3270
0
                if (NULL == (tmp_dtype = H5T_copy(old_path->dst, H5T_COPY_ALL)))
3271
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy dst datatype");
3272
3273
0
                if ((tmp_sid = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0)
3274
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
3275
0
                                "unable to register ID for source datatype");
3276
0
                if ((tmp_did = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0)
3277
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
3278
0
                                "unable to register ID for destination datatype");
3279
3280
                /* Prepare & restore library for user callback */
3281
0
                H5_BEFORE_USER_CB(FAIL)
3282
0
                    {
3283
0
                        ret_value = (conv->u.app_func)(tmp_sid, tmp_did, &cdata, 0, 0, 0, NULL, NULL,
3284
0
                                                       H5CX_get_dxpl());
3285
0
                    }
3286
0
                H5_AFTER_USER_CB(FAIL)
3287
0
                if (ret_value < 0) {
3288
0
                    if (H5I_dec_ref(tmp_sid) < 0)
3289
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL,
3290
0
                                    "unable to decrement reference count on temporary ID");
3291
0
                    if (H5I_dec_ref(tmp_did) < 0)
3292
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL,
3293
0
                                    "unable to decrement reference count on temporary ID");
3294
0
                    tmp_sid = tmp_did = H5I_INVALID_HID;
3295
0
                    tmp_stype = tmp_dtype = NULL;
3296
0
                    if (H5E_clear_stack() < 0)
3297
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
3298
0
                    continue;
3299
0
                } /* end if */
3300
0
            }     /* end if */
3301
0
            else if ((conv->u.lib_func)(old_path->src, old_path->dst, &cdata, &conv_ctx, 0, 0, 0, NULL,
3302
0
                                        NULL) < 0) {
3303
0
                if (H5E_clear_stack() < 0)
3304
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
3305
0
                continue;
3306
0
            } /* end if */
3307
3308
            /* Create a new conversion path */
3309
0
            if (NULL == (new_path = H5FL_CALLOC(H5T_path_t)))
3310
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
3311
0
            strncpy(new_path->name, name, (size_t)H5T_NAMELEN - 1);
3312
0
            new_path->name[H5T_NAMELEN - 1] = '\0';
3313
0
            if (NULL == (new_path->src = H5T_copy(old_path->src, H5T_COPY_ALL)) ||
3314
0
                NULL == (new_path->dst = H5T_copy(old_path->dst, H5T_COPY_ALL)))
3315
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy data types");
3316
0
            new_path->conv    = *conv;
3317
0
            new_path->is_hard = false;
3318
0
            new_path->cdata   = cdata;
3319
3320
            /* Replace previous path */
3321
0
            H5T_g.path[i] = new_path;
3322
0
            new_path      = NULL; /*so we don't free it on error*/
3323
3324
            /* Free old path */
3325
0
            conv_ctx.u.free.src_type_id = tmp_sid;
3326
0
            conv_ctx.u.free.dst_type_id = tmp_did;
3327
0
            if (H5T__path_free(old_path, &conv_ctx) < 0)
3328
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype conversion path");
3329
3330
            /* Release temporary atoms */
3331
0
            if (tmp_sid >= 0) {
3332
0
                if (H5I_dec_ref(tmp_sid) < 0)
3333
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
3334
0
                tmp_sid   = H5I_INVALID_HID;
3335
0
                tmp_stype = NULL;
3336
0
            }
3337
0
            if (tmp_did >= 0) {
3338
0
                if (H5I_dec_ref(tmp_did) < 0)
3339
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
3340
0
                tmp_did   = H5I_INVALID_HID;
3341
0
                tmp_dtype = NULL;
3342
0
            }
3343
3344
            /* We don't care about any failures during the freeing process */
3345
0
            if (H5E_clear_stack() < 0)
3346
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
3347
0
        } /* end for */
3348
33
    }     /* end else */
3349
3350
274
done:
3351
274
    if (ret_value < 0) {
3352
0
        if (new_path) {
3353
0
            if (new_path->src && (H5T_close_real(new_path->src) < 0))
3354
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype");
3355
0
            if (new_path->dst && (H5T_close_real(new_path->dst) < 0))
3356
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype");
3357
0
            new_path = H5FL_FREE(H5T_path_t, new_path);
3358
0
        } /* end if */
3359
0
    }     /* end if */
3360
3361
274
    if (tmp_sid >= 0) {
3362
0
        if (H5I_dec_ref(tmp_sid) < 0)
3363
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
3364
0
    }
3365
274
    else if (tmp_stype) {
3366
0
        if (H5T_close(tmp_stype) < 0)
3367
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype");
3368
0
    }
3369
274
    if (tmp_did >= 0) {
3370
0
        if (H5I_dec_ref(tmp_did) < 0)
3371
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
3372
0
    }
3373
274
    else if (tmp_dtype) {
3374
0
        if (H5T_close(tmp_dtype) < 0)
3375
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype");
3376
0
    }
3377
3378
274
    FUNC_LEAVE_NOAPI(ret_value)
3379
274
} /* end H5T__register() */
3380
3381
/*-------------------------------------------------------------------------
3382
 * Function:    H5Tregister
3383
 *
3384
 * Purpose:    Register a hard or soft conversion function for a data type
3385
 *        conversion path.  The path is specified by the source and
3386
 *        destination data types SRC_ID and DST_ID (for soft functions
3387
 *        only the class of these types is important). If FUNC is a
3388
 *        hard function then it replaces any previous path; if it's a
3389
 *        soft function then it replaces all existing paths to which it
3390
 *        applies and is used for any new path to which it applies as
3391
 *        long as that path doesn't have a hard function.
3392
 *
3393
 * Return:    Non-negative on success/Negative on failure
3394
 *
3395
 *-------------------------------------------------------------------------
3396
 */
3397
herr_t
3398
H5Tregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, H5T_conv_t func)
3399
0
{
3400
0
    H5T_t          *src;                 /*source data type descriptor    */
3401
0
    H5T_t          *dst;                 /*destination data type desc     */
3402
0
    H5T_conv_func_t conv_func;           /* Conversion function wrapper */
3403
0
    herr_t          ret_value = SUCCEED; /*return value                   */
3404
3405
0
    FUNC_ENTER_API(FAIL)
3406
3407
    /* Check args */
3408
0
    if (H5T_PERS_HARD != pers && H5T_PERS_SOFT != pers)
3409
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid function persistence");
3410
0
    if (!name || !*name)
3411
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "conversion must have a name for debugging");
3412
0
    if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)))
3413
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
3414
0
    if (NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE)))
3415
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
3416
0
    if (!func)
3417
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no conversion function specified");
3418
3419
    /* Set up conversion function wrapper */
3420
0
    conv_func.is_app     = true;
3421
0
    conv_func.u.app_func = func;
3422
3423
    /* Go register the function */
3424
0
    if (H5T__register(pers, name, src, dst, &conv_func) < 0)
3425
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register conversion function");
3426
3427
0
done:
3428
0
    FUNC_LEAVE_API(ret_value)
3429
0
} /* end H5Tregister() */
3430
3431
/*-------------------------------------------------------------------------
3432
 * Function:   H5T_unregister
3433
 *
3434
 * Purpose:    Removes conversion paths that match the specified criteria.
3435
 *        All arguments are optional. Missing arguments are wild cards.
3436
 *        The special no-op path cannot be removed.
3437
 *
3438
 * Return:    Success:    non-negative
3439
 *            Failure:    negative
3440
 *
3441
 *-------------------------------------------------------------------------
3442
 */
3443
herr_t
3444
H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5VL_object_t *owned_vol_obj,
3445
               H5T_conv_t func)
3446
83
{
3447
83
    H5T_conv_ctx_t conv_ctx  = {0};  /* Conversion context object   */
3448
83
    H5T_path_t    *path      = NULL; /* Conversion path             */
3449
83
    H5T_soft_t    *soft      = NULL; /* Soft conversion information */
3450
83
    herr_t         ret_value = SUCCEED;
3451
3452
83
    FUNC_ENTER_NOAPI(FAIL)
3453
3454
83
    conv_ctx.u.free.src_type_id = H5I_INVALID_HID;
3455
83
    conv_ctx.u.free.dst_type_id = H5I_INVALID_HID;
3456
3457
    /*
3458
     * Remove matching entries from the soft list if:
3459
     *
3460
     *  - The caller didn't specify a particular type (soft or hard)
3461
     *    of conversion path to match against or specified that soft
3462
     *    conversion paths should be matched against
3463
     *
3464
     *  AND
3465
     *
3466
     *  - The caller didn't provide the `owned_vol_obj` parameter;
3467
     *    if this parameter is provided, we want to leave the soft
3468
     *    list untouched and only remove cached conversion paths
3469
     *    below where the file VOL object associated with the path's
3470
     *    source or destination types matches the given VOL object.
3471
     */
3472
83
    if ((H5T_PERS_DONTCARE == pers || H5T_PERS_SOFT == pers) && !owned_vol_obj) {
3473
0
        for (int i = H5T_g.nsoft - 1; i >= 0; --i) {
3474
0
            soft = H5T_g.soft + i;
3475
0
            assert(soft);
3476
0
            if (name && *name && strcmp(name, soft->name) != 0)
3477
0
                continue;
3478
0
            if (src && src->shared->type != soft->src)
3479
0
                continue;
3480
0
            if (dst && dst->shared->type != soft->dst)
3481
0
                continue;
3482
0
            if (func && func != soft->conv.u.app_func)
3483
0
                continue;
3484
3485
0
            memmove(H5T_g.soft + i, H5T_g.soft + i + 1, (size_t)(H5T_g.nsoft - (i + 1)) * sizeof(H5T_soft_t));
3486
0
            --H5T_g.nsoft;
3487
0
        }
3488
0
    }
3489
3490
    /* Remove matching conversion paths, except no-op path */
3491
15.4k
    for (int i = H5T_g.npaths - 1; i > 0; --i) {
3492
15.3k
        bool nomatch;
3493
3494
15.3k
        path = H5T_g.path[i];
3495
15.3k
        assert(path);
3496
3497
15.3k
        nomatch = !H5T_path_match(path, pers, name, src, dst, owned_vol_obj, func);
3498
3499
        /* Not a match */
3500
15.3k
        if (nomatch) {
3501
            /*
3502
             * Notify all other functions to recalculate private data since some
3503
             * functions might cache a list of conversion functions.  For
3504
             * instance, the compound type converter caches a list of conversion
3505
             * functions for the members, so removing a function should cause
3506
             * the list to be recalculated to avoid the removed function.
3507
             */
3508
15.2k
            path->cdata.recalc = true;
3509
15.2k
        }
3510
144
        else {
3511
            /* Remove from table */
3512
144
            memmove(H5T_g.path + i, H5T_g.path + i + 1,
3513
144
                    (size_t)(H5T_g.npaths - (i + 1)) * sizeof(H5T_path_t *));
3514
144
            --H5T_g.npaths;
3515
3516
144
            if (H5T__path_free(path, &conv_ctx) < 0)
3517
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype conversion path");
3518
144
        }
3519
15.3k
    }
3520
3521
83
done:
3522
83
    FUNC_LEAVE_NOAPI(ret_value)
3523
83
} /* end H5T_unregister() */
3524
3525
/*-------------------------------------------------------------------------
3526
 * Function:  H5Tunregister
3527
 *
3528
 * Purpose:   Removes conversion paths that match the specified criteria.
3529
 *        All arguments are optional. Missing arguments are wild cards.
3530
 *        The special no-op path cannot be removed.
3531
 *
3532
 * Return:    Success:    non-negative
3533
 *
3534
 *            Failure:    negative
3535
 *
3536
 *-------------------------------------------------------------------------
3537
 */
3538
herr_t
3539
H5Tunregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, H5T_conv_t func)
3540
0
{
3541
0
    H5T_t *src = NULL, *dst = NULL; /* Datatype descriptors */
3542
0
    herr_t ret_value = SUCCEED;     /* Return value */
3543
3544
0
    FUNC_ENTER_API(FAIL)
3545
3546
    /* Check arguments */
3547
0
    if (src_id > 0 && (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE))))
3548
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src is not a data type");
3549
0
    if (dst_id > 0 && (NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE))))
3550
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst is not a data type");
3551
3552
0
    if (H5T_unregister(pers, name, src, dst, NULL, func) < 0)
3553
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "internal unregister function failed");
3554
3555
0
done:
3556
0
    FUNC_LEAVE_API(ret_value)
3557
0
} /* end H5Tunregister() */
3558
3559
/*-------------------------------------------------------------------------
3560
 * Function:  H5Tfind
3561
 *
3562
 * Purpose:   Finds a conversion function that can handle a conversion from
3563
 *        type SRC_ID to type DST_ID.  The PCDATA argument is a pointer
3564
 *        to a pointer to type conversion data which was created and
3565
 *        initialized by the type conversion function of this path
3566
 *        when the conversion function was installed on the path.
3567
 *
3568
 * Return:    Success:    A pointer to a suitable conversion function.
3569
 *
3570
 *            Failure:    NULL
3571
 *
3572
 *-------------------------------------------------------------------------
3573
 */
3574
H5T_conv_t
3575
H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata /*out*/)
3576
0
{
3577
0
    H5T_t      *src, *dst;
3578
0
    H5T_path_t *path;
3579
0
    H5T_conv_t  ret_value; /* Return value */
3580
3581
0
    FUNC_ENTER_API(NULL)
3582
3583
    /* Check args */
3584
0
    if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
3585
0
        NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE)))
3586
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type");
3587
0
    if (!pcdata)
3588
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "no address to receive cdata pointer");
3589
3590
    /* Find it */
3591
0
    if (NULL == (path = H5T_path_find(src, dst)))
3592
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "conversion function not found");
3593
3594
0
    if (pcdata)
3595
0
        *pcdata = &(path->cdata);
3596
3597
    /* Set return value */
3598
0
    ret_value = path->conv.u.app_func;
3599
3600
0
done:
3601
0
    FUNC_LEAVE_API(ret_value)
3602
0
} /* end H5Tfind() */
3603
3604
/*-------------------------------------------------------------------------
3605
 * Function:  H5Tcompiler_conv
3606
 *
3607
 * Purpose:   Finds out whether the library's conversion function from
3608
 *            type src_id to type dst_id is a compiler (hard) conversion.
3609
 *            A hard conversion uses compiler's casting; a soft conversion
3610
 *            uses the library's own conversion function.
3611
 *
3612
 * Return:    true:           hard conversion.
3613
 *            false:          soft conversion.
3614
 *            FAIL:           failed.
3615
 *
3616
 *-------------------------------------------------------------------------
3617
 */
3618
htri_t
3619
H5Tcompiler_conv(hid_t src_id, hid_t dst_id)
3620
0
{
3621
0
    H5T_t *src, *dst;
3622
0
    htri_t ret_value; /* Return value */
3623
3624
0
    FUNC_ENTER_API(FAIL)
3625
3626
    /* Check args */
3627
0
    if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
3628
0
        NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE)))
3629
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
3630
3631
    /* Find it */
3632
0
    if ((ret_value = H5T__compiler_conv(src, dst)) < 0)
3633
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "conversion function not found");
3634
3635
0
done:
3636
0
    FUNC_LEAVE_API(ret_value)
3637
0
} /* end H5Tcompiler_conv() */
3638
3639
/*-------------------------------------------------------------------------
3640
 * Function:  H5Tconvert
3641
 *
3642
 * Purpose:   Convert NELMTS elements from type SRC_ID to type DST_ID.  The
3643
 *        source elements are packed in BUF and on return the
3644
 *        destination will be packed in BUF.  That is, the conversion
3645
 *        is performed in place.  The optional background buffer is an
3646
 *        array of NELMTS values of destination type which are merged
3647
 *        with the converted values to fill in cracks (for instance,
3648
 *        BACKGROUND might be an array of structs with the `a' and `b'
3649
 *        fields already initialized and the conversion of BUF supplies
3650
 *        the `c' and `d' field values).  The PLIST_ID a dataset transfer
3651
 *        property list which is passed to the conversion functions.  (It's
3652
 *        currently only used to pass along the VL datatype custom allocation
3653
 *        information -QAK 7/1/99)
3654
 *
3655
 * Return:    Non-negative on success/Negative on failure
3656
 *
3657
 *-------------------------------------------------------------------------
3658
 */
3659
herr_t
3660
H5Tconvert(hid_t src_id, hid_t dst_id, size_t nelmts, void *buf, void *background, hid_t dxpl_id)
3661
0
{
3662
0
    H5T_path_t *tpath;               /* type conversion info    */
3663
0
    H5T_t      *src, *dst;           /* unregistered types      */
3664
0
    herr_t      ret_value = SUCCEED; /* Return value            */
3665
3666
0
    FUNC_ENTER_API(FAIL)
3667
3668
    /* Check args */
3669
0
    if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
3670
0
        NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE)))
3671
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
3672
0
    if (H5P_DEFAULT == dxpl_id)
3673
0
        dxpl_id = H5P_DATASET_XFER_DEFAULT;
3674
0
    else if (true != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
3675
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset transfer property list");
3676
3677
    /* Set DXPL for operation */
3678
0
    H5CX_set_dxpl(dxpl_id);
3679
3680
    /* Find the conversion function */
3681
0
    if (NULL == (tpath = H5T_path_find(src, dst)))
3682
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst data types");
3683
3684
0
    if (H5T_convert(tpath, src, dst, nelmts, 0, 0, buf, background) < 0)
3685
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed");
3686
3687
0
done:
3688
0
    FUNC_LEAVE_API(ret_value)
3689
0
} /* end H5Tconvert() */
3690
3691
/*-------------------------------------------------------------------------
3692
 * Function:    H5Treclaim
3693
 *
3694
 * Purpose: Frees the buffers allocated for storing variable-length data
3695
 *      in memory.  Only frees the VL data in the selection defined in the
3696
 *      dataspace.  The dataset transfer property list is required to find the
3697
 *      correct allocation/free methods for the VL data in the buffer.
3698
 *
3699
 * Return:  Non-negative on success, negative on failure
3700
 *
3701
 *-------------------------------------------------------------------------
3702
 */
3703
herr_t
3704
H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf)
3705
322
{
3706
322
    const H5T_t *type;
3707
322
    H5S_t       *space;     /* Dataspace for iteration */
3708
322
    herr_t       ret_value; /* Return value */
3709
3710
644
    FUNC_ENTER_API(FAIL)
3711
3712
    /* Check args */
3713
644
    if (buf == NULL)
3714
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "'buf' pointer is NULL");
3715
322
    if (NULL == (type = (const H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
3716
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype");
3717
322
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
3718
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace");
3719
322
    if (!(H5S_has_extent(space)))
3720
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set");
3721
3722
    /* Get the default dataset transfer property list if the user didn't provide one */
3723
322
    if (H5P_DEFAULT == dxpl_id)
3724
322
        dxpl_id = H5P_DATASET_XFER_DEFAULT;
3725
0
    else if (true != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
3726
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms");
3727
3728
    /* Set DXPL for operation */
3729
322
    H5CX_set_dxpl(dxpl_id);
3730
3731
    /* Call internal routine */
3732
322
    ret_value = H5T_reclaim(type, space, buf);
3733
3734
322
done:
3735
322
    FUNC_LEAVE_API(ret_value)
3736
322
} /* end H5Treclaim() */
3737
3738
/*-------------------------------------------------------------------------
3739
 * Function:  H5Tencode
3740
 *
3741
 * Purpose:   Given an datatype ID, converts the object description into
3742
 *            binary in a buffer.
3743
 *
3744
 * Return:    Success:    non-negative
3745
 *
3746
 *            Failure:    negative
3747
 *
3748
 *-------------------------------------------------------------------------
3749
 */
3750
herr_t
3751
H5Tencode(hid_t obj_id, void *buf, size_t *nalloc)
3752
0
{
3753
0
    H5T_t *dtype;
3754
0
    herr_t ret_value = SUCCEED;
3755
3756
0
    FUNC_ENTER_API(FAIL)
3757
3758
    /* Check argument and retrieve object */
3759
0
    if (NULL == (dtype = (H5T_t *)H5I_object_verify(obj_id, H5I_DATATYPE)))
3760
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
3761
0
    if (nalloc == NULL)
3762
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL pointer for buffer size");
3763
3764
    /* Go encode the datatype */
3765
0
    if (H5T_encode(dtype, (unsigned char *)buf, nalloc) < 0)
3766
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype");
3767
3768
0
done:
3769
0
    FUNC_LEAVE_API(ret_value)
3770
0
} /* end H5Tencode() */
3771
3772
/*-------------------------------------------------------------------------
3773
 * Function:  H5Tdecode2
3774
 *
3775
 * Purpose:   Decode a binary object description and return a new object
3776
 *            handle.
3777
 *
3778
 * Return:    Success:    datatype ID(non-negative)
3779
 *
3780
 *            Failure:    negative
3781
 *
3782
 *-------------------------------------------------------------------------
3783
 */
3784
hid_t
3785
H5Tdecode2(const void *buf, size_t buf_size)
3786
0
{
3787
0
    H5T_t *dt;
3788
0
    hid_t  ret_value; /* Return value */
3789
3790
0
    FUNC_ENTER_API(H5I_INVALID_HID)
3791
3792
    /* Check args */
3793
0
    if (buf == NULL)
3794
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "empty buffer");
3795
3796
    /* Create datatype by decoding buffer */
3797
0
    if (NULL == (dt = H5T_decode(buf_size, buf)))
3798
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, H5I_INVALID_HID, "can't decode object");
3799
3800
    /* Register the type and return the ID */
3801
0
    if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0)
3802
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register data type");
3803
3804
0
done:
3805
0
    FUNC_LEAVE_API(ret_value)
3806
0
} /* end H5Tdecode2() */
3807
3808
/*-------------------------------------------------------------------------
3809
 * API functions are above; library-private functions are below...
3810
 *-------------------------------------------------------------------------
3811
 */
3812
3813
/*-------------------------------------------------------------------------
3814
 * Function:  H5T_encode
3815
 *
3816
 * Purpose:   Private function for H5Tencode.  Converts an object
3817
 *            description into binary in a buffer.
3818
 *
3819
 * Return:    Success:    non-negative
3820
 *
3821
 *            Failure:    negative
3822
 *
3823
 *-------------------------------------------------------------------------
3824
 */
3825
herr_t
3826
H5T_encode(H5T_t *obj, unsigned char *buf, size_t *nalloc)
3827
2
{
3828
2
    size_t buf_size;         /* Encoded size of datatype */
3829
2
    H5F_t *f         = NULL; /* Fake file structure*/
3830
2
    herr_t ret_value = SUCCEED;
3831
3832
2
    FUNC_ENTER_NOAPI_NOINIT
3833
3834
    /* Allocate "fake" file structure */
3835
2
    if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
3836
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct");
3837
3838
    /* Find out the size of buffer needed */
3839
2
    if ((buf_size = H5O_msg_raw_size(f, H5O_DTYPE_ID, true, obj)) == 0)
3840
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "can't find datatype size");
3841
3842
    /* Don't encode if buffer size isn't big enough or buffer is empty */
3843
2
    if (!buf || *nalloc < (buf_size + 1 + 1))
3844
1
        *nalloc = buf_size + 1 + 1;
3845
1
    else {
3846
        /* Encode the type of the information */
3847
1
        *buf++ = H5O_DTYPE_ID;
3848
3849
        /* Encode the version of the dataspace information */
3850
1
        *buf++ = H5T_ENCODE_VERSION;
3851
3852
        /* Encode into user's buffer */
3853
1
        if (H5O_msg_encode(f, H5O_DTYPE_ID, true, buf, obj) < 0)
3854
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode object");
3855
1
    } /* end else */
3856
3857
2
done:
3858
    /* Release fake file structure */
3859
2
    if (f && H5F_fake_free(f) < 0)
3860
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release fake file struct");
3861
3862
2
    FUNC_LEAVE_NOAPI(ret_value)
3863
2
} /* end H5T_encode() */
3864
3865
/*-------------------------------------------------------------------------
3866
 * Function:  H5T_decode
3867
 *
3868
 * Purpose:   Private function for H5Tdecode.  Reconstructs a binary
3869
 *            description of datatype and returns a new object handle.
3870
 *
3871
 * Return:    Success:    Pointer to the new type.
3872
 *
3873
 *            Failure:    NULL
3874
 *
3875
 *-------------------------------------------------------------------------
3876
 */
3877
H5T_t *
3878
H5T_decode(size_t buf_size, const unsigned char *buf)
3879
1
{
3880
1
    H5F_t *f         = NULL; /* Fake file structure*/
3881
1
    H5T_t *ret_value = NULL; /* Return value */
3882
3883
1
    FUNC_ENTER_NOAPI_NOINIT
3884
3885
    /* Allocate "fake" file structure */
3886
1
    if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
3887
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "can't allocate fake file struct");
3888
3889
1
    if (buf_size != SIZE_MAX && H5_IS_BUFFER_OVERFLOW(buf, 1, buf + buf_size - 1))
3890
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADMESG, NULL, "buffer too small to be datatype message");
3891
3892
    /* Decode the type of the information */
3893
1
    if (*buf++ != H5O_DTYPE_ID)
3894
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADMESG, NULL, "not an encoded datatype");
3895
3896
1
    if (buf_size != SIZE_MAX && H5_IS_BUFFER_OVERFLOW(buf, 1, buf + buf_size - 1))
3897
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADMESG, NULL, "buffer too small to be datatype message");
3898
3899
    /* Decode the version of the datatype information */
3900
1
    if (*buf++ != H5T_ENCODE_VERSION)
3901
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, NULL, "unknown version of encoded datatype");
3902
3903
    /* Decode the serialized datatype message */
3904
1
    if (NULL == (ret_value = (H5T_t *)H5O_msg_decode(f, NULL, H5O_DTYPE_ID, buf_size, buf)))
3905
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object");
3906
3907
    /* Mark datatype as being in memory now */
3908
1
    if (H5T_set_loc(ret_value, NULL, H5T_LOC_MEMORY) < 0)
3909
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location");
3910
3911
    /* No VOL object */
3912
1
    ret_value->vol_obj = NULL;
3913
1
done:
3914
    /* Release fake file structure */
3915
1
    if (f && H5F_fake_free(f) < 0)
3916
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, NULL, "unable to release fake file struct");
3917
3918
1
    FUNC_LEAVE_NOAPI(ret_value)
3919
1
} /* end H5T_decode() */
3920
3921
/*-------------------------------------------------------------------------
3922
 * Function:  H5T__create
3923
 *
3924
 * Purpose:   Creates a new data type and initializes it to reasonable
3925
 *            values.     The new data type is SIZE bytes and an instance of
3926
 *            the class TYPE.
3927
 *
3928
 * Return:    Success:    Pointer to the new type.
3929
 *
3930
 *            Failure:    NULL
3931
 *
3932
 *-------------------------------------------------------------------------
3933
 */
3934
H5T_t *
3935
H5T__create(H5T_class_t type, size_t size)
3936
2
{
3937
2
    H5T_t *dt        = NULL;
3938
2
    H5T_t *ret_value = NULL;
3939
3940
2
    FUNC_ENTER_PACKAGE
3941
3942
2
    switch (type) {
3943
0
        case H5T_INTEGER:
3944
0
        case H5T_FLOAT:
3945
0
        case H5T_TIME:
3946
0
        case H5T_STRING: {
3947
0
            H5T_t *origin_dt = NULL;
3948
3949
0
            if (NULL == (origin_dt = (H5T_t *)H5I_object(H5T_C_S1)))
3950
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "can't get structure for string type");
3951
3952
            /* Copy the default string datatype */
3953
0
            if (NULL == (dt = H5T_copy(origin_dt, H5T_COPY_TRANSIENT)))
3954
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy");
3955
0
            dt->shared->type = type;
3956
3957
            /* Modify the datatype */
3958
0
            if (H5T__set_size(dt, size) < 0)
3959
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to set size for string type");
3960
0
        } break;
3961
3962
0
        case H5T_BITFIELD:
3963
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "type class is not appropriate - use H5Tcopy()");
3964
3965
0
        case H5T_OPAQUE:
3966
1
        case H5T_COMPOUND:
3967
1
            if (NULL == (dt = H5T__alloc()))
3968
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
3969
1
            dt->shared->type = type;
3970
3971
1
            if (type == H5T_COMPOUND) {
3972
1
                dt->shared->u.compnd.packed    = false; /* Start out unpacked */
3973
1
                dt->shared->u.compnd.memb_size = 0;
3974
1
            } /* end if */
3975
0
            else if (type == H5T_OPAQUE)
3976
                /* Initialize the tag in case it's not set later.  A null tag will
3977
                 * cause problems for later operations. */
3978
0
                dt->shared->u.opaque.tag = H5MM_strdup("");
3979
1
            break;
3980
3981
1
        case H5T_ENUM: {
3982
1
            hid_t  subtype;
3983
1
            H5T_t *sub_t_obj;
3984
3985
1
            if (sizeof(char) == size)
3986
1
                subtype = H5T_NATIVE_SCHAR_g;
3987
0
            else if (sizeof(short) == size)
3988
0
                subtype = H5T_NATIVE_SHORT_g;
3989
0
            else if (sizeof(int) == size)
3990
0
                subtype = H5T_NATIVE_INT_g;
3991
0
            else if (sizeof(long) == size)
3992
0
                subtype = H5T_NATIVE_LONG_g;
3993
#if H5_SIZEOF_LONG != H5_SIZEOF_LONG_LONG
3994
            else if (sizeof(long long) == size)
3995
                subtype = H5T_NATIVE_LLONG_g;
3996
#endif /* H5_SIZEOF_LONG != H5_SIZEOF_LONG_LONG */
3997
0
            else
3998
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no applicable native integer type");
3999
1
            if (NULL == (dt = H5T__alloc()))
4000
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
4001
1
            dt->shared->type = type;
4002
1
            if (NULL == (sub_t_obj = (H5T_t *)H5I_object(subtype)))
4003
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "unable to get datatype object");
4004
1
            if (NULL == (dt->shared->parent = H5T_copy(sub_t_obj, H5T_COPY_ALL)))
4005
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy base datatype");
4006
1
        } break;
4007
4008
1
        case H5T_VLEN: /* Variable length datatype */
4009
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tvlen_create()");
4010
4011
0
        case H5T_ARRAY: /* Array datatype */
4012
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tarray_create2()");
4013
4014
0
        case H5T_COMPLEX: /* Complex number datatype */
4015
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tcomplex_create()");
4016
4017
0
        case H5T_NO_CLASS:
4018
0
        case H5T_REFERENCE:
4019
0
        case H5T_NCLASSES:
4020
0
        default:
4021
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "unknown data type class");
4022
2
    } /* end switch */
4023
4024
    /* Set the size except VL string */
4025
2
    if (H5T_STRING != type || H5T_VARIABLE != size)
4026
2
        dt->shared->size = size;
4027
4028
    /* No VOL object */
4029
2
    dt->vol_obj = NULL;
4030
4031
    /* Set return value */
4032
2
    ret_value = dt;
4033
4034
2
done:
4035
2
    if (NULL == ret_value) {
4036
0
        if (dt) {
4037
0
            if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
4038
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object");
4039
0
            dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
4040
0
            dt         = H5FL_FREE(H5T_t, dt);
4041
0
        }
4042
0
    }
4043
4044
2
    FUNC_LEAVE_NOAPI(ret_value)
4045
2
} /* end H5T__create() */
4046
4047
/*-------------------------------------------------------------------------
4048
 * Function:  H5T__initiate_copy
4049
 *
4050
 * Purpose:   Allocates datatype structures, copies core fields, and initializes
4051
 *            VOL fields.
4052
 *
4053
 * Return:    Success:    Pointer to a new copy of the OLD_DT argument.
4054
 *            Failure:    NULL
4055
 *
4056
 * Note:      Common code for both H5T_copy and H5T_copy_reopen, as part of
4057
 *            the const-correct datatype copying routines.
4058
 *
4059
 *-------------------------------------------------------------------------
4060
 */
4061
static H5T_t *
4062
H5T__initiate_copy(const H5T_t *old_dt)
4063
20.0k
{
4064
20.0k
    H5T_t *new_dt    = NULL; /* Copy of datatype */
4065
20.0k
    H5T_t *ret_value = NULL; /* Return value */
4066
4067
20.0k
    FUNC_ENTER_PACKAGE
4068
4069
    /* Allocate space */
4070
20.0k
    if (NULL == (new_dt = H5FL_MALLOC(H5T_t)))
4071
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_t memory allocation failed");
4072
20.0k
    if (NULL == (new_dt->shared = H5FL_MALLOC(H5T_shared_t)))
4073
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_shared_t memory allocation failed");
4074
4075
    /* Copy shared information */
4076
20.0k
    *(new_dt->shared) = *(old_dt->shared);
4077
4078
    /* Increment ref count on owned VOL object */
4079
20.0k
    if (new_dt->shared->owned_vol_obj)
4080
1.71k
        (void)H5VL_object_inc_rc(new_dt->shared->owned_vol_obj);
4081
4082
    /* Reset vol_obj field */
4083
20.0k
    new_dt->vol_obj = NULL;
4084
4085
    /* Set return value */
4086
20.0k
    ret_value = new_dt;
4087
4088
20.0k
done:
4089
20.0k
    if (ret_value == NULL)
4090
0
        if (new_dt) {
4091
0
            if (new_dt->shared) {
4092
0
                if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
4093
0
                    HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object");
4094
0
                new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
4095
0
            } /* end if */
4096
0
            new_dt = H5FL_FREE(H5T_t, new_dt);
4097
0
        } /* end if */
4098
4099
20.0k
    FUNC_LEAVE_NOAPI(ret_value)
4100
20.0k
} /* end H5T__initiate_copy() */
4101
4102
/*-------------------------------------------------------------------------
4103
 * Function:  H5T__copy_transient
4104
 *
4105
 * Purpose:   Part of recursive framework for const-correct datatype copying.
4106
 *
4107
 * Return:    Success:    Pointer to a new copy of the OLD_DT argument.
4108
 *            Failure:    NULL
4109
 *
4110
 *-------------------------------------------------------------------------
4111
 */
4112
static H5T_t *
4113
H5T__copy_transient(H5T_t *old_dt)
4114
0
{
4115
0
    H5T_t *ret_value = NULL; /* Return value */
4116
4117
0
    FUNC_ENTER_PACKAGE
4118
4119
    /* Copy datatype, with correct method */
4120
0
    if (NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_TRANSIENT)))
4121
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'transient' copy of datatype");
4122
4123
0
done:
4124
0
    FUNC_LEAVE_NOAPI(ret_value)
4125
0
} /* end H5T__copy_transient() */
4126
4127
/*-------------------------------------------------------------------------
4128
 * Function:  H5T__copy_all
4129
 *
4130
 * Purpose:   Part of recursive framework for const-correct datatype copying.
4131
 *
4132
 * Return:    Success:    Pointer to a new copy of the OLD_DT argument.
4133
 *            Failure:    NULL
4134
 *
4135
 *-------------------------------------------------------------------------
4136
 */
4137
static H5T_t *
4138
H5T__copy_all(H5T_t *old_dt)
4139
220
{
4140
220
    H5T_t *ret_value = NULL; /* Return value */
4141
4142
220
    FUNC_ENTER_PACKAGE
4143
4144
    /* Copy datatype, with correct method */
4145
220
    if (NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_ALL)))
4146
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'all' copy of datatype");
4147
4148
220
done:
4149
220
    FUNC_LEAVE_NOAPI(ret_value)
4150
220
} /* end H5T__copy_transient() */
4151
4152
/*-------------------------------------------------------------------------
4153
 * Function:  H5T__complete_copy
4154
 *
4155
 * Purpose:   Completes copying datatype fields, as part of the recursive
4156
 *            const-correct datatype copy routines.
4157
 *
4158
 * Return:    Success:    non-negative
4159
 *            Failure:    negative
4160
 *
4161
 * Note:      Common code for both H5T_copy and H5T_copy_reopen.
4162
 *
4163
 *-------------------------------------------------------------------------
4164
 */
4165
static herr_t
4166
H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo, bool set_memory_type,
4167
                   H5T_copy_func_t copyfn)
4168
20.0k
{
4169
20.0k
    H5T_t   *tmp = NULL;          /* Temporary copy of compound field's datatype */
4170
20.0k
    char    *s;                   /* Temporary copy of compound field name / enum value name */
4171
20.0k
    unsigned i;                   /* Local index variable */
4172
20.0k
    herr_t   ret_value = SUCCEED; /* Return value */
4173
4174
20.0k
    FUNC_ENTER_PACKAGE
4175
4176
    /* Update fields in the new struct, if we aren't sharing an already opened
4177
     * committed datatype */
4178
20.0k
    if (!reopened_fo) {
4179
        /* Copy parent information */
4180
20.0k
        if (old_dt->shared->parent)
4181
656
            if (NULL == (new_dt->shared->parent = (*copyfn)(old_dt->shared->parent)))
4182
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype's parent type");
4183
4184
20.0k
        switch (new_dt->shared->type) {
4185
0
            case H5T_COMPOUND: {
4186
0
                ssize_t accum_change = 0; /* Amount of change in the offset of the fields */
4187
4188
                /*
4189
                 * Copy all member fields to new type, then overwrite the
4190
                 * name and type fields of each new member with copied values.
4191
                 * That is, H5T_copy() is a deep copy.
4192
                 */
4193
                /* Only malloc if space has been allocated for members - NAF */
4194
0
                if (new_dt->shared->u.compnd.nalloc > 0) {
4195
0
                    if (NULL == (new_dt->shared->u.compnd.memb =
4196
0
                                     H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t))))
4197
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed");
4198
4199
0
                    H5MM_memcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
4200
0
                                new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t));
4201
0
                } /* end if */
4202
4203
0
                for (i = 0; i < new_dt->shared->u.compnd.nmembs; i++) {
4204
0
                    unsigned j;
4205
0
                    int      old_match;
4206
4207
0
                    if (NULL == (s = H5MM_xstrdup(new_dt->shared->u.compnd.memb[i].name)))
4208
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
4209
0
                                    "can't copy string for compound field's name");
4210
0
                    new_dt->shared->u.compnd.memb[i].name = s;
4211
0
                    if (NULL == (tmp = (*copyfn)(old_dt->shared->u.compnd.memb[i].type)))
4212
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy compound field's datatype");
4213
0
                    new_dt->shared->u.compnd.memb[i].type = tmp;
4214
0
                    assert(tmp != NULL);
4215
4216
                    /* Range check against compound member's offset */
4217
0
                    if ((accum_change < 0) &&
4218
0
                        ((ssize_t)new_dt->shared->u.compnd.memb[i].offset < accum_change))
4219
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
4220
4221
                    /* Apply the accumulated size change to the offset of the field */
4222
0
                    new_dt->shared->u.compnd.memb[i].offset += (size_t)accum_change;
4223
4224
0
                    if (old_dt->shared->u.compnd.sorted != H5T_SORT_VALUE) {
4225
0
                        for (old_match = -1, j = 0; j < old_dt->shared->u.compnd.nmembs; j++) {
4226
0
                            if (!strcmp(new_dt->shared->u.compnd.memb[i].name,
4227
0
                                        old_dt->shared->u.compnd.memb[j].name)) {
4228
0
                                old_match = (int)j;
4229
0
                                break;
4230
0
                            } /* end if */
4231
0
                        }     /* end for */
4232
4233
                        /* check if we couldn't find a match */
4234
0
                        if (old_match < 0)
4235
0
                            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "fields in datatype corrupted");
4236
0
                    } /* end if */
4237
0
                    else
4238
0
                        old_match = (int)i;
4239
4240
                    /* If the field changed size, add that change to the accumulated size change */
4241
0
                    if (new_dt->shared->u.compnd.memb[i].type->shared->size !=
4242
0
                        old_dt->shared->u.compnd.memb[old_match].type->shared->size) {
4243
                        /* Adjust the size of the member */
4244
0
                        new_dt->shared->u.compnd.memb[i].size =
4245
0
                            (old_dt->shared->u.compnd.memb[old_match].size * tmp->shared->size) /
4246
0
                            old_dt->shared->u.compnd.memb[old_match].type->shared->size;
4247
4248
0
                        accum_change +=
4249
0
                            (ssize_t)(new_dt->shared->u.compnd.memb[i].type->shared->size -
4250
0
                                      old_dt->shared->u.compnd.memb[old_match].type->shared->size);
4251
0
                    } /* end if */
4252
0
                }     /* end for */
4253
4254
                /* Range check against datatype size */
4255
0
                if ((accum_change < 0) && ((ssize_t)new_dt->shared->size < accum_change))
4256
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
4257
4258
                /* Apply the accumulated size change to the size of the compound struct */
4259
0
                new_dt->shared->size += (size_t)accum_change;
4260
0
            } break;
4261
4262
0
            case H5T_ENUM:
4263
                /*
4264
                 * Copy all member fields to new type, then overwrite the name fields
4265
                 * of each new member with copied values. That is, H5T_copy() is a
4266
                 * deep copy.
4267
                 */
4268
0
                if (old_dt->shared->u.enumer.nalloc > 0) {
4269
0
                    if (NULL == (new_dt->shared->u.enumer.name =
4270
0
                                     H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char *))))
4271
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
4272
0
                                    "enam name array memory allocation failed");
4273
0
                    if (NULL == (new_dt->shared->u.enumer.value =
4274
0
                                     H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size)))
4275
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
4276
0
                                    "enam value array memory allocation failed");
4277
0
                    H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
4278
0
                                new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
4279
0
                    for (i = 0; i < new_dt->shared->u.enumer.nmembs; i++) {
4280
0
                        if (NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i])))
4281
0
                            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
4282
0
                                        "can't copy string for enum value's name");
4283
0
                        new_dt->shared->u.enumer.name[i] = s;
4284
0
                    }
4285
0
                }
4286
0
                else {
4287
                    /* Empty enum */
4288
0
                    memset(&new_dt->shared->u.enumer, 0, sizeof(H5T_enum_t));
4289
0
                }
4290
0
                break;
4291
4292
578
            case H5T_VLEN:
4293
2.61k
            case H5T_REFERENCE:
4294
2.61k
                if (set_memory_type)
4295
                    /* H5T_copy converts any type into a memory type */
4296
1.94k
                    if (H5T_set_loc(new_dt, NULL, H5T_LOC_MEMORY) < 0)
4297
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
4298
2.61k
                break;
4299
4300
2.61k
            case H5T_OPAQUE:
4301
                /*
4302
                 * Copy the tag name.
4303
                 */
4304
9
                new_dt->shared->u.opaque.tag = H5MM_xstrdup(new_dt->shared->u.opaque.tag);
4305
9
                break;
4306
4307
0
            case H5T_ARRAY:
4308
                /* Re-compute the array's size, in case it's base type changed size */
4309
0
                new_dt->shared->size = new_dt->shared->u.array.nelem * new_dt->shared->parent->shared->size;
4310
0
                break;
4311
4312
0
            case H5T_NO_CLASS:
4313
6.64k
            case H5T_INTEGER:
4314
10.8k
            case H5T_FLOAT:
4315
10.8k
            case H5T_TIME:
4316
17.3k
            case H5T_STRING:
4317
17.3k
            case H5T_BITFIELD:
4318
17.4k
            case H5T_COMPLEX:
4319
17.4k
            case H5T_NCLASSES:
4320
17.4k
            default:
4321
17.4k
                break;
4322
20.0k
        } /* end switch */
4323
20.0k
    }     /* end if */
4324
4325
    /* Set the cached location & name path if the original type was a named
4326
     * type and the new type is also named.
4327
     */
4328
20.0k
    if (H5O_loc_reset(&new_dt->oloc) < 0)
4329
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location");
4330
20.0k
    if (H5G_name_reset(&new_dt->path) < 0)
4331
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path");
4332
4333
20.0k
    if (new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
4334
0
        if (H5O_loc_copy_deep(&(new_dt->oloc), &(old_dt->oloc)) < 0)
4335
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy object location");
4336
0
        if (H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0)
4337
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy path");
4338
0
    } /* end if */
4339
4340
    /* Copy shared location information if the new type is named or if it is
4341
     * shared in the heap.
4342
     */
4343
20.0k
    if ((old_dt->sh_loc.type == H5O_SHARE_TYPE_SOHM || old_dt->sh_loc.type == H5O_SHARE_TYPE_HERE) ||
4344
20.0k
        new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
4345
0
        if (H5O_set_shared(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0)
4346
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy shared information");
4347
0
    } /* end if */
4348
20.0k
    else
4349
        /* Reset shared component info */
4350
20.0k
        H5O_msg_reset_share(H5O_DTYPE_ID, new_dt);
4351
4352
20.0k
done:
4353
20.0k
    FUNC_LEAVE_NOAPI(ret_value)
4354
20.0k
} /* end H5T__complete_copy() */
4355
4356
/*-------------------------------------------------------------------------
4357
 * Function:  H5T_copy
4358
 *
4359
 * Purpose:   Copies datatype OLD_DT.     The resulting data type is not
4360
 *            locked and is a transient type.
4361
 *
4362
 * Return:    Success:    Pointer to a new copy of the OLD_DT argument.
4363
 *            Failure:    NULL
4364
 *
4365
 *-------------------------------------------------------------------------
4366
 */
4367
H5T_t *
4368
H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
4369
8.62k
{
4370
8.62k
    H5T_t          *new_dt = NULL;    /* New datatype */
4371
8.62k
    H5T_copy_func_t copyfn;           /* Pointer to correct copy routine */
4372
8.62k
    H5T_t          *ret_value = NULL; /* Return value */
4373
4374
8.62k
    FUNC_ENTER_NOAPI(NULL)
4375
4376
    /* check args */
4377
8.62k
    assert(old_dt);
4378
4379
    /* Allocate and copy core datatype information */
4380
8.62k
    if (NULL == (new_dt = H5T__initiate_copy(old_dt)))
4381
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info");
4382
4383
    /* Check what sort of copy we are making */
4384
8.62k
    switch (method) {
4385
1.18k
        case H5T_COPY_TRANSIENT:
4386
            /*
4387
             * Return an unlocked transient type.
4388
             */
4389
1.18k
            new_dt->shared->state = H5T_STATE_TRANSIENT;
4390
1.18k
            copyfn                = H5T__copy_transient;
4391
1.18k
            break;
4392
4393
7.44k
        case H5T_COPY_ALL:
4394
            /*
4395
             * Return a transient type (locked or unlocked) or an unopened named
4396
             * type.  Immutable transient types are degraded to read-only.
4397
             */
4398
7.44k
            if (H5T_STATE_OPEN == old_dt->shared->state)
4399
0
                new_dt->shared->state = H5T_STATE_NAMED;
4400
7.44k
            else if (H5T_STATE_IMMUTABLE == old_dt->shared->state)
4401
393
                new_dt->shared->state = H5T_STATE_RDONLY;
4402
7.44k
            copyfn = H5T__copy_all;
4403
7.44k
            break;
4404
4405
0
        default:
4406
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type");
4407
8.62k
    } /* end switch */
4408
4409
    /* Finish making the copy of the datatype */
4410
8.62k
    if (H5T__complete_copy(new_dt, old_dt, NULL, (method == H5T_COPY_TRANSIENT), copyfn) < 0)
4411
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization");
4412
4413
    /* Set return value */
4414
8.62k
    ret_value = new_dt;
4415
4416
8.62k
done:
4417
8.62k
    if (ret_value == NULL)
4418
0
        if (new_dt) {
4419
0
            assert(new_dt->shared);
4420
0
            if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
4421
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object");
4422
0
            new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
4423
0
            new_dt         = H5FL_FREE(H5T_t, new_dt);
4424
0
        } /* end if */
4425
4426
8.62k
    FUNC_LEAVE_NOAPI(ret_value)
4427
8.62k
} /* end H5T_copy() */
4428
4429
/*-------------------------------------------------------------------------
4430
 * Function:  H5T_copy_reopen
4431
 *
4432
 * Purpose:   Copy a datatype, possibly reopening a named datatype, as part
4433
 *            the const-correct datatype copying routines.
4434
 *
4435
 * Return:    Success:    Pointer to a new copy of the OLD_DT argument.
4436
 *            Failure:    NULL
4437
 *
4438
 *-------------------------------------------------------------------------
4439
 */
4440
H5T_t *
4441
H5T_copy_reopen(H5T_t *old_dt)
4442
11.4k
{
4443
11.4k
    H5T_t        *new_dt      = NULL; /* New datatype */
4444
11.4k
    H5T_shared_t *reopened_fo = NULL; /* Pointer to reopened existing named datatype */
4445
11.4k
    H5T_t        *ret_value   = NULL; /* Return value */
4446
4447
11.4k
    FUNC_ENTER_NOAPI(NULL)
4448
4449
    /* check args */
4450
11.4k
    assert(old_dt);
4451
4452
    /* Allocate and copy core datatype information */
4453
11.4k
    if (NULL == (new_dt = H5T__initiate_copy(old_dt)))
4454
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info");
4455
4456
    /*
4457
     * Return a transient type (locked or unlocked) or an opened named
4458
     * type.  Immutable transient types are degraded to read-only.
4459
     */
4460
11.4k
    if (old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
4461
        /* Check if the object is already open */
4462
0
        if (NULL ==
4463
0
            (reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) {
4464
            /* Clear any errors from H5FO_opened() */
4465
0
            H5E_clear_stack();
4466
4467
            /* Open named datatype again */
4468
0
            if (H5O_open(&old_dt->oloc) < 0)
4469
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type");
4470
4471
            /* Insert opened named datatype into opened object list for the file */
4472
0
            if (H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, false) < 0)
4473
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL,
4474
0
                            "can't insert datatype into list of open objects");
4475
4476
            /* Increment object count for the object in the top file */
4477
0
            if (H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
4478
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count");
4479
4480
0
            new_dt->shared->fo_count = 1;
4481
0
        } /* end if */
4482
0
        else {
4483
            /* The object is already open.  Free the H5T_shared_t struct
4484
             * we had been using and use the one that already exists.
4485
             * Not terribly efficient. */
4486
0
            if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
4487
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object");
4488
0
            new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
4489
0
            new_dt->shared = reopened_fo;
4490
4491
0
            reopened_fo->fo_count++;
4492
4493
            /* Check if the object has been opened through the top file yet */
4494
0
            if (H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) {
4495
                /* Open the object through this top file */
4496
0
                if (H5O_open(&old_dt->oloc) < 0)
4497
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header");
4498
0
            } /* end if */
4499
4500
            /* Increment object count for the object in the top file */
4501
0
            if (H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
4502
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count");
4503
0
        } /* end else */
4504
4505
        /* Set state for new datatype */
4506
0
        new_dt->shared->state = H5T_STATE_OPEN;
4507
0
    } /* end if */
4508
11.4k
    else
4509
        /* Downgrade immutable datatypes to read-only */
4510
11.4k
        if (H5T_STATE_IMMUTABLE == old_dt->shared->state)
4511
0
            new_dt->shared->state = H5T_STATE_RDONLY;
4512
4513
    /* Finish making the copy of the datatype */
4514
11.4k
    if (H5T__complete_copy(new_dt, old_dt, reopened_fo, true, H5T_copy_reopen) < 0)
4515
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization");
4516
4517
    /* Set return value */
4518
11.4k
    ret_value = new_dt;
4519
4520
11.4k
done:
4521
11.4k
    if (ret_value == NULL)
4522
0
        if (new_dt) {
4523
0
            assert(new_dt->shared);
4524
0
            if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
4525
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object");
4526
0
            new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
4527
0
            new_dt         = H5FL_FREE(H5T_t, new_dt);
4528
0
        } /* end if */
4529
4530
11.4k
    FUNC_LEAVE_NOAPI(ret_value)
4531
11.4k
} /* end H5T_copy_reopen() */
4532
4533
/*-------------------------------------------------------------------------
4534
 * Function:  H5T_lock
4535
 *
4536
 * Purpose:   Lock a transient data type making it read-only.  If IMMUTABLE
4537
 *        is set then the type cannot be closed except when the library
4538
 *        itself closes.
4539
 *
4540
 *        This function is a no-op if the type is not transient or if
4541
 *        the type is already read-only or immutable.
4542
 *
4543
 * Return:    Non-negative on success/Negative on failure
4544
 *
4545
 *-------------------------------------------------------------------------
4546
 */
4547
herr_t
4548
H5T_lock(H5T_t *dt, bool immutable)
4549
10.9k
{
4550
10.9k
    herr_t ret_value = SUCCEED; /* Return value */
4551
4552
10.9k
    FUNC_ENTER_NOAPI(FAIL)
4553
4554
10.9k
    assert(dt);
4555
4556
10.9k
    switch (dt->shared->state) {
4557
10.9k
        case H5T_STATE_TRANSIENT:
4558
10.9k
            dt->shared->state = immutable ? H5T_STATE_IMMUTABLE : H5T_STATE_RDONLY;
4559
10.9k
            break;
4560
0
        case H5T_STATE_RDONLY:
4561
0
            if (immutable)
4562
0
                dt->shared->state = H5T_STATE_IMMUTABLE;
4563
0
            break;
4564
0
        case H5T_STATE_IMMUTABLE:
4565
0
        case H5T_STATE_NAMED:
4566
0
        case H5T_STATE_OPEN:
4567
            /*void*/
4568
0
            break;
4569
0
        default:
4570
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid datatype state");
4571
10.9k
    }
4572
4573
10.9k
done:
4574
10.9k
    FUNC_LEAVE_NOAPI(ret_value)
4575
10.9k
}
4576
4577
/*-------------------------------------------------------------------------
4578
 * Function:  H5T__alloc
4579
 *
4580
 * Purpose:   Allocates a new H5T_t structure, initializing it correctly.
4581
 *
4582
 * Return:    Pointer to new H5T_t on success/NULL on failure
4583
 *
4584
 *-------------------------------------------------------------------------
4585
 */
4586
H5T_t *
4587
H5T__alloc(void)
4588
8.21k
{
4589
8.21k
    H5T_t *dt        = NULL; /* Pointer to datatype allocated */
4590
8.21k
    H5T_t *ret_value = NULL; /* Return value */
4591
4592
8.21k
    FUNC_ENTER_PACKAGE
4593
4594
    /* Allocate & initialize datatype wrapper info */
4595
8.21k
    if (NULL == (dt = H5FL_CALLOC(H5T_t)))
4596
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
4597
8.21k
    H5O_loc_reset(&(dt->oloc));
4598
8.21k
    H5G_name_reset(&(dt->path));
4599
8.21k
    H5O_msg_reset_share(H5O_DTYPE_ID, dt);
4600
4601
    /* Allocate & initialize shared datatype structure */
4602
8.21k
    if (NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t)))
4603
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
4604
8.21k
    dt->shared->version = H5O_DTYPE_VERSION_1;
4605
4606
    /* No VOL object initially */
4607
8.21k
    dt->vol_obj = NULL;
4608
4609
    /* Assign return value */
4610
8.21k
    ret_value = dt;
4611
4612
8.21k
done:
4613
8.21k
    if (ret_value == NULL)
4614
0
        if (dt) {
4615
0
            if (dt->shared) {
4616
0
                assert(!dt->shared->owned_vol_obj);
4617
0
                dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
4618
0
            } /* end if */
4619
0
            dt = H5FL_FREE(H5T_t, dt);
4620
0
        } /* end if */
4621
4622
8.21k
    FUNC_LEAVE_NOAPI(ret_value)
4623
8.21k
} /* end H5T__alloc() */
4624
4625
/*-------------------------------------------------------------------------
4626
 * Function:  H5T__free
4627
 *
4628
 * Purpose:   Frees all memory associated with a datatype, but does not
4629
 *            free the H5T_t or H5T_shared_t structures (which should
4630
 *            be done in H5T_close / H5T_close_real).
4631
 *
4632
 * Return:    Non-negative on success/Negative on failure
4633
 *
4634
 *-------------------------------------------------------------------------
4635
 */
4636
herr_t
4637
H5T__free(H5T_t *dt)
4638
31.0k
{
4639
31.0k
    unsigned i;
4640
31.0k
    herr_t   ret_value = SUCCEED; /* Return value */
4641
4642
31.0k
    FUNC_ENTER_PACKAGE
4643
4644
31.0k
    assert(dt && dt->shared);
4645
4646
    /* Free the ID to name info */
4647
31.0k
    H5G_name_free(&(dt->path));
4648
4649
    /* Don't free locked datatypes */
4650
31.0k
    if (H5T_STATE_IMMUTABLE == dt->shared->state)
4651
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close immutable datatype");
4652
4653
    /* Close the datatype */
4654
31.0k
    switch (dt->shared->type) {
4655
1
        case H5T_COMPOUND:
4656
1
            for (i = 0; i < dt->shared->u.compnd.nmembs; i++) {
4657
0
                dt->shared->u.compnd.memb[i].name = (char *)H5MM_xfree(dt->shared->u.compnd.memb[i].name);
4658
0
                if (H5T_close_real(dt->shared->u.compnd.memb[i].type) < 0)
4659
                    /* Push errors, but keep going */
4660
0
                    HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL,
4661
0
                                "unable to close datatype for compound member");
4662
0
            }
4663
1
            dt->shared->u.compnd.memb   = (H5T_cmemb_t *)H5MM_xfree(dt->shared->u.compnd.memb);
4664
1
            dt->shared->u.compnd.nmembs = 0;
4665
1
            break;
4666
4667
7
        case H5T_ENUM:
4668
7
            for (i = 0; i < dt->shared->u.enumer.nmembs; i++)
4669
0
                dt->shared->u.enumer.name[i] = (char *)H5MM_xfree(dt->shared->u.enumer.name[i]);
4670
7
            dt->shared->u.enumer.name   = (char **)H5MM_xfree(dt->shared->u.enumer.name);
4671
7
            dt->shared->u.enumer.value  = (uint8_t *)H5MM_xfree(dt->shared->u.enumer.value);
4672
7
            dt->shared->u.enumer.nmembs = 0;
4673
7
            break;
4674
4675
11
        case H5T_OPAQUE:
4676
11
            dt->shared->u.opaque.tag = (char *)H5MM_xfree(dt->shared->u.opaque.tag);
4677
11
            break;
4678
4679
2.82k
        case H5T_NO_CLASS:
4680
11.7k
        case H5T_INTEGER:
4681
16.9k
        case H5T_FLOAT:
4682
16.9k
        case H5T_TIME:
4683
27.9k
        case H5T_STRING:
4684
27.9k
        case H5T_BITFIELD:
4685
30.1k
        case H5T_REFERENCE:
4686
30.9k
        case H5T_VLEN:
4687
30.9k
        case H5T_ARRAY:
4688
31.0k
        case H5T_COMPLEX:
4689
31.0k
        case H5T_NCLASSES:
4690
31.0k
        default:
4691
31.0k
            break;
4692
31.0k
    } /* end switch */
4693
31.0k
    dt->shared->type = H5T_NO_CLASS;
4694
4695
    /* Close the parent */
4696
31.0k
    assert(dt->shared->parent != dt);
4697
31.0k
    if (dt->shared->parent && H5T_close_real(dt->shared->parent) < 0)
4698
        /* Push errors, but keep going */
4699
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close parent data type");
4700
31.0k
    dt->shared->parent = NULL;
4701
4702
    /* Close the owned VOL object */
4703
31.0k
    if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
4704
        /* Push errors, but keep going */
4705
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object");
4706
31.0k
    dt->shared->owned_vol_obj = NULL;
4707
4708
31.0k
done:
4709
31.0k
    FUNC_LEAVE_NOAPI(ret_value)
4710
31.0k
} /* end H5T__free() */
4711
4712
/*-------------------------------------------------------------------------
4713
 * Function:  H5T_close_real
4714
 *
4715
 * Purpose:   Frees a datatype and all associated memory.
4716
 *
4717
 * Note:      Does _not_ deal with open named datatypes, etc. so this
4718
 *            should never see a type managed by a VOL connector.
4719
 *
4720
 * Return:    Non-negative on success/Negative on failure
4721
 *
4722
 *-------------------------------------------------------------------------
4723
 */
4724
herr_t
4725
H5T_close_real(H5T_t *dt)
4726
28.2k
{
4727
28.2k
    herr_t ret_value = SUCCEED; /* Return value */
4728
4729
28.2k
    FUNC_ENTER_NOAPI(FAIL)
4730
4731
    /* Sanity check */
4732
28.2k
    assert(dt);
4733
4734
    /* Clean up resources, depending on shared state */
4735
28.2k
    if (dt->shared && (dt->shared->state != H5T_STATE_OPEN)) {
4736
28.2k
        if (H5T__free(dt) < 0)
4737
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype");
4738
4739
28.2k
        assert(!dt->shared->owned_vol_obj);
4740
28.2k
        dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
4741
28.2k
    } /* end if */
4742
0
    else
4743
        /* Free the group hier. path since we're not calling H5T__free() */
4744
0
        H5G_name_free(&(dt->path));
4745
4746
    /* Free the 'top' datatype struct */
4747
28.2k
    dt = H5FL_FREE(H5T_t, dt);
4748
4749
28.2k
done:
4750
28.2k
    FUNC_LEAVE_NOAPI(ret_value)
4751
28.2k
} /* end H5T_close_real() */
4752
4753
/*-------------------------------------------------------------------------
4754
 * Function:    H5T_close
4755
 *
4756
 * Purpose:     Frees a data type and all associated memory.  Deals with
4757
 *              open named datatypes appropriately.
4758
 *
4759
 * Return:      Non-negative on success/Negative on failure
4760
 *
4761
 *-------------------------------------------------------------------------
4762
 */
4763
herr_t
4764
H5T_close(H5T_t *dt)
4765
17.9k
{
4766
17.9k
    herr_t ret_value = SUCCEED; /* Return value */
4767
4768
17.9k
    FUNC_ENTER_NOAPI(FAIL)
4769
4770
    /* Sanity check */
4771
17.9k
    assert(dt);
4772
4773
    /* Named datatype cleanups */
4774
17.9k
    if (dt->shared && (dt->shared->state == H5T_STATE_OPEN)) {
4775
        /* Decrement refcount count on open named datatype */
4776
1
        dt->shared->fo_count--;
4777
4778
        /* Sanity checks */
4779
1
        assert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
4780
1
        assert(H5_addr_defined(dt->sh_loc.u.loc.oh_addr));
4781
1
        assert(H5_addr_defined(dt->oloc.addr));
4782
4783
        /* If a named type is being closed then close the object header and
4784
         * remove from the list of open objects in the file.
4785
         */
4786
4787
        /* Decrement the ref. count for this object in the top file */
4788
1
        if (H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
4789
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object");
4790
4791
        /* Close things down if this is the last reference to the open named datatype */
4792
1
        if (0 == dt->shared->fo_count) {
4793
1
            bool corked; /* Whether the named datatype is corked or not */
4794
4795
            /* Uncork cache entries with object address tag for named datatype */
4796
1
            if (H5AC_cork(dt->oloc.file, dt->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
4797
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status");
4798
1
            if (corked)
4799
0
                if (H5AC_cork(dt->oloc.file, dt->oloc.addr, H5AC__UNCORK, NULL) < 0)
4800
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTUNCORK, FAIL, "unable to uncork an object");
4801
4802
            /* Remove the datatype from the list of opened objects in the file */
4803
1
            if (H5FO_delete(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
4804
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL,
4805
1
                            "can't remove datatype from list of open objects");
4806
1
            if (H5O_close(&dt->oloc, NULL) < 0)
4807
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header");
4808
4809
            /* Mark named datatype closed now */
4810
1
            dt->shared->state = H5T_STATE_NAMED;
4811
1
        } /* end if */
4812
0
        else {
4813
            /* Check reference count for this object in the top file */
4814
0
            if (H5FO_top_count(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) == 0) {
4815
                /* Close object location for named datatype */
4816
0
                if (H5O_close(&dt->oloc, NULL) < 0)
4817
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close");
4818
0
            } /* end if */
4819
0
            else
4820
                /* Free object location (i.e. "unhold" the file if appropriate) */
4821
0
                if (H5O_loc_free(&(dt->oloc)) < 0)
4822
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "problem attempting to free location");
4823
0
        } /* end else */
4824
1
    }     /* end if */
4825
4826
    /* Clean up resources */
4827
17.9k
    if (H5T_close_real(dt) < 0)
4828
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to free datatype");
4829
4830
17.9k
done:
4831
17.9k
    FUNC_LEAVE_NOAPI(ret_value)
4832
17.9k
} /* end H5T_close() */
4833
4834
/*-------------------------------------------------------------------------
4835
 * Function:    H5T__set_size
4836
 *
4837
 * Purpose:    Sets the total size in bytes for a data type (this operation
4838
 *        is not permitted on reference data types).  If the size is
4839
 *        decreased so that the significant bits of the data type
4840
 *        extend beyond the edge of the new size, then the `offset'
4841
 *        property is decreased toward zero.  If the `offset' becomes
4842
 *        zero and the significant bits of the data type still hang
4843
 *        over the edge of the new size, then the number of significant
4844
 *        bits is decreased.
4845
 *
4846
 *        Adjusting the size of an H5T_STRING automatically sets the
4847
 *        precision to 8*size.
4848
 *
4849
 *        All data types have a positive size.
4850
 *
4851
 * Return:    Success:    non-negative
4852
 *
4853
 *            Failure:    negative
4854
 *
4855
 *-------------------------------------------------------------------------
4856
 */
4857
static herr_t
4858
H5T__set_size(H5T_t *dt, size_t size)
4859
0
{
4860
0
    size_t prec, offset;
4861
0
    herr_t ret_value = SUCCEED; /* Return value */
4862
4863
0
    FUNC_ENTER_PACKAGE
4864
4865
    /* Check args */
4866
0
    assert(dt);
4867
0
    assert(dt->shared);
4868
0
    assert(size != 0);
4869
0
    assert(H5T_ARRAY != dt->shared->type);
4870
0
    assert(H5T_REFERENCE != dt->shared->type);
4871
0
    assert(H5T_COMPLEX != dt->shared->type);
4872
0
    assert(H5T_VLEN != dt->shared->type || H5T_VLEN_STRING == dt->shared->u.vlen.type);
4873
0
    assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs));
4874
4875
0
    if (dt->shared->parent) {
4876
0
        if (H5T__set_size(dt->shared->parent, size) < 0)
4877
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type");
4878
0
    }
4879
0
    else {
4880
0
        if (H5T_IS_ATOMIC(dt->shared)) {
4881
0
            offset = dt->shared->u.atomic.offset;
4882
0
            prec   = dt->shared->u.atomic.prec;
4883
4884
            /* Decrement the offset and precision if necessary */
4885
0
            if (prec > 8 * size)
4886
0
                offset = 0;
4887
0
            else if (offset + prec > 8 * size)
4888
0
                offset = 8 * size - prec;
4889
0
            if (prec > 8 * size)
4890
0
                prec = 8 * size;
4891
0
        }
4892
0
        else
4893
0
            prec = offset = 0;
4894
4895
0
        switch (dt->shared->type) {
4896
0
            case H5T_INTEGER:
4897
0
            case H5T_TIME:
4898
0
            case H5T_BITFIELD:
4899
0
            case H5T_OPAQUE:
4900
                /* nothing to check */
4901
0
                break;
4902
4903
0
            case H5T_COMPOUND:
4904
                /* If decreasing size, check the last member isn't being cut. */
4905
0
                if (size < dt->shared->size) {
4906
0
                    int      num_membs = 0;
4907
0
                    unsigned i, max_index            = 0;
4908
0
                    size_t   memb_offset, max_offset = 0;
4909
0
                    size_t   max_size;
4910
4911
0
                    if ((num_membs = H5T_get_nmembers(dt)) < 0)
4912
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to get number of members");
4913
4914
0
                    if (num_membs) {
4915
0
                        for (i = 0; i < (unsigned)num_membs; i++) {
4916
0
                            memb_offset = H5T_get_member_offset(dt, i);
4917
0
                            if (memb_offset > max_offset) {
4918
0
                                max_offset = memb_offset;
4919
0
                                max_index  = i;
4920
0
                            } /* end if */
4921
0
                        }     /* end for */
4922
4923
0
                        max_size = H5T__get_member_size(dt, max_index);
4924
4925
0
                        if (size < (max_offset + max_size))
4926
0
                            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
4927
0
                                        "size shrinking will cut off last member ");
4928
0
                    } /* end if */
4929
4930
                    /* Compound must not have been packed previously */
4931
                    /* We will check if resizing changed the packed state of
4932
                     * this type at the end of this function */
4933
0
                    assert(!dt->shared->u.compnd.packed);
4934
0
                } /* end if */
4935
4936
0
                break;
4937
4938
0
            case H5T_STRING:
4939
                /* Convert string to variable-length datatype */
4940
0
                if (size == H5T_VARIABLE) {
4941
0
                    H5T_t     *base = NULL; /* base data type */
4942
0
                    H5T_cset_t tmp_cset;    /* Temp. cset info */
4943
0
                    H5T_str_t  tmp_strpad;  /* Temp. strpad info */
4944
4945
                    /* Get a copy of unsigned char type as the base/parent type */
4946
0
                    if (NULL == (base = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR)))
4947
0
                        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype");
4948
0
                    if (NULL == (dt->shared->parent = H5T_copy(base, H5T_COPY_ALL)))
4949
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy base datatype");
4950
4951
                    /* change this datatype into a VL string */
4952
0
                    dt->shared->type = H5T_VLEN;
4953
4954
                    /*
4955
                     * Force conversions (i.e. memory to memory conversions
4956
                     * should duplicate data, not point to the same VL strings)
4957
                     */
4958
0
                    dt->shared->force_conv = true;
4959
4960
                    /* Before we mess with the info in the union, extract the
4961
                     * values we need */
4962
0
                    tmp_cset   = dt->shared->u.atomic.u.s.cset;
4963
0
                    tmp_strpad = dt->shared->u.atomic.u.s.pad;
4964
4965
                    /* This is a string, not a sequence */
4966
0
                    dt->shared->u.vlen.type = H5T_VLEN_STRING;
4967
4968
                    /* Set character set and padding information */
4969
0
                    dt->shared->u.vlen.cset = tmp_cset;
4970
0
                    dt->shared->u.vlen.pad  = tmp_strpad;
4971
4972
                    /* Set up VL information */
4973
0
                    if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
4974
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
4975
0
                } /* end if */
4976
0
                else {
4977
0
                    prec   = 8 * size;
4978
0
                    offset = 0;
4979
0
                } /* end else */
4980
0
                break;
4981
4982
0
            case H5T_FLOAT:
4983
                /*
4984
                 * The sign, mantissa, and exponent fields should be adjusted
4985
                 * first when decreasing the size of a floating point type.
4986
                 */
4987
0
                if (dt->shared->u.atomic.u.f.sign >= prec + offset ||
4988
0
                    dt->shared->u.atomic.u.f.epos + dt->shared->u.atomic.u.f.esize > prec + offset ||
4989
0
                    dt->shared->u.atomic.u.f.mpos + dt->shared->u.atomic.u.f.msize > prec + offset) {
4990
0
                    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
4991
0
                                "adjust sign, mantissa, and exponent fields first");
4992
0
                }
4993
0
                break;
4994
4995
0
            case H5T_ENUM:
4996
0
            case H5T_VLEN:
4997
0
            case H5T_ARRAY:
4998
0
            case H5T_REFERENCE:
4999
0
            case H5T_COMPLEX:
5000
0
                assert("can't happen" && 0);
5001
0
                break;
5002
5003
0
            case H5T_NO_CLASS:
5004
0
            case H5T_NCLASSES:
5005
0
                assert("invalid type" && 0);
5006
0
                break;
5007
5008
0
            default:
5009
0
                assert("not implemented yet" && 0);
5010
0
                break;
5011
0
        } /* end switch */
5012
5013
        /* Commit (if we didn't convert this type to a VL string) */
5014
0
        if (dt->shared->type != H5T_VLEN) {
5015
0
            dt->shared->size = size;
5016
0
            if (H5T_IS_ATOMIC(dt->shared)) {
5017
0
                dt->shared->u.atomic.offset = offset;
5018
0
                dt->shared->u.atomic.prec   = prec;
5019
0
            }
5020
0
        } /* end if */
5021
5022
        /* Check if the new compound type is packed */
5023
0
        if (dt->shared->type == H5T_COMPOUND)
5024
0
            H5T__update_packed(dt);
5025
0
    } /* end else */
5026
5027
0
done:
5028
0
    FUNC_LEAVE_NOAPI(ret_value)
5029
0
} /* end H5T__set_size() */
5030
5031
/*-------------------------------------------------------------------------
5032
 * Function:  H5T_get_size
5033
 *
5034
 * Purpose:   Determines the total size of a data type in bytes.
5035
 *
5036
 * Return:    Success:    Size of the data type in bytes.     The size of
5037
 *                the data type is the size of an instance of
5038
 *                that data type.
5039
 *
5040
 *            Failure:    0 (valid data types are never zero size)
5041
 *
5042
 *-------------------------------------------------------------------------
5043
 */
5044
size_t
5045
H5T_get_size(const H5T_t *dt)
5046
37.7k
{
5047
    /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
5048
37.7k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
5049
5050
    /* check args */
5051
37.7k
    assert(dt);
5052
37.7k
    assert(dt->shared);
5053
5054
37.7k
    FUNC_LEAVE_NOAPI(dt->shared->size)
5055
37.7k
} /* end H5T_get_size() */
5056
5057
/*-------------------------------------------------------------------------
5058
 * Function:  H5T_cmp
5059
 *
5060
 * Purpose:   Compares two data types.
5061
 *
5062
 * Return:    Success:    0 if DT1 and DT2 are equal.
5063
 *                       <0 if DT1 is less than DT2.
5064
 *                       >0 if DT1 is greater than DT2.
5065
 *
5066
 *            Failure:    0, never fails
5067
 *
5068
 *-------------------------------------------------------------------------
5069
 */
5070
int
5071
H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, bool superset)
5072
35.5k
{
5073
35.5k
    unsigned *idx1 = NULL, *idx2 = NULL;
5074
35.5k
    size_t    base_size;
5075
35.5k
    bool      swapped;
5076
35.5k
    unsigned  u;
5077
35.5k
    int       tmp;
5078
35.5k
    int       ret_value = 0;
5079
5080
35.5k
    FUNC_ENTER_NOAPI(0)
5081
5082
    /* Sanity check */
5083
35.5k
    assert(dt1);
5084
35.5k
    assert(dt2);
5085
5086
    /* the easy case */
5087
35.5k
    if (dt1 == dt2)
5088
1
        HGOTO_DONE(0);
5089
5090
35.5k
    assert(dt1->shared);
5091
35.5k
    assert(dt2->shared);
5092
5093
    /* compare */
5094
35.5k
    if (dt1->shared->type < dt2->shared->type)
5095
5.30k
        HGOTO_DONE(-1);
5096
30.2k
    if (dt1->shared->type > dt2->shared->type)
5097
4.48k
        HGOTO_DONE(1);
5098
5099
25.7k
    if (dt1->shared->size < dt2->shared->size)
5100
1.08k
        HGOTO_DONE(-1);
5101
24.6k
    if (dt1->shared->size > dt2->shared->size)
5102
3.99k
        HGOTO_DONE(1);
5103
5104
20.6k
    if (dt1->shared->parent && !dt2->shared->parent)
5105
0
        HGOTO_DONE(-1);
5106
20.6k
    if (!dt1->shared->parent && dt2->shared->parent)
5107
0
        HGOTO_DONE(1);
5108
20.6k
    if (dt1->shared->parent) {
5109
907
        tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset);
5110
907
        if (tmp < 0)
5111
1
            HGOTO_DONE(-1);
5112
906
        if (tmp > 0)
5113
0
            HGOTO_DONE(1);
5114
906
    } /* end if */
5115
5116
20.6k
    switch (dt1->shared->type) {
5117
0
        case H5T_COMPOUND:
5118
            /*
5119
             * Compound data types...
5120
             */
5121
0
            if (dt1->shared->u.compnd.nmembs == 0 && dt2->shared->u.compnd.nmembs == 0)
5122
0
                HGOTO_DONE(0);
5123
0
            if (dt1->shared->u.compnd.nmembs < dt2->shared->u.compnd.nmembs)
5124
0
                HGOTO_DONE(-1);
5125
0
            if (dt1->shared->u.compnd.nmembs > dt2->shared->u.compnd.nmembs)
5126
0
                HGOTO_DONE(1);
5127
5128
            /* Build an index for each type so the names are sorted */
5129
0
            if (NULL == (idx1 = (unsigned *)H5MM_malloc(dt1->shared->u.compnd.nmembs * sizeof(unsigned))) ||
5130
0
                NULL == (idx2 = (unsigned *)H5MM_malloc(dt2->shared->u.compnd.nmembs * sizeof(unsigned))))
5131
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
5132
0
            for (u = 0; u < dt1->shared->u.compnd.nmembs; u++)
5133
0
                idx1[u] = idx2[u] = u;
5134
0
            if (dt1->shared->u.enumer.nmembs > 1) {
5135
0
                int i;
5136
5137
0
                for (i = (int)dt1->shared->u.compnd.nmembs - 1, swapped = true; swapped && i >= 0; --i) {
5138
0
                    int j;
5139
5140
0
                    for (j = 0, swapped = false; j < i; j++)
5141
0
                        if (strcmp(dt1->shared->u.compnd.memb[idx1[j]].name,
5142
0
                                   dt1->shared->u.compnd.memb[idx1[j + 1]].name) > 0) {
5143
0
                            unsigned tmp_idx = idx1[j];
5144
0
                            idx1[j]          = idx1[j + 1];
5145
0
                            idx1[j + 1]      = tmp_idx;
5146
0
                            swapped          = true;
5147
0
                        }
5148
0
                }
5149
0
                for (i = (int)dt2->shared->u.compnd.nmembs - 1, swapped = true; swapped && i >= 0; --i) {
5150
0
                    int j;
5151
5152
0
                    for (j = 0, swapped = false; j < i; j++)
5153
0
                        if (strcmp(dt2->shared->u.compnd.memb[idx2[j]].name,
5154
0
                                   dt2->shared->u.compnd.memb[idx2[j + 1]].name) > 0) {
5155
0
                            unsigned tmp_idx = idx2[j];
5156
0
                            idx2[j]          = idx2[j + 1];
5157
0
                            idx2[j + 1]      = tmp_idx;
5158
0
                            swapped          = true;
5159
0
                        }
5160
0
                }
5161
0
            } /* end if */
5162
5163
#ifdef H5T_DEBUG
5164
            /* I don't quite trust the code above yet :-)  --RPM */
5165
            if (dt1->shared->u.compnd.nmembs > 0) {
5166
                for (u = 0; u < dt1->shared->u.compnd.nmembs - 1; u++) {
5167
                    assert(strcmp(dt1->shared->u.compnd.memb[idx1[u]].name,
5168
                                  dt1->shared->u.compnd.memb[idx1[u + 1]].name));
5169
                    assert(strcmp(dt2->shared->u.compnd.memb[idx2[u]].name,
5170
                                  dt2->shared->u.compnd.memb[idx2[u + 1]].name));
5171
                }
5172
            }
5173
#endif
5174
5175
            /* Compare the members */
5176
0
            for (u = 0; u < dt1->shared->u.compnd.nmembs; u++) {
5177
0
                tmp = strcmp(dt1->shared->u.compnd.memb[idx1[u]].name,
5178
0
                             dt2->shared->u.compnd.memb[idx2[u]].name);
5179
0
                if (tmp < 0)
5180
0
                    HGOTO_DONE(-1);
5181
0
                if (tmp > 0)
5182
0
                    HGOTO_DONE(1);
5183
5184
0
                if (dt1->shared->u.compnd.memb[idx1[u]].offset < dt2->shared->u.compnd.memb[idx2[u]].offset)
5185
0
                    HGOTO_DONE(-1);
5186
0
                if (dt1->shared->u.compnd.memb[idx1[u]].offset > dt2->shared->u.compnd.memb[idx2[u]].offset)
5187
0
                    HGOTO_DONE(1);
5188
5189
0
                if (dt1->shared->u.compnd.memb[idx1[u]].size < dt2->shared->u.compnd.memb[idx2[u]].size)
5190
0
                    HGOTO_DONE(-1);
5191
0
                if (dt1->shared->u.compnd.memb[idx1[u]].size > dt2->shared->u.compnd.memb[idx2[u]].size)
5192
0
                    HGOTO_DONE(1);
5193
5194
0
                tmp = H5T_cmp(dt1->shared->u.compnd.memb[idx1[u]].type,
5195
0
                              dt2->shared->u.compnd.memb[idx2[u]].type, superset);
5196
0
                if (tmp < 0)
5197
0
                    HGOTO_DONE(-1);
5198
0
                if (tmp > 0)
5199
0
                    HGOTO_DONE(1);
5200
0
            }
5201
0
            break;
5202
5203
0
        case H5T_ENUM:
5204
            /*
5205
             * Enumeration data types...
5206
             */
5207
0
            if (dt1->shared->u.enumer.nmembs == 0 && dt2->shared->u.enumer.nmembs == 0)
5208
0
                HGOTO_DONE(0);
5209
5210
            /* If we are doing a "superset" comparison, dt2 is allowed to have
5211
             * more members than dt1
5212
             */
5213
0
            if (superset) {
5214
0
                if (dt1->shared->u.enumer.nmembs > dt2->shared->u.enumer.nmembs)
5215
0
                    HGOTO_DONE(1);
5216
0
            } /* end if */
5217
0
            else {
5218
0
                if (dt1->shared->u.enumer.nmembs < dt2->shared->u.enumer.nmembs)
5219
0
                    HGOTO_DONE(-1);
5220
0
                if (dt1->shared->u.enumer.nmembs > dt2->shared->u.enumer.nmembs)
5221
0
                    HGOTO_DONE(1);
5222
0
            } /* end else */
5223
5224
            /* Build an index for each type so the names are sorted */
5225
0
            if (NULL == (idx1 = (unsigned *)H5MM_malloc(dt1->shared->u.enumer.nmembs * sizeof(unsigned))) ||
5226
0
                NULL == (idx2 = (unsigned *)H5MM_malloc(dt2->shared->u.enumer.nmembs * sizeof(unsigned))))
5227
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
5228
0
            for (u = 0; u < dt1->shared->u.enumer.nmembs; u++)
5229
0
                idx1[u] = u;
5230
0
            if (dt1->shared->u.enumer.nmembs > 1) {
5231
0
                int i;
5232
0
                for (i = (int)dt1->shared->u.enumer.nmembs - 1, swapped = true; swapped && i >= 0; --i) {
5233
0
                    int j;
5234
5235
0
                    for (j = 0, swapped = false; j < i; j++)
5236
0
                        if (strcmp(dt1->shared->u.enumer.name[idx1[j]],
5237
0
                                   dt1->shared->u.enumer.name[idx1[j + 1]]) > 0) {
5238
0
                            unsigned tmp_idx = idx1[j];
5239
0
                            idx1[j]          = idx1[j + 1];
5240
0
                            idx1[j + 1]      = tmp_idx;
5241
0
                            swapped          = true;
5242
0
                        }
5243
0
                }
5244
0
            }
5245
0
            for (u = 0; u < dt2->shared->u.enumer.nmembs; u++)
5246
0
                idx2[u] = u;
5247
0
            if (dt2->shared->u.enumer.nmembs > 1) {
5248
0
                int i;
5249
5250
0
                for (i = (int)dt2->shared->u.enumer.nmembs - 1, swapped = true; swapped && i >= 0; --i) {
5251
0
                    int j;
5252
5253
0
                    for (j = 0, swapped = false; j < i; j++)
5254
0
                        if (strcmp(dt2->shared->u.enumer.name[idx2[j]],
5255
0
                                   dt2->shared->u.enumer.name[idx2[j + 1]]) > 0) {
5256
0
                            unsigned tmp_idx = idx2[j];
5257
0
                            idx2[j]          = idx2[j + 1];
5258
0
                            idx2[j + 1]      = tmp_idx;
5259
0
                            swapped          = true;
5260
0
                        }
5261
0
                }
5262
0
            }
5263
5264
#ifdef H5T_DEBUG
5265
            /* I don't quite trust the code above yet :-)  --RPM */
5266
            if (dt1->shared->u.enumer.nmembs > 0) {
5267
                for (u = 0; u < dt1->shared->u.enumer.nmembs - 1; u++) {
5268
                    assert(
5269
                        strcmp(dt1->shared->u.enumer.name[idx1[u]], dt1->shared->u.enumer.name[idx1[u + 1]]));
5270
                    assert(
5271
                        strcmp(dt2->shared->u.enumer.name[idx2[u]], dt2->shared->u.enumer.name[idx2[u + 1]]));
5272
                }
5273
            }
5274
#endif
5275
5276
            /* Compare the members */
5277
0
            base_size = dt1->shared->parent->shared->size;
5278
0
            for (u = 0; u < dt1->shared->u.enumer.nmembs; u++) {
5279
0
                unsigned idx = 0;
5280
5281
0
                if (superset) {
5282
0
                    unsigned lt  = 0, rt; /* Final, left & right key indices */
5283
0
                    int      cmp = 1;     /* Key comparison value */
5284
5285
                    /* If a superset is allowed, dt2 may have more members
5286
                     * than dt1, so binary search for matching member name in
5287
                     * dt2
5288
                     */
5289
0
                    rt = dt2->shared->u.enumer.nmembs;
5290
5291
0
                    while (lt < rt && cmp) {
5292
0
                        idx = (lt + rt) / 2;
5293
5294
                        /* compare */
5295
0
                        if ((cmp = strcmp(dt1->shared->u.enumer.name[idx1[u]],
5296
0
                                          dt2->shared->u.enumer.name[idx2[idx]])) < 0)
5297
0
                            rt = idx;
5298
0
                        else
5299
0
                            lt = idx + 1;
5300
0
                    }
5301
                    /* Leave, if we couldn't find match */
5302
0
                    if (cmp)
5303
0
                        HGOTO_DONE(-1);
5304
0
                } /* end if */
5305
0
                else {
5306
                    /* Check for exact member name match when not doing
5307
                     * "superset" comparison
5308
                     */
5309
0
                    tmp = strcmp(dt1->shared->u.enumer.name[idx1[u]], dt2->shared->u.enumer.name[idx2[u]]);
5310
0
                    if (tmp < 0)
5311
0
                        HGOTO_DONE(-1);
5312
0
                    if (tmp > 0)
5313
0
                        HGOTO_DONE(1);
5314
5315
                    /* Set index value appropriately */
5316
0
                    idx = u;
5317
0
                } /* end else */
5318
5319
0
                tmp = memcmp((uint8_t *)dt1->shared->u.enumer.value + idx1[u] * base_size,
5320
0
                             (uint8_t *)dt2->shared->u.enumer.value + idx2[idx] * base_size, base_size);
5321
0
                if (tmp < 0)
5322
0
                    HGOTO_DONE(-1);
5323
0
                if (tmp > 0)
5324
0
                    HGOTO_DONE(1);
5325
0
            }
5326
0
            break;
5327
5328
790
        case H5T_VLEN:
5329
790
            assert(dt1->shared->u.vlen.type > H5T_VLEN_BADTYPE &&
5330
790
                   dt1->shared->u.vlen.type < H5T_VLEN_MAXTYPE);
5331
790
            assert(dt2->shared->u.vlen.type > H5T_VLEN_BADTYPE &&
5332
790
                   dt2->shared->u.vlen.type < H5T_VLEN_MAXTYPE);
5333
790
            assert(dt1->shared->u.vlen.loc >= H5T_LOC_BADLOC && dt1->shared->u.vlen.loc < H5T_LOC_MAXLOC);
5334
790
            assert(dt2->shared->u.vlen.loc >= H5T_LOC_BADLOC && dt2->shared->u.vlen.loc < H5T_LOC_MAXLOC);
5335
5336
            /* Arbitrarily sort sequence VL datatypes before string VL datatypes */
5337
790
            if (dt1->shared->u.vlen.type == H5T_VLEN_SEQUENCE &&
5338
790
                dt2->shared->u.vlen.type == H5T_VLEN_STRING) {
5339
0
                HGOTO_DONE(-1);
5340
0
            }
5341
790
            else if (dt1->shared->u.vlen.type == H5T_VLEN_STRING &&
5342
0
                     dt2->shared->u.vlen.type == H5T_VLEN_SEQUENCE) {
5343
0
                HGOTO_DONE(1);
5344
0
            }
5345
            /* Arbitrarily sort VL datatypes in memory before disk */
5346
790
            if (dt1->shared->u.vlen.loc == H5T_LOC_MEMORY && dt2->shared->u.vlen.loc == H5T_LOC_DISK) {
5347
0
                HGOTO_DONE(-1);
5348
0
            }
5349
790
            else if (dt1->shared->u.vlen.loc == H5T_LOC_DISK && dt2->shared->u.vlen.loc == H5T_LOC_MEMORY) {
5350
0
                HGOTO_DONE(1);
5351
0
            }
5352
790
            else if (dt1->shared->u.vlen.loc == H5T_LOC_BADLOC && dt2->shared->u.vlen.loc != H5T_LOC_BADLOC) {
5353
0
                HGOTO_DONE(1);
5354
0
            }
5355
5356
            /* Don't allow VL types in different files to compare as equal */
5357
790
            if (dt1->shared->u.vlen.file < dt2->shared->u.vlen.file)
5358
0
                HGOTO_DONE(-1);
5359
790
            if (dt1->shared->u.vlen.file > dt2->shared->u.vlen.file)
5360
62
                HGOTO_DONE(1);
5361
728
            break;
5362
5363
728
        case H5T_OPAQUE:
5364
0
            if (dt1->shared->u.opaque.tag && dt2->shared->u.opaque.tag)
5365
0
                HGOTO_DONE(strcmp(dt1->shared->u.opaque.tag, dt2->shared->u.opaque.tag));
5366
0
            break;
5367
5368
0
        case H5T_ARRAY:
5369
0
            if (dt1->shared->u.array.ndims < dt2->shared->u.array.ndims)
5370
0
                HGOTO_DONE(-1);
5371
0
            if (dt1->shared->u.array.ndims > dt2->shared->u.array.ndims)
5372
0
                HGOTO_DONE(1);
5373
5374
0
            for (u = 0; u < dt1->shared->u.array.ndims; u++) {
5375
0
                if (dt1->shared->u.array.dim[u] < dt2->shared->u.array.dim[u])
5376
0
                    HGOTO_DONE(-1);
5377
0
                if (dt1->shared->u.array.dim[u] > dt2->shared->u.array.dim[u])
5378
0
                    HGOTO_DONE(1);
5379
0
            }
5380
5381
0
            tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset);
5382
0
            if (tmp < 0)
5383
0
                HGOTO_DONE(-1);
5384
0
            if (tmp > 0)
5385
0
                HGOTO_DONE(1);
5386
0
            break;
5387
5388
116
        case H5T_COMPLEX:
5389
            /* Make sure the complex number datatypes are both in the same form */
5390
116
            tmp = (dt1->shared->u.cplx.form > dt2->shared->u.cplx.form) -
5391
116
                  (dt1->shared->u.cplx.form < dt2->shared->u.cplx.form);
5392
116
            if (tmp < 0)
5393
0
                HGOTO_DONE(-1);
5394
116
            if (tmp > 0)
5395
0
                HGOTO_DONE(1);
5396
5397
116
            tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset);
5398
116
            if (tmp < 0)
5399
0
                HGOTO_DONE(-1);
5400
116
            if (tmp > 0)
5401
0
                HGOTO_DONE(1);
5402
5403
116
            break;
5404
5405
116
        case H5T_NO_CLASS:
5406
9.16k
        case H5T_INTEGER:
5407
10.9k
        case H5T_FLOAT:
5408
10.9k
        case H5T_TIME:
5409
17.6k
        case H5T_STRING:
5410
17.6k
        case H5T_BITFIELD:
5411
19.7k
        case H5T_REFERENCE:
5412
19.7k
        case H5T_NCLASSES:
5413
19.7k
        default:
5414
            /*
5415
             * Atomic datatypes...
5416
             */
5417
19.7k
            if (dt1->shared->u.atomic.order < dt2->shared->u.atomic.order)
5418
3
                HGOTO_DONE(-1);
5419
19.7k
            if (dt1->shared->u.atomic.order > dt2->shared->u.atomic.order)
5420
29
                HGOTO_DONE(1);
5421
5422
19.7k
            if (dt1->shared->u.atomic.prec < dt2->shared->u.atomic.prec)
5423
3
                HGOTO_DONE(-1);
5424
19.7k
            if (dt1->shared->u.atomic.prec > dt2->shared->u.atomic.prec)
5425
0
                HGOTO_DONE(1);
5426
5427
19.7k
            if (dt1->shared->u.atomic.offset < dt2->shared->u.atomic.offset)
5428
0
                HGOTO_DONE(-1);
5429
19.7k
            if (dt1->shared->u.atomic.offset > dt2->shared->u.atomic.offset)
5430
42
                HGOTO_DONE(1);
5431
5432
19.6k
            if (dt1->shared->u.atomic.lsb_pad < dt2->shared->u.atomic.lsb_pad)
5433
3
                HGOTO_DONE(-1);
5434
19.6k
            if (dt1->shared->u.atomic.lsb_pad > dt2->shared->u.atomic.lsb_pad)
5435
6
                HGOTO_DONE(1);
5436
5437
19.6k
            if (dt1->shared->u.atomic.msb_pad < dt2->shared->u.atomic.msb_pad)
5438
0
                HGOTO_DONE(-1);
5439
19.6k
            if (dt1->shared->u.atomic.msb_pad > dt2->shared->u.atomic.msb_pad)
5440
0
                HGOTO_DONE(1);
5441
5442
19.6k
            switch (dt1->shared->type) {
5443
9.12k
                case H5T_INTEGER:
5444
9.12k
                    if (dt1->shared->u.atomic.u.i.sign < dt2->shared->u.atomic.u.i.sign)
5445
1.53k
                        HGOTO_DONE(-1);
5446
7.58k
                    if (dt1->shared->u.atomic.u.i.sign > dt2->shared->u.atomic.u.i.sign)
5447
67
                        HGOTO_DONE(1);
5448
7.52k
                    break;
5449
5450
7.52k
                case H5T_FLOAT:
5451
1.77k
                    if (dt1->shared->u.atomic.u.f.sign < dt2->shared->u.atomic.u.f.sign)
5452
0
                        HGOTO_DONE(-1);
5453
1.77k
                    if (dt1->shared->u.atomic.u.f.sign > dt2->shared->u.atomic.u.f.sign)
5454
0
                        HGOTO_DONE(1);
5455
5456
1.77k
                    if (dt1->shared->u.atomic.u.f.epos < dt2->shared->u.atomic.u.f.epos)
5457
0
                        HGOTO_DONE(-1);
5458
1.77k
                    if (dt1->shared->u.atomic.u.f.epos > dt2->shared->u.atomic.u.f.epos)
5459
0
                        HGOTO_DONE(1);
5460
5461
1.77k
                    if (dt1->shared->u.atomic.u.f.esize < dt2->shared->u.atomic.u.f.esize)
5462
19
                        HGOTO_DONE(-1);
5463
1.76k
                    if (dt1->shared->u.atomic.u.f.esize > dt2->shared->u.atomic.u.f.esize)
5464
6
                        HGOTO_DONE(1);
5465
5466
1.75k
                    if (dt1->shared->u.atomic.u.f.ebias < dt2->shared->u.atomic.u.f.ebias)
5467
2
                        HGOTO_DONE(-1);
5468
1.75k
                    if (dt1->shared->u.atomic.u.f.ebias > dt2->shared->u.atomic.u.f.ebias)
5469
13
                        HGOTO_DONE(1);
5470
5471
1.73k
                    if (dt1->shared->u.atomic.u.f.mpos < dt2->shared->u.atomic.u.f.mpos)
5472
0
                        HGOTO_DONE(-1);
5473
1.73k
                    if (dt1->shared->u.atomic.u.f.mpos > dt2->shared->u.atomic.u.f.mpos)
5474
0
                        HGOTO_DONE(1);
5475
5476
1.73k
                    if (dt1->shared->u.atomic.u.f.msize < dt2->shared->u.atomic.u.f.msize)
5477
31
                        HGOTO_DONE(-1);
5478
1.70k
                    if (dt1->shared->u.atomic.u.f.msize > dt2->shared->u.atomic.u.f.msize)
5479
0
                        HGOTO_DONE(1);
5480
5481
1.70k
                    if (dt1->shared->u.atomic.u.f.norm < dt2->shared->u.atomic.u.f.norm)
5482
0
                        HGOTO_DONE(-1);
5483
1.70k
                    if (dt1->shared->u.atomic.u.f.norm > dt2->shared->u.atomic.u.f.norm)
5484
9
                        HGOTO_DONE(1);
5485
5486
1.69k
                    if (dt1->shared->u.atomic.u.f.pad < dt2->shared->u.atomic.u.f.pad)
5487
0
                        HGOTO_DONE(-1);
5488
1.69k
                    if (dt1->shared->u.atomic.u.f.pad > dt2->shared->u.atomic.u.f.pad)
5489
0
                        HGOTO_DONE(1);
5490
5491
1.69k
                    break;
5492
5493
1.69k
                case H5T_TIME: /* order and precision are checked above */
5494
                    /*void */
5495
0
                    break;
5496
5497
6.64k
                case H5T_STRING:
5498
6.64k
                    if (dt1->shared->u.atomic.u.s.cset < dt2->shared->u.atomic.u.s.cset)
5499
0
                        HGOTO_DONE(-1);
5500
6.64k
                    if (dt1->shared->u.atomic.u.s.cset > dt2->shared->u.atomic.u.s.cset)
5501
0
                        HGOTO_DONE(1);
5502
5503
6.64k
                    if (dt1->shared->u.atomic.u.s.pad < dt2->shared->u.atomic.u.s.pad)
5504
0
                        HGOTO_DONE(-1);
5505
6.64k
                    if (dt1->shared->u.atomic.u.s.pad > dt2->shared->u.atomic.u.s.pad)
5506
0
                        HGOTO_DONE(1);
5507
5508
6.64k
                    break;
5509
5510
6.64k
                case H5T_BITFIELD:
5511
                    /*void */
5512
0
                    break;
5513
5514
2.10k
                case H5T_REFERENCE:
5515
2.10k
                    if (dt1->shared->u.atomic.u.r.rtype < dt2->shared->u.atomic.u.r.rtype)
5516
0
                        HGOTO_DONE(-1);
5517
2.10k
                    if (dt1->shared->u.atomic.u.r.rtype > dt2->shared->u.atomic.u.r.rtype)
5518
0
                        HGOTO_DONE(1);
5519
2.10k
                    if (dt1->shared->u.atomic.u.r.loc < dt2->shared->u.atomic.u.r.loc)
5520
0
                        HGOTO_DONE(-1);
5521
2.10k
                    if (dt1->shared->u.atomic.u.r.loc > dt2->shared->u.atomic.u.r.loc)
5522
0
                        HGOTO_DONE(1);
5523
2.10k
                    if (dt1->shared->u.atomic.u.r.file < dt2->shared->u.atomic.u.r.file)
5524
0
                        HGOTO_DONE(-1);
5525
2.10k
                    if (dt1->shared->u.atomic.u.r.file > dt2->shared->u.atomic.u.r.file)
5526
147
                        HGOTO_DONE(1);
5527
1.95k
                    break;
5528
5529
1.95k
                case H5T_NO_CLASS:
5530
0
                case H5T_OPAQUE:
5531
0
                case H5T_COMPOUND:
5532
0
                case H5T_ENUM:
5533
0
                case H5T_VLEN:
5534
0
                case H5T_ARRAY:
5535
0
                case H5T_COMPLEX:
5536
0
                case H5T_NCLASSES:
5537
0
                default:
5538
0
                    assert("not implemented yet" && 0);
5539
0
                    break;
5540
19.6k
            }
5541
17.8k
            break;
5542
20.6k
    } /* end switch */
5543
5544
35.5k
done:
5545
35.5k
    if (NULL != idx1)
5546
0
        H5MM_xfree(idx1);
5547
35.5k
    if (NULL != idx2)
5548
0
        H5MM_xfree(idx2);
5549
5550
35.5k
    FUNC_LEAVE_NOAPI(ret_value)
5551
35.5k
} /* end H5T_cmp() */
5552
5553
/*-------------------------------------------------------------------------
5554
 * Function:    H5T__path_table_search
5555
 *
5556
 * Purpose:     Searches the global datatype conversion path table for a
5557
 *              conversion path between two datatypes.
5558
 *
5559
 *              Sets `idx` to be the index of the last table entry compared
5560
 *              (which will be the index of the matching conversion path on
5561
 *              success). If no matching path is found, the value for `idx`
5562
 *              will be the index into the path table where a new path
5563
 *              entry with source and destination datatypes matching src
5564
 *              and dst should be inserted. In this case, the caller should
5565
 *              be sure to increment the index value by 1 if the value of
5566
 *              the last comparison is > 0.
5567
 *
5568
 *              If `last_cmp` is non-NULL, the value of the last comparison
5569
 *              (-1, 0, or 1) is returned through it.
5570
 *
5571
 * Return:    Success:    true (conversion path found, index in *idx)
5572
 *            Failure:    false (no conversion path between types)
5573
 *
5574
 *-------------------------------------------------------------------------
5575
 */
5576
static bool
5577
H5T__path_table_search(const H5T_t *src, const H5T_t *dst, int *idx, int *last_cmp)
5578
2.59k
{
5579
2.59k
    int  lt, rt, md;        /* Left, middle, and right edges */
5580
2.59k
    int  cmp;               /* Comparison result  */
5581
2.59k
    bool ret_value = false; /* Return value */
5582
5583
2.59k
    FUNC_ENTER_PACKAGE_NOERR
5584
5585
    /* Sanity check */
5586
2.59k
    assert(0 != H5T_g.npaths);
5587
2.59k
    assert(src);
5588
2.59k
    assert(src->shared);
5589
2.59k
    assert(dst);
5590
2.59k
    assert(dst->shared);
5591
2.59k
    assert(idx);
5592
5593
    /* Find the conversion path in the table, using a binary search */
5594
    /* NOTE: Doesn't match against entry 0, which is the no-op path */
5595
2.59k
    lt = md = 1;
5596
2.59k
    rt      = H5T_g.npaths;
5597
2.59k
    cmp     = -1;
5598
5599
19.6k
    while (cmp && lt < rt) {
5600
17.0k
        md = (lt + rt) / 2;
5601
17.0k
        assert(H5T_g.path[md]);
5602
17.0k
        cmp = H5T_cmp(src, H5T_g.path[md]->src, false);
5603
17.0k
        if (0 == cmp)
5604
5.02k
            cmp = H5T_cmp(dst, H5T_g.path[md]->dst, false);
5605
17.0k
        if (cmp < 0)
5606
7.74k
            rt = md;
5607
9.28k
        else if (cmp > 0)
5608
7.10k
            lt = md + 1;
5609
2.17k
        else
5610
            /* Match found */
5611
2.17k
            ret_value = true;
5612
17.0k
    }
5613
5614
    /* Set middle index & comparison values */
5615
2.59k
    *idx = md;
5616
2.59k
    if (last_cmp)
5617
2.21k
        *last_cmp = cmp;
5618
5619
2.59k
    FUNC_LEAVE_NOAPI(ret_value)
5620
2.59k
} /* end H5T__path_table_search() */
5621
5622
/*-------------------------------------------------------------------------
5623
 * Function:    H5T_path_find
5624
 *
5625
 * Purpose:    Library-internal wrapper to find the path which converts
5626
 *             type SRC to type DST.
5627
 *
5628
 *             If SRC and DST are both null pointers then the special no-op
5629
 *             conversion path is used.
5630
 *
5631
 * Return:    Success:    Pointer to the path, valid until the path
5632
 *                        database is modified.
5633
 *
5634
 *            Failure:    NULL if the path does not exist and no
5635
 *                        function can be found to apply to the new path.
5636
 *
5637
 *-------------------------------------------------------------------------
5638
 */
5639
H5T_path_t *
5640
H5T_path_find(const H5T_t *src, const H5T_t *dst)
5641
12.4k
{
5642
12.4k
    H5T_conv_func_t conv_func;        /* Conversion function wrapper */
5643
12.4k
    H5T_path_t     *ret_value = NULL; /* Return value */
5644
5645
12.4k
    FUNC_ENTER_NOAPI(NULL)
5646
5647
    /* Sanity check */
5648
12.4k
    assert(src);
5649
12.4k
    assert(src->shared);
5650
12.4k
    assert(dst);
5651
12.4k
    assert(dst->shared);
5652
5653
    /* Set up conversion function wrapper */
5654
12.4k
    conv_func.is_app     = false;
5655
12.4k
    conv_func.u.lib_func = NULL;
5656
5657
    /* Call the internal routine, with additional parameters */
5658
12.4k
    if (NULL == (ret_value = H5T__path_find_real(src, dst, NULL, &conv_func)))
5659
6
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "can't find datatype conversion path");
5660
5661
12.4k
done:
5662
12.4k
    FUNC_LEAVE_NOAPI(ret_value)
5663
12.4k
} /* end H5T_path_find() */
5664
5665
/*-------------------------------------------------------------------------
5666
 * Function:    H5T__path_find_real
5667
 *
5668
 * Purpose:    Finds the path which converts type SRC to type DST, creating
5669
 *             a new path if necessary.
5670
 *
5671
 *             If `conv->u.app_func`/`conv->u.lib_func` is non-NULL then it
5672
 *             is set as the hard conversion function for that path
5673
 *             regardless of whether the path previously existed. Changing
5674
 *             the conversion function of a path causes statistics to be
5675
 *             reset to zero after printing them. `name` is used only when
5676
 *             creating a new path and is just for debugging.
5677
 *
5678
 *             If no "force conversion" flags are set for either the source
5679
 *             or destination datatype and the two datatypes compare equal
5680
 *             to each other, then the special no-op conversion path is
5681
 *             used. This path is always stored as the first path in the
5682
 *             path table.
5683
 *
5684
 * Return:    Success:    Pointer to the path, valid until the path
5685
 *                        database is modified.
5686
 *
5687
 *            Failure:    NULL if the path does not exist and no
5688
 *                        function can be found to apply to the new path.
5689
 *
5690
 *-------------------------------------------------------------------------
5691
 */
5692
static H5T_path_t *
5693
H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv)
5694
12.6k
{
5695
12.6k
    H5T_conv_ctx_t tmp_ctx      = {0};   /* Temporary conversion context object */
5696
12.6k
    H5T_path_t    *matched_path = NULL;  /* Path existing in the table */
5697
12.6k
    H5T_path_t    *path         = NULL;  /* Pointer to current path */
5698
12.6k
    bool           noop_conv    = false; /* Whether this is a no-op conversion */
5699
12.6k
    bool           new_path     = false; /* Whether we're creating a new path */
5700
12.6k
    bool new_api_func = false; /* If the caller is an API function specifying a new conversion function */
5701
12.6k
    bool new_lib_func = false; /* If the caller is a private function specifying a new conversion function */
5702
12.6k
    int  old_npaths;           /* Previous number of paths in table */
5703
12.6k
    int  last_cmp         = 0; /* Value of last comparison during binary search */
5704
12.6k
    int  path_idx         = 0; /* Index into path table for path */
5705
12.6k
    H5T_path_t *ret_value = NULL; /* Return value */
5706
5707
12.6k
    FUNC_ENTER_PACKAGE
5708
5709
    /* Sanity check */
5710
12.6k
    assert(src);
5711
12.6k
    assert(src->shared);
5712
12.6k
    assert(dst);
5713
12.6k
    assert(dst->shared);
5714
5715
    /*
5716
     * Get the datatype conversion exception callback structure.
5717
     * Note that we have to first check if an API context has been
5718
     * pushed, since we could have arrived here during library
5719
     * initialization of the H5T package.
5720
     */
5721
12.6k
    if (H5CX_pushed() && (H5CX_get_dt_conv_cb(&tmp_ctx.u.init.cb_struct) < 0))
5722
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "unable to get conversion exception callback");
5723
5724
    /* Make sure the path table is initialized */
5725
12.6k
    if ((0 == H5T_g.npaths) && (H5T__init_path_table() < 0))
5726
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize type conversion path table");
5727
5728
    /* Find the conversion path. If no "force conversion" flags are
5729
     * set and the source and destination types are equal, then use
5730
     * the no-op conversion path. Otherwise, do a binary search over
5731
     * the remaining entries.
5732
     */
5733
12.6k
    noop_conv =
5734
12.6k
        src->shared->force_conv == false && dst->shared->force_conv == false && 0 == H5T_cmp(src, dst, true);
5735
12.6k
    if (noop_conv)
5736
10.4k
        matched_path = H5T_g.path[0];
5737
2.21k
    else {
5738
        /* Search the table of conversion paths */
5739
2.21k
        if (H5T__path_table_search(src, dst, &path_idx, &last_cmp))
5740
1.87k
            matched_path = H5T_g.path[path_idx];
5741
2.21k
    }
5742
5743
    /* Keep a record of the number of paths in the table, in case one of the
5744
     * initialization calls below (hard or soft) causes more entries to be
5745
     * added to the table - QAK, 1/26/02
5746
     */
5747
12.6k
    old_npaths = H5T_g.npaths;
5748
5749
    /* Set a few convenience variables */
5750
12.6k
    new_api_func = (matched_path && !noop_conv && conv->is_app && conv->u.app_func);
5751
12.6k
    new_lib_func = (matched_path && !noop_conv && !conv->is_app && conv->u.lib_func);
5752
5753
    /* If we didn't find the path, if the caller is an API function specifying
5754
     * a new hard conversion function, or if the caller is a private function
5755
     * specifying a new hard conversion and the path is a soft conversion, then
5756
     * create a new path and add the new function to the path.
5757
     */
5758
12.6k
    new_path = !matched_path || new_api_func || (new_lib_func && !matched_path->is_hard);
5759
5760
12.6k
    if (new_path) {
5761
344
        if (NULL == (path = H5FL_CALLOC(H5T_path_t)))
5762
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path");
5763
344
        if (name && *name) {
5764
182
            strncpy(path->name, name, (size_t)H5T_NAMELEN - 1);
5765
182
            path->name[H5T_NAMELEN - 1] = '\0';
5766
182
        } /* end if */
5767
162
        else
5768
162
            snprintf(path->name, sizeof(path->name), "NONAME");
5769
344
        if (NULL == (path->src = H5T_copy(src, H5T_COPY_ALL)))
5770
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy datatype for conversion path");
5771
344
        if (NULL == (path->dst = H5T_copy(dst, H5T_COPY_ALL)))
5772
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy datatype for conversion path");
5773
344
    } /* end if */
5774
12.3k
    else
5775
12.3k
        path = matched_path;
5776
5777
    /* Initialize the path if it's a new path */
5778
12.6k
    if (new_path && H5T__path_find_init_new_path(path, src, dst, conv, &tmp_ctx) < 0)
5779
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize new conversion path");
5780
5781
    /* Fail if the path still doesn't have a conversion function at this point */
5782
12.6k
    if (!path->conv.u.app_func)
5783
6
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no appropriate function for conversion path");
5784
5785
    /* Check if paths were inserted into the table through a recursive call
5786
     * and re-compute the correct location for this path if so. - QAK, 1/26/02
5787
     */
5788
12.6k
    if (old_npaths != H5T_g.npaths)
5789
0
        if (H5T__path_table_search(src, dst, &path_idx, &last_cmp))
5790
0
            matched_path = H5T_g.path[path_idx];
5791
5792
    /* Replace an existing table entry or add a new entry */
5793
12.6k
    if (matched_path && new_path) {
5794
0
        assert(matched_path == H5T_g.path[path_idx]);
5795
5796
0
        tmp_ctx.u.free.src_type_id = H5I_INVALID_HID;
5797
0
        tmp_ctx.u.free.dst_type_id = H5I_INVALID_HID;
5798
0
        if (H5T__path_free(matched_path, &tmp_ctx) < 0)
5799
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, NULL, "unable to free datatype conversion path");
5800
5801
0
        H5T_g.path[path_idx] = path;
5802
0
    }
5803
12.6k
    else if (new_path) {
5804
        /* Make space in the table for the new path if necessary */
5805
338
        if ((size_t)H5T_g.npaths >= H5T_g.apaths) {
5806
1
            size_t       na = MAX(H5T_DEF_CONV_TABLE_SLOTS, 2 * H5T_g.apaths);
5807
1
            H5T_path_t **x;
5808
5809
1
            if (NULL == (x = H5MM_realloc(H5T_g.path, na * sizeof(H5T_path_t *))))
5810
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
5811
1
            H5T_g.apaths = na;
5812
1
            H5T_g.path   = x;
5813
1
        }
5814
5815
        /* Adjust final location in table for new path if the last comparison
5816
         * of paths during binary search was > 0, then shift down all path
5817
         * entries in the table starting at that location to make room for
5818
         * the new path
5819
         */
5820
338
        assert(last_cmp != 0);
5821
338
        if (last_cmp > 0)
5822
189
            path_idx++;
5823
338
        memmove(H5T_g.path + path_idx + 1, H5T_g.path + path_idx,
5824
338
                (size_t)(H5T_g.npaths - path_idx) * sizeof(H5T_path_t *));
5825
5826
338
        H5T_g.npaths++;
5827
338
        H5T_g.path[path_idx] = path;
5828
338
    }
5829
5830
12.6k
    ret_value = path;
5831
5832
12.6k
done:
5833
12.6k
    if (!ret_value && path && new_path) {
5834
6
        if (path->src && (H5T_close_real(path->src) < 0))
5835
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype");
5836
6
        if (path->dst && (H5T_close_real(path->dst) < 0))
5837
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype");
5838
6
        path = H5FL_FREE(H5T_path_t, path);
5839
6
    }
5840
5841
12.6k
    FUNC_LEAVE_NOAPI(ret_value)
5842
12.6k
} /* end H5T__path_find_real() */
5843
5844
/*-------------------------------------------------------------------------
5845
 * Function:  H5T__init_path_table
5846
 *
5847
 * Purpose:   Helper function to allocate and initialize the table holding
5848
 *            pointers to datatype conversion paths. Sets the no-op
5849
 *            conversion path as the first entry in the table.
5850
 *
5851
 * Return:    Non-negative on success/Negative on failure
5852
 *
5853
 *-------------------------------------------------------------------------
5854
 */
5855
static herr_t
5856
H5T__init_path_table(void)
5857
1
{
5858
1
    herr_t ret_value = SUCCEED;
5859
5860
1
    FUNC_ENTER_PACKAGE
5861
5862
    /* Sanity check */
5863
1
    if (0 != H5T_g.npaths)
5864
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_ALREADYINIT, FAIL,
5865
1
                    "datatype conversion path table is already initialized");
5866
5867
1
    if (NULL == (H5T_g.path = H5MM_calloc(H5T_DEF_CONV_TABLE_SLOTS * sizeof(H5T_path_t *))))
5868
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
5869
1
                    "memory allocation failed for type conversion path table");
5870
1
    H5T_g.apaths = H5T_DEF_CONV_TABLE_SLOTS;
5871
5872
    /*
5873
     * Allocate a path for the no-op conversion function
5874
     * and set it as the first entry in the table
5875
     */
5876
1
    if (NULL == (H5T_g.path[0] = H5FL_CALLOC(H5T_path_t)))
5877
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for no-op conversion path");
5878
5879
    /* Initialize the no-op path */
5880
1
    snprintf(H5T_g.path[0]->name, sizeof(H5T_g.path[0]->name), "no-op");
5881
1
    H5T_g.path[0]->conv.is_app     = false;
5882
1
    H5T_g.path[0]->conv.u.lib_func = H5T__conv_noop;
5883
1
    H5T_g.path[0]->cdata.command   = H5T_CONV_INIT;
5884
5885
1
    if (H5T__conv_noop(NULL, NULL, &(H5T_g.path[0]->cdata), NULL, 0, 0, 0, NULL, NULL) < 0) {
5886
#ifdef H5T_DEBUG
5887
        if (H5DEBUG(T))
5888
            fprintf(H5DEBUG(T), "H5T: unable to initialize no-op conversion function (ignored)\n");
5889
#endif
5890
        /* Ignore any errors from the conversion function */
5891
0
        if (H5E_clear_stack() < 0)
5892
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
5893
0
    } /* end if */
5894
5895
1
    H5T_g.path[0]->is_noop = true;
5896
5897
    /* Set # of initial paths in the table */
5898
1
    H5T_g.npaths = 1;
5899
5900
1
done:
5901
1
    if (ret_value < 0) {
5902
0
        if (H5T_g.path)
5903
0
            H5FL_FREE(H5T_path_t, H5T_g.path[0]);
5904
0
        H5MM_free(H5T_g.path);
5905
0
    }
5906
5907
1
    FUNC_LEAVE_NOAPI(ret_value)
5908
1
} /* end H5T__init_path_table() */
5909
5910
/*-------------------------------------------------------------------------
5911
 * Function:  H5T__path_find_init_new_path
5912
 *
5913
 * Purpose:   Helper function to initialize a new conversion path that's
5914
 *            being added to the path conversion table.
5915
 *
5916
 * Return:    Non-negative on success/Negative on failure
5917
 *
5918
 *-------------------------------------------------------------------------
5919
 */
5920
static herr_t
5921
H5T__path_find_init_new_path(H5T_path_t *path, const H5T_t *src, const H5T_t *dst, H5T_conv_func_t *conv,
5922
                             H5T_conv_ctx_t *conv_ctx)
5923
344
{
5924
344
    H5T_t *tmp_stype = NULL;            /* temporary source datatype */
5925
344
    H5T_t *tmp_dtype = NULL;            /* temporary destination datatype */
5926
344
    hid_t  src_id    = H5I_INVALID_HID; /* source datatype identifier */
5927
344
    hid_t  dst_id    = H5I_INVALID_HID; /* destination datatype identifier */
5928
344
    herr_t status    = SUCCEED;
5929
344
    herr_t ret_value = SUCCEED;
5930
5931
344
    FUNC_ENTER_PACKAGE
5932
5933
344
    assert(path);
5934
344
    assert(conv);
5935
344
    assert(conv_ctx);
5936
344
    assert(NULL == path->conv.u.app_func);
5937
5938
    /* If a hard conversion function was specified, initialize that
5939
     * function and finish setting up the new path.
5940
     */
5941
344
    if (conv->u.app_func) {
5942
182
        path->cdata.command = H5T_CONV_INIT;
5943
182
        if (conv->is_app) {
5944
            /* Copy the conversion path's source and destination datatypes and
5945
             * register an ID for them so we can pass these to the application
5946
             * conversion function
5947
             */
5948
0
            if (path->src && (NULL == (tmp_stype = H5T_copy(path->src, H5T_COPY_ALL))))
5949
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy source datatype");
5950
0
            if (path->dst && (NULL == (tmp_dtype = H5T_copy(path->dst, H5T_COPY_ALL))))
5951
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy destination datatype");
5952
5953
0
            if (tmp_stype && ((src_id = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0))
5954
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
5955
0
                            "unable to register ID for source datatype");
5956
0
            if (tmp_dtype && ((dst_id = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0))
5957
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
5958
0
                            "unable to register ID for destination datatype");
5959
5960
            /* Prepare & restore library for user callback */
5961
0
            H5_BEFORE_USER_CB(FAIL)
5962
0
                {
5963
0
                    status = (conv->u.app_func)(src_id, dst_id, &(path->cdata), 0, 0, 0, NULL, NULL,
5964
0
                                                H5CX_get_dxpl());
5965
0
                }
5966
0
            H5_AFTER_USER_CB(FAIL)
5967
0
        }
5968
182
        else
5969
182
            status = (conv->u.lib_func)(path->src, path->dst, &(path->cdata), conv_ctx, 0, 0, 0, NULL, NULL);
5970
5971
182
        if (status < 0)
5972
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize conversion function");
5973
5974
182
        if (src_id >= 0) {
5975
0
            if (H5I_dec_ref(src_id) < 0)
5976
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
5977
0
            src_id    = H5I_INVALID_HID;
5978
0
            tmp_stype = NULL;
5979
0
        }
5980
182
        if (dst_id >= 0) {
5981
0
            if (H5I_dec_ref(dst_id) < 0)
5982
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
5983
0
            dst_id    = H5I_INVALID_HID;
5984
0
            tmp_dtype = NULL;
5985
0
        }
5986
5987
182
        path->conv    = *conv;
5988
182
        path->is_hard = true;
5989
182
    }
5990
5991
    /*
5992
     * Otherwise, scan the soft list for an applicable function
5993
     * and add it to the path.
5994
     */
5995
344
    assert(path->conv.u.app_func || (src && dst));
5996
2.20k
    for (int i = H5T_g.nsoft - 1; i >= 0 && !path->conv.u.app_func; --i) {
5997
1.86k
        bool path_init_error = false;
5998
5999
1.86k
        if (src->shared->type != H5T_g.soft[i].src || dst->shared->type != H5T_g.soft[i].dst)
6000
1.46k
            continue;
6001
6002
397
        path->cdata.command = H5T_CONV_INIT;
6003
397
        if (H5T_g.soft[i].conv.is_app) {
6004
            /* Copy the conversion path's source and destination datatypes and
6005
             * register an ID for them so we can pass these to the application
6006
             * conversion function
6007
             */
6008
0
            if (NULL == (tmp_stype = H5T_copy(path->src, H5T_COPY_ALL)))
6009
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy source datatype");
6010
0
            if (NULL == (tmp_dtype = H5T_copy(path->dst, H5T_COPY_ALL)))
6011
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy destination datatype");
6012
6013
0
            if ((src_id = H5I_register(H5I_DATATYPE, tmp_stype, false)) < 0)
6014
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
6015
0
                            "unable to register ID for source datatype");
6016
0
            if ((dst_id = H5I_register(H5I_DATATYPE, tmp_dtype, false)) < 0)
6017
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
6018
0
                            "unable to register ID for destination datatype");
6019
6020
            /* Prepare & restore library for user callback */
6021
0
            H5_BEFORE_USER_CB(FAIL)
6022
0
                {
6023
0
                    status = (H5T_g.soft[i].conv.u.app_func)(src_id, dst_id, &(path->cdata), 0, 0, 0, NULL,
6024
0
                                                             NULL, H5CX_get_dxpl());
6025
0
                }
6026
0
            H5_AFTER_USER_CB(FAIL)
6027
0
        }
6028
397
        else
6029
397
            status = (H5T_g.soft[i].conv.u.lib_func)(path->src, path->dst, &(path->cdata), conv_ctx, 0, 0, 0,
6030
397
                                                     NULL, NULL);
6031
6032
397
        if (status < 0) {
6033
241
            memset(&(path->cdata), 0, sizeof(H5T_cdata_t));
6034
            /* ignore the error */
6035
241
            if (H5E_clear_stack() < 0)
6036
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
6037
241
            path_init_error = true;
6038
241
        }
6039
6040
        /* Finish operation, if no error */
6041
397
        if (!path_init_error) {
6042
156
            strncpy(path->name, H5T_g.soft[i].name, (size_t)H5T_NAMELEN);
6043
156
            path->name[H5T_NAMELEN - 1] = '\0';
6044
156
            path->conv                  = H5T_g.soft[i].conv;
6045
156
            path->is_hard               = false;
6046
156
        }
6047
6048
397
        if (src_id >= 0) {
6049
0
            if (H5I_dec_ref(src_id) < 0)
6050
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
6051
0
            src_id    = H5I_INVALID_HID;
6052
0
            tmp_stype = NULL;
6053
0
        }
6054
397
        if (dst_id >= 0) {
6055
0
            if (H5I_dec_ref(dst_id) < 0)
6056
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
6057
0
            dst_id    = H5I_INVALID_HID;
6058
0
            tmp_dtype = NULL;
6059
0
        }
6060
397
    }
6061
6062
344
done:
6063
344
    if (src_id >= 0) {
6064
0
        if (H5I_dec_ref(src_id) < 0)
6065
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
6066
0
    }
6067
344
    else if (tmp_stype) {
6068
0
        if (H5T_close(tmp_stype) < 0)
6069
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype");
6070
0
    }
6071
344
    if (dst_id >= 0) {
6072
0
        if (H5I_dec_ref(dst_id) < 0)
6073
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement reference on temporary ID");
6074
0
    }
6075
344
    else if (tmp_dtype) {
6076
0
        if (H5T_close(tmp_dtype) < 0)
6077
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype");
6078
0
    }
6079
6080
344
    FUNC_LEAVE_NOAPI(ret_value)
6081
344
}
6082
6083
/*-------------------------------------------------------------------------
6084
 * Function:  H5T__path_free
6085
 *
6086
 * Purpose:   Helper function to free a datatype conversion path. This
6087
 *            function assumes that the 'free' member of the passed in
6088
 *            'conv_ctx' has been initialized.
6089
 *
6090
 * Return:    Non-negative on success/Negative on failure
6091
 *
6092
 *-------------------------------------------------------------------------
6093
 */
6094
static herr_t
6095
H5T__path_free(H5T_path_t *path, H5T_conv_ctx_t *conv_ctx)
6096
339
{
6097
339
    herr_t status    = SUCCEED;
6098
339
    int    nprint    = 0;
6099
339
    herr_t ret_value = SUCCEED;
6100
6101
339
    FUNC_ENTER_PACKAGE
6102
6103
339
    assert(path);
6104
339
    assert(conv_ctx);
6105
6106
339
    if (path->conv.u.app_func) {
6107
339
        H5T__print_path_stats(path, &nprint);
6108
6109
339
        path->cdata.command = H5T_CONV_FREE;
6110
6111
339
        if (path->conv.is_app) {
6112
            /* Prepare & restore library for user callback */
6113
0
            H5_BEFORE_USER_CB_NOERR(FAIL)
6114
0
                {
6115
0
                    status =
6116
0
                        (path->conv.u.app_func)(conv_ctx->u.free.src_type_id, conv_ctx->u.free.dst_type_id,
6117
0
                                                &(path->cdata), 0, 0, 0, NULL, NULL, H5CX_get_dxpl());
6118
0
                }
6119
0
            H5_AFTER_USER_CB_NOERR(FAIL)
6120
0
        }
6121
339
        else
6122
339
            status =
6123
339
                (path->conv.u.lib_func)(path->src, path->dst, &(path->cdata), conv_ctx, 0, 0, 0, NULL, NULL);
6124
6125
339
        if (status < 0) {
6126
            /* Ignore any error from shutting down the path */
6127
0
            if (H5E_clear_stack() < 0)
6128
                /* Push error, but keep going */
6129
0
                HDONE_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack");
6130
6131
#ifdef H5T_DEBUG
6132
            if (H5DEBUG(T)) {
6133
                fprintf(H5DEBUG(T), "H5T: conversion function 0x%016zx free failed for %s (ignored)\n",
6134
                        path->conv.is_app ? (size_t)path->conv.u.app_func : (size_t)path->conv.u.lib_func,
6135
                        path->name);
6136
            }
6137
#endif
6138
0
        }
6139
339
    }
6140
6141
339
    if (path->src && (H5T_close_real(path->src) < 0))
6142
        /* Push error, but keep going */
6143
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close source datatype");
6144
339
    if (path->dst && (H5T_close_real(path->dst) < 0))
6145
        /* Push error, but keep going */
6146
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close destination datatype");
6147
6148
339
    path = H5FL_FREE(H5T_path_t, path);
6149
6150
339
    FUNC_LEAVE_NOAPI(ret_value)
6151
339
}
6152
6153
/*-------------------------------------------------------------------------
6154
 * Function:  H5T_path_match
6155
 *
6156
 * Purpose:   Helper function to determine whether a datatype conversion
6157
 *            path object matches against a given set of criteria.
6158
 *
6159
 * Return:    true/false (can't fail)
6160
 *
6161
 *-------------------------------------------------------------------------
6162
 */
6163
static bool
6164
H5T_path_match(H5T_path_t *path, H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
6165
               H5VL_object_t *owned_vol_obj, H5T_conv_t func)
6166
15.3k
{
6167
15.3k
    bool ret_value = true;
6168
6169
15.3k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6170
6171
15.3k
    assert(path);
6172
6173
15.3k
    if (
6174
        /* Check that the specified conversion function persistence matches */
6175
15.3k
        ((H5T_PERS_SOFT == pers && path->is_hard) || (H5T_PERS_HARD == pers && !path->is_hard)) ||
6176
6177
        /* Check that the specified conversion path name matches */
6178
455
        (name && *name && strcmp(name, path->name) != 0) ||
6179
6180
        /*
6181
         * Check that the specified source and destination datatypes match
6182
         * the source and destination datatypes in the conversion path
6183
         */
6184
455
        (src && H5T_cmp(src, path->src, false)) || (dst && H5T_cmp(dst, path->dst, false)) ||
6185
6186
        /*
6187
         * Check that the specified VOL object pointer matches the `owned_vol_obj`
6188
         * field for either the source datatype or destination datatype in the
6189
         * conversion path
6190
         */
6191
455
        (owned_vol_obj && (H5T_path_match_find_type_with_volobj(path->src, owned_vol_obj) == false) &&
6192
311
         (H5T_path_match_find_type_with_volobj(path->dst, owned_vol_obj) == false)) ||
6193
6194
        /* Check that the specified conversion function matches */
6195
144
        (func && func != path->conv.u.app_func))
6196
15.2k
        ret_value = false;
6197
6198
15.3k
    FUNC_LEAVE_NOAPI(ret_value)
6199
15.3k
} /* H5T_path_match() */
6200
6201
/*-------------------------------------------------------------------------
6202
 * Function:  H5T_path_match_find_type_with_volobj
6203
 *
6204
 * Purpose:   Helper function to determine whether a datatype is or
6205
 *            contains a datatype that has a VOL object pointer matching
6206
 *            the given VOL object pointer.
6207
 *
6208
 * Return:    true/false (can't fail)
6209
 *
6210
 *-------------------------------------------------------------------------
6211
 */
6212
static bool
6213
H5T_path_match_find_type_with_volobj(const H5T_t *datatype, const H5VL_object_t *owned_vol_obj)
6214
826
{
6215
826
    bool ret_value = false;
6216
6217
826
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6218
6219
826
    assert(datatype);
6220
826
    assert(owned_vol_obj);
6221
6222
826
    ret_value = (datatype->shared->owned_vol_obj == owned_vol_obj);
6223
826
    if (!ret_value) {
6224
682
        switch (datatype->shared->type) {
6225
0
            case H5T_COMPOUND:
6226
0
                for (unsigned i = 0; i < datatype->shared->u.compnd.nmembs; i++) {
6227
0
                    if (ret_value)
6228
0
                        break;
6229
0
                    ret_value = H5T_path_match_find_type_with_volobj(datatype->shared->u.compnd.memb[i].type,
6230
0
                                                                     owned_vol_obj);
6231
0
                }
6232
0
                break;
6233
6234
60
            case H5T_VLEN:
6235
                /* Should be an error if no parent, but simplify logic for a true/false return value */
6236
60
                if (datatype->shared->parent)
6237
60
                    ret_value = H5T_path_match_find_type_with_volobj(datatype->shared->parent, owned_vol_obj);
6238
60
                break;
6239
6240
0
            case H5T_ARRAY:
6241
                /* Should be an error if no parent, but simplify logic for a true/false return value */
6242
0
                if (datatype->shared->parent)
6243
0
                    ret_value = H5T_path_match_find_type_with_volobj(datatype->shared->parent, owned_vol_obj);
6244
0
                break;
6245
6246
232
            case H5T_INTEGER:
6247
502
            case H5T_FLOAT:
6248
502
            case H5T_TIME:
6249
562
            case H5T_STRING:
6250
562
            case H5T_BITFIELD:
6251
562
            case H5T_OPAQUE:
6252
622
            case H5T_REFERENCE: /* Should have been determined by above check */
6253
622
            case H5T_ENUM:
6254
622
            case H5T_COMPLEX:
6255
622
            case H5T_NO_CLASS: /* Error value, but simplify logic for a true/false return value */
6256
622
            case H5T_NCLASSES: /* Error value, but simplify logic for a true/false return value */
6257
622
            default:
6258
622
                ret_value = false;
6259
622
                break;
6260
682
        }
6261
682
    }
6262
6263
826
    FUNC_LEAVE_NOAPI(ret_value)
6264
826
}
6265
6266
/*-------------------------------------------------------------------------
6267
 * Function:  H5T_path_noop
6268
 *
6269
 * Purpose:   Is the path the special no-op path? The no-op function can be
6270
 *            set by the application and there might be more than one no-op
6271
 *            path in a multi-threaded application if one thread is using
6272
 *            the no-op path when some other thread changes its definition.
6273
 *
6274
 * Return:    true/false (can't fail)
6275
 *
6276
 *-------------------------------------------------------------------------
6277
 */
6278
bool
6279
H5T_path_noop(const H5T_path_t *p)
6280
12.7k
{
6281
12.7k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6282
6283
12.7k
    assert(p);
6284
6285
12.7k
    FUNC_LEAVE_NOAPI(p->is_noop || (p->is_hard && 0 == H5T_cmp(p->src, p->dst, false)))
6286
12.7k
} /* end H5T_path_noop() */
6287
6288
/*-------------------------------------------------------------------------
6289
 * Function:    H5T_noop_conv
6290
 *
6291
 * Purpose:     Check if a conversion between two dataypes will be a no-op
6292
 *
6293
 * Return:      true / false (can't fail)
6294
 *
6295
 *-------------------------------------------------------------------------
6296
 */
6297
bool
6298
H5T_noop_conv(const H5T_t *src, const H5T_t *dst)
6299
379
{
6300
379
    bool ret_value = false; /* Return value */
6301
6302
379
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6303
6304
    /* Sanity check */
6305
379
    assert(src);
6306
379
    assert(src->shared);
6307
379
    assert(dst);
6308
379
    assert(dst->shared);
6309
6310
    /* Check the conversion path.  If source and destination types are equal
6311
     * then its a no-op conversion, as long as neither type has a "force conversion"
6312
     * flag.  Otherwise search over the conversion table entries.
6313
     */
6314
379
    if (src->shared->force_conv == false && dst->shared->force_conv == false &&
6315
0
        0 == H5T_cmp(src, dst, true)) {
6316
0
        ret_value = true;
6317
0
    } /* end if */
6318
379
    else {
6319
379
        int idx = 0; /* Matching entry */
6320
6321
        /* Search the table of conversion paths */
6322
379
        if (H5T__path_table_search(src, dst, &idx, NULL))
6323
304
            ret_value = H5T_path_noop(H5T_g.path[idx]);
6324
379
    } /* end else */
6325
6326
379
    FUNC_LEAVE_NOAPI(ret_value)
6327
379
} /* end H5T_noop_conv() */
6328
6329
/*-------------------------------------------------------------------------
6330
 * Function:  H5T_path_compound_subset
6331
 *
6332
 * Purpose:   Checks if the library's compound conversion function
6333
 *            is in use. Tells whether whether the source members are
6334
 *            a subset of destination, and the order is the same, and
6335
 *            no conversion is needed.  For example:
6336
 *                  struct source {            struct destination {
6337
 *                      TYPE1 A;      -->          TYPE1 A;
6338
 *                      TYPE2 B;      -->          TYPE2 B;
6339
 *                      TYPE3 C;      -->          TYPE3 C;
6340
 *                  };                             TYPE4 D;
6341
 *                                                 TYPE5 E;
6342
 *                                             };
6343
 *
6344
 * Return:    A pointer to the subset info struct in p, or NULL if the
6345
 *            library's compound conversion function is not in use.
6346
 *            Points directly into the H5T_path_t structure.
6347
 *
6348
 *-------------------------------------------------------------------------
6349
 */
6350
H5T_subset_info_t *
6351
H5T_path_compound_subset(const H5T_path_t *p)
6352
874
{
6353
874
    H5T_subset_info_t *ret_value = NULL;
6354
6355
874
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6356
6357
874
    assert(p);
6358
6359
    /* Only retrieve private info if the library compound conversion
6360
     * function is in use */
6361
874
    if (!p->conv.is_app && (p->conv.u.lib_func == H5T__conv_struct))
6362
0
        ret_value = H5T__conv_struct_subset(&(p->cdata));
6363
6364
874
    FUNC_LEAVE_NOAPI(ret_value)
6365
874
} /* end H5T_path_compound_subset */
6366
6367
/*-------------------------------------------------------------------------
6368
 * Function:  H5T_path_bkg
6369
 *
6370
 * Purpose:   Get the "background" flag for the conversion path.
6371
 *
6372
 * Return:    Background flag (can't fail)
6373
 *
6374
 *-------------------------------------------------------------------------
6375
 */
6376
H5T_bkg_t
6377
H5T_path_bkg(const H5T_path_t *p)
6378
1.97k
{
6379
1.97k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
6380
6381
1.97k
    assert(p);
6382
6383
1.97k
    FUNC_LEAVE_NOAPI(p->cdata.need_bkg)
6384
1.97k
} /* end H5T_path_bkg() */
6385
6386
/*-------------------------------------------------------------------------
6387
 * Function:  H5T__compiler_conv
6388
 *
6389
 * Purpose:   Private function for H5Tcompiler_conv.  Finds out whether the
6390
 *            library's conversion function from type SRC to type DST
6391
 *            is a hard conversion.
6392
 *
6393
 * Return:    true:           hard conversion.
6394
 *            false:          soft conversion.
6395
 *            FAIL:           function failed.
6396
 *
6397
 *-------------------------------------------------------------------------
6398
 */
6399
static htri_t
6400
H5T__compiler_conv(H5T_t *src, H5T_t *dst)
6401
0
{
6402
0
    H5T_path_t *path;
6403
0
    htri_t      ret_value = FAIL; /* Return value */
6404
6405
0
    FUNC_ENTER_PACKAGE
6406
6407
    /* Find it */
6408
0
    if (NULL == (path = H5T_path_find(src, dst)))
6409
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "conversion function not found");
6410
6411
0
    ret_value = (htri_t)path->is_hard;
6412
6413
0
done:
6414
0
    FUNC_LEAVE_NOAPI(ret_value)
6415
0
} /* end H5T__compiler_conv() */
6416
6417
/*-------------------------------------------------------------------------
6418
 * Function:  H5T_convert
6419
 *
6420
 * Purpose:   Call a conversion function to convert from source to
6421
 *            destination data type and accumulate timing statistics.
6422
 *
6423
 * Return:    Success:    non-negative
6424
 *
6425
 *            Failure:    negative
6426
 *
6427
 *-------------------------------------------------------------------------
6428
 */
6429
herr_t
6430
H5T_convert(H5T_path_t *tpath, const H5T_t *src_type, const H5T_t *dst_type, size_t nelmts, size_t buf_stride,
6431
            size_t bkg_stride, void *buf, void *bkg)
6432
1.97k
{
6433
1.97k
    H5T_conv_ctx_t conv_ctx = {0};
6434
#ifdef H5T_DEBUG
6435
    H5_timer_t timer = {0}; /* Timer for conversion */
6436
#endif
6437
1.97k
    hid_t  src_type_id = H5I_INVALID_HID;
6438
1.97k
    hid_t  dst_type_id = H5I_INVALID_HID;
6439
1.97k
    herr_t ret_value   = SUCCEED;
6440
6441
1.97k
    FUNC_ENTER_NOAPI(FAIL)
6442
6443
#ifdef H5T_DEBUG
6444
    if (H5DEBUG(T)) {
6445
        /* Initialize and start timer */
6446
        H5_timer_init(&timer);
6447
        H5_timer_start(&timer);
6448
    } /* end if */
6449
#endif
6450
6451
    /* Get the datatype conversion exception callback structure from the API context */
6452
1.97k
    if (H5CX_get_dt_conv_cb(&conv_ctx.u.conv.cb_struct) < 0)
6453
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
6454
6455
    /*
6456
     * If this is an application conversion function or an exception callback
6457
     * function was supplied, register IDs for the datatypes so we can pass
6458
     * those as appropriate. Also grab the DXPL if necessary so we can pass
6459
     * that to the app conversion function.
6460
     */
6461
1.97k
    if (tpath->conv.is_app || conv_ctx.u.conv.cb_struct.func) {
6462
0
        if ((src_type_id = H5I_register(H5I_DATATYPE, src_type, false)) < 0)
6463
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register ID for source datatype");
6464
0
        if ((dst_type_id = H5I_register(H5I_DATATYPE, dst_type, false)) < 0)
6465
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL,
6466
0
                        "unable to register ID for destination datatype");
6467
6468
0
        if (tpath->conv.is_app)
6469
0
            conv_ctx.u.conv.dxpl_id = H5CX_get_dxpl();
6470
0
    }
6471
1.97k
    conv_ctx.u.conv.src_type_id = src_type_id;
6472
1.97k
    conv_ctx.u.conv.dst_type_id = dst_type_id;
6473
6474
1.97k
    if (H5T_convert_with_ctx(tpath, src_type, dst_type, &conv_ctx, nelmts, buf_stride, bkg_stride, buf, bkg) <
6475
1.97k
        0)
6476
115
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed");
6477
6478
1.97k
done:
6479
    /* Remove IDs, but don't decrement their reference counts, as they
6480
     * could have been registered for datatypes that weren't copied
6481
     */
6482
1.97k
    if ((src_type_id >= 0) && (NULL == H5I_remove(src_type_id)))
6483
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't decrement temporary datatype ID");
6484
1.97k
    if ((dst_type_id >= 0) && (NULL == H5I_remove(dst_type_id)))
6485
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't decrement temporary datatype ID");
6486
6487
#ifdef H5T_DEBUG
6488
    if (H5DEBUG(T)) {
6489
        /* Stop timer */
6490
        H5_timer_stop(&timer);
6491
6492
        /* Record elapsed timer info */
6493
        H5_timer_get_times(timer, &tpath->stats.times);
6494
6495
        /* Increment # of calls and # of elements converted */
6496
        tpath->stats.ncalls++;
6497
        tpath->stats.nelmts += nelmts;
6498
    } /* end if */
6499
#endif
6500
6501
1.97k
    FUNC_LEAVE_NOAPI(ret_value)
6502
1.97k
} /* end H5T_convert() */
6503
6504
/*-------------------------------------------------------------------------
6505
 * Function:  H5T_convert_with_ctx
6506
 *
6507
 * Purpose:   Helper routine for H5T_convert that accepts a pointer to a
6508
 *            H5T_conv_ctx_t conversion context structure. Useful for
6509
 *            conversion routines involving container datatypes, such as
6510
 *            compounds, where the conversion context structure that was
6511
 *            setup during the initial H5T_convert call can be reused.
6512
 *            This avoids the expensive and unnecessary overhead of
6513
 *            recreating this structure and possibly re-registering IDs for
6514
 *            the source and destination datatypes for every single member
6515
 *            of the container datatype and every single element being
6516
 *            converted that consists of that container datatype.
6517
 *
6518
 * Return:    Non-negative on success/Negative on failure
6519
 *
6520
 *-------------------------------------------------------------------------
6521
 */
6522
herr_t
6523
H5T_convert_with_ctx(H5T_path_t *tpath, const H5T_t *src_type, const H5T_t *dst_type,
6524
                     const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride,
6525
                     void *buf, void *bkg)
6526
1.97k
{
6527
1.97k
    herr_t ret_value = SUCCEED;
6528
6529
1.97k
    FUNC_ENTER_NOAPI(FAIL)
6530
6531
    /* Call the appropriate conversion callback */
6532
1.97k
    tpath->cdata.command = H5T_CONV_CONV;
6533
1.97k
    if (tpath->conv.is_app) {
6534
        /* Prepare & restore library for user callback */
6535
0
        H5_BEFORE_USER_CB(FAIL)
6536
0
            {
6537
0
                ret_value = (tpath->conv.u.app_func)(
6538
0
                    conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, &(tpath->cdata), nelmts,
6539
0
                    buf_stride, bkg_stride, buf, bkg, conv_ctx->u.conv.dxpl_id);
6540
0
            }
6541
0
        H5_AFTER_USER_CB(FAIL)
6542
0
        if (ret_value < 0)
6543
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed");
6544
0
    } /* end if */
6545
1.97k
    else if ((tpath->conv.u.lib_func)(src_type, dst_type, &(tpath->cdata), conv_ctx, nelmts, buf_stride,
6546
1.97k
                                      bkg_stride, buf, bkg) < 0)
6547
115
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed");
6548
6549
1.97k
done:
6550
1.97k
    FUNC_LEAVE_NOAPI(ret_value)
6551
1.97k
} /* end H5T_convert_with_ctx() */
6552
6553
/*-------------------------------------------------------------------------
6554
 * Function:  H5T_oloc
6555
 *
6556
 * Purpose:   Returns a pointer to the object location for a named datatype.
6557
 *
6558
 * Return:    Success:    Ptr directly into named datatype
6559
 *            Failure:    NULL
6560
 *
6561
 *-------------------------------------------------------------------------
6562
 */
6563
H5O_loc_t *
6564
H5T_oloc(H5T_t *dt)
6565
0
{
6566
0
    H5O_loc_t *ret_value = NULL;
6567
6568
0
    FUNC_ENTER_NOAPI(NULL)
6569
6570
0
    assert(dt);
6571
6572
0
    switch (dt->shared->state) {
6573
0
        case H5T_STATE_TRANSIENT:
6574
0
        case H5T_STATE_RDONLY:
6575
0
        case H5T_STATE_IMMUTABLE:
6576
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype");
6577
0
        case H5T_STATE_NAMED:
6578
0
        case H5T_STATE_OPEN:
6579
0
            assert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
6580
0
            ret_value = &dt->oloc;
6581
0
            break;
6582
0
        default:
6583
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid datatype state");
6584
0
    } /* end switch */
6585
6586
0
done:
6587
0
    FUNC_LEAVE_NOAPI(ret_value)
6588
0
} /* end H5T_oloc() */
6589
6590
/*-------------------------------------------------------------------------
6591
 * Function:  H5T_nameof
6592
 *
6593
 * Purpose:   Returns a pointer to the path for a named datatype.
6594
 *
6595
 * Return:    Success:    Ptr directly into named datatype
6596
 *            Failure:    NULL
6597
 *
6598
 *-------------------------------------------------------------------------
6599
 */
6600
H5G_name_t *
6601
H5T_nameof(H5T_t *dt)
6602
0
{
6603
0
    H5G_name_t *ret_value = NULL;
6604
6605
0
    FUNC_ENTER_NOAPI(NULL)
6606
6607
0
    assert(dt);
6608
6609
0
    switch (dt->shared->state) {
6610
0
        case H5T_STATE_TRANSIENT:
6611
0
        case H5T_STATE_RDONLY:
6612
0
        case H5T_STATE_IMMUTABLE:
6613
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype");
6614
0
        case H5T_STATE_NAMED:
6615
0
        case H5T_STATE_OPEN:
6616
0
            ret_value = &(dt->path);
6617
0
            break;
6618
0
        default:
6619
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid datatype state");
6620
0
    } /* end switch */
6621
6622
0
done:
6623
0
    FUNC_LEAVE_NOAPI(ret_value)
6624
0
} /* end H5T_nameof() */
6625
6626
/*-------------------------------------------------------------------------
6627
 * Function:    H5T_is_immutable
6628
 *
6629
 * Purpose:     Check if a datatype is immutable.
6630
 *
6631
 * Return:      true
6632
 *
6633
 *              false
6634
 *
6635
 *-------------------------------------------------------------------------
6636
 */
6637
htri_t
6638
H5T_is_immutable(const H5T_t *dt)
6639
0
{
6640
0
    htri_t ret_value = false;
6641
6642
0
    FUNC_ENTER_NOAPI(FAIL)
6643
6644
0
    assert(dt);
6645
6646
0
    if (dt->shared->state == H5T_STATE_IMMUTABLE)
6647
0
        ret_value = true;
6648
6649
0
done:
6650
0
    FUNC_LEAVE_NOAPI(ret_value)
6651
0
}
6652
6653
/*-------------------------------------------------------------------------
6654
 * Function:    H5T_is_named
6655
 *
6656
 * Purpose:     Check if a datatype is named/committed.
6657
 *
6658
 * Return:      true/false/FAIL
6659
 *
6660
 *-------------------------------------------------------------------------
6661
 */
6662
htri_t
6663
H5T_is_named(const H5T_t *dt)
6664
10.9k
{
6665
10.9k
    htri_t ret_value = false;
6666
6667
10.9k
    FUNC_ENTER_NOAPI(FAIL)
6668
6669
10.9k
    assert(dt);
6670
6671
10.9k
    if (dt->vol_obj)
6672
0
        ret_value = true;
6673
10.9k
    else
6674
10.9k
        ret_value = (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state);
6675
6676
10.9k
done:
6677
10.9k
    FUNC_LEAVE_NOAPI(ret_value)
6678
10.9k
}
6679
6680
/*-------------------------------------------------------------------------
6681
 * Function:    H5T_convert_committed_datatype
6682
 *
6683
 * Purpose:     To convert the committed datatype "dt" to a transient embedded
6684
 *        type if the file location associated with the committed datatype is
6685
 *        different from the parameter "f".
6686
 *        "f" is the file location where the dataset or attribute will be created.
6687
 *
6688
 * Notes:       See HDFFV-9940
6689
 *
6690
 * Return:      Success:        non-negative
6691
 *              Failure:        negative
6692
 *
6693
 *-------------------------------------------------------------------------
6694
 */
6695
herr_t
6696
H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f)
6697
0
{
6698
0
    herr_t ret_value = SUCCEED; /* Return value */
6699
6700
0
    FUNC_ENTER_NOAPI(FAIL)
6701
6702
0
    assert(dt);
6703
0
    assert(f);
6704
6705
0
    if (H5T_is_named(dt) && (dt->sh_loc.file != f)) {
6706
0
        assert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
6707
6708
0
        H5O_msg_reset_share(H5O_DTYPE_ID, dt);
6709
0
        if (H5O_loc_free(&dt->oloc) < 0)
6710
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location");
6711
0
        if (H5G_name_free(&dt->path) < 0)
6712
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path");
6713
6714
        /* If the datatype is committed through the VOL, close it */
6715
0
        if (NULL != dt->vol_obj) {
6716
0
            H5VL_object_t *vol_obj = dt->vol_obj;
6717
6718
            /* Close the datatype through the VOL*/
6719
0
            if (H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
6720
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype");
6721
6722
            /* Free the datatype and set the VOL object pointer to NULL */
6723
0
            if (H5VL_free_object(vol_obj) < 0)
6724
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object");
6725
0
            dt->vol_obj = NULL;
6726
0
        } /* end if */
6727
6728
0
        dt->shared->state = H5T_STATE_TRANSIENT;
6729
0
    } /* end if */
6730
6731
0
done:
6732
0
    FUNC_LEAVE_NOAPI(ret_value)
6733
0
} /* end H5T_convert_committed_datatype() */
6734
6735
/*--------------------------------------------------------------------------
6736
 * Function:    H5T_get_ref_type
6737
 *
6738
 * Purpose:     Retrieves the type of reference for a datatype
6739
 *              H5T_t *dt;  IN: datatype pointer for the reference datatype
6740
 *
6741
 * Return:      Success:        A reference type defined in H5Rpublic.h
6742
 *              Failure:        H5R_BADTYPE
6743
 * Notes:       Given a reference datatype object, this function returns the reference type
6744
 *              of the datatype.
6745
 *--------------------------------------------------------------------------
6746
 */
6747
H5R_type_t
6748
H5T_get_ref_type(const H5T_t *dt)
6749
0
{
6750
0
    H5R_type_t ret_value = H5R_BADTYPE;
6751
6752
0
    FUNC_ENTER_NOAPI(H5R_BADTYPE)
6753
6754
0
    assert(dt);
6755
6756
0
    if (dt->shared->type == H5T_REFERENCE)
6757
0
        ret_value = dt->shared->u.atomic.u.r.rtype;
6758
6759
0
done:
6760
0
    FUNC_LEAVE_NOAPI(ret_value)
6761
0
} /* end H5T_get_ref_type() */
6762
6763
/*-------------------------------------------------------------------------
6764
 * Function:  H5T_is_sensible
6765
 *
6766
 * Purpose:   Determines if a data type is sensible to store on disk
6767
 *            (i.e. not partially initialized)
6768
 *
6769
 * Return:    Success:    true, false
6770
 *
6771
 *            Failure:    Negative
6772
 *
6773
 *-------------------------------------------------------------------------
6774
 */
6775
htri_t
6776
H5T_is_sensible(const H5T_t *dt)
6777
0
{
6778
0
    htri_t ret_value = FAIL; /* Return value */
6779
6780
0
    FUNC_ENTER_NOAPI(FAIL)
6781
6782
0
    assert(dt);
6783
6784
0
    switch (dt->shared->type) {
6785
0
        case H5T_COMPOUND:
6786
            /* Only allow compound datatypes with at least one member to be stored on disk */
6787
0
            if (dt->shared->u.compnd.nmembs > 0)
6788
0
                ret_value = true;
6789
0
            else
6790
0
                ret_value = false;
6791
0
            break;
6792
6793
0
        case H5T_ENUM:
6794
            /* Only allow enum datatypes with at least one member to be stored on disk */
6795
0
            if (dt->shared->u.enumer.nmembs > 0)
6796
0
                ret_value = true;
6797
0
            else
6798
0
                ret_value = false;
6799
0
            break;
6800
6801
0
        case H5T_NO_CLASS:
6802
0
        case H5T_INTEGER:
6803
0
        case H5T_FLOAT:
6804
0
        case H5T_TIME:
6805
0
        case H5T_STRING:
6806
0
        case H5T_BITFIELD:
6807
0
        case H5T_OPAQUE:
6808
0
        case H5T_REFERENCE:
6809
0
        case H5T_VLEN:
6810
0
        case H5T_ARRAY:
6811
0
        case H5T_COMPLEX:
6812
0
        case H5T_NCLASSES:
6813
0
        default:
6814
            /* Assume all other datatype are sensible to store on disk */
6815
0
            ret_value = true;
6816
0
            break;
6817
0
    } /* end switch */
6818
6819
0
done:
6820
0
    FUNC_LEAVE_NOAPI(ret_value)
6821
0
}
6822
6823
/*--------------------------------------------------------------------------
6824
 NAME
6825
    H5T_set_loc
6826
 PURPOSE
6827
    Recursively mark any datatypes as on disk/in memory
6828
 USAGE
6829
    htri_t H5T_set_loc(dt,f,loc)
6830
        H5T_t *dt;              IN/OUT: Pointer to the datatype to mark
6831
        H5F_t *f;               IN: Pointer to the file the datatype is in
6832
        H5T_loc_t loc           IN: location of type
6833
6834
 RETURNS
6835
    One of two values on success:
6836
        true - If the location of any vlen types changed
6837
        false - If the location of any vlen types is the same
6838
    <0 is returned on failure
6839
 DESCRIPTION
6840
    Recursively descends any VL or compound datatypes to mark all VL datatypes
6841
    as either on disk or in memory.
6842
 --------------------------------------------------------------------------
6843
 */
6844
htri_t
6845
H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc)
6846
26.4k
{
6847
26.4k
    htri_t   changed;       /* Whether H5T_set_loc changed the type (even if the size didn't change) */
6848
26.4k
    htri_t   ret_value = 0; /* Indicate that success, but no location change */
6849
26.4k
    unsigned i;             /* Local index variable */
6850
26.4k
    size_t   old_size;      /* Previous size of a field */
6851
6852
26.4k
    FUNC_ENTER_NOAPI(FAIL)
6853
6854
26.4k
    assert(dt);
6855
26.4k
    assert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
6856
6857
    /* Datatypes can't change in size if the force_conv flag is not set */
6858
26.4k
    if (dt->shared->force_conv) {
6859
        /* Check the datatype of this element */
6860
3.97k
        switch (dt->shared->type) {
6861
0
            case H5T_ARRAY: /* Recurse on VL, compound and array base element type */
6862
                /* Recurse if it's VL, compound, enum or array */
6863
                /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */
6864
0
                if (dt->shared->parent->shared->force_conv &&
6865
0
                    H5T_IS_COMPOSITE(dt->shared->parent->shared->type)) {
6866
                    /* Keep the old base element size for later */
6867
0
                    old_size = dt->shared->parent->shared->size;
6868
6869
                    /* Mark the VL, compound or array type */
6870
0
                    if ((changed = H5T_set_loc(dt->shared->parent, file, loc)) < 0)
6871
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
6872
0
                    if (changed > 0)
6873
0
                        ret_value = changed;
6874
6875
                    /* Check if the field changed size */
6876
0
                    if (old_size != dt->shared->parent->shared->size) {
6877
                        /* Adjust the size of the array */
6878
0
                        dt->shared->size = dt->shared->u.array.nelem * dt->shared->parent->shared->size;
6879
0
                    } /* end if */
6880
0
                }     /* end if */
6881
0
                break;
6882
6883
0
            case H5T_COMPOUND: /* Check each field and recurse on VL, compound and array type */
6884
0
            {
6885
0
                ssize_t accum_change = 0; /* Amount of change in the offset of the fields */
6886
6887
                /* Sort the fields based on offsets */
6888
0
                H5T__sort_value(dt, NULL);
6889
6890
0
                for (i = 0; i < dt->shared->u.compnd.nmembs; i++) {
6891
0
                    H5T_t *memb_type; /* Member's datatype pointer */
6892
6893
                    /* Range check against compound member's offset */
6894
0
                    if ((accum_change < 0) && ((ssize_t)dt->shared->u.compnd.memb[i].offset < accum_change))
6895
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
6896
6897
                    /* Apply the accumulated size change to the offset of the field */
6898
0
                    dt->shared->u.compnd.memb[i].offset += (size_t)accum_change;
6899
6900
                    /* Set the member type pointer (for convenience) */
6901
0
                    memb_type = dt->shared->u.compnd.memb[i].type;
6902
6903
                    /* Recurse if it's VL, compound, enum or array */
6904
                    /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse)
6905
                     */
6906
0
                    if (memb_type->shared->force_conv && H5T_IS_COMPOSITE(memb_type->shared->type)) {
6907
                        /* Keep the old field size for later */
6908
0
                        old_size = memb_type->shared->size;
6909
6910
                        /* Mark the VL, compound, enum or array type */
6911
0
                        if ((changed = H5T_set_loc(memb_type, file, loc)) < 0)
6912
0
                            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
6913
0
                        if (changed > 0)
6914
0
                            ret_value = changed;
6915
6916
                        /* Check if the field changed size */
6917
0
                        if (old_size != memb_type->shared->size) {
6918
6919
                            /* Fail if the old_size is zero */
6920
0
                            if (0 == old_size)
6921
0
                                HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL,
6922
0
                                            "old_size of zero would cause division by zero");
6923
6924
                            /* Adjust the size of the member */
6925
0
                            dt->shared->u.compnd.memb[i].size =
6926
0
                                (dt->shared->u.compnd.memb[i].size * memb_type->shared->size) / old_size;
6927
6928
                            /* Add that change to the accumulated size change */
6929
0
                            accum_change += (ssize_t)(memb_type->shared->size - old_size);
6930
0
                        } /* end if */
6931
0
                    }     /* end if */
6932
0
                }         /* end for */
6933
6934
                /* Range check against datatype size */
6935
0
                if ((accum_change < 0) && ((ssize_t)dt->shared->size < accum_change))
6936
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
6937
6938
                /* Apply the accumulated size change to the datatype */
6939
0
                dt->shared->size += (size_t)accum_change;
6940
0
            } break;
6941
6942
1.56k
            case H5T_VLEN: /* Recurse on the VL information if it's VL, compound or array, then free VL
6943
                              sequence */
6944
                /* Recurse if it's VL, compound, enum or array (ignore references here so that we can encode
6945
                 * them as part of the same blob)*/
6946
                /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */
6947
1.56k
                if (dt->shared->parent->shared->force_conv &&
6948
0
                    H5T_IS_COMPOSITE(dt->shared->parent->shared->type) &&
6949
0
                    (dt->shared->parent->shared->type != H5T_REFERENCE)) {
6950
0
                    if ((changed = H5T_set_loc(dt->shared->parent, file, loc)) < 0)
6951
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
6952
0
                    if (changed > 0)
6953
0
                        ret_value = changed;
6954
0
                } /* end if */
6955
6956
                /* Mark this VL sequence */
6957
1.56k
                if ((changed = H5T__vlen_set_loc(dt, file, loc)) < 0)
6958
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
6959
1.56k
                if (changed > 0)
6960
677
                    ret_value = changed;
6961
1.56k
                break;
6962
6963
2.40k
            case H5T_REFERENCE:
6964
                /* Reference types go through type conversion */
6965
2.40k
                if ((ret_value = H5T__ref_set_loc(dt, file, loc)) < 0)
6966
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "Unable to set reference location");
6967
2.40k
                break;
6968
6969
2.40k
            case H5T_NO_CLASS:
6970
0
            case H5T_INTEGER:
6971
0
            case H5T_FLOAT:
6972
0
            case H5T_TIME:
6973
0
            case H5T_STRING:
6974
0
            case H5T_BITFIELD:
6975
0
            case H5T_OPAQUE:
6976
0
            case H5T_ENUM:
6977
0
            case H5T_COMPLEX:
6978
0
            case H5T_NCLASSES:
6979
0
            default:
6980
0
                break;
6981
3.97k
        } /* end switch */
6982
3.97k
    }     /* end if */
6983
6984
26.4k
done:
6985
26.4k
    FUNC_LEAVE_NOAPI(ret_value)
6986
26.4k
} /* end H5T_set_loc() */
6987
6988
/*-------------------------------------------------------------------------
6989
 * Function:    H5T_is_relocatable
6990
 *
6991
 * Purpose:     Check if a datatype will change between disk and memory.
6992
 *
6993
 * Notes:       Currently, only variable-length and references change
6994
 *              between disk & memory (see cases where things are changed in
6995
 *              the H5T_set_loc() code above).
6996
 *
6997
 * Return:
6998
 *  One of two values on success:
6999
 *      true - If the location of any vlen types changed
7000
 *      false - If the location of any vlen types is the same
7001
 *  <0 is returned on failure
7002
 *
7003
 *-------------------------------------------------------------------------
7004
 */
7005
htri_t
7006
H5T_is_relocatable(const H5T_t *dt)
7007
0
{
7008
0
    htri_t ret_value = false;
7009
7010
0
    FUNC_ENTER_NOAPI(FAIL)
7011
7012
    /* Sanity check */
7013
0
    assert(dt);
7014
7015
    /* VL and reference datatypes are relocatable */
7016
0
    if (H5T_detect_class(dt, H5T_VLEN, false) || H5T_detect_class(dt, H5T_REFERENCE, false))
7017
0
        ret_value = true;
7018
7019
0
done:
7020
0
    FUNC_LEAVE_NOAPI(ret_value)
7021
0
} /* end H5T_is_relocatable() */
7022
7023
/*-------------------------------------------------------------------------
7024
 * Function:   H5T__detect_vlen_ref
7025
 *
7026
 * Purpose:    Check whether a datatype contains (or is) a vlen reference
7027
 *             datatype.
7028
 *
7029
 * Return:      true (1) or false (0) on success
7030
 *        (Can't fail)
7031
 *
7032
 *-------------------------------------------------------------------------
7033
 */
7034
static bool
7035
H5T__detect_vlen_ref(const H5T_t *dt)
7036
0
{
7037
0
    unsigned u;                 /* Local index variable */
7038
0
    bool     ret_value = false; /* Return value */
7039
7040
0
    FUNC_ENTER_PACKAGE_NOERR
7041
7042
    /* Sanity checks */
7043
0
    assert(dt);
7044
7045
    /* Check if this datatype is a vlen reference */
7046
    /* TODO currently H5T_STD_REF is always considered as a vlen type */
7047
0
    if (H5T_REFERENCE == dt->shared->type && !dt->shared->u.atomic.u.r.opaque)
7048
0
        HGOTO_DONE(true);
7049
7050
    /* Check for types that might have the correct type as a component */
7051
0
    switch (dt->shared->type) {
7052
0
        case H5T_COMPOUND:
7053
            /* Iterate over all the compound datatype's fields */
7054
0
            for (u = 0; u < dt->shared->u.compnd.nmembs; u++)
7055
                /* Recurse on field's datatype */
7056
0
                if (H5T__detect_vlen_ref(dt->shared->u.compnd.memb[u].type))
7057
0
                    HGOTO_DONE(true);
7058
0
            break;
7059
7060
0
        case H5T_ARRAY:
7061
0
        case H5T_VLEN:
7062
0
        case H5T_ENUM:
7063
0
            HGOTO_DONE(H5T__detect_vlen_ref(dt->shared->parent));
7064
0
            break;
7065
7066
0
        case H5T_NO_CLASS:
7067
0
        case H5T_INTEGER:
7068
0
        case H5T_FLOAT:
7069
0
        case H5T_TIME:
7070
0
        case H5T_STRING:
7071
0
        case H5T_BITFIELD:
7072
0
        case H5T_OPAQUE:
7073
0
        case H5T_REFERENCE:
7074
0
        case H5T_COMPLEX:
7075
0
        case H5T_NCLASSES:
7076
0
        default:
7077
0
            break;
7078
0
    } /* end if */
7079
7080
0
done:
7081
0
    FUNC_LEAVE_NOAPI(ret_value)
7082
0
} /* end H5T__detect_vlen_ref() */
7083
7084
/*-------------------------------------------------------------------------
7085
 * Function:    H5T_is_vl_storage
7086
 *
7087
 * Purpose:     Check if a datatype will be stored in a variable-length form.
7088
 *
7089
 * Notes:       Currently, only variable-length string & sequences and region
7090
 *              references are stored in a variable-length form.
7091
 *
7092
 * Return:
7093
 *  One of two values on success:
7094
 *      true - If the datatype will be stored in a variable-length form
7095
 *      false - If the datatype will NOT be stored in a variable-length form
7096
 *  <0 is returned on failure
7097
 *
7098
 *-------------------------------------------------------------------------
7099
 */
7100
htri_t
7101
H5T_is_vl_storage(const H5T_t *dt)
7102
0
{
7103
0
    htri_t ret_value = false;
7104
7105
0
    FUNC_ENTER_NOAPI(FAIL)
7106
7107
    /* Sanity check */
7108
0
    assert(dt);
7109
7110
    /* VL and region reference datatypes are stored in variable-length form */
7111
0
    if (H5T_detect_class(dt, H5T_VLEN, false))
7112
0
        ret_value = true;
7113
0
    else if (H5T_detect_class(dt, H5T_REFERENCE, false))
7114
0
        ret_value = H5T__detect_vlen_ref(dt);
7115
0
    else
7116
0
        ret_value = false;
7117
7118
0
done:
7119
0
    FUNC_LEAVE_NOAPI(ret_value)
7120
0
} /* end H5T_is_vl_storage() */
7121
7122
/*-------------------------------------------------------------------------
7123
 * Function:    H5T__upgrade_version_cb
7124
 *
7125
 * Purpose:     H5T__visit callback to Upgrade the version of a datatype
7126
 *              (if there's any benefit to doing so)
7127
 *
7128
 * Note:        The behavior below is tightly coupled with the "better"
7129
 *              encodings for datatype messages in the datatype message
7130
 *              encoding routine.
7131
 *
7132
 * Return:      Non-negative on success/Negative on failure
7133
 *
7134
 *-------------------------------------------------------------------------
7135
 */
7136
static herr_t
7137
H5T__upgrade_version_cb(H5T_t *dt, void *op_value)
7138
0
{
7139
0
    FUNC_ENTER_PACKAGE_NOERR
7140
7141
    /* Sanity check */
7142
0
    assert(dt);
7143
0
    assert(op_value);
7144
7145
    /* Special behavior for each type of datatype */
7146
0
    switch (dt->shared->type) {
7147
0
        case H5T_COMPOUND:
7148
0
        case H5T_ARRAY:
7149
0
        case H5T_ENUM:
7150
            /* These types benefit from "upgrading" their version */
7151
0
            if (*(unsigned *)op_value > dt->shared->version)
7152
0
                dt->shared->version = *(unsigned *)op_value;
7153
0
            break;
7154
7155
0
        case H5T_VLEN:
7156
0
            if (dt->shared->parent->shared->version > dt->shared->version)
7157
0
                dt->shared->version = dt->shared->parent->shared->version;
7158
0
            break;
7159
7160
0
        case H5T_COMPLEX:
7161
0
            if (dt->shared->parent->shared->version > dt->shared->version)
7162
0
                dt->shared->version = dt->shared->parent->shared->version;
7163
0
            break;
7164
7165
0
        case H5T_NO_CLASS:
7166
0
        case H5T_INTEGER:
7167
0
        case H5T_FLOAT:
7168
0
        case H5T_TIME:
7169
0
        case H5T_STRING:
7170
0
        case H5T_BITFIELD:
7171
0
        case H5T_OPAQUE:
7172
0
        case H5T_REFERENCE:
7173
0
        case H5T_NCLASSES:
7174
0
        default:
7175
0
            break;
7176
0
    } /* end switch */
7177
7178
0
    FUNC_LEAVE_NOAPI(SUCCEED)
7179
0
} /* end H5T__upgrade_version_cb() */
7180
7181
/*-------------------------------------------------------------------------
7182
 * Function:    H5T__upgrade_version
7183
 *
7184
 * Purpose:     Upgrade the version of a datatype (if there's any benefit to
7185
 *              doing so) and recursively apply to compound members and/or
7186
 *              parent datatypes.
7187
 *
7188
 * Return:      Non-negative on success/Negative on failure
7189
 *
7190
 *-------------------------------------------------------------------------
7191
 */
7192
herr_t
7193
H5T__upgrade_version(H5T_t *dt, unsigned new_version)
7194
0
{
7195
0
    herr_t ret_value = SUCCEED; /* Return value */
7196
7197
0
    FUNC_ENTER_PACKAGE
7198
7199
    /* Sanity check */
7200
0
    assert(dt);
7201
7202
    /* Iterate over entire datatype, upgrading the version of components, if it's useful */
7203
0
    if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPOSITE_LAST), H5T__upgrade_version_cb, &new_version) <
7204
0
        0)
7205
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADITER, FAIL, "iteration to upgrade datatype encoding version failed");
7206
7207
0
done:
7208
0
    FUNC_LEAVE_NOAPI(ret_value)
7209
0
} /* end H5T__upgrade_version() */
7210
7211
/*-------------------------------------------------------------------------
7212
 * Function:    H5T_set_version
7213
 *
7214
 * Purpose:     Set the encoding for a datatype to the version indicated by
7215
 *              the file's low bound if that is higher than the datatype's
7216
 *              version.
7217
 *
7218
 * Return:      Non-negative on success/Negative on failure
7219
 *
7220
 *-------------------------------------------------------------------------
7221
 */
7222
herr_t
7223
H5T_set_version(H5F_t *f, H5T_t *dt)
7224
0
{
7225
0
    unsigned vers;                /* The version */
7226
0
    herr_t   ret_value = SUCCEED; /* Return value */
7227
7228
0
    FUNC_ENTER_NOAPI(FAIL)
7229
7230
    /* Sanity check */
7231
0
    assert(f);
7232
0
    assert(dt);
7233
7234
0
    vers = H5O_dtype_ver_bounds[H5F_LOW_BOUND(f)];
7235
0
    if (vers > dt->shared->version) {
7236
        /* Upgrade the format version for the datatype */
7237
0
        if (H5T__upgrade_version(dt, vers) < 0)
7238
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade datatype encoding");
7239
0
    }
7240
7241
    /* Version bounds check */
7242
0
    if (dt->shared->version > H5O_dtype_ver_bounds[H5F_HIGH_BOUND(f)])
7243
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "Datatype version out of bounds");
7244
7245
0
done:
7246
0
    FUNC_LEAVE_NOAPI(ret_value)
7247
0
} /* end H5T_set_version() */
7248
7249
/*-------------------------------------------------------------------------
7250
 * Function:    H5T_patch_file
7251
 *
7252
 * Purpose:     Patch the top-level file pointers contained in dt to point
7253
 *              to f, if dt is a committed type.  This is possible because
7254
 *              the top-level file pointer can be closed out from under
7255
 *              dt while dt is contained in the shared file's cache.
7256
 *
7257
 * Return:      SUCCEED
7258
 *
7259
 *-------------------------------------------------------------------------
7260
 */
7261
herr_t
7262
H5T_patch_file(H5T_t *dt, H5F_t *f)
7263
10.9k
{
7264
10.9k
    herr_t ret_value = SUCCEED;
7265
7266
10.9k
    FUNC_ENTER_NOAPI(FAIL)
7267
7268
    /* Sanity check */
7269
10.9k
    assert(dt);
7270
10.9k
    assert(f);
7271
7272
10.9k
    if (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state) {
7273
0
        dt->oloc.file   = f;
7274
0
        dt->sh_loc.file = f;
7275
0
    } /* end if */
7276
7277
10.9k
done:
7278
10.9k
    FUNC_LEAVE_NOAPI(ret_value)
7279
10.9k
} /* end H5T_patch_file() */
7280
7281
/*-------------------------------------------------------------------------
7282
 * Function:    H5T_patch_vlen_file
7283
 *
7284
 * Purpose:     Patch the top-level file pointer contained in (dt->shared->u.vlen.file)
7285
 *              to point to file.  This is possible because
7286
 *              the top-level file pointer can be closed out from under
7287
 *              dt while dt is contained in the shared file's cache.
7288
 *
7289
 * Return:      SUCCEED
7290
 *
7291
 *-------------------------------------------------------------------------
7292
 */
7293
herr_t
7294
H5T_patch_vlen_file(H5T_t *dt, H5VL_object_t *file)
7295
11.6k
{
7296
11.6k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
7297
7298
    /* Sanity check */
7299
11.6k
    assert(dt);
7300
11.6k
    assert(dt->shared);
7301
11.6k
    assert(file);
7302
7303
11.6k
    if ((dt->shared->type == H5T_VLEN) && dt->shared->u.vlen.file != file)
7304
0
        dt->shared->u.vlen.file = file;
7305
7306
11.6k
    FUNC_LEAVE_NOAPI(SUCCEED)
7307
11.6k
} /* end H5T_patch_vlen_file() */
7308
7309
/*-------------------------------------------------------------------------
7310
 * Function:    H5T_own_vol_obj
7311
 *
7312
 * Purpose:     Transfers ownership of the supplied VOL object to the
7313
 *              datatype, the VOL object will be freed when the datatype
7314
 *              is closed.
7315
 *
7316
 * Return:      Non-negative on success/Negative on failure
7317
 *
7318
 *-------------------------------------------------------------------------
7319
 */
7320
herr_t
7321
H5T_own_vol_obj(H5T_t *dt, H5VL_object_t *vol_obj)
7322
619
{
7323
619
    herr_t ret_value = SUCCEED;
7324
7325
619
    FUNC_ENTER_NOAPI(FAIL)
7326
7327
    /* Sanity check */
7328
619
    assert(dt);
7329
619
    assert(dt->shared);
7330
619
    assert(vol_obj);
7331
7332
    /* Currently no support for owning multiple VOL objects, free the previous
7333
     * owned object.  Currently this is only used for holding open VOL objects
7334
     * used in the "loc" for vlens and references, so if this is being
7335
     * overwritten we don't need the old one anyways. */
7336
619
    if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
7337
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object");
7338
7339
    /* Take ownership */
7340
619
    dt->shared->owned_vol_obj = vol_obj;
7341
619
    (void)H5VL_object_inc_rc(vol_obj);
7342
7343
619
done:
7344
619
    FUNC_LEAVE_NOAPI(ret_value)
7345
619
} /* end H5T_own_vol_obj() */
7346
7347
/*-------------------------------------------------------------------------
7348
 * Function:    H5T__get_path_table_npaths
7349
 *
7350
 * Purpose:     Testing function to return the number of type conversion
7351
 *              paths currently stored in the type conversion path table
7352
 *              cache.
7353
 *
7354
 * Return:      Number of type conversion paths (can't fail)
7355
 *
7356
 *-------------------------------------------------------------------------
7357
 */
7358
int
7359
H5T__get_path_table_npaths(void)
7360
0
{
7361
0
    int ret_value = 0;
7362
7363
0
    FUNC_ENTER_PACKAGE_NOERR
7364
7365
0
    ret_value = H5T_g.npaths;
7366
7367
0
    FUNC_LEAVE_NOAPI(ret_value)
7368
0
}
7369
7370
/*-------------------------------------------------------------------------
7371
 * Function:    H5T_is_numeric_with_unusual_unused_bits
7372
 *
7373
 * Purpose:     Detect if a datatype is a numeric datatype (int, float, or
7374
 *              bitfield) with an unusual # of unused bits.  This means
7375
 *              that the precision (i.e. the # of bits used) is less than
7376
 *              the size of the datatype, at power-of-two boundaries.
7377
 *
7378
 * Return:      true/false on success, can't fail
7379
 *
7380
 *-------------------------------------------------------------------------
7381
 */
7382
bool
7383
H5T_is_numeric_with_unusual_unused_bits(const H5T_t *dt)
7384
8.08k
{
7385
8.08k
    bool ret_value = false;
7386
7387
8.08k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
7388
7389
    /* Sanity check */
7390
8.08k
    assert(dt);
7391
8.08k
    assert(dt->shared);
7392
7393
    /* Is the correct type? */
7394
8.08k
    if (H5T_INTEGER == dt->shared->type || H5T_FLOAT == dt->shared->type ||
7395
4.94k
        H5T_BITFIELD == dt->shared->type) {
7396
7397
        /* Has unused bits? */
7398
3.13k
        if (dt->shared->size > 1 && dt->shared->u.atomic.prec < (dt->shared->size * 8))
7399
            /* Unused bits are unusually large? */
7400
8
            ret_value =
7401
8
                (dt->shared->size * 8) > (2 * (dt->shared->u.atomic.prec + dt->shared->u.atomic.offset));
7402
3.13k
    }
7403
7404
8.08k
    FUNC_LEAVE_NOAPI(ret_value)
7405
8.08k
} /* end H5T_is_numeric_with_unusual_unused_bits() */