Coverage Report

Created: 2026-03-09 06:11

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