Coverage Report

Created: 2026-10-28 18:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5I.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
 * H5I.c - Public routines for handling IDs
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
21
#include "H5Imodule.h" /* This source code file is part of the H5I module */
22
23
/***********/
24
/* Headers */
25
/***********/
26
#include "H5private.h"   /* Generic Functions                        */
27
#include "H5Eprivate.h"  /* Error handling                           */
28
#include "H5Fprivate.h"  /* Files                                    */
29
#include "H5Ipkg.h"      /* IDs                                      */
30
#include "H5MMprivate.h" /* Memory management                        */
31
#include "H5Pprivate.h"  /* Property lists                           */
32
33
/****************/
34
/* Local Macros */
35
/****************/
36
37
/******************/
38
/* Local Typedefs */
39
/******************/
40
41
typedef struct {
42
    H5I_search_func_t app_cb;  /* Application's callback routine */
43
    void             *app_key; /* Application's "key" (user data) */
44
    void             *ret_obj; /* Object to return */
45
} H5I_search_ud_t;
46
47
typedef struct {
48
    H5I_iterate_func_t op;      /* Application's callback routine */
49
    void              *op_data; /* Application's user data */
50
} H5I_iterate_pub_ud_t;
51
52
/********************/
53
/* Package Typedefs */
54
/********************/
55
56
/********************/
57
/* Local Prototypes */
58
/********************/
59
60
static int H5I__search_cb(void *obj, hid_t id, void *_udata);
61
static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata);
62
63
/*********************/
64
/* Package Variables */
65
/*********************/
66
67
/*****************************/
68
/* Library Private Variables */
69
/*****************************/
70
71
/*******************/
72
/* Local Variables */
73
/*******************/
74
75
/*-------------------------------------------------------------------------
76
 * Function:    H5Iregister_type2
77
 *
78
 * Purpose:     Public interface to H5I_register_type2.  Creates a new type
79
 *              of ID's to give out.  A specific number (RESERVED) of type
80
 *              entries may be reserved to enable "constant" values to be handed
81
 *              out which are valid IDs in the type, but which do not map to any
82
 *              data structures and are not allocated dynamically later.
83
 *              FREE_FUNC is called with an object pointer when the object is
84
 *              removed from the type.
85
 *
86
 * Return:      Success:    Type ID of the new type
87
 *              Failure:    H5I_BADID
88
 *
89
 *-------------------------------------------------------------------------
90
 */
91
H5I_type_t
92
H5Iregister_type2(unsigned reserved, H5I_free_t free_func)
93
0
{
94
0
    H5I_type_t ret_value = H5I_BADID;
95
96
0
    FUNC_ENTER_API(H5I_BADID)
97
98
0
    if (H5I_BADID == (ret_value = H5I__register_type_common(reserved, free_func)))
99
0
        HGOTO_ERROR(H5E_ID, H5E_CANTINIT, H5I_BADID, "can't initialize ID class");
100
101
0
done:
102
0
    FUNC_LEAVE_API(ret_value)
103
0
} /* end H5Iregister_type2() */
104
105
/*-------------------------------------------------------------------------
106
 * Function:    H5Itype_exists
107
 *
108
 * Purpose:     Query function to inform the user if a given type is
109
 *              currently registered with the library.
110
 *
111
 * Return:      true/false/FAIL
112
 *
113
 *-------------------------------------------------------------------------
114
 */
115
htri_t
116
H5Itype_exists(H5I_type_t type)
117
0
{
118
0
    htri_t ret_value = true; /* Return value */
119
120
0
    FUNC_ENTER_API(FAIL)
121
122
    /* Validate parameter */
123
0
    if (H5I_IS_LIB_TYPE(type))
124
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "cannot call public function on library type");
125
0
    if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
126
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
127
128
0
    if (NULL == H5I_type_info_array_g[type])
129
0
        ret_value = false;
130
131
0
done:
132
0
    FUNC_LEAVE_API(ret_value)
133
0
} /* end H5Itype_exists() */
134
135
/*-------------------------------------------------------------------------
136
 * Function:    H5Inmembers
137
 *
138
 * Purpose:     Returns the number of members in a type.  Public interface to
139
 *              H5I_nmembers.  The public interface throws an error if the
140
 *              supplied type does not exist.  This is different than the
141
 *              private interface, which will just return 0.
142
 *
143
 * Return:      SUCCEED/FAIL
144
 *
145
 *-------------------------------------------------------------------------
146
 */
