Coverage Report

Created: 2026-03-09 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tcompound.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 the functionality for compound datatypes
15
 *      in the H5T interface.
16
 */
17
18
/****************/
19
/* Module Setup */
20
/****************/
21
22
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
23
24
/***********/
25
/* Headers */
26
/***********/
27
#include "H5private.h"   /*generic functions        */
28
#include "H5Eprivate.h"  /*error handling       */
29
#include "H5Iprivate.h"  /*ID functions           */
30
#include "H5MMprivate.h" /*memory management        */
31
#include "H5Tpkg.h"      /*data-type functions        */
32
33
/****************/
34
/* Local Macros */
35
/****************/
36
37
/******************/
38
/* Local Typedefs */
39
/******************/
40
41
/********************/
42
/* Package Typedefs */
43
/********************/
44
45
/********************/
46
/* Local Prototypes */
47
/********************/
48
static herr_t H5T__pack(const H5T_t *dt);
49
static htri_t H5T__is_packed(const H5T_t *dt);
50
static H5T_t *H5T__reopen_member_type(const H5T_t *dt, unsigned membno);
51
52
/*********************/
53
/* Public Variables */
54
/*********************/
55
56
/*********************/
57
/* Package Variables */
58
/*********************/
59
60
/*****************************/
61
/* Library Private Variables */
62
/*****************************/
63
64
/*******************/
65
/* Local Variables */
66
/*******************/
67
68
/*-------------------------------------------------------------------------
69
 * Function:  H5Tget_member_offset
70
 *
71
 * Purpose: Returns the byte offset of the beginning of a member with
72
 *    respect to the beginning of the compound datatype datum.
73
 *
74
 * Return:  Success:  Byte offset.
75
 *
76
 *    Failure:  Zero. Zero is a valid offset, but this
77
 *        function will fail only if a call to
78
 *        H5Tget_member_dims() fails with the same
79
 *        arguments.
80
 *
81
 *-------------------------------------------------------------------------
82
 */
83
size_t
84
H5Tget_member_offset(hid_t type_id, unsigned membno)
85
0
{
86
0
    H5T_t *dt;        /* Datatype to query */
87
0
    size_t ret_value; /* Return value */
88
89
0
    FUNC_ENTER_API(0)
90
91
    /* Check args */
92
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
93
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound datatype");
94
0
    if (membno >= dt->shared->u.compnd.nmembs)
95
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number");
96
97
    /* Value */
98
0
    ret_value = H5T_GET_MEMBER_OFFSET(dt->shared, membno);
99
100
0
done:
101
0
    FUNC_LEAVE_API(ret_value)
102
0
} /* end H5Tget_member_offset() */
103
104
/*-------------------------------------------------------------------------
105
 * Function:  H5T_get_member_offset
106
 *
107
 * Purpose: Private function for H5Tget_member_offset.  Returns the byte
108
 *              offset of the beginning of a member with respect to the
109
 *              beginning of the compound datatype datum.
110
 *
111
 * Return:  Success:  Byte offset.
112
 *
113
 *    Failure:  Zero. Zero is a valid offset, but this
114
 *        function will fail only if a call to
115
 *        H5Tget_member_dims() fails with the same
116
 *        arguments.
117
 *
118
 *-------------------------------------------------------------------------
119
 */
120
size_t
121
H5T_get_member_offset(const H5T_t *dt, unsigned membno)
122
0
{
123
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
124
125
0
    assert(dt);
126
0
    assert(membno < dt->shared->u.compnd.nmembs);
127
128
0
    FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].offset)
129
0
} /* end H5T_get_member_offset() */
130
131
/*-------------------------------------------------------------------------
132
 * Function:  H5Tget_member_class
133
 *
134
 * Purpose: Returns the datatype class of a member of a compound datatype.
135
 *
136
 * Return:  Success: Non-negative
137
 *
138
 *    Failure: H5T_NO_CLASS
139
 *
140
 *-------------------------------------------------------------------------
141
 */