147
herr_t
148
H5Inmembers(H5I_type_t type, hsize_t *num_members)
149
0
{
150
0
    herr_t ret_value = SUCCEED; /* Return value */
151
152
0
    FUNC_ENTER_API(FAIL)
153
154
0
    if (H5I_IS_LIB_TYPE(type))
155
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "cannot call public function on library type");
156
157
    /* Validate parameters.  This needs to be done here, instead of letting
158
     * the private interface handle it, because the public interface throws
159
     * an error when the supplied type does not exist.
160
     */
161
0
    if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
162
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
163
0
    if (NULL == H5I_type_info_array_g[type])
164
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist");
165
166
0
    if (num_members) {
167
0
        int64_t members;
168
169
0
        if ((members = H5I_nmembers(type)) < 0)
170
0
            HGOTO_ERROR(H5E_ID, H5E_CANTCOUNT, FAIL, "can't compute number of members");
171
172
0
        H5_CHECKED_ASSIGN(*num_members, hsize_t, members, int64_t);
173
0
    }
174
175
0
done:
176
0
    FUNC_LEAVE_API(ret_value)
177
0
} /* end H5Inmembers() */
178
179
/*-------------------------------------------------------------------------
180
 * Function:    H5Iclear_type
181
 *
182
 * Purpose:     Removes all objects from the type, calling the free
183
 *              function for each object regardless of the reference count.
184
 *              Public interface to H5I_clear_type.
185
 *
186
 * Return:      SUCCEED/FAIL
187
 *
188
 *-------------------------------------------------------------------------
189
 */
190
herr_t
191
H5Iclear_type(H5I_type_t type, bool force)
192
0
{
193
0
    herr_t ret_value = FAIL; /* Return value */
194
195
0
    FUNC_ENTER_API(FAIL)
196
197
0
    if (H5I_IS_LIB_TYPE(type))
198
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "cannot call public function on library type");
199
200
0
    ret_value = H5I_clear_type(type, force, true);
201
202
0
done:
203
0
    FUNC_LEAVE_API(ret_value)
204
0
} /* end H5Iclear_type() */
205
206
/*-------------------------------------------------------------------------
207
 * Function:    H5Idestroy_type
208
 *
209
 * Purpose:     Destroys a type along with all IDs in that type
210
 *              regardless of their reference counts. Destroying IDs
211
 *              involves calling the free-func for each ID's object and
212
 *              then adding the ID struct to the ID free list.  Public
213
 *              interface to H5I__destroy_type.
214
 *
215
 * Return:      SUCCEED/FAIL
216
 *
217
 *-------------------------------------------------------------------------
218
 */
219
herr_t
220
H5Idestroy_type(H5I_type_t type)
221
0
{
222
0
    herr_t ret_value = FAIL; /* Return value */
223
224
0
    FUNC_ENTER_API(FAIL)
225
226
0
    if (H5I_IS_LIB_TYPE(type))
227
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "cannot call public function on library type");
228
229
0
    ret_value = H5I__destroy_type(type);
230
231
0
done:
232
0
    FUNC_LEAVE_API(ret_value)
233
0
} /* end H5Idestroy_type() */
234
235
/*-------------------------------------------------------------------------
236
 * Function:    H5Iregister
237
 *
238
 * Purpose:     Register an object.
239
 *
240
 * Return:      Success:    New object ID
241
 *              Failure:    H5I_INVALID_HID
242
 *
243
 *-------------------------------------------------------------------------
244
 */
245
hid_t
246
H5Iregister(H5I_type_t type, const void *object)
247
0
{
248
0
    hid_t ret_value = H5I_INVALID_HID; /* Return value */
249
250
0
    FUNC_ENTER_API(H5I_INVALID_HID)
251
252
0
    if (H5I_IS_LIB_TYPE(type))
253
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, H5I_INVALID_HID, "cannot call public function on library type");
254
255
    /* Register the object */
256
0
    if ((ret_value = H5I__register(type, object, true, NULL, NULL)) < 0)
257
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object");
258
259
0
done:
260
0
    FUNC_LEAVE_API(ret_value)
261
0
} /* end H5Iregister() */
262
263
/*-------------------------------------------------------------------------
264
 * Function:    H5Iregister_future
265
 *
266
 * Purpose:     Register a "future" object.
267
 *
268
 * Return:      Success:    New future object ID
269
 *              Failure:    H5I_INVALID_HID
270
 *
271
 *-------------------------------------------------------------------------
272
 */
273
hid_t
274
H5Iregister_future(H5I_type_t type, const void *object, H5I_future_realize_func_t realize_cb,
275
                   H5I_future_discard_func_t discard_cb)
276
0
{
277
0
    hid_t ret_value = H5I_INVALID_HID; /* Return value */
278
279
0
    FUNC_ENTER_API(H5I_INVALID_HID)
280
281
    /* Check arguments */
282
0
    if (NULL == realize_cb)
283
0
        HGOTO_ERROR(H5E_ID, H5E_BADVALUE, H5I_INVALID_HID, "NULL pointer for realize_cb not allowed");
284
0
    if (NULL == discard_cb)
285
0
        HGOTO_ERROR(H5E_ID, H5E_BADVALUE, H5I_INVALID_HID, "NULL pointer for realize_cb not allowed");
286
287
    /* Register the future object */
288
0
    if ((ret_value = H5I__register(type, object, true, realize_cb, discard_cb)) < 0)
289
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object");
290
291
0
done:
292
0
    FUNC_LEAVE_API(ret_value)
293
0
} /* end H5Iregister_future() */
294
295
/*-------------------------------------------------------------------------
296
 * Function:    H5Iobject_verify
297
 *
298
 * Purpose:     Find an object pointer for the specified ID, verifying that
299
 *              its in a particular type.  Public interface to
300
 *              H5I_object_verify.
301
 *
302
 * Return:      Success:    Non-NULL object pointer associated with the
303
 *                          specified ID.
304
 *              Failure:    NULL
305
 *
306
 *-------------------------------------------------------------------------
307
 */
308
void *
309
H5Iobject_verify(hid_t id, H5I_type_t type)
310
0
{
311
0
    void *ret_value = NULL; /* Return value */
312
313
0
    FUNC_ENTER_API(NULL)
314
315
    /* Validate parameters */
316
0
    if (H5I_IS_LIB_TYPE(type))
317
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, NULL, "cannot call public function on library type");
318
0
    if (type < 1 || (int)type >= H5I_next_type_g)
319
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, NULL, "identifier has invalid type");
320
321
0
    ret_value = H5I_object_verify(id, type);
322
323
0
done:
324
0
    FUNC_LEAVE_API(ret_value)
325
0
} /* end H5Iobject_verify() */
326
327
/*-------------------------------------------------------------------------
328
 * Function:    H5Iget_type
329
 *
330
 * Purpose:     The public version of H5I_get_type(), obtains a type number
331
 *              when given an ID.  The ID need not be the ID of an
332
 *              object which currently exists because the type number is
333
 *              encoded as part of the ID.
334
 *
335
 * Return:      Success:    A positive integer (corresponding to an H5I_type_t
336
 *                          enum value for library ID types, but not for user
337
 *                          ID types).
338
 *              Failure:    H5I_BADID
339
 *
340
 *-------------------------------------------------------------------------
341
 */
342
H5I_type_t
343
H5Iget_type(hid_t id)
344
303k
{
345
303k
    H5I_type_t ret_value = H5I_BADID; /* Return value */
346
347
607k
    FUNC_ENTER_API(H5I_BADID)
348
349
607k
    ret_value = H5I_get_type(id);
350
351
607k
    if (ret_value <= H5I_BADID || (int)ret_value >= H5I_next_type_g || NULL == H5I_object(id))
352
0
        HGOTO_DONE(H5I_BADID);
353
354
303k
done:
355
303k
    FUNC_LEAVE_API(ret_value)
356
607k
} /* end H5Iget_type() */
357
358
/*-------------------------------------------------------------------------
359
 * Function:    H5Iremove_verify
360
 *
361
 * Purpose:     Removes the specified ID from its type, first checking that the
362
 *              type of the ID and the type type are the same.  Public interface to
363
 *              H5I__remove_verify.
364
 *
365
 * Return:      Success:    A pointer to the object that was removed, the
366
 *                          same pointer which would have been found by
367
 *                          calling H5I_object().
368
 *              Failure:    NULL
369
 *
370
 *-------------------------------------------------------------------------
371
 */