142
H5T_class_t
143
H5Tget_member_class(hid_t type_id, unsigned membno)
144
0
{
145
0
    H5T_t      *dt;        /* Datatype to query */
146
0
    H5T_class_t ret_value; /* Return value */
147
148
0
    FUNC_ENTER_API(H5T_NO_CLASS)
149
150
    /* Check args */
151
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
152
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound datatype");
153
0
    if (membno >= dt->shared->u.compnd.nmembs)
154
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number");
155
156
    /* Get the type's class.  We have to use this function to get type class
157
     *  because of the concern of variable-length string.
158
     */
159
0
    ret_value = H5T_GET_CLASS(dt->shared->u.compnd.memb[membno].type->shared, false);
160
161
0
done:
162
0
    FUNC_LEAVE_API(ret_value)
163
0
} /* end H5Tget_member_class() */
164
165
/*-------------------------------------------------------------------------
166
 * Function:  H5Tget_member_type
167
 *
168
 * Purpose: Returns the datatype of the specified member. The caller
169
 *    should invoke H5Tclose() to release resources associated with
170
 *    the type.
171
 *
172
 * Return:  Success:  An OID of a copy of the member datatype;
173
 *        modifying the returned datatype does not
174
 *        modify the member type.
175
 *
176
 *    Failure:  H5I_INVALID_HID
177
 *
178
 *-------------------------------------------------------------------------
179
 */
180
hid_t
181
H5Tget_member_type(hid_t type_id, unsigned membno)
182
0
{
183
0
    H5T_t *dt;             /* Datatype to query */
184
0
    H5T_t *memb_dt = NULL; /* Member datatype */
185
0
    hid_t  ret_value;      /* Return value */
186
187
0
    FUNC_ENTER_API(H5I_INVALID_HID)
188
189
    /* Check args */
190
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
191
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a compound datatype");
192
0
    if (membno >= dt->shared->u.compnd.nmembs)
193
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid member number");
194
195
    /* Retrieve the datatype for the member */
196
0
    if (NULL == (memb_dt = H5T__reopen_member_type(dt, membno)))
197
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to retrieve member type");
198
199
    /* Get an ID for the datatype */
200
0
    if ((ret_value = H5I_register(H5I_DATATYPE, memb_dt, true)) < 0)
201
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable register datatype ID");
202
203
0
done:
204
0
    if (ret_value < 0)
205
0
        if (memb_dt && H5T_close(memb_dt) < 0)
206
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, H5I_INVALID_HID, "can't close datatype");
207
208
0
    FUNC_LEAVE_API(ret_value)
209
0
} /* end H5Tget_member_type() */
210
211
/*-------------------------------------------------------------------------
212
 * Function:  H5T_get_member_type
213
 *
214
 * Purpose:     Returns a copy of the data type of the specified member.
215
 *
216
 * Return:  Success:  A copy of the member datatype;
217
 *        modifying the returned datatype does not
218
 *        modify the member type.
219
 *
220
 *    Failure:        NULL
221
 *
222
 *-------------------------------------------------------------------------
223
 */
224
H5T_t *
225
H5T_get_member_type(const H5T_t *dt, unsigned membno)
226
0
{
227
0
    H5T_t *ret_value = NULL; /* Return value */
228
229
0
    FUNC_ENTER_NOAPI(NULL)
230
231
    /* Sanity checks */
232
0
    assert(dt);
233
0
    assert(membno < dt->shared->u.compnd.nmembs);
234
235
    /* Copy datatype */
236
0
    if (NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, H5T_COPY_TRANSIENT)))
237
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy member datatype");
238
239
0
done:
240
0
    FUNC_LEAVE_NOAPI(ret_value)
241
0
} /* end H5T_get_member_type() */
242
243
/*-------------------------------------------------------------------------
244
 * Function:  H5T__reopen_member_type
245
 *
246
 * Purpose: Private function for H5Tget_member_type.  Returns a re-opened
247
 *              copy of the data type of the specified member.
248
 *
249
 * Return:  Success:  A copy of the member datatype;
250
 *        modifying the returned datatype does not
251
 *        modify the member type.
252
 *
253
 *    Failure:        NULL
254
 *
255
 *-------------------------------------------------------------------------
256
 */
257
static H5T_t *
258
H5T__reopen_member_type(const H5T_t *dt, unsigned membno)
259
0
{
260
0
    H5T_t *ret_value = NULL; /* Return value */
261
262
0
    FUNC_ENTER_PACKAGE
263
264
    /* Sanity checks */
265
0
    assert(dt);
266
0
    assert(membno < dt->shared->u.compnd.nmembs);
267
268
    /* Copy datatype, possibly re-opening it */
269
0
    if (NULL == (ret_value = H5T_copy_reopen(dt->shared->u.compnd.memb[membno].type)))
270
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to reopen member datatype");
271
272
0
done:
273
0
    FUNC_LEAVE_NOAPI(ret_value)
274
0
} /* end H5T__reopen_member_type() */
275
276
/*-------------------------------------------------------------------------
277
 * Function:  H5T__get_member_size
278
 *
279
 * Purpose: Returns the size of the specified member.
280
 *
281
 * Return:  Success:  The size in bytes of the member's datatype.
282
 *    Failure:        0
283
 *
284
 *-------------------------------------------------------------------------
285
 */
286
size_t
287
H5T__get_member_size(const H5T_t *dt, unsigned membno)
288
0
{
289
0
    FUNC_ENTER_PACKAGE_NOERR
290
291
0
    assert(dt);
292
0
    assert(membno < dt->shared->u.compnd.nmembs);
293
294
0
    FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].type->shared->size)
295
0
} /* end H5T__get_member_size() */
296
297
/*-------------------------------------------------------------------------
298
 * Function:  H5Tinsert
299
 *
300
 * Purpose: Adds another member to the compound datatype PARENT_ID.  The
301
 *    new member has a NAME which must be unique within the
302
 *    compound datatype. The OFFSET argument defines the start of
303
 *    the member in an instance of the compound datatype, and
304
 *    MEMBER_ID is the type of the new member.
305
 *
306
 * Return:  Success:  Non-negative, the PARENT_ID compound data
307
 *        type is modified to include a copy of the
308
 *        member type MEMBER_ID.
309
 *
310
 *    Failure:  Negative
311
 *
312
 * Errors:
313
 *
314
 *-------------------------------------------------------------------------
315
 */
316
herr_t
317
H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id)
318
0
{
319
0
    H5T_t *parent;              /* The compound parent datatype */
320
0
    H5T_t *member;              /* The member datatype  */
321
0
    herr_t ret_value = SUCCEED; /* Return value */
322
323
0
    FUNC_ENTER_API(FAIL)
324
325
    /* Check args */
326
0
    if (parent_id == member_id)
327
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself");
328
0
    if (NULL == (parent = (H5T_t *)H5I_object_verify(parent_id, H5I_DATATYPE)) ||
329
0
        H5T_COMPOUND != parent->shared->type)
330
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype");
331
0
    if (H5T_STATE_TRANSIENT != parent->shared->state)
332
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only");
333
0
    if (!name || !*name)
334
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name");
335
0
    if (NULL == (member = (H5T_t *)H5I_object_verify(member_id, H5I_DATATYPE)))
336
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
337
338
    /* Insert */
339
0
    if (H5T__insert(parent, name, offset, member) < 0)
340
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member");
341
342
0
done:
343
0
    FUNC_LEAVE_API(ret_value)
344
0
} /* end H5Tinsert() */
345
346
/*-------------------------------------------------------------------------
347
 * Function:  H5Tpack
348
 *
349
 * Purpose: Recursively removes padding from within a compound datatype
350
 *    to make it more efficient (space-wise) to store that data.
351
 *
352
 * Return:  Non-negative on success/Negative on failure
353
 *
354
 *-------------------------------------------------------------------------
355
 */
356
herr_t
357
H5Tpack(hid_t type_id)
358
0
{
359
0
    H5T_t *dt;                  /* Datatype to modify */
360
0
    herr_t ret_value = SUCCEED; /* Return value */
361
362
0
    FUNC_ENTER_API(FAIL)
363
364
    /* Check args */
365
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) ||
366
0
        H5T_detect_class(dt, H5T_COMPOUND, true) <= 0)
367
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype");
368
369
    /* Pack */
370
0
    if (H5T__pack(dt) < 0)
371
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound datatype");
372
373
0
done:
374
0
    FUNC_LEAVE_API(ret_value)
375
0
} /* end H5Tpack() */
376
377
/*-------------------------------------------------------------------------
378
 * Function:  H5T__insert
379
 *
380
 * Purpose: Adds a new MEMBER to the compound datatype PARENT.  The new
381
 *    member will have a NAME that is unique within PARENT and an
382
 *    instance of PARENT will have the member begin at byte offset
383
 *    OFFSET from the beginning.
384
 *
385
 * Return:  Non-negative on success/Negative on failure
386
 *
387
 *-------------------------------------------------------------------------
388
 */