372
void *
373
H5Iremove_verify(hid_t id, H5I_type_t type)
374
0
{
375
0
    void *ret_value = NULL; /* Return value */
376
377
0
    FUNC_ENTER_API(NULL)
378
379
0
    if (H5I_IS_LIB_TYPE(type))
380
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, NULL, "cannot call public function on library type");
381
382
    /* Remove the id */
383
0
    ret_value = H5I__remove_verify(id, type);
384
385
0
done:
386
0
    FUNC_LEAVE_API(ret_value)
387
0
} /* end H5Iremove_verify() */
388
389
/*-------------------------------------------------------------------------
390
 * Function:    H5Idec_ref
391
 *
392
 * Purpose:     Decrements the number of references outstanding for an ID.
393
 *              If the reference count for an ID reaches zero, the object
394
 *              will be closed.
395
 *
396
 * Return:      Success:    New reference count
397
 *              Failure:    -1
398
 *
399
 *-------------------------------------------------------------------------
400
 */
401
int
402
H5Idec_ref(hid_t id)
403
0
{
404
0
    int ret_value = 0; /* Return value */
405
406
0
    FUNC_ENTER_API((-1))
407
408
    /* Check arguments */
409
0
    if (id < 0)
410
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "invalid ID");
411
412
    /* Do actual decrement operation */
413
0
    if ((ret_value = H5I_dec_app_ref(id)) < 0)
414
0
        HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't decrement ID ref count");
415
416
0
done:
417
0
    FUNC_LEAVE_API(ret_value)
418
0
} /* end H5Idec_ref() */
419
420
/*-------------------------------------------------------------------------
421
 * Function:    H5Iinc_ref
422
 *
423
 * Purpose:     Increments the number of references outstanding for an ID.
424
 *
425
 * Return:      Success:    New reference count
426
 *              Failure:    -1
427
 *
428
 *-------------------------------------------------------------------------
429
 */
430
int
431
H5Iinc_ref(hid_t id)
432
70.6k
{
433
70.6k
    int ret_value = -1; /* Return value */
434
435
141k
    FUNC_ENTER_API((-1))
436
437
    /* Check arguments */
438
141k
    if (id < 0)
439
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "invalid ID");
440
441
    /* Do actual increment operation */
442
70.6k
    if ((ret_value = H5I_inc_ref(id, true)) < 0)
443
0
        HGOTO_ERROR(H5E_ID, H5E_CANTINC, (-1), "can't increment ID ref count");
444
445
70.6k
done:
446
70.6k
    FUNC_LEAVE_API(ret_value)
447
70.6k
} /* end H5Iinc_ref() */
448
449
/*-------------------------------------------------------------------------
450
 * Function:    H5Iget_ref
451
 *
452
 * Purpose:     Retrieves the number of references outstanding for an ID.
453
 *
454
 * Return:      Success:    Reference count
455
 *              Failure:    -1
456
 *
457
 *-------------------------------------------------------------------------
458
 */
459
int
460
H5Iget_ref(hid_t id)
461
0
{
462
0
    int ret_value = -1; /* Return value */
463
464
0
    FUNC_ENTER_API((-1))
465
466
    /* Check arguments */
467
0
    if (id < 0)
468
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "invalid ID");
469
470
    /* Do actual retrieve operation */
471
0
    if ((ret_value = H5I_get_ref(id, true)) < 0)
472
0
        HGOTO_ERROR(H5E_ID, H5E_CANTGET, (-1), "can't get ID ref count");
473
474
0
done:
475
0
    FUNC_LEAVE_API(ret_value)
476
0
} /* end H5Iget_ref() */
477
478
/*-------------------------------------------------------------------------
479
 * Function:    H5Iinc_type_ref
480
 *
481
 * Purpose:     Increments the number of references outstanding for an ID type.
482
 *
483
 * Return:      Success:    New reference count
484
 *              Failure:    -1
485
 *
486
 *-------------------------------------------------------------------------
487
 */