389
herr_t
390
H5T__insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
391
0
{
392
0
    unsigned idx; /* Index of member to insert */
393
0
    size_t   total_size;
394
0
    unsigned i;                   /* Local index variable */
395
0
    herr_t   ret_value = SUCCEED; /* Return value */
396
397
0
    FUNC_ENTER_PACKAGE
398
399
    /* check args */
400
0
    assert(parent && H5T_COMPOUND == parent->shared->type);
401
0
    assert(H5T_STATE_TRANSIENT == parent->shared->state);
402
0
    assert(member);
403
0
    assert(name && *name);
404
405
    /* Does NAME already exist in PARENT? */
406
0
    for (i = 0; i < parent->shared->u.compnd.nmembs; i++)
407
0
        if (!strcmp(parent->shared->u.compnd.memb[i].name, name))
408
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member name is not unique");
409
410
    /* Does the new member overlap any existing member ? */
411
0
    total_size = member->shared->size;
412
0
    for (i = 0; i < parent->shared->u.compnd.nmembs; i++)
413
0
        if ((offset <= parent->shared->u.compnd.memb[i].offset &&
414
0
             (offset + total_size) > parent->shared->u.compnd.memb[i].offset) ||
415
0
            (parent->shared->u.compnd.memb[i].offset <= offset &&
416
0
             (parent->shared->u.compnd.memb[i].offset + parent->shared->u.compnd.memb[i].size) > offset))
417
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member");
418
419
    /* Does the new member overlap the end of the compound type? */
420
0
    if ((offset + total_size) > parent->shared->size)
421
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member extends past end of compound type");
422
423
    /* Increase member array if necessary */
424
0
    if (parent->shared->u.compnd.nmembs >= parent->shared->u.compnd.nalloc) {
425
0
        unsigned     na = MAX(1, parent->shared->u.compnd.nalloc * 2);
426
0
        H5T_cmemb_t *x = (H5T_cmemb_t *)H5MM_realloc(parent->shared->u.compnd.memb, na * sizeof(H5T_cmemb_t));
427
428
0
        if (!x)
429
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed");
430
0
        parent->shared->u.compnd.nalloc = na;
431
0
        parent->shared->u.compnd.memb   = x;
432
0
    } /* end if */
433
434
    /* Add member to end of member array */
435
0
    idx                                       = parent->shared->u.compnd.nmembs;
436
0
    parent->shared->u.compnd.memb[idx].offset = offset;
437
0
    parent->shared->u.compnd.memb[idx].size   = total_size;
438
0
    if (NULL == (parent->shared->u.compnd.memb[idx].name = H5MM_xstrdup(name)))
439
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't duplicate name string");
440
0
    if (NULL == (parent->shared->u.compnd.memb[idx].type = H5T_copy(member, H5T_COPY_ALL)))
441
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "couldn't copy datatype");
442
443
0
    parent->shared->u.compnd.sorted = H5T_SORT_NONE;
444
0
    parent->shared->u.compnd.nmembs++;
445
0
    parent->shared->u.compnd.memb_size += total_size;
446
447
    /* It should not be possible to get this far if the type is already packed
448
     * - the new member would overlap something */
449
0
    assert(!(parent->shared->u.compnd.packed));
450
451
    /* Determine if the compound datatype becomes packed */
452
0
    H5T__update_packed(parent);
453
454
    /* Set the "force conversion" flag if the field's datatype indicates */
455
0
    if (member->shared->force_conv == true)
456
0
        parent->shared->force_conv = true;
457
458
    /* Check for member having a later version than the parent */
459
0
    if (parent->shared->version < member->shared->version)
460
        /* Upgrade parent datatype (and all other members also) */
461
        /* (can't use a partial datatype and later versions of the format are
462
         *  more efficient, so might as well upgrade all members also... -QAK)
463
         */
464
0
        if (H5T__upgrade_version(parent, member->shared->version) < 0)
465
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade member encoding version");
466
467
0
done:
468
0
    FUNC_LEAVE_NOAPI(ret_value)
469
0
} /* end H5T__insert() */
470
471
/*-------------------------------------------------------------------------
472
 * Function:  H5T__pack
473
 *
474
 * Purpose: Recursively packs a compound datatype by removing padding
475
 *    bytes. This is done in place (that is, destructively).
476
 *
477
 * Return:  Non-negative on success/Negative on failure
478
 *
479
 *-------------------------------------------------------------------------
480
 */