488
int
489
H5Iinc_type_ref(H5I_type_t type)
490
0
{
491
0
    int ret_value = -1; /* Return value */
492
493
0
    FUNC_ENTER_API((-1))
494
495
    /* Check arguments */
496
0
    if (type <= 0 || (int)type >= H5I_next_type_g)
497
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "invalid ID type");
498
0
    if (H5I_IS_LIB_TYPE(type))
499
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "cannot call public function on library type");
500
501
    /* Do actual increment operation */
502
0
    if ((ret_value = H5I__inc_type_ref(type)) < 0)
503
0
        HGOTO_ERROR(H5E_ID, H5E_CANTINC, (-1), "can't increment ID type ref count");
504
505
0
done:
506
0
    FUNC_LEAVE_API(ret_value)
507
0
} /* end H5Iinc_ref() */
508
509
/*-------------------------------------------------------------------------
510
 * Function:    H5Idec_type_ref
511
 *
512
 * Purpose:     Decrements the reference count on an entire type of IDs.
513
 *              If the type reference count becomes zero then the type is
514
 *              destroyed along with all IDs in that type regardless of
515
 *              their reference counts. Destroying IDs involves calling
516
 *              the free-func for each ID's object and then adding the ID
517
 *              struct to the ID free list.  Public interface to
518
 *              H5I_dec_type_ref.
519
 *              Returns the number of references to the type on success; a
520
 *              return value of 0 means that the type will have to be
521
 *              re-initialized before it can be used again (and should probably
522
 *              be set to H5I_UNINIT).
523
 *
524
 * NOTE:        Using an error type to also represent a count is semantially
525
 *              incorrect. We should consider fixing this in a future major
526
 *              release (DER).
527
 *
528
 * Return:      Success:    Number of references to type
529
 *              Failure:    -1
530
 *
531
 *-------------------------------------------------------------------------
532
 */
533
herr_t
534
H5Idec_type_ref(H5I_type_t type)
535
0
{
536
0
    herr_t ret_value = 0; /* Return value */
537
538
0
    FUNC_ENTER_API((-1))
539
540
0
    if (H5I_IS_LIB_TYPE(type))
541
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "cannot call public function on library type");
542
543
0
    ret_value = H5I_dec_type_ref(type);
544
545
0
done:
546
0
    FUNC_LEAVE_API(ret_value)
547
0
} /* end H5Idec_type_ref() */
548
549
/*-------------------------------------------------------------------------
550
 * Function:    H5Iget_type_ref
551
 *
552
 * Purpose:     Retrieves the number of references outstanding for a type.
553
 *
554
 * Return:      Success:    Reference count
555
 *              Failure:    -1
556
 *
557
 *-------------------------------------------------------------------------
558
 */
559
int
560
H5Iget_type_ref(H5I_type_t type)
561
0
{
562
0
    int ret_value = -1; /* Return value */
563
564
0
    FUNC_ENTER_API((-1))
565
566
    /* Check arguments */
567
0
    if (type <= 0 || (int)type >= H5I_next_type_g)
568
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, (-1), "invalid ID type");
569
0
    if (H5I_IS_LIB_TYPE(type))
570
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, (-1), "cannot call public function on library type");
571
572
    /* Do actual retrieve operation */
573
0
    if ((ret_value = H5I__get_type_ref(type)) < 0)
574
0
        HGOTO_ERROR(H5E_ID, H5E_CANTGET, (-1), "can't get ID type ref count");
575
576
0
done:
577
0
    FUNC_LEAVE_API(ret_value)
578
0
} /* end H5Iget_ref() */
579
580
/*-------------------------------------------------------------------------
581
 * Function:    H5Iis_valid
582
 *
583
 * Purpose:     Check if the given id is valid.  An id is valid if it is in
584
 *              use and has an application reference count of at least 1.
585
 *
586
 * Return:      true/false/FAIL
587
 *
588
 *-------------------------------------------------------------------------
589
 */
590
htri_t
591
H5Iis_valid(hid_t id)
592
0
{
593
0
    H5I_id_info_t *info      = NULL; /* Pointer to the ID info */
594
0
    htri_t         ret_value = true; /* Return value */
595
596
0
    FUNC_ENTER_API(FAIL)
597
598
    /* Find the ID */
599
0
    if (NULL == (info = H5I__find_id(id)))
600
0
        ret_value = false;
601
0
    else if (!info->app_count) /* Check if the found id is an internal id */
602
0
        ret_value = false;
603
604
0
done:
605
0
    FUNC_LEAVE_API(ret_value)
606
0
} /* end H5Iis_valid() */
607
608
/*-------------------------------------------------------------------------
609
 * Function:    H5I__search_cb
610
 *
611
 * Purpose:     Callback routine for H5Isearch, when it calls H5I_iterate.
612
 *              Calls "user" callback search function, and then sets return
613
 *              value, based on the result of that callback.
614
 *
615
 * Return:      Success:    H5_ITER_CONT (0) or H5_ITER_STOP (1)
616
 *              Failure:    H5_ITER_ERROR (-1)
617
 *
618
 *-------------------------------------------------------------------------
619
 */
620
static int
621
H5I__search_cb(void *obj, hid_t id, void *_udata)
622
0
{
623
0
    H5I_search_ud_t *udata      = (H5I_search_ud_t *)_udata; /* User data for callback */
624
0
    herr_t           cb_ret_val = FAIL;                      /* User callback return value */
625
0
    int              ret_value  = H5_ITER_ERROR;             /* Callback return value */
626
627
0
    FUNC_ENTER_PACKAGE_NOERR
628
629
    /* Prepare & restore library for user callback */
630
0
    H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR)
631
0
        {
632
0
            cb_ret_val = (*udata->app_cb)(obj, id, udata->app_key);
633
0
        }
634
0
    H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR)
635
636
    /* Set the return value based on the callback's return value */
637
0
    if (cb_ret_val > 0) {
638
0
        ret_value      = H5_ITER_STOP; /* terminate iteration early */
639
0
        udata->ret_obj = obj;          /* also set out parameter */
640
0
    }
641
0
    else if (cb_ret_val < 0)
642
0
        ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
643
644
0
    FUNC_LEAVE_NOAPI(ret_value)
645
0
} /* end H5I__search_cb() */
646
647
/*-------------------------------------------------------------------------
648
 * Function:    H5Isearch
649
 *
650
 * Purpose:     Apply function FUNC to each member of type TYPE and return a
651
 *              pointer to the first object for which FUNC returns non-zero.
652
 *              The FUNC should take a pointer to the object and the KEY as
653
 *              arguments and return non-zero to terminate the search (zero
654
 *              to continue).  Public interface to H5I_search.
655
 *
656
 * Limitation:  Currently there is no way to start searching from where a
657
 *              previous search left off.
658
 *
659
 * Return:      Success:    The first object in the type for which FUNC
660
 *                          returns non-zero. NULL if FUNC returned zero
661
 *                          for every object in the type.
662
 *
663
 *              Failure:    NULL
664
 *
665
 *-------------------------------------------------------------------------
666
 */
667
void *
668
H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
669
0
{
670
0
    H5I_search_ud_t udata;            /* Context for iteration */
671
0
    void           *ret_value = NULL; /* Return value */
672
673
0
    FUNC_ENTER_API(NULL)
674
675
    /* Check arguments */
676
0
    if (H5I_IS_LIB_TYPE(type))
677
0
        HGOTO_ERROR(H5E_ID, H5E_BADGROUP, NULL, "cannot call public function on library type");
678
679
    /* Set up udata struct */
680
0
    udata.app_cb  = func;
681
0
    udata.app_key = key;
682
0
    udata.ret_obj = NULL;
683
684
    /* Note that H5I_iterate returns an error code.  We ignore it
685
     * here, as we can't do anything with it without revising the API.
686
     */
687
0
    (void)H5I_iterate(type, H5I__search_cb, &udata, true);
688
689
    /* Set return value */
690
0
    ret_value = udata.ret_obj;
691
692
0
done:
693
0
    FUNC_LEAVE_API(ret_value)
694
0
} /* end H5Isearch() */
695
696
/*-------------------------------------------------------------------------
697
 * Function:    H5I__iterate_pub_cb
698
 *
699
 * Purpose:     Callback routine for H5Iiterate, when it calls
700
 *              H5I_iterate.  Calls "user" callback search function, and
701
 *              then sets return value, based on the result of that
702
 *              callback.
703
 *
704
 * Return:      Success:    H5_ITER_CONT (0) or H5_ITER_STOP (1)
705
 *              Failure:    H5_ITER_ERROR (-1)
706
 *
707
 *-------------------------------------------------------------------------
708
 */