481
static herr_t
482
H5T__pack(const H5T_t *dt)
483
0
{
484
0
    herr_t ret_value = SUCCEED; /* Return value */
485
486
0
    FUNC_ENTER_PACKAGE
487
488
0
    assert(dt);
489
490
0
    if (H5T_detect_class(dt, H5T_COMPOUND, false) > 0) {
491
        /* If datatype has been packed, skip packing it and indicate success */
492
0
        if (true == H5T__is_packed(dt))
493
0
            HGOTO_DONE(SUCCEED);
494
495
        /* Check for packing unmodifiable datatype */
496
0
        if (H5T_STATE_TRANSIENT != dt->shared->state)
497
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is read-only");
498
499
0
        if (dt->shared->parent) {
500
0
            if (H5T__pack(dt->shared->parent) < 0)
501
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack parent of datatype");
502
503
            /* Adjust size of datatype appropriately */
504
0
            if (dt->shared->type == H5T_ARRAY)
505
0
                dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
506
0
            else if (dt->shared->type == H5T_COMPLEX)
507
0
                dt->shared->size = 2 * dt->shared->parent->shared->size;
508
0
            else if (dt->shared->type != H5T_VLEN)
509
0
                dt->shared->size = dt->shared->parent->shared->size;
510
0
        } /* end if */
511
0
        else if (dt->shared->type == H5T_COMPOUND) {
512
0
            size_t   offset; /* Offset of member */
513
0
            unsigned i;      /* Local index variable */
514
515
            /* Recursively pack the members */
516
0
            for (i = 0; i < dt->shared->u.compnd.nmembs; i++) {
517
0
                if (H5T__pack(dt->shared->u.compnd.memb[i].type) < 0)
518
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
519
0
                                "unable to pack part of a compound datatype");
520
521
                /* Update the member size */
522
0
                dt->shared->u.compnd.memb[i].size = (dt->shared->u.compnd.memb[i].type)->shared->size;
523
0
            } /* end for */
524
525
            /* Remove padding between members */
526
0
            if (H5T__sort_value(dt, NULL) < 0)
527
0
                HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOMPARE, FAIL, "value sort failed");
528
0
            for (i = 0, offset = 0; i < dt->shared->u.compnd.nmembs; i++) {
529
0
                dt->shared->u.compnd.memb[i].offset = offset;
530
0
                offset += dt->shared->u.compnd.memb[i].size;
531
0
            }
532
533
            /* Change total size */
534
0
            dt->shared->size = MAX(1, offset);
535
536
            /* Mark the type as packed now */
537
0
            dt->shared->u.compnd.packed = true;
538
0
        } /* end if */
539
0
    }     /* end if */
540
541
0
done:
542
0
    FUNC_LEAVE_NOAPI(ret_value)
543
0
} /* end H5T__pack() */
544
545
/*-------------------------------------------------------------------------
546
 * Function:  H5T__is_packed
547
 *
548
 * Purpose: Checks whether a datatype which is compound (or has compound
549
 *              components) is packed.
550
 *
551
 * Return:  Non-negative on success/Negative on failure
552
 *
553
 *-------------------------------------------------------------------------
554
 */
555
static htri_t
556
H5T__is_packed(const H5T_t *dt)
557
0
{
558
0
    htri_t ret_value = true; /* Return value */
559
560
0
    FUNC_ENTER_PACKAGE_NOERR
561
562
0
    assert(dt);
563
564
    /* Go up the chain as far as possible */
565
0
    while (dt->shared->parent)
566
0
        dt = dt->shared->parent;
567
568
    /* If this is a compound datatype, check if it is packed */
569
0
    if (dt->shared->type == H5T_COMPOUND)
570
0
        ret_value = (htri_t)(dt->shared->u.compnd.packed);
571
572
0
    FUNC_LEAVE_NOAPI(ret_value)
573
0
} /* end H5T__is_packed() */
574
575
/*-------------------------------------------------------------------------
576
 * Function:  H5T__update_packed
577
 *
578
 * Purpose: Checks whether a datatype which is compound became packed
579
 *              after recent changes.  This function does not assume that
580
 *              the status of the "packed" field is correct, and sets
581
 *              this field to the correct value.
582
 *
583
 * Return:  void
584
 *
585
 *-------------------------------------------------------------------------
586
 */
587
void
588
H5T__update_packed(const H5T_t *dt)
589
0
{
590
0
    unsigned i; /* Index */
591
592
0
    FUNC_ENTER_PACKAGE_NOERR
593
594
0
    assert(dt);
595
0
    assert(dt->shared->type == H5T_COMPOUND);
596
597
    /* First check if all space is used in the "top level" type */
598
0
    if (dt->shared->size == dt->shared->u.compnd.memb_size) {
599
        /* Set the packed flag to true */
600
0
        dt->shared->u.compnd.packed = true;
601
602
        /* Now check if all members are packed */
603
0
        for (i = 0; i < dt->shared->u.compnd.nmembs; i++)
604
0
            if (!H5T__is_packed(dt->shared->u.compnd.memb[i].type)) {
605
0
                dt->shared->u.compnd.packed = false;
606
0
                break;
607
0
            } /* end if */
608
0
    }         /* end if */
609
0
    else
610
0
        dt->shared->u.compnd.packed = false;
611
612
0
    FUNC_LEAVE_NOAPI_VOID
613
0
} /* end H5T__update_packed() */