709
static int
710
H5I__iterate_pub_cb(void H5_ATTR_UNUSED *obj, hid_t id, void *_udata)
711
0
{
712
0
    H5I_iterate_pub_ud_t *udata      = (H5I_iterate_pub_ud_t *)_udata; /* User data for callback */
713
0
    herr_t                cb_ret_val = FAIL;                           /* User callback return value */
714
0
    int                   ret_value  = H5_ITER_ERROR;                  /* Callback return value */
715
716
0
    FUNC_ENTER_PACKAGE_NOERR
717
718
    /* Prepare & restore library for user callback */
719
0
    H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR)
720
0
        {
721
            /* Invoke the callback */
722
0
            cb_ret_val = (*udata->op)(id, udata->op_data);
723
0
        }
724
0
    H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR)
725
726
    /* Set the return value based on the callback's return value */
727
0
    if (cb_ret_val > 0)
728
0
        ret_value = H5_ITER_STOP; /* terminate iteration early */
729
0
    else if (cb_ret_val < 0)
730
0
        ret_value = H5_ITER_ERROR; /* indicate failure (which terminates iteration) */
731
0
    else
732
0
        ret_value = H5_ITER_CONT; /* continue iteration */
733
734
0
    FUNC_LEAVE_NOAPI(ret_value)
735
0
} /* end H5I__iterate_pub_cb() */
736
737
/*-------------------------------------------------------------------------
738
 * Function:    H5Iiterate
739
 *
740
 * Purpose:     Call the callback function op for each member of the id
741
 *              type type.  op takes as parameters the id and a
742
 *              passthrough of op_data, and returns an herr_t.  A positive
743
 *              return from op will cause the iteration to stop and
744
 *              H5Iiterate will return the value returned by op.  A
745
 *              negative return from op will cause the iteration to stop
746
 *              and H5Iiterate will return failure.  A zero return from op
747
 *              will allow iteration to continue, as long as there are
748
 *              other ids remaining in type.
749
 *
750
 * Limitation:  Currently there is no way to start searching from where a
751
 *              previous search left off.
752
 *
753
 * Return:      The last value returned by op
754
 *
755
 *-------------------------------------------------------------------------
756
 */
757
herr_t
758
H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data)
759
0
{
760
0
    H5I_iterate_pub_ud_t int_udata;        /* Internal user data */
761
0
    herr_t               ret_value = FAIL; /* Return value */
762
763
0
    FUNC_ENTER_API(FAIL)
764
765
    /* Set up udata struct */
766
0
    int_udata.op      = op;
767
0
    int_udata.op_data = op_data;
768
769
    /* Note that H5I_iterate returns an error code.  We ignore it
770
     * here, as we can't do anything with it without revising the API.
771
     */
772
0
    if ((ret_value = H5I_iterate(type, H5I__iterate_pub_cb, &int_udata, true)) < 0)
773
0
        HGOTO_ERROR(H5E_ID, H5E_BADITER, FAIL, "can't iterate over ids");
774
775
0
done:
776
0
    FUNC_LEAVE_API(ret_value)
777
0
} /* end H5Iiterate() */
778
779
/*-------------------------------------------------------------------------
780
 * Function:    H5Iget_file_id
781
 *
782
 * Purpose:     Obtains the file ID given an object ID.  The user has to
783
 *              close this ID.
784
 *
785
 * Return:      Success:    The file ID associated with the object
786
 *
787
 *              Failure:    H5I_INVALID_HID
788
 *
789
 *-------------------------------------------------------------------------
790
 */
791
hid_t
792
H5Iget_file_id(hid_t obj_id)
793
0
{
794
0
    H5I_type_t type;                        /* ID type */
795
0
    hid_t      ret_value = H5I_INVALID_HID; /* Return value */
796
797
0
    FUNC_ENTER_API(H5I_INVALID_HID)
798
799
    /* Get object type */
800
0
    type = H5I_TYPE(obj_id);
801
802
    /* Call internal function */
803
0
    if (H5I_FILE == type || H5I_DATATYPE == type || H5I_GROUP == type || H5I_DATASET == type ||
804
0
        H5I_ATTR == type) {
805
0
        H5VL_object_t *vol_obj; /* Object of obj_id */
806
807
        /* Get the VOL object */
808
0
        if (NULL == (vol_obj = H5VL_vol_object(obj_id)))
809
0
            HGOTO_ERROR(H5E_ID, H5E_BADTYPE, H5I_INVALID_HID, "invalid location identifier");
810
811
        /* Get the file ID */
812
0
        if ((ret_value = H5F_get_file_id(vol_obj, type, true)) < 0)
813
0
            HGOTO_ERROR(H5E_ID, H5E_CANTGET, H5I_INVALID_HID, "can't retrieve file ID");
814
0
    }
815
0
    else
816
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_INVALID_HID, "not an ID of a file object");
817
818
0
done:
819
0
    FUNC_LEAVE_API(ret_value)
820
0
} /* end H5Iget_file_id() */
821
822
/*-------------------------------------------------------------------------
823
 * Function:    H5Iget_name
824
 *
825
 * Purpose:     Gets a name of an object from its ID.
826
 *
827
 * Description:
828
 *              When 'name' is non-NULL:
829
 *                - if 'size' > 0: writes up to 'size' bytes into the buffer
830
 *                  (including null terminator) and returns the actual length
831
 *                  of the name (excluding null terminator).
832
 *                - if 'size' == 0: treats the call as length query, does not
833
 *                  write anything to the buffer (not even a null terminator), and
834
 *                  returns the actual length of the name (excluding null terminator).
835
 *
836
 *              When 'name' is NULL: does not write anything regardless of 'size'
837
 *              and returns the actual length of the name (excluding null terminator).
838
 *
839
 *              On error, the buffer is unchanged and the function returns
840
 *              a negative value.
841
 *
842
 * Return:      Success:    The length of the name (excluding null terminator)
843
 *              Failure:    Negative
844
 *
845
 * Notes:
846
 *              If a zero is returned for the name's length, then there is no name
847
 *              associated with the ID.
848
 *
849
 *-------------------------------------------------------------------------
850
 */
851
ssize_t
852
H5Iget_name(hid_t id, char *name /*out*/, size_t size)
853
0
{
854
0
    H5VL_object_t         *vol_obj = NULL; /* Object stored in ID */
855
0
    H5VL_object_get_args_t vol_cb_args;    /* Arguments to VOL callback */
856
0
    H5VL_loc_params_t      loc_params;
857
0
    size_t                 obj_name_len = 0;  /* Length of object's name */
858
0
    ssize_t                ret_value    = -1; /* Return value */
859
860
0
    FUNC_ENTER_API((-1))
861
862
    /* If name size is zero, treat as length query and do not write, even a '\0' */
863
0
    if (name && size == 0)
864
0
        name = NULL;
865
866
    /* Get the object pointer */
867
0
    if (NULL == (vol_obj = H5VL_vol_object(id)))
868
0
        HGOTO_ERROR(H5E_ID, H5E_BADTYPE, (-1), "invalid identifier");
869
870
    /* Set location parameters */
871
0
    loc_params.type     = H5VL_OBJECT_BY_SELF;
872
0
    loc_params.obj_type = H5I_get_type(id);
873
874
    /* Set up VOL callback arguments */
875
0
    vol_cb_args.op_type                = H5VL_OBJECT_GET_NAME;
876
0
    vol_cb_args.args.get_name.buf_size = size;
877
0
    vol_cb_args.args.get_name.buf      = name;
878
0
    vol_cb_args.args.get_name.name_len = &obj_name_len;
879
880
    /* Retrieve object's name */
881
0
    if (H5VL_object_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
882
0
        HGOTO_ERROR(H5E_ID, H5E_CANTGET, (-1), "can't retrieve object name");
883
884
    /* Set return value */
885
0
    ret_value = (ssize_t)obj_name_len;
886
887
0
done:
888
    FUNC_LEAVE_API(ret_value)
889
0
} /* end H5Iget_name() */