Coverage Report

Created: 2026-08-13 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Pint.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
 * Purpose: Generic Property Functions
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
21
#include "H5Pmodule.h" /* This source code file is part of the H5P module */
22
23
/***********/
24
/* Headers */
25
/***********/
26
#include "H5private.h"   /* Generic Functions     */
27
#include "H5Eprivate.h"  /* Error handling        */
28
#include "H5FLprivate.h" /* Free lists                           */
29
#include "H5Iprivate.h"  /* IDs           */
30
#include "H5MMprivate.h" /* Memory management     */
31
#include "H5Ppkg.h"      /* Property lists        */
32
#include "H5SLprivate.h" /* Skip Lists                               */
33
34
/****************/
35
/* Local Macros */
36
/****************/
37
38
/******************/
39
/* Local Typedefs */
40
/******************/
41
42
/* Typedef for checking for duplicate class names in parent class */
43
typedef struct {
44
    const H5P_genclass_t *parent;    /* Pointer to parent class */
45
    const char           *name;      /* Pointer to name to check */
46
    H5P_genclass_t       *new_class; /* Pointer to class during path traversal */
47
} H5P_check_class_t;
48
49
/* Typedef for property list iterator callback */
50
typedef struct {
51
    H5P_iterate_int_t     cb_func;      /* Iterator callback */
52
    void                 *udata;        /* Iterator callback pointer */
53
    const H5P_genplist_t *plist;        /* Property list pointer */
54
    H5SL_t               *seen;         /* Skip list to hold names of properties already seen */
55
    int                  *curr_idx_ptr; /* Pointer to current iteration index */
56
    int                   prev_idx;     /* Previous iteration index */
57
} H5P_iter_plist_ud_t;
58
59
/* Typedef for property list class iterator callback */
60
typedef struct {
61
    H5P_iterate_int_t cb_func;      /* Iterator callback */
62
    void             *udata;        /* Iterator callback pointer */
63
    int              *curr_idx_ptr; /* Pointer to current iteration index */
64
    int               prev_idx;     /* Previous iteration index */
65
} H5P_iter_pclass_ud_t;
66
67
/* Typedef for property list comparison callback */
68
typedef struct {
69
    const H5P_genplist_t *plist2;    /* Pointer to second property list */
70
    int                   cmp_value; /* Value from property comparison */
71
} H5P_plist_cmp_ud_t;
72
73
/* Typedef for property list set/poke callbacks */
74
typedef struct {
75
    const void *value; /* Pointer to value to set */
76
} H5P_prop_set_ud_t;
77
78
/* Typedef for property list get/peek callbacks */
79
typedef struct {
80
    void *value; /* Pointer for retrieved value */
81
} H5P_prop_get_ud_t;
82
83
/* Typedef for H5P__do_prop() callbacks */
84
typedef herr_t (*H5P_do_plist_op_t)(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
85
                                    void *udata);
86
typedef herr_t (*H5P_do_pclass_op_t)(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop,
87
                                     void *udata);
88
89
/********************/
90
/* Local Prototypes */
91
/********************/
92
93
/* Infrastructure routines */
94
static herr_t H5P__close_class_cb(void *space, void **request);
95
static herr_t H5P__close_list_cb(void *space, void **request);
96
97
/* General helper routines */
98
static H5P_genplist_t *H5P__create(H5P_genclass_t *pclass);
99
static H5P_genprop_t  *H5P__create_prop(const char *name, size_t size, H5P_prop_within_t type,
100
                                        const void *value, H5P_prp_create_func_t prp_create,
101
                                        H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
102
                                        H5P_prp_encode_func_t prp_encode, H5P_prp_decode_func_t prp_decode,
103
                                        H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
104
                                        H5P_prp_compare_func_t prp_cmp, H5P_prp_close_func_t prp_close);
105
static H5P_genprop_t  *H5P__dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type);
106
static herr_t          H5P__free_prop(H5P_genprop_t *prop);
107
static int             H5P__cmp_prop(const H5P_genprop_t *prop1, const H5P_genprop_t *prop2);
108
static herr_t          H5P__do_prop(H5P_genplist_t *plist, const char *name, H5P_do_plist_op_t plist_op,
109
                                    H5P_do_pclass_op_t pclass_op, void *udata);
110
static int             H5P__open_class_path_cb(void *_obj, hid_t H5_ATTR_UNUSED id, void *_key);
111
static H5P_genprop_t  *H5P__find_prop_pclass(H5P_genclass_t *pclass, const char *name);
112
static herr_t          H5P__free_prop_cb(void *item, void H5_ATTR_UNUSED *key, void *op_data);
113
static herr_t H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *op_data);
114
115
/*********************/
116
/* Package Variables */
117
/*********************/
118
119
/*
120
 * Predefined property list classes. These are initialized at runtime by
121
 * H5P__init_package() in this source file.
122
 */
123
hid_t           H5P_CLS_ROOT_ID_g = H5I_INVALID_HID;
124
H5P_genclass_t *H5P_CLS_ROOT_g    = NULL;
125
126
hid_t           H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
127
H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g    = NULL;
128
hid_t           H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
129
H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g    = NULL;
130
hid_t           H5P_CLS_DATASET_ACCESS_ID_g   = H5I_INVALID_HID;
131
H5P_genclass_t *H5P_CLS_DATASET_ACCESS_g      = NULL;
132
hid_t           H5P_CLS_DATASET_CREATE_ID_g   = H5I_INVALID_HID;
133
H5P_genclass_t *H5P_CLS_DATASET_CREATE_g      = NULL;
134
hid_t           H5P_CLS_DATASET_XFER_ID_g     = H5I_INVALID_HID;
135
H5P_genclass_t *H5P_CLS_DATASET_XFER_g        = NULL;
136
hid_t           H5P_CLS_DATATYPE_ACCESS_ID_g  = H5I_INVALID_HID;
137
H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g     = NULL;
138
hid_t           H5P_CLS_DATATYPE_CREATE_ID_g  = H5I_INVALID_HID;
139
H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g     = NULL;
140
hid_t           H5P_CLS_FILE_ACCESS_ID_g      = H5I_INVALID_HID;
141
H5P_genclass_t *H5P_CLS_FILE_ACCESS_g         = NULL;
142
hid_t           H5P_CLS_FILE_CREATE_ID_g      = H5I_INVALID_HID;
143
H5P_genclass_t *H5P_CLS_FILE_CREATE_g         = NULL;
144
hid_t           H5P_CLS_FILE_MOUNT_ID_g       = H5I_INVALID_HID;
145
H5P_genclass_t *H5P_CLS_FILE_MOUNT_g          = NULL;
146
hid_t           H5P_CLS_GROUP_ACCESS_ID_g     = H5I_INVALID_HID;
147
H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g        = NULL;
148
hid_t           H5P_CLS_GROUP_CREATE_ID_g     = H5I_INVALID_HID;
149
H5P_genclass_t *H5P_CLS_GROUP_CREATE_g        = NULL;
150
hid_t           H5P_CLS_LINK_ACCESS_ID_g      = H5I_INVALID_HID;
151
H5P_genclass_t *H5P_CLS_LINK_ACCESS_g         = NULL;
152
hid_t           H5P_CLS_LINK_CREATE_ID_g      = H5I_INVALID_HID;
153
H5P_genclass_t *H5P_CLS_LINK_CREATE_g         = NULL;
154
hid_t           H5P_CLS_MAP_ACCESS_ID_g       = H5I_INVALID_HID;
155
H5P_genclass_t *H5P_CLS_MAP_ACCESS_g          = NULL;
156
hid_t           H5P_CLS_MAP_CREATE_ID_g       = H5I_INVALID_HID;
157
H5P_genclass_t *H5P_CLS_MAP_CREATE_g          = NULL;
158
hid_t           H5P_CLS_OBJECT_COPY_ID_g      = H5I_INVALID_HID;
159
H5P_genclass_t *H5P_CLS_OBJECT_COPY_g         = NULL;
160
hid_t           H5P_CLS_OBJECT_CREATE_ID_g    = H5I_INVALID_HID;
161
H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g       = NULL;
162
hid_t           H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
163
H5P_genclass_t *H5P_CLS_REFERENCE_ACCESS_g    = NULL;
164
hid_t           H5P_CLS_STRING_CREATE_ID_g    = H5I_INVALID_HID;
165
H5P_genclass_t *H5P_CLS_STRING_CREATE_g       = NULL;
166
hid_t           H5P_CLS_VOL_INITIALIZE_ID_g   = H5I_INVALID_HID;
167
H5P_genclass_t *H5P_CLS_VOL_INITIALIZE_g      = NULL;
168
169
/*
170
 * Predefined property lists for each predefined class. These are initialized
171
 * at runtime by H5P__init_package() in this source file.
172
 */
173
hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
174
hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
175
hid_t H5P_LST_DATASET_ACCESS_ID_g   = H5I_INVALID_HID;
176
hid_t H5P_LST_DATASET_CREATE_ID_g   = H5I_INVALID_HID;
177
hid_t H5P_LST_DATASET_XFER_ID_g     = H5I_INVALID_HID;
178
hid_t H5P_LST_DATATYPE_ACCESS_ID_g  = H5I_INVALID_HID;
179
hid_t H5P_LST_DATATYPE_CREATE_ID_g  = H5I_INVALID_HID;
180
hid_t H5P_LST_FILE_ACCESS_ID_g      = H5I_INVALID_HID;
181
hid_t H5P_LST_FILE_CREATE_ID_g      = H5I_INVALID_HID;
182
hid_t H5P_LST_FILE_MOUNT_ID_g       = H5I_INVALID_HID;
183
hid_t H5P_LST_GROUP_ACCESS_ID_g     = H5I_INVALID_HID;
184
hid_t H5P_LST_GROUP_CREATE_ID_g     = H5I_INVALID_HID;
185
hid_t H5P_LST_LINK_ACCESS_ID_g      = H5I_INVALID_HID;
186
hid_t H5P_LST_LINK_CREATE_ID_g      = H5I_INVALID_HID;
187
hid_t H5P_LST_MAP_ACCESS_ID_g       = H5I_INVALID_HID;
188
hid_t H5P_LST_MAP_CREATE_ID_g       = H5I_INVALID_HID;
189
hid_t H5P_LST_OBJECT_COPY_ID_g      = H5I_INVALID_HID;
190
hid_t H5P_LST_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
191
hid_t H5P_LST_VOL_INITIALIZE_ID_g   = H5I_INVALID_HID;
192
193
/* Root property list class library initialization object */
194
const H5P_libclass_t H5P_CLS_ROOT[1] = {{
195
    "root",        /* Class name for debugging     */
196
    H5P_TYPE_ROOT, /* Class type                   */
197
198
    NULL,               /* Parent class                 */
199
    &H5P_CLS_ROOT_g,    /* Pointer to class             */
200
    &H5P_CLS_ROOT_ID_g, /* Pointer to class ID          */
201
    NULL,               /* Pointer to default property list ID */
202
    NULL,               /* Default property registration routine */
203
204
    NULL, /* Class creation callback      */
205
    NULL, /* Class creation callback info */
206
    NULL, /* Class copy callback          */
207
    NULL, /* Class copy callback info     */
208
    NULL, /* Class close callback         */
209
    NULL  /* Class close callback info    */
210
}};
211
212
/* Attribute access property list class library initialization object */
213
/* (move to proper source code file when used for real) */
214
const H5P_libclass_t H5P_CLS_AACC[1] = {{
215
    "attribute access",        /* Class name for debugging     */
216
    H5P_TYPE_ATTRIBUTE_ACCESS, /* Class type                   */
217
218
    &H5P_CLS_LINK_ACCESS_g,         /* Parent class                 */
219
    &H5P_CLS_ATTRIBUTE_ACCESS_g,    /* Pointer to class             */
220
    &H5P_CLS_ATTRIBUTE_ACCESS_ID_g, /* Pointer to class ID          */
221
    &H5P_LST_ATTRIBUTE_ACCESS_ID_g, /* Pointer to default property list ID */
222
    NULL,                           /* Default property registration routine */
223
224
    NULL, /* Class creation callback      */
225
    NULL, /* Class creation callback info */
226
    NULL, /* Class copy callback          */
227
    NULL, /* Class copy callback info     */
228
    NULL, /* Class close callback         */
229
    NULL  /* Class close callback info    */
230
}};
231
232
/* Group access property list class library initialization object */
233
/* (move to proper source code file when used for real) */
234
const H5P_libclass_t H5P_CLS_GACC[1] = {{
235
    "group access",        /* Class name for debugging     */
236
    H5P_TYPE_GROUP_ACCESS, /* Class type                   */
237
238
    &H5P_CLS_LINK_ACCESS_g,     /* Parent class                 */
239
    &H5P_CLS_GROUP_ACCESS_g,    /* Pointer to class             */
240
    &H5P_CLS_GROUP_ACCESS_ID_g, /* Pointer to class ID          */
241
    &H5P_LST_GROUP_ACCESS_ID_g, /* Pointer to default property list ID */
242
    NULL,                       /* Default property registration routine */
243
244
    NULL, /* Class creation callback      */
245
    NULL, /* Class creation callback info */
246
    NULL, /* Class copy callback          */
247
    NULL, /* Class copy callback info     */
248
    NULL, /* Class close callback         */
249
    NULL  /* Class close callback info    */
250
}};
251
252
/* Datatype creation property list class library initialization object */
253
/* (move to proper source code file when used for real) */
254
const H5P_libclass_t H5P_CLS_TCRT[1] = {{
255
    "datatype create",        /* Class name for debugging     */
256
    H5P_TYPE_DATATYPE_CREATE, /* Class type                   */
257
258
    &H5P_CLS_OBJECT_CREATE_g,      /* Parent class                 */
259
    &H5P_CLS_DATATYPE_CREATE_g,    /* Pointer to class             */
260
    &H5P_CLS_DATATYPE_CREATE_ID_g, /* Pointer to class ID          */
261
    &H5P_LST_DATATYPE_CREATE_ID_g, /* Pointer to default property list ID */
262
    NULL,                          /* Default property registration routine */
263
264
    NULL, /* Class creation callback      */
265
    NULL, /* Class creation callback info */
266
    NULL, /* Class copy callback          */
267
    NULL, /* Class copy callback info     */
268
    NULL, /* Class close callback         */
269
    NULL  /* Class close callback info    */
270
}};
271
272
/* Datatype access property list class library initialization object */
273
/* (move to proper source code file when used for real) */
274
const H5P_libclass_t H5P_CLS_TACC[1] = {{
275
    "datatype access",        /* Class name for debugging     */
276
    H5P_TYPE_DATATYPE_ACCESS, /* Class type                   */
277
278
    &H5P_CLS_LINK_ACCESS_g,        /* Parent class                 */
279
    &H5P_CLS_DATATYPE_ACCESS_g,    /* Pointer to class             */
280
    &H5P_CLS_DATATYPE_ACCESS_ID_g, /* Pointer to class ID          */
281
    &H5P_LST_DATATYPE_ACCESS_ID_g, /* Pointer to default property list ID */
282
    NULL,                          /* Default property registration routine */
283
284
    NULL, /* Class creation callback      */
285
    NULL, /* Class creation callback info */
286
    NULL, /* Class copy callback          */
287
    NULL, /* Class copy callback info     */
288
    NULL, /* Class close callback         */
289
    NULL  /* Class close callback info    */
290
}};
291
292
/* VOL initialization property list class library initialization object */
293
/* (move to proper source code file when used for real) */
294
const H5P_libclass_t H5P_CLS_VINI[1] = {{
295
    "VOL initialization",    /* Class name for debugging     */
296
    H5P_TYPE_VOL_INITIALIZE, /* Class type                   */
297
298
    &H5P_CLS_ROOT_g,              /* Parent class                 */
299
    &H5P_CLS_VOL_INITIALIZE_g,    /* Pointer to class             */
300
    &H5P_CLS_VOL_INITIALIZE_ID_g, /* Pointer to class ID          */
301
    &H5P_LST_VOL_INITIALIZE_ID_g, /* Pointer to default property list ID */
302
    NULL,                         /* Default property registration routine */
303
304
    NULL, /* Class creation callback      */
305
    NULL, /* Class creation callback info */
306
    NULL, /* Class copy callback          */
307
    NULL, /* Class copy callback info     */
308
    NULL, /* Class close callback         */
309
    NULL  /* Class close callback info    */
310
}};
311
312
/* Reference access property list class library initialization object */
313
/* (move to proper source code file when used for real) */
314
const H5P_libclass_t H5P_CLS_RACC[1] = {{
315
    "reference access",        /* Class name for debugging     */
316
    H5P_TYPE_REFERENCE_ACCESS, /* Class type                   */
317
318
    &H5P_CLS_FILE_ACCESS_g,         /* Parent class                         */
319
    &H5P_CLS_REFERENCE_ACCESS_g,    /* Pointer to class                     */
320
    &H5P_CLS_REFERENCE_ACCESS_ID_g, /* Pointer to class ID                  */
321
    &H5P_LST_REFERENCE_ACCESS_ID_g, /* Pointer to default property list ID  */
322
    NULL,                           /* Default property registration routine*/
323
324
    NULL, /* Class creation callback              */
325
    NULL, /* Class creation callback info         */
326
    NULL, /* Class copy callback                  */
327
    NULL, /* Class copy callback info             */
328
    NULL, /* Class close callback                 */
329
    NULL  /* Class close callback info            */
330
}};
331
332
/* Library property list classes defined in other code modules */
333
/* (And not present in src/H5Pprivate.h) */
334
H5_DLLVAR const H5P_libclass_t H5P_CLS_OCRT[1];   /* Object creation */
335
H5_DLLVAR const H5P_libclass_t H5P_CLS_STRCRT[1]; /* String create */
336
H5_DLLVAR const H5P_libclass_t H5P_CLS_GCRT[1];   /* Group create */
337
H5_DLLVAR const H5P_libclass_t H5P_CLS_FCRT[1];   /* File creation */
338
H5_DLLVAR const H5P_libclass_t H5P_CLS_DCRT[1];   /* Dataset creation */
339
H5_DLLVAR const H5P_libclass_t H5P_CLS_MCRT[1];   /* Map creation */
340
H5_DLLVAR const H5P_libclass_t H5P_CLS_DXFR[1];   /* Data transfer */
341
H5_DLLVAR const H5P_libclass_t H5P_CLS_FMNT[1];   /* File mount */
342
H5_DLLVAR const H5P_libclass_t H5P_CLS_ACRT[1];   /* Attribute creation */
343
344
/*****************************/
345
/* Library Private Variables */
346
/*****************************/
347
348
/*******************/
349
/* Local Variables */
350
/*******************/
351
352
/* Track the revision count of a class, to make comparisons faster */
353
static unsigned H5P_next_rev = 0;
354
136
#define H5P_GET_NEXT_REV (H5P_next_rev++)
355
356
/* List of all property list classes in the library */
357
/* (order here is not important, they will be initialized in the proper
358
 *      order according to their parent class dependencies)
359
 */
360
static H5P_libclass_t const *const init_class[] = {
361
    H5P_CLS_ROOT,   /* Root */
362
    H5P_CLS_OCRT,   /* Object create */
363
    H5P_CLS_STRCRT, /* String create */
364
    H5P_CLS_LACC,   /* Link access */
365
    H5P_CLS_GCRT,   /* Group create */
366
    H5P_CLS_OCPY,   /* Object copy */
367
    H5P_CLS_GACC,   /* Group access */
368
    H5P_CLS_FCRT,   /* File creation */
369
    H5P_CLS_FACC,   /* File access */
370
    H5P_CLS_DCRT,   /* Dataset creation */
371
    H5P_CLS_DACC,   /* Dataset access */
372
    H5P_CLS_DXFR,   /* Data transfer */
373
    H5P_CLS_FMNT,   /* File mount */
374
    H5P_CLS_TCRT,   /* Datatype creation */
375
    H5P_CLS_TACC,   /* Datatype access */
376
    H5P_CLS_MCRT,   /* Map creation */
377
    H5P_CLS_MACC,   /* Map access */
378
    H5P_CLS_ACRT,   /* Attribute creation */
379
    H5P_CLS_AACC,   /* Attribute access */
380
    H5P_CLS_LCRT,   /* Link creation */
381
    H5P_CLS_VINI,   /* VOL initialization */
382
    H5P_CLS_RACC    /* Reference access */
383
};
384
385
/* Declare a free list to manage the H5P_genclass_t struct */
386
H5FL_DEFINE_STATIC(H5P_genclass_t);
387
388
/* Declare a free list to manage the H5P_genprop_t struct */
389
H5FL_DEFINE_STATIC(H5P_genprop_t);
390
391
/* Declare a free list to manage the H5P_genplist_t struct */
392
H5FL_DEFINE_STATIC(H5P_genplist_t);
393
394
/* Generic Property Class ID class */
395
static const H5I_class_t H5I_GENPROPCLS_CLS[1] = {{
396
    H5I_GENPROP_CLS,    /* ID class value */
397
    0,                  /* Class flags */
398
    0,                  /* # of reserved IDs for class */
399
    H5P__close_class_cb /* Callback routine for closing objects of this class */
400
}};
401
402
/* Generic Property List ID class */
403
static const H5I_class_t H5I_GENPROPLST_CLS[1] = {{
404
    H5I_GENPROP_LST,   /* ID class value */
405
    0,                 /* Class flags */
406
    0,                 /* # of reserved IDs for class */
407
    H5P__close_list_cb /* Callback routine for closing objects of this class */
408
}};
409
410
/*-------------------------------------------------------------------------
411
 * Function:    H5P_init_phase1
412
 *
413
 * Purpose:     Initialize the interface from some other layer. This should
414
 *              be followed with a call to H5P_init_phase2 after the H5P
415
 *              interface is completely setup.
416
 *
417
 * Return:      Success:    non-negative
418
 *              Failure:    negative
419
 *
420
 *-------------------------------------------------------------------------
421
 */
422
herr_t
423
H5P_init_phase1(void)
424
1
{
425
1
    herr_t ret_value = SUCCEED; /* Return value */
426
427
1
    FUNC_ENTER_NOAPI(FAIL)
428
    /* FUNC_ENTER() does all the work */
429
430
1
done:
431
1
    FUNC_LEAVE_NOAPI(ret_value)
432
1
} /* end H5P_init_phase1() */
433
434
/*-------------------------------------------------------------------------
435
 * Function:    H5P_init_phase2
436
 *
437
 * Purpose:     Finish initializing the interface from some other package.
438
 *
439
 * Note:        This is broken out as a separate routine so that the
440
 *              library's default VFL driver can be chosen and initialized
441
 *              after the entire H5P interface has been initialized.
442
 *
443
 * Return:      Success:    Non-negative
444
 *              Failure:    Negative
445
 *
446
 *-------------------------------------------------------------------------
447
 */
448
herr_t
449
H5P_init_phase2(void)
450
1
{
451
1
    herr_t ret_value = SUCCEED;
452
453
1
    FUNC_ENTER_NOAPI(FAIL)
454
455
    /* Set up the default VFL driver */
456
1
    if (H5P__facc_set_def_driver() < 0)
457
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set default VFL driver");
458
459
1
done:
460
1
    FUNC_LEAVE_NOAPI(ret_value)
461
1
} /* end H5P_init_phase2() */
462
463
/*--------------------------------------------------------------------------
464
NAME
465
   H5P__init_package -- Initialize interface-specific information
466
USAGE
467
    herr_t H5P__init_package()
468
RETURNS
469
    Non-negative on success/Negative on failure
470
DESCRIPTION
471
    Initializes any interface-specific data or routines.
472
--------------------------------------------------------------------------*/
473
herr_t
474
H5P__init_package(void)
475
1
{
476
1
    size_t tot_init = 0; /* Total # of classes initialized */
477
1
    size_t pass_init;    /* # of classes initialized in each pass */
478
1
    size_t u;
479
1
    herr_t ret_value = SUCCEED; /* Return value */
480
481
1
    FUNC_ENTER_PACKAGE
482
483
    /* Sanity check */
484
1
    HDcompile_assert(H5P_TYPE_REFERENCE_ACCESS == (H5P_TYPE_MAX_TYPE - 1));
485
486
    /*
487
     * Initialize the Generic Property class & object groups.
488
     */
489
1
    if (H5I_register_type(H5I_GENPROPCLS_CLS) < 0)
490
0
        HGOTO_ERROR(H5E_ID, H5E_CANTINIT, FAIL, "unable to initialize ID group");
491
1
    if (H5I_register_type(H5I_GENPROPLST_CLS) < 0)
492
0
        HGOTO_ERROR(H5E_ID, H5E_CANTINIT, FAIL, "unable to initialize ID group");
493
494
    /* Repeatedly pass over the list of property list classes for the library,
495
     * initializing each class if its parent class is initialized, until no
496
     * more progress is made.
497
     */
498
1
    tot_init = 0;
499
2
    do {
500
        /* Reset pass initialization counter */
501
2
        pass_init = 0;
502
503
        /* Make a pass over all the library's property list classes */
504
46
        for (u = 0; u < NELMTS(init_class); u++) {
505
44
            H5P_libclass_t const *lib_class = init_class[u]; /* Current class to operate on */
506
507
            /* Check if the current class hasn't been initialized and can be now */
508
44
            assert(lib_class->class_id);
509
44
            if (*lib_class->class_id == (-1) &&
510
22
                (lib_class->par_pclass == NULL || *lib_class->par_pclass != NULL)) {
511
                /* Sanity check - only the root class is not allowed to have a parent class */
512
22
                assert(lib_class->par_pclass || lib_class == H5P_CLS_ROOT);
513
514
                /* Allocate the new class */
515
22
                if (NULL == (*lib_class->pclass = H5P__create_class(
516
22
                                 lib_class->par_pclass ? *lib_class->par_pclass : NULL, lib_class->name,
517
22
                                 lib_class->type, lib_class->create_func, lib_class->create_data,
518
22
                                 lib_class->copy_func, lib_class->copy_data, lib_class->close_func,
519
22
                                 lib_class->close_data)))
520
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed");
521
522
                /* Call routine to register properties for class */
523
22
                if (lib_class->reg_prop_func && (*lib_class->reg_prop_func)(*lib_class->pclass) < 0)
524
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register properties");
525
526
                /* Register the new class */
527
22
                if ((*lib_class->class_id = H5I_register(H5I_GENPROP_CLS, *lib_class->pclass, false)) < 0)
528
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class");
529
530
                /* Only register the default property list if it hasn't been created yet */
531
22
                if (lib_class->def_plist_id && *lib_class->def_plist_id == (-1)) {
532
                    /* Register the default property list for the new class*/
533
19
                    if ((*lib_class->def_plist_id = H5P_create_id(*lib_class->pclass, false)) < 0)
534
0
                        HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL,
535
19
                                    "can't register default property list for class");
536
19
                } /* end if */
537
538
                /* Increment class initialization counters */
539
22
                pass_init++;
540
22
                tot_init++;
541
22
            } /* end if */
542
44
        }     /* end for */
543
2
    } while (pass_init > 0);
544
545
    /* Verify that all classes were initialized */
546
1
    assert(tot_init == NELMTS(init_class));
547
548
1
done:
549
1
    if (ret_value < 0 && tot_init > 0) {
550
        /* First uninitialize all default property lists */
551
0
        H5I_clear_type(H5I_GENPROP_LST, false, false);
552
553
        /* Then uninitialize any initialized libclass */
554
0
        for (u = 0; u < NELMTS(init_class); u++) {
555
0
            H5P_libclass_t const *lib_class = init_class[u]; /* Current class to operate on */
556
557
0
            assert(lib_class->class_id);
558
0
            if (*lib_class->class_id >= 0) {
559
                /* Close the class ID */
560
0
                if (H5I_dec_ref(*lib_class->class_id) < 0)
561
0
                    HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class ID");
562
0
            }
563
0
            else if (lib_class->pclass && *lib_class->pclass) {
564
                /* Close a half-initialized pclass */
565
0
                if (H5P__close_class(*lib_class->pclass) < 0)
566
0
                    HDONE_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class");
567
0
            }
568
0
        }
569
0
    }
570
571
1
    FUNC_LEAVE_NOAPI(ret_value)
572
1
} /* end H5P__init_package() */
573
574
/*--------------------------------------------------------------------------
575
 NAME
576
    H5P_term_package
577
 PURPOSE
578
    Terminate various H5P objects
579
 USAGE
580
    void H5P_term_package()
581
 RETURNS
582
    Non-negative on success/Negative on failure
583
 DESCRIPTION
584
    Release the ID group and any other resources allocated.
585
 GLOBAL VARIABLES
586
 COMMENTS, BUGS, ASSUMPTIONS
587
     Can't report errors...
588
 EXAMPLES
589
 REVISION LOG
590
--------------------------------------------------------------------------*/
591
int
592
H5P_term_package(void)
593
99
{
594
99
    int n = 0;
595
596
99
    FUNC_ENTER_NOAPI_NOINIT_NOERR
597
598
3
    if (H5_PKG_INIT_VAR) {
599
3
        int64_t nlist, nclass;
600
601
        /* Destroy HDF5 library property classes & lists */
602
603
        /* Check if there are any open property list classes or lists */
604
3
        nclass = H5I_nmembers(H5I_GENPROP_CLS);
605
3
        nlist  = H5I_nmembers(H5I_GENPROP_LST);
606
607
        /* If there are any open classes or groups, attempt to get rid of them. */
608
3
        if ((nclass + nlist) > 0) {
609
            /* Clear the lists */
610
2
            if (nlist > 0) {
611
1
                (void)H5I_clear_type(H5I_GENPROP_LST, false, false);
612
613
                /* Reset the default property lists, if they've been closed */
614
1
                if (H5I_nmembers(H5I_GENPROP_LST) == 0) {
615
1
                    H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
616
1
                    H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
617
1
                    H5P_LST_DATASET_ACCESS_ID_g   = H5I_INVALID_HID;
618
1
                    H5P_LST_DATASET_CREATE_ID_g   = H5I_INVALID_HID;
619
1
                    H5P_LST_DATASET_XFER_ID_g     = H5I_INVALID_HID;
620
1
                    H5P_LST_DATATYPE_ACCESS_ID_g  = H5I_INVALID_HID;
621
1
                    H5P_LST_DATATYPE_CREATE_ID_g  = H5I_INVALID_HID;
622
1
                    H5P_LST_FILE_ACCESS_ID_g      = H5I_INVALID_HID;
623
1
                    H5P_LST_FILE_CREATE_ID_g      = H5I_INVALID_HID;
624
1
                    H5P_LST_FILE_MOUNT_ID_g       = H5I_INVALID_HID;
625
1
                    H5P_LST_GROUP_ACCESS_ID_g     = H5I_INVALID_HID;
626
1
                    H5P_LST_GROUP_CREATE_ID_g     = H5I_INVALID_HID;
627
1
                    H5P_LST_LINK_ACCESS_ID_g      = H5I_INVALID_HID;
628
1
                    H5P_LST_LINK_CREATE_ID_g      = H5I_INVALID_HID;
629
1
                    H5P_LST_MAP_ACCESS_ID_g       = H5I_INVALID_HID;
630
1
                    H5P_LST_MAP_CREATE_ID_g       = H5I_INVALID_HID;
631
1
                    H5P_LST_OBJECT_COPY_ID_g      = H5I_INVALID_HID;
632
1
                    H5P_LST_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
633
1
                    H5P_LST_VOL_INITIALIZE_ID_g   = H5I_INVALID_HID;
634
1
                }
635
1
            }
636
637
            /* Only attempt to close the classes after all the lists are closed */
638
2
            if (nlist == 0 && nclass > 0) {
639
1
                (void)H5I_clear_type(H5I_GENPROP_CLS, false, false);
640
641
                /* Reset the default property classes and IDs if they've been closed */
642
1
                if (H5I_nmembers(H5I_GENPROP_CLS) == 0) {
643
1
                    H5P_CLS_ROOT_g = NULL;
644
645
1
                    H5P_CLS_ATTRIBUTE_ACCESS_g = NULL;
646
1
                    H5P_CLS_ATTRIBUTE_CREATE_g = NULL;
647
1
                    H5P_CLS_DATASET_ACCESS_g   = NULL;
648
1
                    H5P_CLS_DATASET_CREATE_g   = NULL;
649
1
                    H5P_CLS_DATASET_XFER_g     = NULL;
650
1
                    H5P_CLS_DATATYPE_ACCESS_g  = NULL;
651
1
                    H5P_CLS_DATATYPE_CREATE_g  = NULL;
652
1
                    H5P_CLS_FILE_ACCESS_g      = NULL;
653
1
                    H5P_CLS_FILE_CREATE_g      = NULL;
654
1
                    H5P_CLS_FILE_MOUNT_g       = NULL;
655
1
                    H5P_CLS_GROUP_ACCESS_g     = NULL;
656
1
                    H5P_CLS_GROUP_CREATE_g     = NULL;
657
1
                    H5P_CLS_LINK_ACCESS_g      = NULL;
658
1
                    H5P_CLS_LINK_CREATE_g      = NULL;
659
1
                    H5P_CLS_MAP_ACCESS_g       = NULL;
660
1
                    H5P_CLS_MAP_CREATE_g       = NULL;
661
1
                    H5P_CLS_OBJECT_COPY_g      = NULL;
662
1
                    H5P_CLS_OBJECT_CREATE_g    = NULL;
663
1
                    H5P_CLS_REFERENCE_ACCESS_g = NULL;
664
1
                    H5P_CLS_STRING_CREATE_g    = NULL;
665
1
                    H5P_CLS_VOL_INITIALIZE_g   = NULL;
666
667
1
                    H5P_CLS_ROOT_ID_g = H5I_INVALID_HID;
668
669
1
                    H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID;
670
1
                    H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID;
671
1
                    H5P_CLS_DATASET_ACCESS_ID_g   = H5I_INVALID_HID;
672
1
                    H5P_CLS_DATASET_CREATE_ID_g   = H5I_INVALID_HID;
673
1
                    H5P_CLS_DATASET_XFER_ID_g     = H5I_INVALID_HID;
674
1
                    H5P_CLS_DATATYPE_ACCESS_ID_g  = H5I_INVALID_HID;
675
1
                    H5P_CLS_DATATYPE_CREATE_ID_g  = H5I_INVALID_HID;
676
1
                    H5P_CLS_FILE_ACCESS_ID_g      = H5I_INVALID_HID;
677
1
                    H5P_CLS_FILE_CREATE_ID_g      = H5I_INVALID_HID;
678
1
                    H5P_CLS_FILE_MOUNT_ID_g       = H5I_INVALID_HID;
679
1
                    H5P_CLS_GROUP_ACCESS_ID_g     = H5I_INVALID_HID;
680
1
                    H5P_CLS_GROUP_CREATE_ID_g     = H5I_INVALID_HID;
681
1
                    H5P_CLS_LINK_ACCESS_ID_g      = H5I_INVALID_HID;
682
1
                    H5P_CLS_LINK_CREATE_ID_g      = H5I_INVALID_HID;
683
1
                    H5P_CLS_MAP_ACCESS_ID_g       = H5I_INVALID_HID;
684
1
                    H5P_CLS_MAP_CREATE_ID_g       = H5I_INVALID_HID;
685
1
                    H5P_CLS_OBJECT_COPY_ID_g      = H5I_INVALID_HID;
686
1
                    H5P_CLS_OBJECT_CREATE_ID_g    = H5I_INVALID_HID;
687
1
                    H5P_CLS_REFERENCE_ACCESS_ID_g = H5I_INVALID_HID;
688
1
                    H5P_CLS_STRING_CREATE_ID_g    = H5I_INVALID_HID;
689
1
                    H5P_CLS_VOL_INITIALIZE_ID_g   = H5I_INVALID_HID;
690
1
                }
691
1
            }
692
693
2
            n++; /*H5I*/
694
2
        }
695
1
        else {
696
            /* Destroy the property list and class id groups */
697
1
            n += (H5I_dec_type_ref(H5I_GENPROP_LST) > 0);
698
1
            n += (H5I_dec_type_ref(H5I_GENPROP_CLS) > 0);
699
700
            /* Mark closed */
701
1
            if (0 == n)
702
1
                H5_PKG_INIT_VAR = false;
703
1
        } /* end else */
704
3
    }     /* end if */
705
706
3
    FUNC_LEAVE_NOAPI(n)
707
99
} /* end H5P_term_package() */
708
709
/*-------------------------------------------------------------------------
710
 * Function:    H5P__close_class_cb
711
 *
712
 * Purpose:     Called when the ref count reaches zero on a property class's ID
713
 *
714
 * Return:      SUCCEED / FAIL
715
 *
716
 *-------------------------------------------------------------------------
717
 */
718
static herr_t
719
H5P__close_class_cb(void *_pclass, void H5_ATTR_UNUSED **request)
720
22
{
721
22
    H5P_genclass_t *pclass    = (H5P_genclass_t *)_pclass; /* Property list class to close */
722
22
    herr_t          ret_value = SUCCEED;                   /* Return value */
723
724
22
    FUNC_ENTER_PACKAGE
725
726
    /* Sanity check */
727
22
    assert(pclass);
728
729
    /* Close the property list class object */
730
22
    if (H5P__close_class(pclass) < 0)
731
0
        HGOTO_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list class");
732
733
22
done:
734
22
    FUNC_LEAVE_NOAPI(ret_value)
735
22
} /* end H5P__close_class_cb() */
736
737
/*-------------------------------------------------------------------------
738
 * Function:    H5P__close_list_cb
739
 *
740
 * Purpose:     Called when the ref count reaches zero on a property list's ID
741
 *
742
 * Return:      SUCCEED / FAIL
743
 *
744
 *-------------------------------------------------------------------------
745
 */
746
static herr_t
747
H5P__close_list_cb(void *_plist, void H5_ATTR_UNUSED **request)
748
2.04k
{
749
2.04k
    H5P_genplist_t *plist     = (H5P_genplist_t *)_plist; /* Property list to close */
750
2.04k
    herr_t          ret_value = SUCCEED;                  /* Return value */
751
752
2.04k
    FUNC_ENTER_PACKAGE
753
754
    /* Sanity check */
755
2.04k
    assert(plist);
756
757
    /* Close the property list object */
758
2.04k
    if (H5P_close(plist) < 0)
759
0
        HGOTO_ERROR(H5E_PLIST, H5E_CLOSEERROR, FAIL, "unable to close property list");
760
761
2.04k
done:
762
2.04k
    FUNC_LEAVE_NOAPI(ret_value)
763
2.04k
} /* end H5P__close_list_cb() */
764
765
/*--------------------------------------------------------------------------
766
 NAME
767
    H5P__do_prop_cb1
768
 PURPOSE
769
    Internal routine to call a property list callback routine and update
770
    the property list accordingly.
771
 USAGE
772
    herr_t H5P__do_prop_cb1(slist,prop,cb)
773
        H5SL_t *slist;          IN/OUT: Skip list to hold changed properties
774
        H5P_genprop_t *prop;    IN: Property to call callback for
775
        H5P_prp_cb1_t *cb;      IN: Callback routine to call
776
 RETURNS
777
    Returns non-negative on success, negative on failure.
778
 DESCRIPTION
779
        Calls the callback routine passed in.  If the callback routine changes
780
    the property value, then the property is duplicated and added to skip list.
781
782
 GLOBAL VARIABLES
783
 COMMENTS, BUGS, ASSUMPTIONS
784
 EXAMPLES
785
 REVISION LOG
786
--------------------------------------------------------------------------*/
787
static herr_t
788
H5P__do_prop_cb1(H5SL_t *slist, H5P_genprop_t *prop, H5P_prp_cb1_t cb)
789
4.75k
{
790
4.75k
    void          *tmp_value = NULL;    /* Temporary value buffer */
791
4.75k
    H5P_genprop_t *pcopy     = NULL;    /* Copy of property to insert into skip list */
792
4.75k
    herr_t         ret_value = SUCCEED; /* Return value */
793
794
4.75k
    FUNC_ENTER_PACKAGE
795
796
    /* Sanity check */
797
4.75k
    assert(slist);
798
4.75k
    assert(prop);
799
4.75k
    assert(prop->cmp);
800
4.75k
    assert(cb);
801
802
    /* Allocate space for a temporary copy of the property value */
803
4.75k
    if (NULL == (tmp_value = H5MM_malloc(prop->size)))
804
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed for temporary property value");
805
4.75k
    H5MM_memcpy(tmp_value, prop->value, prop->size);
806
807
    /* Prepare & restore library for user callback */
808
4.75k
    H5_BEFORE_USER_CB(FAIL)
809
4.75k
        {
810
            /* Call "type 1" callback ('create', 'copy' or 'close') */
811
4.75k
            ret_value = cb(prop->name, prop->size, tmp_value);
812
4.75k
        }
813
4.75k
    H5_AFTER_USER_CB(FAIL)
814
4.75k
    if (ret_value < 0)
815
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "Property callback failed");
816
817
    /* Make a copy of the class's property */
818
4.75k
    if (NULL == (pcopy = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)))
819
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
820
821
    /* Copy the changed value into the new property */
822
4.75k
    H5MM_memcpy(pcopy->value, tmp_value, prop->size);
823
824
    /* Insert the changed property into the property list */
825
4.75k
    if (H5P__add_prop(slist, pcopy) < 0)
826
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert property into skip list");
827
828
4.75k
done:
829
    /* Release the temporary value buffer */
830
4.75k
    if (tmp_value)
831
4.75k
        H5MM_xfree(tmp_value);
832
833
    /* Cleanup on failure */
834
4.75k
    if (ret_value < 0)
835
0
        if (pcopy)
836
0
            H5P__free_prop(pcopy);
837
838
4.75k
    FUNC_LEAVE_NOAPI(ret_value)
839
4.75k
} /* end H5P__do_prop_cb1() */
840
841
/*--------------------------------------------------------------------------
842
 NAME
843
    H5P__copy_pclass
844
 PURPOSE
845
    Internal routine to copy a generic property class
846
 USAGE
847
    hid_t H5P__copy_pclass(pclass)
848
        H5P_genclass_t *pclass;      IN: Property class to copy
849
 RETURNS
850
    Success: valid property class ID on success (non-negative)
851
    Failure: negative
852
 DESCRIPTION
853
    Copy a property class and return the ID.  This routine does not make
854
    any callbacks.  (They are only make when operating on property lists).
855
856
 GLOBAL VARIABLES
857
 COMMENTS, BUGS, ASSUMPTIONS
858
 EXAMPLES
859
 REVISION LOG
860
--------------------------------------------------------------------------*/
861
H5P_genclass_t *
862
H5P__copy_pclass(H5P_genclass_t *pclass)
863
0
{
864
0
    H5P_genclass_t *new_pclass = NULL; /* Property list class copied */
865
0
    H5P_genprop_t  *pcopy;             /* Copy of property to insert into class */
866
0
    H5P_genclass_t *ret_value = NULL;  /* return value */
867
868
0
    FUNC_ENTER_PACKAGE
869
870
0
    assert(pclass);
871
872
    /*
873
     * Create new property class object
874
     */
875
876
    /* Create the new property list class */
877
0
    if (NULL == (new_pclass = H5P__create_class(pclass->parent, pclass->name, pclass->type,
878
0
                                                pclass->create_func, pclass->create_data, pclass->copy_func,
879
0
                                                pclass->copy_data, pclass->close_func, pclass->close_data)))
880
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "unable to create property list class");
881
882
    /* Copy the properties registered for this class */
883
0
    if (pclass->nprops > 0) {
884
0
        H5SL_node_t *curr_node; /* Current node in skip list */
885
886
        /* Walk through the properties in the old class */
887
0
        curr_node = H5SL_first(pclass->props);
888
0
        while (curr_node != NULL) {
889
            /* Make a copy of the class's property */
890
0
            if (NULL == (pcopy = H5P__dup_prop((H5P_genprop_t *)H5SL_item(curr_node), H5P_PROP_WITHIN_CLASS)))
891
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "Can't copy property");
892
893
            /* Insert the initialized property into the property list */
894
0
            if (H5P__add_prop(new_pclass->props, pcopy) < 0)
895
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, NULL, "Can't insert property into class");
896
897
            /* Increment property count for class */
898
0
            new_pclass->nprops++;
899
900
            /* Get the next property node in the list */
901
0
            curr_node = H5SL_next(curr_node);
902
0
        } /* end while */
903
0
    }     /* end if */
904
905
    /* Set the return value */
906
0
    ret_value = new_pclass;
907
908
0
done:
909
0
    if (NULL == ret_value && new_pclass)
910
0
        H5P__close_class(new_pclass);
911
912
0
    FUNC_LEAVE_NOAPI(ret_value)
913
0
} /* H5P__copy_pclass() */
914
915
/*--------------------------------------------------------------------------
916
 NAME
917
    H5P_copy_plist
918
 PURPOSE
919
    Internal routine to copy a generic property list
920
 USAGE
921
        hid_t H5P_copy_plist(old_plist_id)
922
            hid_t old_plist_id;             IN: Property list ID to copy
923
 RETURNS
924
    Success: valid property list ID on success (non-negative)
925
    Failure: H5I_INVALID_HID
926
 DESCRIPTION
927
    Copy a property list and return the ID.  This routine calls the
928
    class 'copy' callback after any property 'copy' callbacks are called
929
    (assuming all property 'copy' callbacks return successfully).
930
931
 GLOBAL VARIABLES
932
 COMMENTS, BUGS, ASSUMPTIONS
933
 EXAMPLES
934
 REVISION LOG
935
--------------------------------------------------------------------------*/
936
hid_t
937
H5P_copy_plist(const H5P_genplist_t *old_plist, bool app_ref)
938
2.03k
{
939
2.03k
    H5P_genclass_t *tclass;           /* Temporary class pointer */
940
2.03k
    H5P_genplist_t *new_plist = NULL; /* New property list generated from copy */
941
2.03k
    H5P_genprop_t  *tmp;              /* Temporary pointer to properties */
942
2.03k
    H5P_genprop_t  *new_prop;         /* New property created for copy */
943
2.03k
    hid_t           new_plist_id;     /* Property list ID of new list created */
944
2.03k
    H5SL_node_t    *curr_node;        /* Current node in skip list */
945
2.03k
    H5SL_t         *seen = NULL;      /* Skip list containing properties already seen */
946
2.03k
    size_t          nseen;            /* Number of items 'seen' */
947
2.03k
    bool            has_parent_class; /* Flag to indicate that this property list's class has a parent */
948
2.03k
    hid_t           ret_value = H5I_INVALID_HID; /* return value */
949
950
2.03k
    FUNC_ENTER_NOAPI(H5I_INVALID_HID)
951
952
2.03k
    assert(old_plist);
953
954
    /*
955
     * Create new property list object
956
     */
957
958
    /* Allocate room for the property list */
959
2.03k
    if (NULL == (new_plist = H5FL_CALLOC(H5P_genplist_t)))
960
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed");
961
962
    /* Set class state */
963
2.03k
    new_plist->pclass     = old_plist->pclass;
964
2.03k
    new_plist->nprops     = 0;     /* Initially the plist has the same number of properties as the class */
965
2.03k
    new_plist->class_init = false; /* Initially, wait until the class callback finishes to set */
966
967
    /* Initialize the skip list to hold the changed properties */
968
2.03k
    if ((new_plist->props = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
969
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID,
970
2.03k
                    "can't create skip list for changed properties");
971
972
    /* Create the skip list for deleted properties */
973
2.03k
    if ((new_plist->del = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
974
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID,
975
2.03k
                    "can't create skip list for deleted properties");
976
977
    /* Create the skip list to hold names of properties already seen
978
     * (This prevents a property in the class hierarchy from having it's
979
     * 'create' callback called, if a property in the class hierarchy has
980
     * already been seen)
981
     */
982
2.03k
    if ((seen = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
983
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID, "can't create skip list for seen properties");
984
2.03k
    nseen = 0;
985
986
    /* Cycle through the deleted properties & copy them into the new list's deleted section */
987
2.03k
    if (H5SL_count(old_plist->del) > 0) {
988
0
        curr_node = H5SL_first(old_plist->del);
989
0
        while (curr_node) {
990
0
            char *new_name; /* Pointer to new name */
991
992
            /* Duplicate string for insertion into new deleted property skip list */
993
0
            if ((new_name = H5MM_xstrdup((char *)H5SL_item(curr_node))) == NULL)
994
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed");
995
996
            /* Insert property name into deleted list */
997
0
            if (H5SL_insert(new_plist->del, new_name, new_name) < 0)
998
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5I_INVALID_HID,
999
0
                            "can't insert property into deleted skip list");
1000
1001
            /* Add property name to "seen" list */
1002
0
            if (H5SL_insert(seen, new_name, new_name) < 0)
1003
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5I_INVALID_HID,
1004
0
                            "can't insert property into seen skip list");
1005
0
            nseen++;
1006
1007
            /* Get the next property node in the skip list */
1008
0
            curr_node = H5SL_next(curr_node);
1009
0
        } /* end while */
1010
0
    }     /* end if */
1011
1012
    /* Cycle through the properties and copy them also */
1013
2.03k
    if (H5SL_count(old_plist->props) > 0) {
1014
14
        curr_node = H5SL_first(old_plist->props);
1015
42
        while (curr_node) {
1016
            /* Get a pointer to the node's property */
1017
28
            tmp = (H5P_genprop_t *)H5SL_item(curr_node);
1018
1019
            /* Make a copy of the list's property */
1020
28
            if (NULL == (new_prop = H5P__dup_prop(tmp, H5P_PROP_WITHIN_LIST)))
1021
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, H5I_INVALID_HID, "Can't copy property");
1022
1023
            /* Call property copy callback, if it exists */
1024
28
            if (new_prop->copy) {
1025
28
                herr_t status;
1026
1027
                /* Prepare & restore library for user callback */
1028
28
                H5_BEFORE_USER_CB(H5I_INVALID_HID)
1029
28
                    {
1030
28
                        status = (new_prop->copy)(new_prop->name, new_prop->size, new_prop->value);
1031
28
                    }
1032
28
                H5_AFTER_USER_CB(H5I_INVALID_HID)
1033
28
                if (status < 0) {
1034
0
                    H5P__free_prop(new_prop);
1035
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, H5I_INVALID_HID, "Can't copy property");
1036
0
                } /* end if */
1037
28
            }     /* end if */
1038
1039
            /* Insert the initialized property into the property list */
1040
28
            if (H5P__add_prop(new_plist->props, new_prop) < 0) {
1041
0
                H5P__free_prop(new_prop);
1042
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5I_INVALID_HID, "Can't insert property into list");
1043
0
            } /* end if */
1044
1045
            /* Add property name to "seen" list */
1046
28
            if (H5SL_insert(seen, new_prop->name, new_prop->name) < 0)
1047
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5I_INVALID_HID,
1048
28
                            "can't insert property into seen skip list");
1049
28
            nseen++;
1050
1051
            /* Increment the number of properties in list */
1052
28
            new_plist->nprops++;
1053
1054
            /* Get the next property node in the skip list */
1055
28
            curr_node = H5SL_next(curr_node);
1056
28
        } /* end while */
1057
14
    }     /* end if */
1058
1059
    /*
1060
     * Check for copying class properties (up through list of parent classes also),
1061
     * initialize each with default value & make property 'copy' callback.
1062
     */
1063
2.03k
    tclass           = old_plist->pclass;
1064
2.03k
    has_parent_class = (bool)(tclass != NULL && tclass->parent != NULL && tclass->parent->nprops > 0);
1065
9.22k
    while (tclass != NULL) {
1066
7.19k
        if (tclass->nprops > 0) {
1067
            /* Walk through the properties in the old class */
1068
5.16k
            curr_node = H5SL_first(tclass->props);
1069
39.4k
            while (curr_node != NULL) {
1070
                /* Get pointer to property from node */
1071
34.3k
                tmp = (H5P_genprop_t *)H5SL_item(curr_node);
1072
1073
                /* Only "copy" properties we haven't seen before */
1074
34.3k
                if (nseen == 0 || H5SL_search(seen, tmp->name) == NULL) {
1075
                    /* Call property copy callback, if it exists */
1076
34.3k
                    if (tmp->copy) {
1077
                        /* Call the callback & insert changed value into skip list (if necessary) */
1078
4.75k
                        if (H5P__do_prop_cb1(new_plist->props, tmp, tmp->copy) < 0)
1079
0
                            HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, H5I_INVALID_HID, "Can't create property");
1080
4.75k
                    } /* end if */
1081
1082
                    /* Add property name to "seen" list, if we have other classes to work on */
1083
34.3k
                    if (has_parent_class) {
1084
33.8k
                        if (H5SL_insert(seen, tmp->name, tmp->name) < 0)
1085
0
                            HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5I_INVALID_HID,
1086
33.8k
                                        "can't insert property into seen skip list");
1087
33.8k
                        nseen++;
1088
33.8k
                    } /* end if */
1089
1090
                    /* Increment the number of properties in list */
1091
34.3k
                    new_plist->nprops++;
1092
34.3k
                } /* end if */
1093
1094
                /* Get the next property node in the skip list */
1095
34.3k
                curr_node = H5SL_next(curr_node);
1096
34.3k
            } /* end while */
1097
5.16k
        }     /* end if */
1098
1099
        /* Go up to parent class */
1100
7.19k
        tclass = tclass->parent;
1101
7.19k
    } /* end while */
1102
1103
    /* Increment the number of property lists derived from class */
1104
2.03k
    if (H5P__access_class(new_plist->pclass, H5P_MOD_INC_LST) < 0)
1105
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, H5I_INVALID_HID, "Can't increment class ref count");
1106
1107
    /* Get an ID for the property list */
1108
2.03k
    if ((new_plist_id = H5I_register(H5I_GENPROP_LST, new_plist, app_ref)) < 0)
1109
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register property list");
1110
1111
    /* Save the property list ID in the property list struct, for use in the property class's 'close' callback
1112
     */
1113
2.03k
    new_plist->plist_id = new_plist_id;
1114
1115
    /* Call the class callback (if it exists) now that we have the property list ID
1116
     * (up through chain of parent classes also)
1117
     */
1118
2.03k
    tclass = new_plist->pclass;
1119
9.22k
    while (NULL != tclass) {
1120
7.19k
        if (NULL != tclass->copy_func) {
1121
0
            herr_t status;
1122
1123
            /* Prepare & restore library for user callback */
1124
0
            H5_BEFORE_USER_CB(H5I_INVALID_HID)
1125
0
                {
1126
0
                    status =
1127
0
                        (tclass->copy_func)(new_plist_id, old_plist->plist_id, old_plist->pclass->copy_data);
1128
0
                }
1129
0
            H5_AFTER_USER_CB(H5I_INVALID_HID)
1130
0
            if (status < 0) {
1131
                /* Delete ID, ignore return value */
1132
0
                H5I_remove(new_plist_id);
1133
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, H5I_INVALID_HID, "Can't initialize property");
1134
0
            } /* end if */
1135
0
        }     /* end if */
1136
1137
        /* Go up to parent class */
1138
7.19k
        tclass = tclass->parent;
1139
7.19k
    } /* end while */
1140
1141
    /* Set the class initialization flag */
1142
2.03k
    new_plist->class_init = true;
1143
1144
    /* Set the return value */
1145
2.03k
    ret_value = new_plist_id;
1146
1147
2.03k
done:
1148
    /* Release the list of 'seen' properties */
1149
2.03k
    if (seen != NULL)
1150
2.03k
        H5SL_close(seen);
1151
1152
2.03k
    if (H5I_INVALID_HID == ret_value && new_plist)
1153
0
        H5P_close(new_plist);
1154
1155
2.03k
    FUNC_LEAVE_NOAPI(ret_value)
1156
2.03k
} /* H5P_copy_plist() */
1157
1158
/*--------------------------------------------------------------------------
1159
 NAME
1160
    H5P__dup_prop
1161
 PURPOSE
1162
    Internal routine to duplicate a property
1163
 USAGE
1164
    H5P_genprop_t *H5P__dup_prop(oprop)
1165
        H5P_genprop_t *oprop;   IN: Pointer to property to copy
1166
        H5P_prop_within_t type; IN: Type of object the property will be inserted into
1167
 RETURNS
1168
    Returns a pointer to the newly created duplicate of a property on success,
1169
        NULL on failure.
1170
 DESCRIPTION
1171
    Allocates memory and copies property information into a new property object.
1172
 GLOBAL VARIABLES
1173
 COMMENTS, BUGS, ASSUMPTIONS
1174
 EXAMPLES
1175
 REVISION LOG
1176
--------------------------------------------------------------------------*/
1177
static H5P_genprop_t *
1178
H5P__dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
1179
12.1k
{
1180
12.1k
    H5P_genprop_t *prop      = NULL; /* Pointer to new property copied */
1181
12.1k
    H5P_genprop_t *ret_value = NULL; /* Return value */
1182
1183
12.1k
    FUNC_ENTER_PACKAGE
1184
1185
12.1k
    assert(oprop);
1186
12.1k
    assert(type != H5P_PROP_WITHIN_UNKNOWN);
1187
1188
    /* Allocate the new property */
1189
12.1k
    if (NULL == (prop = H5FL_MALLOC(H5P_genprop_t)))
1190
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1191
1192
    /* Copy basic property information */
1193
12.1k
    H5MM_memcpy(prop, oprop, sizeof(H5P_genprop_t));
1194
1195
    /* Check if we should duplicate the name or share it */
1196
1197
    /* Duplicating property for a class */
1198
12.1k
    if (type == H5P_PROP_WITHIN_CLASS) {
1199
0
        assert(oprop->type == H5P_PROP_WITHIN_CLASS);
1200
0
        assert(oprop->shared_name == false);
1201
1202
        /* Duplicate name */
1203
0
        prop->name = H5MM_xstrdup(oprop->name);
1204
0
    } /* end if */
1205
    /* Duplicating property for a list */
1206
12.1k
    else {
1207
        /* Check if we are duplicating a property from a list or a class */
1208
1209
        /* Duplicating a property from a list */
1210
12.1k
        if (oprop->type == H5P_PROP_WITHIN_LIST) {
1211
            /* If the old property's name wasn't shared, we have to copy it here also */
1212
28
            if (!oprop->shared_name)
1213
0
                prop->name = H5MM_xstrdup(oprop->name);
1214
28
        } /* end if */
1215
        /* Duplicating a property from a class */
1216
12.0k
        else {
1217
12.0k
            assert(oprop->type == H5P_PROP_WITHIN_CLASS);
1218
12.0k
            assert(oprop->shared_name == false);
1219
1220
            /* Share the name */
1221
12.0k
            prop->shared_name = true;
1222
1223
            /* Set the type */
1224
12.0k
            prop->type = type;
1225
12.0k
        } /* end else */
1226
12.1k
    }     /* end else */
1227
1228
    /* Duplicate current value, if it exists */
1229
12.1k
    if (oprop->value != NULL) {
1230
12.1k
        assert(prop->size > 0);
1231
12.1k
        if (NULL == (prop->value = H5MM_malloc(prop->size)))
1232
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1233
12.1k
        H5MM_memcpy(prop->value, oprop->value, prop->size);
1234
12.1k
    } /* end if */
1235
1236
    /* Set return value */
1237
12.1k
    ret_value = prop;
1238
1239
12.1k
done:
1240
    /* Free any resources allocated */
1241
12.1k
    if (ret_value == NULL) {
1242
0
        if (prop != NULL) {
1243
0
            if (prop->name != NULL)
1244
0
                H5MM_xfree(prop->name);
1245
0
            if (prop->value != NULL)
1246
0
                H5MM_xfree(prop->value);
1247
0
            prop = H5FL_FREE(H5P_genprop_t, prop);
1248
0
        } /* end if */
1249
0
    }     /* end if */
1250
1251
12.1k
    FUNC_LEAVE_NOAPI(ret_value)
1252
12.1k
} /* H5P__dup_prop() */
1253
1254
/*--------------------------------------------------------------------------
1255
 NAME
1256
    H5P__create_prop
1257
 PURPOSE
1258
    Internal routine to create a new property
1259
 USAGE
1260
    H5P_genprop_t *H5P__create_prop(name,size,type,value,prp_create,prp_set,
1261
                                   prp_get,prp_delete,prp_close, prp_encode, prp_decode)
1262
        const char *name;       IN: Name of property to register
1263
        size_t size;            IN: Size of property in bytes
1264
        H5P_prop_within_t type; IN: Type of object the property will be inserted into
1265
        void *value;            IN: Pointer to buffer containing value for property
1266
        H5P_prp_create_func_t prp_create;   IN: Function pointer to property
1267
                                    creation callback
1268
        H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback
1269
        H5P_prp_get_func_t prp_get; IN: Function pointer to property get callback
1270
        H5P_prp_encode_func_t prp_encode; IN: Function pointer to property encode
1271
        H5P_prp_decode_func_t prp_decode; IN: Function pointer to property decode
1272
        H5P_prp_delete_func_t prp_delete; IN: Function pointer to property delete callback
1273
        H5P_prp_copy_func_t prp_copy; IN: Function pointer to property copy callback
1274
        H5P_prp_compare_func_t prp_cmp; IN: Function pointer to property compare callback
1275
        H5P_prp_close_func_t prp_close; IN: Function pointer to property close
1276
                                    callback
1277
 RETURNS
1278
    Returns a pointer to the newly created property on success,
1279
        NULL on failure.
1280
 DESCRIPTION
1281
    Allocates memory and copies property information into a new property object.
1282
 GLOBAL VARIABLES
1283
 COMMENTS, BUGS, ASSUMPTIONS
1284
 EXAMPLES
1285
 REVISION LOG
1286
--------------------------------------------------------------------------*/
1287
static H5P_genprop_t *
1288
H5P__create_prop(const char *name, size_t size, H5P_prop_within_t type, const void *value,
1289
                 H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
1290
                 H5P_prp_encode_func_t prp_encode, H5P_prp_decode_func_t prp_decode,
1291
                 H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
1292
                 H5P_prp_compare_func_t prp_cmp, H5P_prp_close_func_t prp_close)
1293
114
{
1294
114
    H5P_genprop_t *prop      = NULL; /* Pointer to new property copied */
1295
114
    H5P_genprop_t *ret_value = NULL; /* Return value */
1296
1297
114
    FUNC_ENTER_PACKAGE
1298
1299
114
    assert(name);
1300
114
    assert((size > 0 && value != NULL) || (size == 0));
1301
114
    assert(type != H5P_PROP_WITHIN_UNKNOWN);
1302
1303
    /* Allocate the new property */
1304
114
    if (NULL == (prop = H5FL_MALLOC(H5P_genprop_t)))
1305
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1306
1307
    /* Set the property initial values */
1308
114
    prop->name        = H5MM_xstrdup(name); /* Duplicate name */
1309
114
    prop->shared_name = false;
1310
114
    prop->size        = size;
1311
114
    prop->type        = type;
1312
1313
    /* Duplicate value, if it exists */
1314
114
    if (value != NULL) {
1315
114
        if (NULL == (prop->value = H5MM_malloc(prop->size)))
1316
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1317
114
        H5MM_memcpy(prop->value, value, prop->size);
1318
114
    } /* end if */
1319
0
    else
1320
0
        prop->value = NULL;
1321
1322
    /* Set the function pointers */
1323
114
    prop->create = prp_create;
1324
114
    prop->set    = prp_set;
1325
114
    prop->get    = prp_get;
1326
114
    prop->encode = prp_encode;
1327
114
    prop->decode = prp_decode;
1328
114
    prop->del    = prp_delete;
1329
114
    prop->copy   = prp_copy;
1330
    /* Use custom comparison routine if available, otherwise default to memcmp() */
1331
114
    if (prp_cmp != NULL)
1332
17
        prop->cmp = prp_cmp;
1333
97
    else
1334
97
        prop->cmp = &memcmp;
1335
114
    prop->close = prp_close;
1336
1337
    /* Set return value */
1338
114
    ret_value = prop;
1339
1340
114
done:
1341
    /* Free any resources allocated */
1342
114
    if (ret_value == NULL) {
1343
0
        if (prop != NULL) {
1344
0
            if (prop->name != NULL)
1345
0
                H5MM_xfree(prop->name);
1346
0
            if (prop->value != NULL)
1347
0
                H5MM_xfree(prop->value);
1348
0
            prop = H5FL_FREE(H5P_genprop_t, prop);
1349
0
        } /* end if */
1350
0
    }     /* end if */
1351
1352
114
    FUNC_LEAVE_NOAPI(ret_value)
1353
114
} /* H5P__create_prop() */
1354
1355
/*--------------------------------------------------------------------------
1356
 NAME
1357
    H5P__add_prop
1358
 PURPOSE
1359
    Internal routine to insert a property into a property skip list
1360
 USAGE
1361
    herr_t H5P__add_prop(slist, prop)
1362
        H5SL_t *slist;          IN/OUT: Pointer to skip list of properties
1363
        H5P_genprop_t *prop;    IN: Pointer to property to insert
1364
 RETURNS
1365
    Returns non-negative on success, negative on failure.
1366
 DESCRIPTION
1367
    Inserts a property into a skip list of properties.
1368
 GLOBAL VARIABLES
1369
 COMMENTS, BUGS, ASSUMPTIONS
1370
 EXAMPLES
1371
 REVISION LOG
1372
--------------------------------------------------------------------------*/
1373
herr_t
1374
H5P__add_prop(H5SL_t *slist, H5P_genprop_t *prop)
1375
12.2k
{
1376
12.2k
    herr_t ret_value = SUCCEED; /* Return value */
1377
1378
12.2k
    FUNC_ENTER_PACKAGE
1379
1380
12.2k
    assert(slist);
1381
12.2k
    assert(prop);
1382
12.2k
    assert(prop->type != H5P_PROP_WITHIN_UNKNOWN);
1383
1384
    /* Insert property into skip list */
1385
12.2k
    if (H5SL_insert(slist, prop, prop->name) < 0)
1386
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into skip list");
1387
1388
12.2k
done:
1389
12.2k
    FUNC_LEAVE_NOAPI(ret_value)
1390
12.2k
} /* H5P__add_prop() */
1391
1392
/*--------------------------------------------------------------------------
1393
 NAME
1394
    H5P__find_prop_plist
1395
 PURPOSE
1396
    Internal routine to check for a property in a property list's skip list
1397
 USAGE
1398
    H5P_genprop_t *H5P_find_prop(plist, name)
1399
        const H5P_genplist_t *plist;  IN: Pointer to property list to check
1400
        const char *name;       IN: Name of property to check for
1401
 RETURNS
1402
    Returns pointer to property on success, NULL on failure.
1403
 DESCRIPTION
1404
    Checks for a property in a property list's skip list of properties.
1405
 GLOBAL VARIABLES
1406
 COMMENTS, BUGS, ASSUMPTIONS
1407
 EXAMPLES
1408
 REVISION LOG
1409
--------------------------------------------------------------------------*/
1410
H5P_genprop_t *
1411
H5P__find_prop_plist(const H5P_genplist_t *plist, const char *name)
1412
0
{
1413
0
    H5P_genprop_t *ret_value = NULL; /* Return value */
1414
1415
0
    FUNC_ENTER_PACKAGE
1416
1417
0
    assert(plist);
1418
0
    assert(name);
1419
1420
    /* Check if the property has been deleted from list */
1421
0
    if (H5SL_search(plist->del, name) != NULL) {
1422
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "property deleted from skip list");
1423
0
    } /* end if */
1424
0
    else {
1425
        /* Get the property data from the skip list */
1426
0
        if (NULL == (ret_value = (H5P_genprop_t *)H5SL_search(plist->props, name))) {
1427
0
            H5P_genclass_t *tclass; /* Temporary class pointer */
1428
1429
            /* Couldn't find property in list itself, start searching through class info */
1430
0
            tclass = plist->pclass;
1431
0
            while (tclass != NULL) {
1432
                /* Find the property in the class */
1433
0
                if (NULL != (ret_value = (H5P_genprop_t *)H5SL_search(tclass->props, name)))
1434
                    /* Got pointer to property - leave now */
1435
0
                    break;
1436
1437
                /* Go up to parent class */
1438
0
                tclass = tclass->parent;
1439
0
            } /* end while */
1440
1441
            /* Check if we haven't found the property */
1442
0
            if (ret_value == NULL)
1443
0
                HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't find property in skip list");
1444
0
        } /* end else */
1445
0
    }     /* end else */
1446
1447
0
done:
1448
0
    FUNC_LEAVE_NOAPI(ret_value)
1449
0
} /* H5P__find_prop_plist() */
1450
1451
/*--------------------------------------------------------------------------
1452
 NAME
1453
    H5P__find_prop_pclass
1454
 PURPOSE
1455
    Internal routine to check for a property in a class skip list
1456
 USAGE
1457
    H5P_genprop_t *H5P__find_prop_class(pclass, name)
1458
        H5P_genclass *pclass;   IN: Pointer generic property class to check
1459
        const char *name;       IN: Name of property to check for
1460
 RETURNS
1461
    Returns pointer to property on success, NULL on failure.
1462
 DESCRIPTION
1463
    Checks for a property in a class's skip list of properties.
1464
 GLOBAL VARIABLES
1465
 COMMENTS, BUGS, ASSUMPTIONS
1466
 EXAMPLES
1467
 REVISION LOG
1468
--------------------------------------------------------------------------*/
1469
static H5P_genprop_t *
1470
H5P__find_prop_pclass(H5P_genclass_t *pclass, const char *name)
1471
0
{
1472
0
    H5P_genprop_t *ret_value = NULL; /* Return value */
1473
1474
0
    FUNC_ENTER_PACKAGE
1475
1476
0
    assert(pclass);
1477
0
    assert(name);
1478
1479
    /* Get the property from the skip list */
1480
0
    if (NULL == (ret_value = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
1481
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't find property in skip list");
1482
1483
0
done:
1484
0
    FUNC_LEAVE_NOAPI(ret_value)
1485
0
} /* H5P__find_prop_pclass() */
1486
1487
/*--------------------------------------------------------------------------
1488
 NAME
1489
    H5P__free_prop
1490
 PURPOSE
1491
    Internal routine to destroy a property node
1492
 USAGE
1493
    herr_t H5P__free_prop(prop)
1494
        H5P_genprop_t *prop;    IN: Pointer to property to destroy
1495
 RETURNS
1496
    Returns non-negative on success, negative on failure.
1497
 DESCRIPTION
1498
    Releases all the memory for a property list.  Does _not_ call the
1499
    properties 'close' callback, that should already have been done.
1500
 GLOBAL VARIABLES
1501
 COMMENTS, BUGS, ASSUMPTIONS
1502
 EXAMPLES
1503
 REVISION LOG
1504
--------------------------------------------------------------------------*/
1505
static herr_t
1506
H5P__free_prop(H5P_genprop_t *prop)
1507
12.2k
{
1508
12.2k
    FUNC_ENTER_PACKAGE_NOERR
1509
1510
12.2k
    assert(prop);
1511
1512
    /* Release the property value if it exists */
1513
12.2k
    if (prop->value)
1514
12.2k
        H5MM_xfree(prop->value);
1515
1516
    /* Only free the name if we own it */
1517
12.2k
    if (!prop->shared_name)
1518
114
        H5MM_xfree(prop->name);
1519
1520
12.2k
    prop = H5FL_FREE(H5P_genprop_t, prop);
1521
1522
12.2k
    FUNC_LEAVE_NOAPI(SUCCEED)
1523
12.2k
} /* H5P__free_prop() */
1524
1525
/*--------------------------------------------------------------------------
1526
 NAME
1527
    H5P__free_prop_cb
1528
 PURPOSE
1529
    Internal routine to free properties from a property skip list
1530
 USAGE
1531
    herr_t H5P__free_prop_cb(item, key, op_data)
1532
        void *item;             IN/OUT: Pointer to property
1533
        void *key;              IN/OUT: Pointer to property key
1534
        void *_make_cb;         IN: Whether to make property callbacks or not
1535
 RETURNS
1536
    Returns zero on success, negative on failure.
1537
 DESCRIPTION
1538
        Calls the property 'close' callback for a property & frees property
1539
    info.
1540
 GLOBAL VARIABLES
1541
 COMMENTS, BUGS, ASSUMPTIONS
1542
 EXAMPLES
1543
 REVISION LOG
1544
--------------------------------------------------------------------------*/
1545
static herr_t
1546
H5P__free_prop_cb(void *item, void H5_ATTR_UNUSED *key, void *op_data)
1547
12.2k
{
1548
12.2k
    H5P_genprop_t *tprop   = (H5P_genprop_t *)item; /* Temporary pointer to property */
1549
12.2k
    bool           make_cb = *(bool *)op_data;      /* Whether to make property 'close' callback */
1550
1551
12.2k
    FUNC_ENTER_PACKAGE_NOERR
1552
1553
12.2k
    assert(tprop);
1554
1555
    /* Call the close callback and ignore the return value, there's nothing we can do about it */
1556
12.2k
    if (make_cb && tprop->close != NULL) {
1557
        /* Prepare & restore library for user callback */
1558
0
        H5_BEFORE_USER_CB_NOCHECK
1559
0
            {
1560
                /* Call user's callback */
1561
0
                (tprop->close)(tprop->name, tprop->size, tprop->value);
1562
0
            }
1563
0
        H5_AFTER_USER_CB_NOCHECK
1564
0
    }
1565
1566
    /* Free the property, ignoring return value, nothing we can do */
1567
12.2k
    H5P__free_prop(tprop);
1568
1569
12.2k
    FUNC_LEAVE_NOAPI(0)
1570
12.2k
} /* H5P__free_prop_cb() */
1571
1572
/*--------------------------------------------------------------------------
1573
 NAME
1574
    H5P__free_del_name_cb
1575
 PURPOSE
1576
    Internal routine to free 'deleted' property name
1577
 USAGE
1578
    herr_t H5P__free_del_name_cb(item, key, op_data)
1579
        void *item;             IN/OUT: Pointer to deleted name
1580
        void *key;              IN/OUT: Pointer to key
1581
        void *op_data;          IN: Operator callback data (unused)
1582
 RETURNS
1583
    Returns zero on success, negative on failure.
1584
 DESCRIPTION
1585
    Frees the deleted property name
1586
 GLOBAL VARIABLES
1587
 COMMENTS, BUGS, ASSUMPTIONS
1588
 EXAMPLES
1589
 REVISION LOG
1590
--------------------------------------------------------------------------*/
1591
static herr_t
1592
H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *op_data)
1593
0
{
1594
0
    char *del_name = (char *)item; /* Temporary pointer to deleted name */
1595
1596
0
    FUNC_ENTER_PACKAGE_NOERR
1597
1598
0
    assert(del_name);
1599
1600
    /* Free the name */
1601
0
    H5MM_xfree(del_name);
1602
1603
0
    FUNC_LEAVE_NOAPI(0)
1604
0
} /* H5P__free_del_name_cb() */
1605
1606
/*--------------------------------------------------------------------------
1607
 NAME
1608
    H5P__access_class
1609
 PURPOSE
1610
    Internal routine to increment or decrement list & class dependencies on a
1611
        property list class
1612
 USAGE
1613
    herr_t H5P__access_class(pclass,mod)
1614
        H5P_genclass_t *pclass;     IN: Pointer to class to modify
1615
        H5P_class_mod_t mod;        IN: Type of modification to class
1616
 RETURNS
1617
    Returns non-negative on success, negative on failure.
1618
 DESCRIPTION
1619
        Increment/Decrement the class or list dependencies for a given class.
1620
    This routine is the final arbiter on decisions about actually releasing a
1621
    class in memory, such action is only taken when the reference counts for
1622
    both dependent classes & lists reach zero.
1623
 GLOBAL VARIABLES
1624
 COMMENTS, BUGS, ASSUMPTIONS
1625
 EXAMPLES
1626
 REVISION LOG
1627
--------------------------------------------------------------------------*/
1628
herr_t
1629
H5P__access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
1630
4.16k
{
1631
4.16k
    FUNC_ENTER_PACKAGE_NOERR
1632
1633
4.16k
    assert(pclass);
1634
4.16k
    assert(mod > H5P_MOD_ERR && mod < H5P_MOD_MAX);
1635
1636
4.16k
    switch (mod) {
1637
21
        case H5P_MOD_INC_CLS: /* Increment the dependent class count*/
1638
21
            pclass->classes++;
1639
21
            break;
1640
1641
21
        case H5P_MOD_DEC_CLS: /* Decrement the dependent class count*/
1642
21
            pclass->classes--;
1643
21
            break;
1644
1645
2.04k
        case H5P_MOD_INC_LST: /* Increment the dependent list count*/
1646
2.04k
            pclass->plists++;
1647
2.04k
            break;
1648
1649
2.04k
        case H5P_MOD_DEC_LST: /* Decrement the dependent list count*/
1650
2.04k
            pclass->plists--;
1651
2.04k
            break;
1652
1653
0
        case H5P_MOD_INC_REF: /* Increment the ID reference count*/
1654
            /* Reset the deleted flag if incrementing the reference count */
1655
0
            if (pclass->deleted)
1656
0
                pclass->deleted = false;
1657
0
            pclass->ref_count++;
1658
0
            break;
1659
1660
22
        case H5P_MOD_DEC_REF: /* Decrement the ID reference count*/
1661
22
            pclass->ref_count--;
1662
1663
            /* Mark the class object as deleted if reference count drops to zero */
1664
22
            if (pclass->ref_count == 0)
1665
22
                pclass->deleted = true;
1666
22
            break;
1667
1668
0
        case H5P_MOD_ERR:
1669
0
        case H5P_MOD_MAX:
1670
0
        default:
1671
0
            assert(0 && "Invalid H5P class modification");
1672
4.16k
    } /* end switch */
1673
1674
    /* Check if we can release the class information now */
1675
4.16k
    if (pclass->deleted && pclass->plists == 0 && pclass->classes == 0) {
1676
22
        H5P_genclass_t *par_class = pclass->parent; /* Pointer to class's parent */
1677
1678
22
        assert(pclass->name);
1679
22
        H5MM_xfree(pclass->name);
1680
1681
        /* Free the class properties without making callbacks */
1682
22
        if (pclass->props) {
1683
22
            bool make_cb = false;
1684
1685
22
            H5SL_destroy(pclass->props, H5P__free_prop_cb, &make_cb);
1686
22
        } /* end if */
1687
1688
22
        pclass = H5FL_FREE(H5P_genclass_t, pclass);
1689
1690
        /* Reduce the number of dependent classes on parent class also */
1691
22
        if (par_class != NULL)
1692
21
            H5P__access_class(par_class, H5P_MOD_DEC_CLS);
1693
22
    } /* end if */
1694
1695
4.16k
    FUNC_LEAVE_NOAPI(SUCCEED)
1696
4.16k
} /* H5P__access_class() */
1697
1698
/*--------------------------------------------------------------------------
1699
 NAME
1700
    H5P__open_class_path_cb
1701
 PURPOSE
1702
    Internal callback routine to check for duplicated names in parent class.
1703
 USAGE
1704
    int H5P__open_class_path_cb(obj, id, key)
1705
        H5P_genclass_t *obj;    IN: Pointer to class
1706
        hid_t id;               IN: ID of object being looked at
1707
        const void *key;        IN: Pointer to information used to compare
1708
                                    classes.
1709
 RETURNS
1710
    Returns >0 on match, 0 on no match and <0 on failure.
1711
 DESCRIPTION
1712
    Checks whether a property list class has the same parent and name as a
1713
    new class being created.  This is a callback routine for H5I_search()
1714
 GLOBAL VARIABLES
1715
 COMMENTS, BUGS, ASSUMPTIONS
1716
 EXAMPLES
1717
 REVISION LOG
1718
--------------------------------------------------------------------------*/
1719
static int
1720
H5P__open_class_path_cb(void *_obj, hid_t H5_ATTR_UNUSED id, void *_key)
1721
0
{
1722
0
    H5P_genclass_t    *obj       = (H5P_genclass_t *)_obj;    /* Pointer to the class for this ID */
1723
0
    H5P_check_class_t *key       = (H5P_check_class_t *)_key; /* Pointer to key information for comparison */
1724
0
    int                ret_value = 0;                         /* Return value */
1725
1726
0
    FUNC_ENTER_PACKAGE_NOERR
1727
1728
0
    assert(obj);
1729
0
    assert(H5I_GENPROP_CLS == H5I_get_type(id));
1730
0
    assert(key);
1731
1732
    /* Check if the class object has the same parent as the new class */
1733
0
    if (obj->parent == key->parent) {
1734
        /* Check if they have the same name */
1735
0
        if (strcmp(obj->name, key->name) == 0) {
1736
0
            key->new_class = obj;
1737
0
            ret_value      = 1; /* Indicate a match */
1738
0
        }                       /* end if */
1739
0
    }                           /* end if */
1740
1741
0
    FUNC_LEAVE_NOAPI(ret_value)
1742
0
} /* end H5P__open_class_path_cb() */
1743
1744
/*--------------------------------------------------------------------------
1745
 NAME
1746
    H5P__create_class
1747
 PURPOSE
1748
    Internal routine to create a new property list class.
1749
 USAGE
1750
    H5P_genclass_t H5P__create_class(par_class, name, type,
1751
                cls_create, create_data, cls_close, close_data)
1752
        H5P_genclass_t *par_class;  IN: Pointer to parent class
1753
        const char *name;       IN: Name of class we are creating
1754
        H5P_plist_type_t type;  IN: Type of class we are creating
1755
        H5P_cls_create_func_t;  IN: The callback function to call when each
1756
                                    property list in this class is created.
1757
        void *create_data;      IN: Pointer to user data to pass along to class
1758
                                    creation callback.
1759
        H5P_cls_copy_func_t;    IN: The callback function to call when each
1760
                                    property list in this class is copied.
1761
        void *copy_data;        IN: Pointer to user data to pass along to class
1762
                                    copy callback.
1763
        H5P_cls_close_func_t;   IN: The callback function to call when each
1764
                                    property list in this class is closed.
1765
        void *close_data;       IN: Pointer to user data to pass along to class
1766
                                    close callback.
1767
 RETURNS
1768
    Returns a pointer to the newly created property list class on success,
1769
        NULL on failure.
1770
 DESCRIPTION
1771
    Allocates memory and attaches a class to the property list class hierarchy.
1772
 GLOBAL VARIABLES
1773
 COMMENTS, BUGS, ASSUMPTIONS
1774
 EXAMPLES
1775
 REVISION LOG
1776
--------------------------------------------------------------------------*/
1777
H5P_genclass_t *
1778
H5P__create_class(H5P_genclass_t *par_class, const char *name, H5P_plist_type_t type,
1779
                  H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy,
1780
                  void *copy_data, H5P_cls_close_func_t cls_close, void *close_data)
1781
22
{
1782
22
    H5P_genclass_t *pclass    = NULL; /* Property list class created */
1783
22
    H5P_genclass_t *ret_value = NULL; /* Return value */
1784
1785
22
    FUNC_ENTER_PACKAGE
1786
1787
22
    assert(name);
1788
    /* Allow internal classes to break some rules */
1789
    /* (This allows the root of the tree to be created with this routine -QAK) */
1790
22
    if (type == H5P_TYPE_USER)
1791
22
        assert(par_class);
1792
1793
    /* Allocate room for the class */
1794
22
    if (NULL == (pclass = H5FL_CALLOC(H5P_genclass_t)))
1795
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, NULL, "property list class allocation failed");
1796
1797
    /* Set class state */
1798
22
    pclass->parent = par_class;
1799
22
    if (NULL == (pclass->name = H5MM_xstrdup(name)))
1800
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, NULL, "property list class name allocation failed");
1801
22
    pclass->type      = type;
1802
22
    pclass->nprops    = 0;                /* Classes are created without properties initially */
1803
22
    pclass->plists    = 0;                /* No properties lists of this class yet */
1804
22
    pclass->classes   = 0;                /* No classes derived from this class yet */
1805
22
    pclass->ref_count = 1;                /* This is the first reference to the new class */
1806
22
    pclass->deleted   = false;            /* Not deleted yet... :-) */
1807
22
    pclass->revision  = H5P_GET_NEXT_REV; /* Get a revision number for the class */
1808
1809
    /* Create the skip list for properties */
1810
22
    if (NULL == (pclass->props = H5SL_create(H5SL_TYPE_STR, NULL)))
1811
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "can't create skip list for properties");
1812
1813
    /* Set callback functions and pass-along data */
1814
22
    pclass->create_func = cls_create;
1815
22
    pclass->create_data = create_data;
1816
22
    pclass->copy_func   = cls_copy;
1817
22
    pclass->copy_data   = copy_data;
1818
22
    pclass->close_func  = cls_close;
1819
22
    pclass->close_data  = close_data;
1820
1821
    /* Increment parent class's derived class value */
1822
22
    if (par_class != NULL) {
1823
21
        if (H5P__access_class(par_class, H5P_MOD_INC_CLS) < 0)
1824
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, NULL, "Can't increment parent class ref count");
1825
21
    } /* end if */
1826
1827
    /* Set return value */
1828
22
    ret_value = pclass;
1829
1830
22
done:
1831
    /* Free any resources allocated */
1832
22
    if (ret_value == NULL)
1833
0
        if (pclass) {
1834
0
            if (pclass->name)
1835
0
                H5MM_xfree(pclass->name);
1836
0
            if (pclass->props) {
1837
0
                bool make_cb = false;
1838
1839
0
                H5SL_destroy(pclass->props, H5P__free_prop_cb, &make_cb);
1840
0
            } /* end if */
1841
0
            pclass = H5FL_FREE(H5P_genclass_t, pclass);
1842
0
        } /* end if */
1843
1844
22
    FUNC_LEAVE_NOAPI(ret_value)
1845
22
} /* H5P__create_class() */
1846
1847
/*--------------------------------------------------------------------------
1848
 NAME
1849
    H5P__create
1850
 PURPOSE
1851
    Internal routine to create a new property list of a property list class.
1852
 USAGE
1853
    H5P_genplist_t *H5P__create(class)
1854
        H5P_genclass_t *class;  IN: Property list class create list from
1855
 RETURNS
1856
    Returns a pointer to the newly created property list on success,
1857
        NULL on failure.
1858
 DESCRIPTION
1859
        Creates a property list of a given class.  If a 'create' callback
1860
    exists for the property list class, it is called before the
1861
    property list is passed back to the user.
1862
1863
 GLOBAL VARIABLES
1864
 COMMENTS, BUGS, ASSUMPTIONS
1865
        If this routine is called from a library routine other than
1866
    H5P_c, the calling routine is responsible for getting an ID for
1867
    the property list and calling the class 'create' callback (if one exists)
1868
    and also setting the "class_init" flag.
1869
 EXAMPLES
1870
 REVISION LOG
1871
--------------------------------------------------------------------------*/
1872
static H5P_genplist_t *
1873
H5P__create(H5P_genclass_t *pclass)
1874
19
{
1875
19
    H5P_genclass_t *tclass;           /* Temporary class pointer */
1876
19
    H5P_genplist_t *plist = NULL;     /* New property list created */
1877
19
    H5P_genprop_t  *tmp;              /* Temporary pointer to parent class properties */
1878
19
    H5SL_t         *seen      = NULL; /* Skip list to hold names of properties already seen */
1879
19
    H5P_genplist_t *ret_value = NULL; /* Return value */
1880
1881
19
    FUNC_ENTER_PACKAGE
1882
1883
19
    assert(pclass);
1884
1885
    /*
1886
     * Create new property list object
1887
     */
1888
1889
    /* Allocate room for the property list */
1890
19
    if (NULL == (plist = H5FL_CALLOC(H5P_genplist_t)))
1891
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1892
1893
    /* Set class state */
1894
19
    plist->pclass     = pclass;
1895
19
    plist->nprops     = 0;     /* Initially the plist has the same number of properties as the class */
1896
19
    plist->class_init = false; /* Initially, wait until the class callback finishes to set */
1897
1898
    /* Create the skip list for changed properties */
1899
19
    if ((plist->props = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
1900
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "can't create skip list for changed properties");
1901
1902
    /* Create the skip list for deleted properties */
1903
19
    if ((plist->del = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
1904
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "can't create skip list for deleted properties");
1905
1906
    /* Create the skip list to hold names of properties already seen
1907
     * (This prevents a property in the class hierarchy from having it's
1908
     * 'create' callback called, if a property in the class hierarchy has
1909
     * already been seen)
1910
     */
1911
19
    if ((seen = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
1912
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "can't create skip list for seen properties");
1913
1914
    /*
1915
     * Check if we should copy class properties (up through list of parent classes also),
1916
     * initialize each with default value & make property 'create' callback.
1917
     */
1918
19
    tclass = pclass;
1919
71
    while (tclass != NULL) {
1920
52
        if (tclass->nprops > 0) {
1921
25
            H5SL_node_t *curr_node; /* Current node in skip list */
1922
1923
            /* Walk through the properties in the old class */
1924
25
            curr_node = H5SL_first(tclass->props);
1925
221
            while (curr_node != NULL) {
1926
                /* Get pointer to property from node */
1927
196
                tmp = (H5P_genprop_t *)H5SL_item(curr_node);
1928
1929
                /* Only "create" properties we haven't seen before */
1930
196
                if (H5SL_search(seen, tmp->name) == NULL) {
1931
                    /* Call property creation callback, if it exists */
1932
196
                    if (tmp->create) {
1933
                        /* Call the callback & insert changed value into skip list (if necessary) */
1934
4
                        if (H5P__do_prop_cb1(plist->props, tmp, tmp->create) < 0)
1935
0
                            HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "Can't create property");
1936
4
                    } /* end if */
1937
1938
                    /* Add property name to "seen" list */
1939
196
                    if (H5SL_insert(seen, tmp->name, tmp->name) < 0)
1940
0
                        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, NULL,
1941
196
                                    "can't insert property into seen skip list");
1942
1943
                    /* Increment the number of properties in list */
1944
196
                    plist->nprops++;
1945
196
                } /* end if */
1946
1947
                /* Get the next property node in the skip list */
1948
196
                curr_node = H5SL_next(curr_node);
1949
196
            } /* end while */
1950
25
        }     /* end if */
1951
1952
        /* Go up to parent class */
1953
52
        tclass = tclass->parent;
1954
52
    } /* end while */
1955
1956
    /* Increment the number of property lists derived from class */
1957
19
    if (H5P__access_class(plist->pclass, H5P_MOD_INC_LST) < 0)
1958
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, NULL, "Can't increment class ref count");
1959
1960
    /* Set return value */
1961
19
    ret_value = plist;
1962
1963
19
done:
1964
    /* Release the skip list of 'seen' properties */
1965
19
    if (seen != NULL)
1966
19
        H5SL_close(seen);
1967
1968
    /* Release resources allocated on failure */
1969
19
    if (ret_value == NULL) {
1970
0
        if (plist != NULL) {
1971
            /* Close & free any changed properties */
1972
0
            if (plist->props) {
1973
0
                unsigned make_cb = 1;
1974
1975
0
                H5SL_destroy(plist->props, H5P__free_prop_cb, &make_cb);
1976
0
            } /* end if */
1977
1978
            /* Close the deleted property skip list */
1979
0
            if (plist->del)
1980
0
                H5SL_close(plist->del);
1981
1982
            /* Release the property list itself */
1983
0
            plist = H5FL_FREE(H5P_genplist_t, plist);
1984
0
        } /* end if */
1985
0
    }     /* end if */
1986
1987
19
    FUNC_LEAVE_NOAPI(ret_value)
1988
19
} /* H5P__create() */
1989
1990
/*--------------------------------------------------------------------------
1991
 NAME
1992
    H5P_create_id
1993
 PURPOSE
1994
    Internal routine to create a new property list of a property list class.
1995
 USAGE
1996
    hid_t H5P_create_id(pclass)
1997
        H5P_genclass_t *pclass;       IN: Property list class create list from
1998
 RETURNS
1999
    Returns a valid property list ID on success, H5I_INVALID_HID on failure.
2000
 DESCRIPTION
2001
        Creates a property list of a given class.  If a 'create' callback
2002
    exists for the property list class, it is called before the
2003
    property list is passed back to the user.  If 'create' callbacks exist for
2004
    any individual properties in the property list, they are called before the
2005
    class 'create' callback.
2006
2007
 GLOBAL VARIABLES
2008
 COMMENTS, BUGS, ASSUMPTIONS
2009
 EXAMPLES
2010
 REVISION LOG
2011
--------------------------------------------------------------------------*/
2012
hid_t
2013
H5P_create_id(H5P_genclass_t *pclass, bool app_ref)
2014
19
{
2015
19
    H5P_genclass_t *tclass;                      /* Temporary class pointer */
2016
19
    H5P_genplist_t *plist     = NULL;            /* Property list created */
2017
19
    hid_t           plist_id  = FAIL;            /* Property list ID */
2018
19
    hid_t           ret_value = H5I_INVALID_HID; /* return value */
2019
2020
19
    FUNC_ENTER_NOAPI(H5I_INVALID_HID)
2021
2022
19
    assert(pclass);
2023
2024
    /* Create the new property list */
2025
19
    if ((plist = H5P__create(pclass)) == NULL)
2026
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create property list");
2027
2028
    /* Get an ID for the property list */
2029
19
    if ((plist_id = H5I_register(H5I_GENPROP_LST, plist, app_ref)) < 0)
2030
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register property list");
2031
2032
    /* Save the property list ID in the property list struct, for use in the property class's 'close' callback
2033
     */
2034
19
    plist->plist_id = plist_id;
2035
2036
    /* Call the class callback (if it exists) now that we have the property list ID
2037
     * (up through chain of parent classes also)
2038
     */
2039
19
    tclass = plist->pclass;
2040
71
    while (NULL != tclass) {
2041
52
        if (NULL != tclass->create_func) {
2042
0
            herr_t status;
2043
2044
            /* Prepare & restore library for user callback */
2045
0
            H5_BEFORE_USER_CB(FAIL)
2046
0
                {
2047
0
                    status = (tclass->create_func)(plist_id, tclass->create_data);
2048
0
                }
2049
0
            H5_AFTER_USER_CB(FAIL)
2050
0
            if (status < 0) {
2051
                /* Delete ID, ignore return value */
2052
0
                H5I_remove(plist_id);
2053
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, H5I_INVALID_HID, "Can't initialize property");
2054
0
            } /* end if */
2055
0
        }     /* end if */
2056
2057
        /* Go up to parent class */
2058
52
        tclass = tclass->parent;
2059
52
    } /* end while */
2060
2061
    /* Set the class initialization flag */
2062
19
    plist->class_init = true;
2063
2064
    /* Set the return value */
2065
19
    ret_value = plist_id;
2066
2067
19
done:
2068
19
    if (H5I_INVALID_HID == ret_value && plist)
2069
0
        H5P_close(plist);
2070
2071
19
    FUNC_LEAVE_NOAPI(ret_value)
2072
19
} /* H5P_create_id() */
2073
2074
/*--------------------------------------------------------------------------
2075
 NAME
2076
    H5P__register_real
2077
 PURPOSE
2078
    Internal routine to register a new property in a property list class.
2079
 USAGE
2080
    herr_t H5P__register_real(class, name, size, default, prp_create, prp_set,
2081
                             prp_get, prp_close, prp_encode, prp_decode)
2082
        H5P_genclass_t *class;  IN: Property list class to modify
2083
        const char *name;       IN: Name of property to register
2084
        size_t size;            IN: Size of property in bytes
2085
        void *def_value;        IN: Pointer to buffer containing default value
2086
                                    for property in newly created property lists
2087
        H5P_prp_create_func_t prp_create;   IN: Function pointer to property
2088
                                    creation callback
2089
        H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback
2090
        H5P_prp_get_func_t prp_get; IN: Function pointer to property get callback
2091
        H5P_prp_encode_func_t prp_encode; IN: Function pointer to property encode
2092
        H5P_prp_decode_func_t prp_decode; IN: Function pointer to property decode
2093
        H5P_prp_delete_func_t prp_delete; IN: Function pointer to property delete callback
2094
        H5P_prp_copy_func_t prp_copy; IN: Function pointer to property copy callback
2095
        H5P_prp_compare_func_t prp_cmp; IN: Function pointer to property compare callback
2096
        H5P_prp_close_func_t prp_close; IN: Function pointer to property close
2097
                                    callback
2098
 RETURNS
2099
    Returns non-negative on success, negative on failure.
2100
 DESCRIPTION
2101
        Registers a new property with a property list class.  The property will
2102
    exist in all property list objects of that class after this routine is
2103
    finished.  The name of the property must not already exist.  The default
2104
    property value must be provided and all new property lists created with this
2105
    property will have the property value set to the default provided.  Any of
2106
    the callback routines may be set to NULL if they are not needed.
2107
2108
        Zero-sized properties are allowed and do not store any data in the
2109
    property list.  These may be used as flags to indicate the presence or
2110
    absence of a particular piece of information.  The 'default' pointer for a
2111
    zero-sized property may be set to NULL.  The property 'create' & 'close'
2112
    callbacks are called for zero-sized properties, but the 'set' and 'get'
2113
    callbacks are never called.
2114
2115
        The 'create' callback is called when a new property list with this
2116
    property is being created.  H5P_prp_create_func_t is defined as:
2117
        typedef herr_t (*H5P_prp_create_func_t)(const char *name, size_t size, void *value);
2118
    where the parameters to the callback function are:
2119
        const char *name;   IN: The name of the property being modified.
2120
        size_t size;        IN: The size of the property value
2121
        void *value;        IN/OUT: The initial value for the property being created.
2122
                                (The 'default' value passed to H5Pregister2)
2123
    The 'create' routine may modify the value to be set and those changes will
2124
    be stored as the initial value of the property.  If the 'create' routine
2125
    returns a negative value, the new property value is not copied into the
2126
    property and the property list creation routine returns an error value.
2127
2128
        The 'set' callback is called before a new value is copied into the
2129
    property.  H5P_prp_set_func_t is defined as:
2130
        typedef herr_t (*H5P_prp_set_func_t)(hid_t prop_id, const char *name,
2131
            size_t size, void *value);
2132
    where the parameters to the callback function are:
2133
        hid_t prop_id;      IN: The ID of the property list being modified.
2134
        const char *name;   IN: The name of the property being modified.
2135
        size_t size;        IN: The size of the property value
2136
        void *value;    IN/OUT: The value being set for the property.
2137
    The 'set' routine may modify the value to be set and those changes will be
2138
    stored as the value of the property.  If the 'set' routine returns a
2139
    negative value, the new property value is not copied into the property and
2140
    the property list set routine returns an error value.
2141
2142
        The 'get' callback is called before a value is retrieved from the
2143
    property.  H5P_prp_get_func_t is defined as:
2144
        typedef herr_t (*H5P_prp_get_func_t)(hid_t prop_id, const char *name,
2145
            size_t size, void *value);
2146
    where the parameters to the callback function are:
2147
        hid_t prop_id;      IN: The ID of the property list being queried.
2148
        const char *name;   IN: The name of the property being queried.
2149
        size_t size;        IN: The size of the property value
2150
        void *value;        IN/OUT: The value being retrieved for the property.
2151
    The 'get' routine may modify the value to be retrieved and those changes
2152
    will be returned to the calling function.  If the 'get' routine returns a
2153
    negative value, the property value is returned and the property list get
2154
    routine returns an error value.
2155
2156
        The 'delete' callback is called when a property is deleted from a
2157
    property list.  H5P_prp_delete_func_t is defined as:
2158
        typedef herr_t (*H5P_prp_delete_func_t)(hid_t prop_id, const char *name,
2159
            size_t size, void *value);
2160
    where the parameters to the callback function are:
2161
        hid_t prop_id;      IN: The ID of the property list the property is deleted from.
2162
        const char *name;   IN: The name of the property being deleted.
2163
        size_t size;        IN: The size of the property value
2164
        void *value;        IN/OUT: The value of the property being deleted.
2165
    The 'delete' routine may modify the value passed in, but the value is not
2166
    used by the library when the 'delete' routine returns.  If the
2167
    'delete' routine returns a negative value, the property list deletion
2168
    routine returns an error value but the property is still deleted.
2169
2170
        The 'copy' callback is called when a property list with this
2171
    property is copied.  H5P_prp_copy_func_t is defined as:
2172
        typedef herr_t (*H5P_prp_copy_func_t)(const char *name, size_t size,
2173
            void *value);
2174
    where the parameters to the callback function are:
2175
        const char *name;   IN: The name of the property being copied.
2176
        size_t size;        IN: The size of the property value
2177
        void *value;        IN: The value of the property being copied.
2178
    The 'copy' routine may modify the value to be copied and those changes will be
2179
    stored as the value of the property.  If the 'copy' routine returns a
2180
    negative value, the new property value is not copied into the property and
2181
    the property list copy routine returns an error value.
2182
2183
        The 'compare' callback is called when a property list with this
2184
    property is compared to another property list.  H5P_prp_compare_func_t is
2185
    defined as:
2186
        typedef int (*H5P_prp_compare_func_t)(const void *value1, const void *value2,
2187
            size_t size);
2188
    where the parameters to the callback function are:
2189
        const void *value1; IN: The value of the first property being compared.
2190
        const void *value2; IN: The value of the second property being compared.
2191
        size_t size;        IN: The size of the property value
2192
    The 'compare' routine may not modify the values to be compared.  The
2193
    'compare' routine should return a positive value if VALUE1 is greater than
2194
    VALUE2, a negative value if VALUE2 is greater than VALUE1 and zero if VALUE1
2195
    and VALUE2 are equal.
2196
2197
        The 'close' callback is called when a property list with this
2198
    property is being destroyed.  H5P_prp_close_func_t is defined as:
2199
        typedef herr_t (*H5P_prp_close_func_t)(const char *name, size_t size,
2200
            void *value);
2201
    where the parameters to the callback function are:
2202
        const char *name;   IN: The name of the property being closed.
2203
        size_t size;        IN: The size of the property value
2204
        void *value;        IN: The value of the property being closed.
2205
    The 'close' routine may modify the value passed in, but the value is not
2206
    used by the library when the 'close' routine returns.  If the
2207
    'close' routine returns a negative value, the property list close
2208
    routine returns an error value but the property list is still closed.
2209
2210
        The 'encode' callback is called when a property list with this
2211
    property is being encoded.  H5P_prp_encode_func_t is defined as:
2212
        typedef herr_t (*H5P_prp_encode_func_t)(const void *value, void **buf, size_t *size);
2213
    where the parameters to the callback function are:
2214
        void *value;        IN: The value of the property being encoded.
2215
        void **buf;         OUT: Pointer to encoding buffer pointer.
2216
        size_t *size;       IN/OUT: The size of the buffer needed to encode the property.
2217
    The 'encode' routine returns the size needed to encode the property value
2218
    if the buffer passed in is NULL or the size is zero. Otherwise it encodes
2219
    the property value as binary in *buf.
2220
2221
        The 'decode' callback is called when a property list with this
2222
    property is being decoded.  H5P_prp_encode_func_t is defined as:
2223
        typedef herr_t (*H5P_prp_encode_func_t)(const void **buf, void *value);
2224
    where the parameters to the callback function are:
2225
        void **buf;         IN: Pointer to encoded buffer pointer.
2226
        void *value;        OUT: The buffer the property value is decoded into.
2227
    The 'decode' routine decodes the binary buffer passed in and transforms it into
2228
    corresponding property values that are set in the property list passed in.
2229
    After the value is decoded, (*buf) must be incremented
2230
    by the size of the encoded value.
2231
2232
 GLOBAL VARIABLES
2233
 COMMENTS, BUGS, ASSUMPTIONS
2234
        The 'set' callback function may be useful to range check the value being
2235
    set for the property or may perform some transformation/translation of the
2236
    value set.  The 'get' callback would then [probably] reverse the
2237
    transformation, etc.  A single 'get' or 'set' callback could handle
2238
    multiple properties by performing different actions based on the property
2239
    name or other properties in the property list.
2240
2241
        I would like to say "the property list is not closed" when a 'close'
2242
    routine fails, but I don't think that's possible due to other properties in
2243
    the list being successfully closed & removed from the property list.  I
2244
    suppose that it would be possible to just remove the properties which have
2245
    successful 'close' callbacks, but I'm not happy with the ramifications
2246
    of a mangled, un-closable property list hanging around...  Any comments? -QAK
2247
2248
 EXAMPLES
2249
 REVISION LOG
2250
--------------------------------------------------------------------------*/
2251
herr_t
2252
H5P__register_real(H5P_genclass_t *pclass, const char *name, size_t size, const void *def_value,
2253
                   H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
2254
                   H5P_prp_encode_func_t prp_encode, H5P_prp_decode_func_t prp_decode,
2255
                   H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy,
2256
                   H5P_prp_compare_func_t prp_cmp, H5P_prp_close_func_t prp_close)
2257
114
{
2258
114
    H5P_genprop_t *new_prop  = NULL;    /* Temporary property pointer */
2259
114
    herr_t         ret_value = SUCCEED; /* Return value */
2260
2261
114
    FUNC_ENTER_PACKAGE
2262
2263
114
    assert(pclass);
2264
114
    assert(0 == pclass->plists);
2265
114
    assert(0 == pclass->classes);
2266
114
    assert(name);
2267
114
    assert((size > 0 && def_value != NULL) || (size == 0));
2268
2269
    /* Check for duplicate named properties */
2270
114
    if (NULL != H5SL_search(pclass->props, name))
2271
0
        HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
2272
2273
    /* Create property object from parameters */
2274
114
    if (NULL == (new_prop = H5P__create_prop(name, size, H5P_PROP_WITHIN_CLASS, def_value, prp_create,
2275
114
                                             prp_set, prp_get, prp_encode, prp_decode, prp_delete, prp_copy,
2276
114
                                             prp_cmp, prp_close)))
2277
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "Can't create property");
2278
2279
    /* Insert property into property list class */
2280
114
    if (H5P__add_prop(pclass->props, new_prop) < 0)
2281
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert property into class");
2282
2283
    /* Increment property count for class */
2284
114
    pclass->nprops++;
2285
2286
    /* Update the revision for the class */
2287
114
    pclass->revision = H5P_GET_NEXT_REV;
2288
2289
114
done:
2290
114
    if (ret_value < 0)
2291
0
        if (new_prop && H5P__free_prop(new_prop) < 0)
2292
0
            HDONE_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to close property");
2293
2294
114
    FUNC_LEAVE_NOAPI(ret_value)
2295
114
} /* H5P__register_real() */
2296
2297
/*--------------------------------------------------------------------------
2298
 NAME
2299
    H5P__register
2300
 PURPOSE
2301
    Internal routine to register a new property in a property list class.
2302
 USAGE
2303
    herr_t H5P__register(class, name, size, default, prp_create, prp_set, prp_get, prp_close)
2304
        H5P_genclass_t **class; IN: Property list class to modify
2305
        const char *name;       IN: Name of property to register
2306
        size_t size;            IN: Size of property in bytes
2307
        void *def_value;        IN: Pointer to buffer containing default value
2308
                                    for property in newly created property lists
2309
        H5P_prp_create_func_t prp_create;   IN: Function pointer to property
2310
                                    creation callback
2311
        H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback
2312
        H5P_prp_get_func_t prp_get; IN: Function pointer to property get callback
2313
        H5P_prp_encode_func_t prp_encode; IN: Function pointer to property encode
2314
        H5P_prp_decode_func_t prp_decode; IN: Function pointer to property decode
2315
        H5P_prp_delete_func_t prp_delete; IN: Function pointer to property delete callback
2316
        H5P_prp_copy_func_t prp_copy; IN: Function pointer to property copy callback
2317
        H5P_prp_compare_func_t prp_cmp; IN: Function pointer to property compare callback
2318
        H5P_prp_close_func_t prp_close; IN: Function pointer to property close
2319
                                    callback
2320
 RETURNS
2321
    Returns non-negative on success, negative on failure.
2322
 DESCRIPTION
2323
        Registers a new property with a property list class.  The property will
2324
    exist in all property list objects of that class after this routine is
2325
    finished.  The name of the property must not already exist.  The default
2326
    property value must be provided and all new property lists created with this
2327
    property will have the property value set to the default provided.  Any of
2328
    the callback routines may be set to NULL if they are not needed.
2329
2330
        Zero-sized properties are allowed and do not store any data in the
2331
    property list.  These may be used as flags to indicate the presence or
2332
    absence of a particular piece of information.  The 'default' pointer for a
2333
    zero-sized property may be set to NULL.  The property 'create' & 'close'
2334
    callbacks are called for zero-sized properties, but the 'set' and 'get'
2335
    callbacks are never called.
2336
2337
        The 'create' callback is called when a new property list with this
2338
    property is being created.  H5P_prp_create_func_t is defined as:
2339
        typedef herr_t (*H5P_prp_create_func_t)(hid_t prop_id, const char *name,
2340
                size_t size, void *initial_value);
2341
    where the parameters to the callback function are:
2342
        hid_t prop_id;      IN: The ID of the property list being created.
2343
        const char *name;   IN: The name of the property being modified.
2344
        size_t size;        IN: The size of the property value
2345
        void *initial_value; IN/OUT: The initial value for the property being created.
2346
                                (The 'default' value passed to H5Pregister2)
2347
    The 'create' routine may modify the value to be set and those changes will
2348
    be stored as the initial value of the property.  If the 'create' routine
2349
    returns a negative value, the new property value is not copied into the
2350
    property and the property list creation routine returns an error value.
2351
2352
        The 'set' callback is called before a new value is copied into the
2353
    property.  H5P_prp_set_func_t is defined as:
2354
        typedef herr_t (*H5P_prp_set_func_t)(hid_t prop_id, const char *name,
2355
            size_t size, void *value);
2356
    where the parameters to the callback function are:
2357
        hid_t prop_id;      IN: The ID of the property list being modified.
2358
        const char *name;   IN: The name of the property being modified.
2359
        size_t size;        IN: The size of the property value
2360
        void *new_value;    IN/OUT: The value being set for the property.
2361
    The 'set' routine may modify the value to be set and those changes will be
2362
    stored as the value of the property.  If the 'set' routine returns a
2363
    negative value, the new property value is not copied into the property and
2364
    the property list set routine returns an error value.
2365
2366
        The 'get' callback is called before a value is retrieved from the
2367
    property.  H5P_prp_get_func_t is defined as:
2368
        typedef herr_t (*H5P_prp_get_func_t)(hid_t prop_id, const char *name,
2369
            size_t size, void *value);
2370
    where the parameters to the callback function are:
2371
        hid_t prop_id;      IN: The ID of the property list being queried.
2372
        const char *name;   IN: The name of the property being queried.
2373
        size_t size;        IN: The size of the property value
2374
        void *value;        IN/OUT: The value being retrieved for the property.
2375
    The 'get' routine may modify the value to be retrieved and those changes
2376
    will be returned to the calling function.  If the 'get' routine returns a
2377
    negative value, the property value is returned and the property list get
2378
    routine returns an error value.
2379
2380
        The 'encode' callback is called when a property list with this
2381
    property is being encoded.  H5P_prp_encode_func_t is defined as:
2382
        typedef herr_t (*H5P_prp_encode_func_t)(void *f, size_t *size,
2383
        void *value, void *plist, uint8_t **buf);
2384
    where the parameters to the callback function are:
2385
        void *f;            IN: A fake file structure used to encode.
2386
        size_t *size;       IN/OUT: The size of the buffer to encode the property.
2387
        void *value;        IN: The value of the property being encoded.
2388
        void *plist;        IN: The property list structure.
2389
        uint8_t **buf;      OUT: The buffer that holds the encoded property;
2390
    The 'encode' routine returns the size needed to encode the property value
2391
    if the buffer passed in is NULL or the size is zero. Otherwise it encodes
2392
    the property value into binary in buf.
2393
2394
        The 'decode' callback is called when a property list with this
2395
    property is being decoded.  H5P_prp_encode_func_t is defined as:
2396
        typedef herr_t (*H5P_prp_encode_func_t)(void *f, size_t *size,
2397
        void *value, void *plist, uint8_t **buf);
2398
    where the parameters to the callback function are:
2399
        void *f;            IN: A fake file structure used to decode.
2400
        size_t *size;       IN: H5_ATTR_UNUSED
2401
        void *value;        IN: H5_ATTR_UNUSED
2402
        void *plist;        IN: The property list structure.
2403
        uint8_t **buf;      IN: The buffer that holds the binary encoded property;
2404
    The 'decode' routine decodes the binary buffer passed in and transforms it into
2405
    corresponding property values that are set in the property list passed in.
2406
2407
        The 'delete' callback is called when a property is deleted from a
2408
    property list.  H5P_prp_delete_func_t is defined as:
2409
        typedef herr_t (*H5P_prp_delete_func_t)(hid_t prop_id, const char *name,
2410
            size_t size, void *value);
2411
    where the parameters to the callback function are:
2412
        hid_t prop_id;      IN: The ID of the property list the property is deleted from.
2413
        const char *name;   IN: The name of the property being deleted.
2414
        size_t size;        IN: The size of the property value
2415
        void *value;        IN/OUT: The value of the property being deleted.
2416
    The 'delete' routine may modify the value passed in, but the value is not
2417
    used by the library when the 'delete' routine returns.  If the
2418
    'delete' routine returns a negative value, the property list deletion
2419
    routine returns an error value but the property is still deleted.
2420
2421
        The 'copy' callback is called when a property list with this
2422
    property is copied.  H5P_prp_copy_func_t is defined as:
2423
        typedef herr_t (*H5P_prp_copy_func_t)(const char *name, size_t size,
2424
            void *value);
2425
    where the parameters to the callback function are:
2426
        const char *name;   IN: The name of the property being copied.
2427
        size_t size;        IN: The size of the property value
2428
        void *value;        IN: The value of the property being copied.
2429
    The 'copy' routine may modify the value to be copied and those changes will be
2430
    stored as the value of the property.  If the 'copy' routine returns a
2431
    negative value, the new property value is not copied into the property and
2432
    the property list copy routine returns an error value.
2433
2434
        The 'compare' callback is called when a property list with this
2435
    property is compared to another property list.  H5P_prp_compare_func_t is
2436
    defined as:
2437
        typedef int (*H5P_prp_compare_func_t)( void *value1, void *value2,
2438
            size_t size);
2439
    where the parameters to the callback function are:
2440
        const void *value1; IN: The value of the first property being compared.
2441
        const void *value2; IN: The value of the second property being compared.
2442
        size_t size;        IN: The size of the property value
2443
    The 'compare' routine may not modify the values to be compared.  The
2444
    'compare' routine should return a positive value if VALUE1 is greater than
2445
    VALUE2, a negative value if VALUE2 is greater than VALUE1 and zero if VALUE1
2446
    and VALUE2 are equal.
2447
2448
        The 'close' callback is called when a property list with this
2449
    property is being destroyed.  H5P_prp_close_func_t is defined as:
2450
        typedef herr_t (*H5P_prp_close_func_t)(const char *name, size_t size,
2451
            void *value);
2452
    where the parameters to the callback function are:
2453
        const char *name;   IN: The name of the property being closed.
2454
        size_t size;        IN: The size of the property value
2455
        void *value;        IN: The value of the property being closed.
2456
    The 'close' routine may modify the value passed in, but the value is not
2457
    used by the library when the 'close' routine returns.  If the
2458
    'close' routine returns a negative value, the property list close
2459
    routine returns an error value but the property list is still closed.
2460
2461
 GLOBAL VARIABLES
2462
 COMMENTS, BUGS, ASSUMPTIONS
2463
        The 'set' callback function may be useful to range check the value being
2464
    set for the property or may perform some transformation/translation of the
2465
    value set.  The 'get' callback would then [probably] reverse the
2466
    transformation, etc.  A single 'get' or 'set' callback could handle
2467
    multiple properties by performing different actions based on the property
2468
    name or other properties in the property list.
2469
2470
        I would like to say "the property list is not closed" when a 'close'
2471
    routine fails, but I don't think that's possible due to other properties in
2472
    the list being successfully closed & removed from the property list.  I
2473
    suppose that it would be possible to just remove the properties which have
2474
    successful 'close' callbacks, but I'm not happy with the ramifications
2475
    of a mangled, un-closable property list hanging around...  Any comments? -QAK
2476
2477
 EXAMPLES
2478
 REVISION LOG
2479
--------------------------------------------------------------------------*/
2480
herr_t
2481
H5P__register(H5P_genclass_t **ppclass, const char *name, size_t size, const void *def_value,
2482
              H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
2483
              H5P_prp_encode_func_t prp_encode, H5P_prp_decode_func_t prp_decode,
2484
              H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_compare_func_t prp_cmp,
2485
              H5P_prp_close_func_t prp_close)
2486
0
{
2487
0
    H5P_genclass_t *pclass    = *ppclass; /* Pointer to class to modify */
2488
0
    H5P_genclass_t *new_class = NULL;     /* New class pointer */
2489
0
    herr_t          ret_value = SUCCEED;  /* Return value */
2490
2491
0
    FUNC_ENTER_PACKAGE
2492
2493
    /* Sanity check */
2494
0
    assert(ppclass);
2495
0
    assert(pclass);
2496
2497
    /* Check if class needs to be split because property lists or classes have
2498
     *  been created since the last modification was made to the class.
2499
     */
2500
0
    if (pclass->plists > 0 || pclass->classes > 0) {
2501
0
        if (NULL == (new_class = H5P__create_class(
2502
0
                         pclass->parent, pclass->name, pclass->type, pclass->create_func, pclass->create_data,
2503
0
                         pclass->copy_func, pclass->copy_data, pclass->close_func, pclass->close_data)))
2504
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy class");
2505
2506
        /* Walk through the skip list of the old class and copy properties */
2507
0
        if (pclass->nprops > 0) {
2508
0
            H5SL_node_t *curr_node; /* Current node in skip list */
2509
2510
            /* Walk through the properties in the old class */
2511
0
            curr_node = H5SL_first(pclass->props);
2512
0
            while (curr_node != NULL) {
2513
0
                H5P_genprop_t *pcopy; /* Property copy */
2514
2515
                /* Make a copy of the class's property */
2516
0
                if (NULL ==
2517
0
                    (pcopy = H5P__dup_prop((H5P_genprop_t *)H5SL_item(curr_node), H5P_PROP_WITHIN_CLASS)))
2518
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
2519
2520
                /* Insert the initialized property into the property class */
2521
0
                if (H5P__add_prop(new_class->props, pcopy) < 0)
2522
0
                    HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert property into class");
2523
2524
                /* Increment property count for class */
2525
0
                new_class->nprops++;
2526
2527
                /* Get the next property node in the skip list */
2528
0
                curr_node = H5SL_next(curr_node);
2529
0
            } /* end while */
2530
0
        }     /* end if */
2531
2532
        /* Use the new class instead of the old one */
2533
0
        pclass = new_class;
2534
0
    } /* end if */
2535
2536
    /* Really register the property in the class */
2537
0
    if (H5P__register_real(pclass, name, size, def_value, prp_create, prp_set, prp_get, prp_encode,
2538
0
                           prp_decode, prp_delete, prp_copy, prp_cmp, prp_close) < 0)
2539
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "can't register property");
2540
2541
    /* Update pointer to pointer to class, if a new one was generated */
2542
0
    if (new_class)
2543
0
        *ppclass = pclass;
2544
2545
0
done:
2546
0
    if (ret_value < 0)
2547
0
        if (new_class && H5P__close_class(new_class) < 0)
2548
0
            HDONE_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to close new property class");
2549
2550
0
    FUNC_LEAVE_NOAPI(ret_value)
2551
0
} /* H5P__register() */
2552
2553
/*--------------------------------------------------------------------------
2554
 NAME
2555
    H5P_insert
2556
 PURPOSE
2557
    Internal routine to insert a new property in a property list.
2558
 USAGE
2559
    herr_t H5P_insert(plist, name, size, value, prp_set, prp_get, prp_close,
2560
                      prp_encode, prp_decode)
2561
        H5P_genplist_t *plist;  IN: Property list to add property to
2562
        const char *name;       IN: Name of property to add
2563
        size_t size;            IN: Size of property in bytes
2564
        void *value;            IN: Pointer to the value for the property
2565
        H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback
2566
        H5P_prp_get_func_t prp_get; IN: Function pointer to property get callback
2567
        H5P_prp_encode_func_t prp_encode; IN: Function pointer to property encode
2568
        H5P_prp_decode_func_t prp_decode; IN: Function pointer to property decode
2569
        H5P_prp_delete_func_t prp_delete; IN: Function pointer to property delete callback
2570
        H5P_prp_copy_func_t prp_copy; IN: Function pointer to property copy callback
2571
        H5P_prp_compare_func_t prp_cmp; IN: Function pointer to property compare callback
2572
        H5P_prp_close_func_t prp_close; IN: Function pointer to property close
2573
                                    callback
2574
 RETURNS
2575
    Returns non-negative on success, negative on failure.
2576
 DESCRIPTION
2577
        Inserts a temporary property into a property list.  The property will
2578
    exist only in this property list object.  The name of the property must not
2579
    already exist.  The value must be provided unless the property is zero-
2580
    sized.  Any of the callback routines may be set to NULL if they are not
2581
    needed.
2582
2583
        Zero-sized properties are allowed and do not store any data in the
2584
    property list.  These may be used as flags to indicate the presence or
2585
    absence of a particular piece of information.  The 'value' pointer for a
2586
    zero-sized property may be set to NULL.  The property 'close' callback is
2587
    called for zero-sized properties, but the 'set' and 'get' callbacks are
2588
    never called.
2589
2590
        The 'set' callback is called before a new value is copied into the
2591
    property.  H5P_prp_set_func_t is defined as:
2592
        typedef herr_t (*H5P_prp_set_func_t)(hid_t prop_id, const char *name,
2593
            size_t size, void *value);
2594
    where the parameters to the callback function are:
2595
        hid_t prop_id;      IN: The ID of the property list being modified.
2596
        const char *name;   IN: The name of the property being modified.
2597
        size_t size;        IN: The size of the property value
2598
        void *new_value;    IN/OUT: The value being set for the property.
2599
    The 'set' routine may modify the value to be set and those changes will be
2600
    stored as the value of the property.  If the 'set' routine returns a
2601
    negative value, the new property value is not copied into the property and
2602
    the property list set routine returns an error value.
2603
2604
        The 'get' callback is called before a value is retrieved from the
2605
    property.  H5P_prp_get_func_t is defined as:
2606
        typedef herr_t (*H5P_prp_get_func_t)(hid_t prop_id, const char *name,
2607
            size_t size, void *value);
2608
    where the parameters to the callback function are:
2609
        hid_t prop_id;      IN: The ID of the property list being queried.
2610
        const char *name;   IN: The name of the property being queried.
2611
        size_t size;        IN: The size of the property value
2612
        void *value;        IN/OUT: The value being retrieved for the property.
2613
    The 'get' routine may modify the value to be retrieved and those changes
2614
    will be returned to the calling function.  If the 'get' routine returns a
2615
    negative value, the property value is returned and the property list get
2616
    routine returns an error value.
2617
2618
        The 'encode' callback is called when a property list with this
2619
    property is being encoded.  H5P_prp_encode_func_t is defined as:
2620
        typedef herr_t (*H5P_prp_encode_func_t)(void *f, size_t *size,
2621
        void *value, void *plist, uint8_t **buf);
2622
    where the parameters to the callback function are:
2623
        void *f;            IN: A fake file structure used to encode.
2624
        size_t *size;       IN/OUT: The size of the buffer to encode the property.
2625
        void *value;        IN: The value of the property being encoded.
2626
        void *plist;        IN: The property list structure.
2627
        uint8_t **buf;      OUT: The buffer that holds the encoded property;
2628
    The 'encode' routine returns the size needed to encode the property value
2629
    if the buffer passed in is NULL or the size is zero. Otherwise it encodes
2630
    the property value into binary in buf.
2631
2632
        The 'decode' callback is called when a property list with this
2633
    property is being decoded.  H5P_prp_encode_func_t is defined as:
2634
        typedef herr_t (*H5P_prp_encode_func_t)(void *f, size_t *size,
2635
        void *value, void *plist, uint8_t **buf);
2636
    where the parameters to the callback function are:
2637
        void *f;            IN: A fake file structure used to decode.
2638
        size_t *size;       IN: H5_ATTR_UNUSED
2639
        void *value;        IN: H5_ATTR_UNUSED
2640
        void *plist;        IN: The property list structure.
2641
        uint8_t **buf;      IN: The buffer that holds the binary encoded property;
2642
    The 'decode' routine decodes the binary buffer passed in and transforms it into
2643
    corresponding property values that are set in the property list passed in.
2644
2645
        The 'delete' callback is called when a property is deleted from a
2646
    property list.  H5P_prp_delete_func_t is defined as:
2647
        typedef herr_t (*H5P_prp_delete_func_t)(hid_t prop_id, const char *name,
2648
            size_t size, void *value);
2649
    where the parameters to the callback function are:
2650
        hid_t prop_id;      IN: The ID of the property list the property is deleted from.
2651
        const char *name;   IN: The name of the property being deleted.
2652
        size_t size;        IN: The size of the property value
2653
        void *value;        IN/OUT: The value of the property being deleted.
2654
    The 'delete' routine may modify the value passed in, but the value is not
2655
    used by the library when the 'delete' routine returns.  If the
2656
    'delete' routine returns a negative value, the property list deletion
2657
    routine returns an error value but the property is still deleted.
2658
2659
        The 'copy' callback is called when a property list with this
2660
    property is copied.  H5P_prp_copy_func_t is defined as:
2661
        typedef herr_t (*H5P_prp_copy_func_t)(const char *name, size_t size,
2662
            void *value);
2663
    where the parameters to the callback function are:
2664
        const char *name;   IN: The name of the property being copied.
2665
        size_t size;        IN: The size of the property value
2666
        void *value;        IN: The value of the property being copied.
2667
    The 'copy' routine may modify the value to be copied and those changes will be
2668
    stored as the value of the property.  If the 'copy' routine returns a
2669
    negative value, the new property value is not copied into the property and
2670
    the property list copy routine returns an error value.
2671
2672
        The 'compare' callback is called when a property list with this
2673
    property is compared to another property list.  H5P_prp_compare_func_t is
2674
    defined as:
2675
        typedef int (*H5P_prp_compare_func_t)(void *value1, void *value2,
2676
            size_t size);
2677
    where the parameters to the callback function are:
2678
        const void *value1; IN: The value of the first property being compared.
2679
        const void *value2; IN: The value of the second property being compared.
2680
        size_t size;        IN: The size of the property value
2681
    The 'compare' routine may not modify the values to be compared.  The
2682
    'compare' routine should return a positive value if VALUE1 is greater than
2683
    VALUE2, a negative value if VALUE2 is greater than VALUE1 and zero if VALUE1
2684
    and VALUE2 are equal.
2685
2686
        The 'close' callback is called when a property list with this
2687
    property is being destroyed.  H5P_prp_close_func_t is defined as:
2688
        typedef herr_t (*H5P_prp_close_func_t)(const char *name, size_t size,
2689
            void *value);
2690
    where the parameters to the callback function are:
2691
        const char *name;   IN: The name of the property being closed.
2692
        size_t size;        IN: The size of the property value
2693
        void *value;        IN: The value of the property being closed.
2694
    The 'close' routine may modify the value passed in, but the value is not
2695
    used by the library when the 'close' routine returns.  If the
2696
    'close' routine returns a negative value, the property list close
2697
    routine returns an error value but the property list is still closed.
2698
2699
 GLOBAL VARIABLES
2700
 COMMENTS, BUGS, ASSUMPTIONS
2701
        The 'set' callback function may be useful to range check the value being
2702
    set for the property or may perform some transformation/translation of the
2703
    value set.  The 'get' callback would then [probably] reverse the
2704
    transformation, etc.  A single 'get' or 'set' callback could handle
2705
    multiple properties by performing different actions based on the property
2706
    name or other properties in the property list.
2707
2708
        There is no 'create' callback routine for temporary property list
2709
    objects, the initial value is assumed to have any necessary setup already
2710
    performed on it.
2711
2712
        I would like to say "the property list is not closed" when a 'close'
2713
    routine fails, but I don't think that's possible due to other properties in
2714
    the list being successfully closed & removed from the property list.  I
2715
    suppose that it would be possible to just remove the properties which have
2716
    successful 'close' callbacks, but I'm not happy with the ramifications
2717
    of a mangled, un-closable property list hanging around...  Any comments? -QAK
2718
2719
 EXAMPLES
2720
 REVISION LOG
2721
--------------------------------------------------------------------------*/
2722
herr_t
2723
H5P_insert(H5P_genplist_t *plist, const char *name, size_t size, void *value, H5P_prp_set_func_t prp_set,
2724
           H5P_prp_get_func_t prp_get, H5P_prp_encode_func_t prp_encode, H5P_prp_decode_func_t prp_decode,
2725
           H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_compare_func_t prp_cmp,
2726
           H5P_prp_close_func_t prp_close)
2727
0
{
2728
0
    H5P_genprop_t *new_prop  = NULL;    /* Temporary property pointer */
2729
0
    herr_t         ret_value = SUCCEED; /* Return value */
2730
2731
0
    FUNC_ENTER_NOAPI_NOINIT
2732
2733
0
    assert(plist);
2734
0
    assert(name);
2735
0
    assert((size > 0 && value != NULL) || (size == 0));
2736
2737
    /* Check for duplicate named properties */
2738
0
    if (NULL != H5SL_search(plist->props, name))
2739
0
        HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
2740
2741
    /* Check if the property has been deleted */
2742
0
    if (NULL != H5SL_search(plist->del, name)) {
2743
0
        char *temp_name = NULL;
2744
2745
        /* Remove the property name from the deleted property skip list */
2746
0
        if (NULL == (temp_name = (char *)H5SL_remove(plist->del, name)))
2747
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't remove property from deleted skip list");
2748
2749
        /* free the name of the removed property */
2750
0
        H5MM_xfree(temp_name);
2751
0
    } /* end if */
2752
0
    else {
2753
0
        H5P_genclass_t *tclass; /* Temporary class pointer */
2754
2755
        /* Check if the property is already in the class hierarchy */
2756
0
        tclass = plist->pclass;
2757
0
        while (tclass) {
2758
0
            if (tclass->nprops > 0) {
2759
                /* Find the property in the class */
2760
0
                if (NULL != H5SL_search(tclass->props, name))
2761
0
                    HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists");
2762
0
            } /* end if */
2763
2764
            /* Go up to parent class */
2765
0
            tclass = tclass->parent;
2766
0
        } /* end while */
2767
0
    }     /* end else */
2768
2769
    /* Ok to add to property list */
2770
2771
    /* Create property object from parameters */
2772
0
    if (NULL ==
2773
0
        (new_prop = H5P__create_prop(name, size, H5P_PROP_WITHIN_LIST, value, NULL, prp_set, prp_get,
2774
0
                                     prp_encode, prp_decode, prp_delete, prp_copy, prp_cmp, prp_close)))
2775
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "Can't create property");
2776
2777
    /* Insert property into property list class */
2778
0
    if (H5P__add_prop(plist->props, new_prop) < 0)
2779
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert property into class");
2780
2781
    /* Increment property count for class */
2782
0
    plist->nprops++;
2783
2784
0
done:
2785
0
    if (ret_value < 0)
2786
0
        if (new_prop && H5P__free_prop(new_prop) < 0)
2787
0
            HDONE_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to close property");
2788
2789
0
    FUNC_LEAVE_NOAPI(ret_value)
2790
0
} /* H5P_insert() */
2791
2792
/*--------------------------------------------------------------------------
2793
 NAME
2794
    H5P__do_prop
2795
 PURPOSE
2796
    Internal routine to perform an operation on a property in a property list
2797
 USAGE
2798
    herr_t H5P__do_prop(plist, name, cb, udata)
2799
        H5P_genplist_t *plist;  IN: Property list to find property in
2800
        const char *name;       IN: Name of property to set
2801
        H5P_do_plist_op_t plist_op;  IN: Pointer to the callback to invoke when the
2802
                                    property is found in the property list
2803
        H5P_do_pclass_op_t pclass_op; IN: Pointer to the callback to invoke when the
2804
                                    property is found in the property class
2805
        void *udata;            IN: Pointer to the user data for the callback
2806
 RETURNS
2807
    Returns non-negative on success, negative on failure.
2808
 DESCRIPTION
2809
        Finds a property in a property list and calls the callback with it.
2810
 GLOBAL VARIABLES
2811
 COMMENTS, BUGS, ASSUMPTIONS
2812
 EXAMPLES
2813
 REVISION LOG
2814
--------------------------------------------------------------------------*/
2815
static herr_t
2816
H5P__do_prop(H5P_genplist_t *plist, const char *name, H5P_do_plist_op_t plist_op,
2817
             H5P_do_pclass_op_t pclass_op, void *udata)
2818
55.0k
{
2819
55.0k
    H5P_genclass_t *tclass;              /* Temporary class pointer */
2820
55.0k
    H5P_genprop_t  *prop;                /* Temporary property pointer */
2821
55.0k
    herr_t          ret_value = SUCCEED; /* Return value */
2822
2823
55.0k
    FUNC_ENTER_PACKAGE
2824
2825
    /* Sanity check */
2826
55.0k
    assert(plist);
2827
55.0k
    assert(name);
2828
55.0k
    assert(plist_op);
2829
55.0k
    assert(pclass_op);
2830
2831
    /* Check if the property has been deleted */
2832
55.0k
    if (NULL != H5SL_search(plist->del, name))
2833
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
2834
2835
    /* Find property in changed list */
2836
55.0k
    if (NULL != (prop = (H5P_genprop_t *)H5SL_search(plist->props, name))) {
2837
        /* Call the 'found in property list' callback */
2838
3.46k
        if ((*plist_op)(plist, name, prop, udata) < 0)
2839
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on property");
2840
3.46k
    } /* end if */
2841
51.5k
    else {
2842
        /*
2843
         * Check if we should set class properties (up through list of parent classes also),
2844
         * & make property 'set' callback.
2845
         */
2846
51.5k
        tclass = plist->pclass;
2847
51.7k
        while (NULL != tclass) {
2848
51.7k
            if (tclass->nprops > 0) {
2849
                /* Find the property in the class */
2850
51.7k
                if (NULL != (prop = (H5P_genprop_t *)H5SL_search(tclass->props, name))) {
2851
                    /* Call the 'found in class' callback */
2852
51.5k
                    if ((*pclass_op)(plist, name, prop, udata) < 0)
2853
0
                        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on property");
2854
2855
                    /* Leave */
2856
51.5k
                    break;
2857
51.5k
                } /* end if */
2858
51.7k
            }     /* end if */
2859
2860
            /* Go up to parent class */
2861
231
            tclass = tclass->parent;
2862
231
        } /* end while */
2863
2864
        /* If we get this far, then it wasn't in the list of changed properties,
2865
         * nor in the properties in the class hierarchy, indicate an error
2866
         */
2867
51.5k
        if (NULL == tclass)
2868
0
            HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "can't find property in skip list");
2869
51.5k
    } /* end else */
2870
2871
55.0k
done:
2872
55.0k
    FUNC_LEAVE_NOAPI(ret_value)
2873
55.0k
} /* H5P__do_prop() */
2874
2875
/*--------------------------------------------------------------------------
2876
 NAME
2877
    H5P__poke_plist_cb
2878
 PURPOSE
2879
    Internal callback for H5P__do_prop, to overwrite a property's value in a property list.
2880
 USAGE
2881
    herr_t H5P__poke_plist_cb(plist, name, value)
2882
        H5P_genplist_t *plist;  IN: Property list to overwrite property in
2883
        const char *name;       IN: Name of property to overwrite
2884
        H5P_genprop_t *prop;    IN: Property to overwrite
2885
        void *udata;            IN: User data for operation
2886
 RETURNS
2887
    Returns non-negative on success, negative on failure.
2888
 DESCRIPTION
2889
    Overwrite a value for a property in a property list.
2890
 GLOBAL VARIABLES
2891
 COMMENTS, BUGS, ASSUMPTIONS
2892
    Called when the property is found in the property list.
2893
 EXAMPLES
2894
 REVISION LOG
2895
--------------------------------------------------------------------------*/
2896
static herr_t
2897
H5P__poke_plist_cb(H5P_genplist_t H5_ATTR_NDEBUG_UNUSED *plist, const char H5_ATTR_NDEBUG_UNUSED *name,
2898
                   H5P_genprop_t *prop, void *_udata)
2899
0
{
2900
0
    H5P_prop_set_ud_t *udata     = (H5P_prop_set_ud_t *)_udata; /* User data for callback */
2901
0
    herr_t             ret_value = SUCCEED;                     /* Return value */
2902
2903
0
    FUNC_ENTER_PACKAGE
2904
2905
    /* Sanity check */
2906
0
    assert(plist);
2907
0
    assert(name);
2908
0
    assert(prop);
2909
2910
    /* Check for property size >0 */
2911
0
    if (0 == prop->size)
2912
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
2913
2914
    /* Overwrite value in property */
2915
0
    H5MM_memcpy(prop->value, udata->value, prop->size);
2916
2917
0
done:
2918
0
    FUNC_LEAVE_NOAPI(ret_value)
2919
0
} /* H5P__poke_plist_cb() */
2920
2921
/*--------------------------------------------------------------------------
2922
 NAME
2923
    H5P__poke_pclass_cb
2924
 PURPOSE
2925
    Internal callback for H5P__do_prop, to overwrite a property's value in a property list.
2926
 USAGE
2927
    herr_t H5P__poke_pclass_cb(plist, name, value)
2928
        H5P_genplist_t *plist;  IN: Property list to overwrite property in
2929
        const char *name;       IN: Name of property to overwrite
2930
        H5P_genprop_t *prop;    IN: Property to overwrite
2931
        void *udata;            IN: User data for operation
2932
 RETURNS
2933
    Returns non-negative on success, negative on failure.
2934
 DESCRIPTION
2935
    Overwrite a value for a property in a property list.
2936
 GLOBAL VARIABLES
2937
 COMMENTS, BUGS, ASSUMPTIONS
2938
    Called when the property is found in the property class.
2939
 EXAMPLES
2940
 REVISION LOG
2941
--------------------------------------------------------------------------*/
2942
static herr_t
2943
H5P__poke_pclass_cb(H5P_genplist_t *plist, const char H5_ATTR_NDEBUG_UNUSED *name, H5P_genprop_t *prop,
2944
                    void *_udata)
2945
0
{
2946
0
    H5P_prop_set_ud_t *udata     = (H5P_prop_set_ud_t *)_udata; /* User data for callback */
2947
0
    H5P_genprop_t     *pcopy     = NULL;    /* Copy of property to insert into skip list */
2948
0
    herr_t             ret_value = SUCCEED; /* Return value */
2949
2950
0
    FUNC_ENTER_PACKAGE
2951
2952
    /* Sanity check */
2953
0
    assert(plist);
2954
0
    assert(name);
2955
0
    assert(prop);
2956
0
    assert(prop->cmp);
2957
2958
    /* Check for property size >0 */
2959
0
    if (0 == prop->size)
2960
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
2961
2962
    /* Make a copy of the class's property */
2963
0
    if (NULL == (pcopy = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)))
2964
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
2965
2966
0
    H5MM_memcpy(pcopy->value, udata->value, pcopy->size);
2967
2968
    /* Insert the changed property into the property list */
2969
0
    if (H5P__add_prop(plist->props, pcopy) < 0)
2970
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert changed property into skip list");
2971
2972
0
done:
2973
    /* Cleanup on failure */
2974
0
    if (ret_value < 0)
2975
0
        if (pcopy)
2976
0
            H5P__free_prop(pcopy);
2977
2978
0
    FUNC_LEAVE_NOAPI(ret_value)
2979
0
} /* H5P__poke_pclass_cb() */
2980
2981
/*--------------------------------------------------------------------------
2982
 NAME
2983
    H5P_poke
2984
 PURPOSE
2985
    Internal routine to overwrite a property's value in a property list.
2986
 USAGE
2987
    herr_t H5P_poke(plist, name, value)
2988
        H5P_genplist_t *plist;  IN: Property list to find property in
2989
        const char *name;       IN: Name of property to overwrite
2990
        void *value;            IN: Pointer to the value for the property
2991
 RETURNS
2992
    Returns non-negative on success, negative on failure.
2993
 DESCRIPTION
2994
        Overwrites a property in a property list (i.e. a "shallow" copy over
2995
    the property value).  The property name must exist or this routine will
2996
    fail.  If there is a setget' callback routine registered for this property,
2997
    it is _NOT_ called.
2998
 GLOBAL VARIABLES
2999
 COMMENTS, BUGS, ASSUMPTIONS
3000
        This routine may not be called for zero-sized properties and will
3001
    return an error in that case.
3002
 EXAMPLES
3003
 REVISION LOG
3004
--------------------------------------------------------------------------*/
3005
herr_t
3006
H5P_poke(H5P_genplist_t *plist, const char *name, const void *value)
3007
0
{
3008
0
    H5P_prop_set_ud_t udata;               /* User data for callback */
3009
0
    herr_t            ret_value = SUCCEED; /* Return value */
3010
3011
0
    FUNC_ENTER_NOAPI(FAIL)
3012
3013
    /* Sanity check */
3014
0
    assert(plist);
3015
0
    assert(name);
3016
0
    assert(value);
3017
3018
    /* Find the property and set the value */
3019
0
    udata.value = value;
3020
0
    if (H5P__do_prop(plist, name, H5P__poke_plist_cb, H5P__poke_pclass_cb, &udata) < 0)
3021
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on plist to overwrite value");
3022
3023
0
done:
3024
0
    FUNC_LEAVE_NOAPI(ret_value)
3025
0
} /* H5P_poke() */
3026
3027
/*--------------------------------------------------------------------------
3028
 NAME
3029
    H5P__set_plist_cb
3030
 PURPOSE
3031
    Internal callback for H5P__do_prop, to set a property's value in a property list.
3032
 USAGE
3033
    herr_t H5P__set_plist_cb(plist, name, value)
3034
        H5P_genplist_t *plist;  IN: Property list to set property in
3035
        const char *name;       IN: Name of property to set
3036
        H5P_genprop_t *prop;    IN: Property to set
3037
        void *udata;            IN: User data for operation
3038
 RETURNS
3039
    Returns non-negative on success, negative on failure.
3040
 DESCRIPTION
3041
    Sets a new value for a property in a property list.
3042
 GLOBAL VARIABLES
3043
 COMMENTS, BUGS, ASSUMPTIONS
3044
    Called when the property is found in the property list.
3045
 EXAMPLES
3046
 REVISION LOG
3047
--------------------------------------------------------------------------*/
3048
static herr_t
3049
H5P__set_plist_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop, void *_udata)
3050
112
{
3051
112
    H5P_prop_set_ud_t *udata     = (H5P_prop_set_ud_t *)_udata; /* User data for callback */
3052
112
    void              *tmp_value = NULL;                        /* Temporary value for property */
3053
112
    const void        *prp_value = NULL;                        /* Property value */
3054
112
    herr_t             ret_value = SUCCEED;                     /* Return value */
3055
3056
112
    FUNC_ENTER_PACKAGE
3057
3058
    /* Sanity check */
3059
112
    assert(plist);
3060
112
    assert(name);
3061
112
    assert(prop);
3062
3063
    /* Check for property size >0 */
3064
112
    if (0 == prop->size)
3065
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
3066
3067
    /* Make a copy of the value and pass to 'set' callback */
3068
112
    if (NULL != prop->set) {
3069
        /* Make a copy of the current value, in case the callback fails */
3070
98
        if (NULL == (tmp_value = H5MM_malloc(prop->size)))
3071
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value");
3072
98
        H5MM_memcpy(tmp_value, udata->value, prop->size);
3073
3074
        /* Prepare & restore library for user callback */
3075
98
        H5_BEFORE_USER_CB(FAIL)
3076
98
            {
3077
                /* Call user's callback */
3078
98
                ret_value = (*(prop->set))(plist->plist_id, name, prop->size, tmp_value);
3079
98
            }
3080
98
        H5_AFTER_USER_CB(FAIL)
3081
98
        if (ret_value < 0)
3082
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
3083
3084
        /* Set the pointer for copying */
3085
98
        prp_value = tmp_value;
3086
98
    } /* end if */
3087
    /* No 'set' callback, just copy value */
3088
14
    else
3089
14
        prp_value = udata->value;
3090
3091
    /* Free any previous value for the property */
3092
112
    if (NULL != prop->del) {
3093
        /* Prepare & restore library for user callback */
3094
98
        H5_BEFORE_USER_CB(FAIL)
3095
98
            {
3096
                /* Call user's callback */
3097
98
                ret_value = (*(prop->del))(plist->plist_id, name, prop->size, prop->value);
3098
98
            }
3099
98
        H5_AFTER_USER_CB(FAIL)
3100
98
        if (ret_value < 0)
3101
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't release property value");
3102
98
    } /* end if */
3103
3104
    /* Copy new [possibly unchanged] value into property value */
3105
112
    H5MM_memcpy(prop->value, prp_value, prop->size);
3106
3107
112
done:
3108
    /* Free the temporary value buffer */
3109
112
    if (tmp_value != NULL)
3110
98
        H5MM_xfree(tmp_value);
3111
3112
112
    FUNC_LEAVE_NOAPI(ret_value)
3113
112
} /* H5P__set_plist_cb() */
3114
3115
/*--------------------------------------------------------------------------
3116
 NAME
3117
    H5P__set_pclass_cb
3118
 PURPOSE
3119
    Internal callback for H5P__do_prop, to set a property's value in a property list.
3120
 USAGE
3121
    herr_t H5P__set_pclass_cb(plist, name, value)
3122
        H5P_genplist_t *plist;  IN: Property list to set property in
3123
        const char *name;       IN: Name of property to set
3124
        H5P_genprop_t *prop;    IN: Property to set
3125
        void *udata;            IN: User data for operation
3126
 RETURNS
3127
    Returns non-negative on success, negative on failure.
3128
 DESCRIPTION
3129
    Sets a new value for a property in a property list.
3130
 GLOBAL VARIABLES
3131
 COMMENTS, BUGS, ASSUMPTIONS
3132
    Called when the property is found in the property class.
3133
 EXAMPLES
3134
 REVISION LOG
3135
--------------------------------------------------------------------------*/
3136
static herr_t
3137
H5P__set_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop, void *_udata)
3138
7.34k
{
3139
7.34k
    H5P_prop_set_ud_t *udata     = (H5P_prop_set_ud_t *)_udata; /* User data for callback */
3140
7.34k
    H5P_genprop_t     *pcopy     = NULL;    /* Copy of property to insert into skip list */
3141
7.34k
    void              *tmp_value = NULL;    /* Temporary value for property */
3142
7.34k
    const void        *prp_value = NULL;    /* Property value */
3143
7.34k
    herr_t             ret_value = SUCCEED; /* Return value */
3144
3145
7.34k
    FUNC_ENTER_PACKAGE
3146
3147
    /* Sanity check */
3148
7.34k
    assert(plist);
3149
7.34k
    assert(name);
3150
7.34k
    assert(prop);
3151
7.34k
    assert(prop->cmp);
3152
3153
    /* Check for property size >0 */
3154
7.34k
    if (0 == prop->size)
3155
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
3156
3157
    /* Make a copy of the value and pass to 'set' callback */
3158
7.34k
    if (NULL != prop->set) {
3159
        /* Make a copy of the current value, in case the callback fails */
3160
0
        if (NULL == (tmp_value = H5MM_malloc(prop->size)))
3161
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value");
3162
0
        H5MM_memcpy(tmp_value, udata->value, prop->size);
3163
3164
        /* Prepare & restore library for user callback */
3165
0
        H5_BEFORE_USER_CB(FAIL)
3166
0
            {
3167
                /* Call user's callback */
3168
0
                ret_value = (*(prop->set))(plist->plist_id, name, prop->size, tmp_value);
3169
0
            }
3170
0
        H5_AFTER_USER_CB(FAIL)
3171
0
        if (ret_value < 0)
3172
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
3173
3174
        /* Set the pointer for copying */
3175
0
        prp_value = tmp_value;
3176
0
    } /* end if */
3177
    /* No 'set' callback, just copy value */
3178
7.34k
    else
3179
7.34k
        prp_value = udata->value;
3180
3181
    /* Make a copy of the class's property */
3182
7.34k
    if (NULL == (pcopy = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)))
3183
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
3184
3185
7.34k
    H5MM_memcpy(pcopy->value, prp_value, pcopy->size);
3186
3187
    /* Insert the changed property into the property list */
3188
7.34k
    if (H5P__add_prop(plist->props, pcopy) < 0)
3189
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert changed property into skip list");
3190
3191
7.34k
done:
3192
    /* Free the temporary value buffer */
3193
7.34k
    if (tmp_value != NULL)
3194
0
        H5MM_xfree(tmp_value);
3195
3196
    /* Cleanup on failure */
3197
7.34k
    if (ret_value < 0)
3198
0
        if (pcopy)
3199
0
            H5P__free_prop(pcopy);
3200
3201
7.34k
    FUNC_LEAVE_NOAPI(ret_value)
3202
7.34k
} /* H5P__set_pclass_cb() */
3203
3204
/*--------------------------------------------------------------------------
3205
 NAME
3206
    H5P_set
3207
 PURPOSE
3208
    Internal routine to set a property's value in a property list.
3209
 USAGE
3210
    herr_t H5P_set(plist, name, value)
3211
        H5P_genplist_t *plist;  IN: Property list to find property in
3212
        const char *name;       IN: Name of property to set
3213
        const void *value;      IN: Pointer to the value for the property
3214
 RETURNS
3215
    Returns non-negative on success, negative on failure.
3216
 DESCRIPTION
3217
        Sets a new value for a property in a property list.  The property name
3218
    must exist or this routine will fail.  If there is a 'set' callback routine
3219
    registered for this property, the 'value' will be passed to that routine and
3220
    any changes to the 'value' will be used when setting the property value.
3221
    The information pointed at by the 'value' pointer (possibly modified by the
3222
    'set' callback) is copied into the property list value and may be changed
3223
    by the application making the H5Pset call without affecting the property
3224
    value.
3225
3226
        If the 'set' callback routine returns an error, the property value will
3227
    not be modified.  This routine may not be called for zero-sized properties
3228
    and will return an error in that case.
3229
3230
 GLOBAL VARIABLES
3231
 COMMENTS, BUGS, ASSUMPTIONS
3232
 EXAMPLES
3233
 REVISION LOG
3234
--------------------------------------------------------------------------*/
3235
herr_t
3236
H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
3237
7.45k
{
3238
7.45k
    H5P_prop_set_ud_t udata;               /* User data for callback */
3239
7.45k
    herr_t            ret_value = SUCCEED; /* Return value */
3240
3241
7.45k
    FUNC_ENTER_NOAPI(FAIL)
3242
3243
    /* Sanity check */
3244
7.45k
    assert(plist);
3245
7.45k
    assert(name);
3246
7.45k
    assert(value);
3247
3248
    /* Find the property and set the value */
3249
7.45k
    udata.value = value;
3250
7.45k
    if (H5P__do_prop(plist, name, H5P__set_plist_cb, H5P__set_pclass_cb, &udata) < 0)
3251
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on plist to set value");
3252
3253
7.45k
done:
3254
7.45k
    FUNC_LEAVE_NOAPI(ret_value)
3255
7.45k
} /* H5P_set() */
3256
3257
/*--------------------------------------------------------------------------
3258
 NAME
3259
    H5P__class_get
3260
 PURPOSE
3261
    Internal routine to get a property's value from a property class.
3262
 USAGE
3263
    herr_t H5P__class_get(pclass, name, value)
3264
        const H5P_genclass_t *pclass; IN: Property class to find property in
3265
        const char *name;       IN: Name of property to get
3266
        void *value;            IN: Pointer to the value for the property
3267
 RETURNS
3268
    Returns non-negative on success, negative on failure.
3269
 DESCRIPTION
3270
        Gets the current value for a property in a property class.  The property
3271
    name must exist or this routine will fail.
3272
 GLOBAL VARIABLES
3273
 COMMENTS, BUGS, ASSUMPTIONS
3274
        The 'get' callback routine registered for this property will _NOT_ be
3275
    called, this routine is designed for internal library use only!
3276
3277
        This routine may not be called for zero-sized properties and will
3278
    return an error in that case.
3279
 EXAMPLES
3280
 REVISION LOG
3281
--------------------------------------------------------------------------*/
3282
herr_t
3283
H5P__class_get(const H5P_genclass_t *pclass, const char *name, void *value)
3284
1
{
3285
1
    H5P_genprop_t *prop;                /* Temporary property pointer */
3286
1
    herr_t         ret_value = SUCCEED; /* Return value */
3287
3288
1
    FUNC_ENTER_PACKAGE
3289
3290
    /* Sanity check */
3291
1
    assert(pclass);
3292
1
    assert(name);
3293
1
    assert(value);
3294
3295
    /* Find property in list */
3296
1
    if (NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
3297
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
3298
3299
    /* Check for property size >0 */
3300
1
    if (0 == prop->size)
3301
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
3302
3303
    /* Copy the property value */
3304
1
    H5MM_memcpy(value, prop->value, prop->size);
3305
3306
1
done:
3307
1
    FUNC_LEAVE_NOAPI(ret_value)
3308
1
} /* H5P__class_get() */
3309
3310
/*--------------------------------------------------------------------------
3311
 NAME
3312
    H5P__class_set
3313
 PURPOSE
3314
    Internal routine to set a property's value in a property class.
3315
 USAGE
3316
    herr_t H5P__class_set(pclass, name, value)
3317
        const H5P_genclass_t *pclass; IN: Property class to find property in
3318
        const char *name;       IN: Name of property to set
3319
        const void *value;      IN: Pointer to the value for the property
3320
 RETURNS
3321
    Returns non-negative on success, negative on failure.
3322
 DESCRIPTION
3323
        Sets a new value for a property in a property class.  The property name
3324
    must exist or this routine will fail.
3325
 GLOBAL VARIABLES
3326
 COMMENTS, BUGS, ASSUMPTIONS
3327
        The 'set' callback routine registered for this property will _NOT_ be
3328
    called, this routine is designed for internal library use only!
3329
3330
        This routine may not be called for zero-sized properties and will
3331
    return an error in that case.
3332
3333
        The previous value is overwritten, not released in any way.
3334
 EXAMPLES
3335
 REVISION LOG
3336
--------------------------------------------------------------------------*/
3337
herr_t
3338
H5P__class_set(const H5P_genclass_t *pclass, const char *name, const void *value)
3339
1
{
3340
1
    H5P_genprop_t *prop;                /* Temporary property pointer */
3341
1
    herr_t         ret_value = SUCCEED; /* Return value */
3342
3343
1
    FUNC_ENTER_PACKAGE
3344
3345
    /* Sanity check */
3346
1
    assert(pclass);
3347
1
    assert(name);
3348
1
    assert(value);
3349
3350
    /* Find property in list */
3351
1
    if (NULL == (prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
3352
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
3353
3354
    /* Check for property size >0 */
3355
1
    if (0 == prop->size)
3356
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
3357
3358
    /* Copy the property value */
3359
1
    H5MM_memcpy(prop->value, value, prop->size);
3360
3361
1
done:
3362
1
    FUNC_LEAVE_NOAPI(ret_value)
3363
1
} /* H5P__class_set() */
3364
3365
/*--------------------------------------------------------------------------
3366
 NAME
3367
    H5P_exist_plist
3368
 PURPOSE
3369
    Internal routine to query the existence of a property in a property list.
3370
 USAGE
3371
    htri_t H5P_exist_plist(plist, name)
3372
        const H5P_genplist_t *plist;  IN: Property list to check
3373
        const char *name;       IN: Name of property to check for
3374
 RETURNS
3375
    Success: Positive if the property exists in the property list, zero
3376
            if the property does not exist.
3377
    Failure: negative value
3378
 DESCRIPTION
3379
        This routine checks if a property exists within a property list.
3380
3381
 GLOBAL VARIABLES
3382
 COMMENTS, BUGS, ASSUMPTIONS
3383
 EXAMPLES
3384
 REVISION LOG
3385
--------------------------------------------------------------------------*/
3386
htri_t
3387
H5P_exist_plist(const H5P_genplist_t *plist, const char *name)
3388
2.14k
{
3389
2.14k
    htri_t ret_value = FAIL; /* return value */
3390
3391
2.14k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
3392
3393
2.14k
    assert(plist);
3394
2.14k
    assert(name);
3395
3396
    /* Check for property in deleted property list */
3397
2.14k
    if (H5SL_search(plist->del, name) != NULL)
3398
0
        ret_value = false;
3399
2.14k
    else {
3400
        /* Check for property in changed property list */
3401
2.14k
        if (H5SL_search(plist->props, name) != NULL)
3402
0
            ret_value = true;
3403
2.14k
        else {
3404
2.14k
            H5P_genclass_t *tclass; /* Temporary class pointer */
3405
3406
2.14k
            tclass = plist->pclass;
3407
2.14k
            while (tclass != NULL) {
3408
2.14k
                if (H5SL_search(tclass->props, name) != NULL)
3409
2.14k
                    HGOTO_DONE(true);
3410
3411
                /* Go up to parent class */
3412
0
                tclass = tclass->parent;
3413
0
            } /* end while */
3414
3415
            /* If we've reached here, we couldn't find the property */
3416
0
            ret_value = false;
3417
0
        } /* end else */
3418
2.14k
    }     /* end else */
3419
3420
2.14k
done:
3421
2.14k
    FUNC_LEAVE_NOAPI(ret_value)
3422
2.14k
} /* H5P_exist_plist() */
3423
3424
/*--------------------------------------------------------------------------
3425
 NAME
3426
    H5P__exist_pclass
3427
 PURPOSE
3428
    Internal routine to query the existence of a property in a property class.
3429
 USAGE
3430
    herr_t H5P__exist_pclass(pclass, name)
3431
        H5P_genclass_t *pclass;  IN: Property class to check
3432
        const char *name;       IN: Name of property to check for
3433
 RETURNS
3434
    Success: Positive if the property exists in the property class, zero
3435
            if the property does not exist.
3436
    Failure: negative value
3437
 DESCRIPTION
3438
        This routine checks if a property exists within a property class.
3439
3440
 GLOBAL VARIABLES
3441
 COMMENTS, BUGS, ASSUMPTIONS
3442
 EXAMPLES
3443
 REVISION LOG
3444
--------------------------------------------------------------------------*/
3445
htri_t
3446
H5P__exist_pclass(H5P_genclass_t *pclass, const char *name)
3447
0
{
3448
0
    htri_t ret_value = FAIL; /* return value */
3449
3450
0
    FUNC_ENTER_PACKAGE_NOERR
3451
3452
0
    assert(pclass);
3453
0
    assert(name);
3454
3455
    /* Check for property in property list */
3456
0
    if (H5SL_search(pclass->props, name) != NULL)
3457
0
        ret_value = true;
3458
0
    else {
3459
0
        H5P_genclass_t *tclass; /* Temporary class pointer */
3460
3461
0
        tclass = pclass->parent;
3462
0
        while (tclass != NULL) {
3463
0
            if (H5SL_search(tclass->props, name) != NULL)
3464
0
                HGOTO_DONE(true);
3465
3466
            /* Go up to parent class */
3467
0
            tclass = tclass->parent;
3468
0
        } /* end while */
3469
3470
        /* If we've reached here, we couldn't find the property */
3471
0
        ret_value = false;
3472
0
    } /* end else */
3473
3474
0
done:
3475
0
    FUNC_LEAVE_NOAPI(ret_value)
3476
0
} /* H5P__exist_pclass() */
3477
3478
/*--------------------------------------------------------------------------
3479
 NAME
3480
    H5P__get_size_plist
3481
 PURPOSE
3482
    Internal routine to query the size of a property in a property list.
3483
 USAGE
3484
    herr_t H5P__get_size_plist(plist, name)
3485
        const H5P_genplist_t *plist;  IN: Property list to check
3486
        const char *name;       IN: Name of property to query
3487
        size_t *size;           OUT: Size of property
3488
 RETURNS
3489
    Success: non-negative value
3490
    Failure: negative value
3491
 DESCRIPTION
3492
        This routine retrieves the size of a property's value in bytes.  Zero-
3493
    sized properties are allowed and return a value of 0.
3494
3495
 GLOBAL VARIABLES
3496
 COMMENTS, BUGS, ASSUMPTIONS
3497
 EXAMPLES
3498
 REVISION LOG
3499
--------------------------------------------------------------------------*/
3500
herr_t
3501
H5P__get_size_plist(const H5P_genplist_t *plist, const char *name, size_t *size)
3502
0
{
3503
0
    H5P_genprop_t *prop;                /* Temporary property pointer */
3504
0
    herr_t         ret_value = SUCCEED; /* return value */
3505
3506
0
    FUNC_ENTER_PACKAGE
3507
3508
0
    assert(plist);
3509
0
    assert(name);
3510
0
    assert(size);
3511
3512
    /* Find property */
3513
0
    if (NULL == (prop = H5P__find_prop_plist(plist, name)))
3514
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
3515
3516
    /* Get property size */
3517
0
    *size = prop->size;
3518
3519
0
done:
3520
0
    FUNC_LEAVE_NOAPI(ret_value)
3521
0
} /* H5P__get_size_plist() */
3522
3523
/*--------------------------------------------------------------------------
3524
 NAME
3525
    H5P__get_size_pclass
3526
 PURPOSE
3527
    Internal routine to query the size of a property in a property class.
3528
 USAGE
3529
    herr_t H5P__get_size_pclass(pclass, name)
3530
        H5P_genclass_t *pclass; IN: Property class to check
3531
        const char *name;       IN: Name of property to query
3532
        size_t *size;           OUT: Size of property
3533
 RETURNS
3534
    Success: non-negative value
3535
    Failure: negative value
3536
 DESCRIPTION
3537
        This routine retrieves the size of a property's value in bytes.  Zero-
3538
    sized properties are allowed and return a value of 0.
3539
3540
 GLOBAL VARIABLES
3541
 COMMENTS, BUGS, ASSUMPTIONS
3542
 EXAMPLES
3543
 REVISION LOG
3544
--------------------------------------------------------------------------*/
3545
herr_t
3546
H5P__get_size_pclass(H5P_genclass_t *pclass, const char *name, size_t *size)
3547
0
{
3548
0
    H5P_genprop_t *prop;                /* Temporary property pointer */
3549
0
    herr_t         ret_value = SUCCEED; /* return value */
3550
3551
0
    FUNC_ENTER_PACKAGE
3552
3553
0
    assert(pclass);
3554
0
    assert(name);
3555
0
    assert(size);
3556
3557
    /* Find property */
3558
0
    if ((prop = H5P__find_prop_pclass(pclass, name)) == NULL)
3559
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
3560
3561
    /* Get property size */
3562
0
    *size = prop->size;
3563
3564
0
done:
3565
0
    FUNC_LEAVE_NOAPI(ret_value)
3566
0
} /* H5P__get_size_pclass() */
3567
3568
/*--------------------------------------------------------------------------
3569
 NAME
3570
    H5P__get_nprops_plist
3571
 PURPOSE
3572
    Internal routine to query the number of properties in a property list
3573
 USAGE
3574
    herr_t H5P__get_nprops_plist(plist, nprops)
3575
        H5P_genplist_t *plist;  IN: Property list to check
3576
        size_t *nprops;         OUT: Number of properties in the property list
3577
 RETURNS
3578
    Success: non-negative value
3579
    Failure: negative value
3580
 DESCRIPTION
3581
        This routine retrieves the number of a properties in a property list.
3582
3583
 GLOBAL VARIABLES
3584
 COMMENTS, BUGS, ASSUMPTIONS
3585
 EXAMPLES
3586
 REVISION LOG
3587
--------------------------------------------------------------------------*/
3588
herr_t
3589
H5P__get_nprops_plist(const H5P_genplist_t *plist, size_t *nprops)
3590
0
{
3591
0
    FUNC_ENTER_PACKAGE_NOERR
3592
3593
0
    assert(plist);
3594
0
    assert(nprops);
3595
3596
    /* Get property size */
3597
0
    *nprops = plist->nprops;
3598
3599
0
    FUNC_LEAVE_NOAPI(SUCCEED)
3600
0
} /* H5P__get_nprops_plist() */
3601
3602
/*--------------------------------------------------------------------------
3603
 NAME
3604
    H5P_get_nprops_pclass
3605
 PURPOSE
3606
    Internal routine to query the number of properties in a property class
3607
 USAGE
3608
    herr_t H5P_get_nprops_pclass(pclass, nprops)
3609
        H5P_genclass_t *pclass;  IN: Property class to check
3610
        size_t *nprops;         OUT: Number of properties in the property list
3611
        bool recurse;        IN: Include properties in parent class(es) also
3612
 RETURNS
3613
    Success: non-negative value (can't fail)
3614
    Failure: negative value
3615
 DESCRIPTION
3616
    This routine retrieves the number of a properties in a property class.
3617
3618
 GLOBAL VARIABLES
3619
 COMMENTS, BUGS, ASSUMPTIONS
3620
 EXAMPLES
3621
 REVISION LOG
3622
--------------------------------------------------------------------------*/
3623
herr_t
3624
H5P_get_nprops_pclass(const H5P_genclass_t *pclass, size_t *nprops, bool recurse)
3625
0
{
3626
0
    herr_t ret_value = SUCCEED; /* Return value */
3627
3628
0
    FUNC_ENTER_NOAPI(FAIL)
3629
3630
0
    assert(pclass);
3631
0
    assert(nprops);
3632
3633
    /* Get number of properties */
3634
0
    *nprops = pclass->nprops;
3635
3636
    /* Check if the class is derived, and walk up the chain, if so */
3637
0
    if (recurse)
3638
0
        while (pclass->parent != NULL) {
3639
0
            pclass = pclass->parent;
3640
0
            *nprops += pclass->nprops;
3641
0
        } /* end while */
3642
3643
0
done:
3644
0
    FUNC_LEAVE_NOAPI(ret_value)
3645
0
} /* H5P_get_nprops_pclass() */
3646
3647
/*--------------------------------------------------------------------------
3648
 NAME
3649
    H5P__cmp_prop
3650
 PURPOSE
3651
    Internal routine to compare two generic properties
3652
 USAGE
3653
    int H5P__cmp_prop(prop1, prop2)
3654
        H5P_genprop_t *prop1;    IN: 1st property to compare
3655
        H5P_genprop_t *prop1;    IN: 2nd property to compare
3656
 RETURNS
3657
    Success: negative if prop1 "less" than prop2, positive if prop1 "greater"
3658
        than prop2, zero if prop1 is "equal" to prop2
3659
    Failure: can't fail
3660
 DESCRIPTION
3661
        This function compares two generic properties together to see if
3662
    they are the same property.
3663
3664
 GLOBAL VARIABLES
3665
 COMMENTS, BUGS, ASSUMPTIONS
3666
 EXAMPLES
3667
 REVISION LOG
3668
--------------------------------------------------------------------------*/
3669
static int
3670
H5P__cmp_prop(const H5P_genprop_t *prop1, const H5P_genprop_t *prop2)
3671
0
{
3672
0
    int cmp_value;     /* Value from comparison */
3673
0
    int ret_value = 0; /* return value */
3674
3675
0
    FUNC_ENTER_PACKAGE_NOERR
3676
3677
0
    assert(prop1);
3678
0
    assert(prop2);
3679
3680
    /* Check the name */
3681
0
    if ((cmp_value = strcmp(prop1->name, prop2->name)) != 0)
3682
0
        HGOTO_DONE(cmp_value);
3683
3684
    /* Check the size of properties */
3685
0
    if (prop1->size < prop2->size)
3686
0
        HGOTO_DONE(-1);
3687
0
    if (prop1->size > prop2->size)
3688
0
        HGOTO_DONE(1);
3689
3690
    /* Check if they both have the same 'create' callback */
3691
0
    if (prop1->create == NULL && prop2->create != NULL)
3692
0
        HGOTO_DONE(-1);
3693
0
    if (prop1->create != NULL && prop2->create == NULL)
3694
0
        HGOTO_DONE(1);
3695
0
    if (prop1->create != prop2->create)
3696
0
        HGOTO_DONE(-1);
3697
3698
    /* Check if they both have the same 'set' callback */
3699
0
    if (prop1->set == NULL && prop2->set != NULL)
3700
0
        HGOTO_DONE(-1);
3701
0
    if (prop1->set != NULL && prop2->set == NULL)
3702
0
        HGOTO_DONE(1);
3703
0
    if (prop1->set != prop2->set)
3704
0
        HGOTO_DONE(-1);
3705
3706
    /* Check if they both have the same 'get' callback */
3707
0
    if (prop1->get == NULL && prop2->get != NULL)
3708
0
        HGOTO_DONE(-1);
3709
0
    if (prop1->get != NULL && prop2->get == NULL)
3710
0
        HGOTO_DONE(1);
3711
0
    if (prop1->get != prop2->get)
3712
0
        HGOTO_DONE(-1);
3713
3714
    /* Check if they both have the same 'encode' callback */
3715
0
    if (prop1->encode == NULL && prop2->encode != NULL)
3716
0
        HGOTO_DONE(-1);
3717
0
    if (prop1->encode != NULL && prop2->encode == NULL)
3718
0
        HGOTO_DONE(1);
3719
0
    if (prop1->encode != prop2->encode)
3720
0
        HGOTO_DONE(-1);
3721
3722
    /* Check if they both have the same 'decode' callback */
3723
0
    if (prop1->decode == NULL && prop2->decode != NULL)
3724
0
        HGOTO_DONE(-1);
3725
0
    if (prop1->decode != NULL && prop2->decode == NULL)
3726
0
        HGOTO_DONE(1);
3727
0
    if (prop1->decode != prop2->decode)
3728
0
        HGOTO_DONE(-1);
3729
3730
    /* Check if they both have the same 'delete' callback */
3731
0
    if (prop1->del == NULL && prop2->del != NULL)
3732
0
        HGOTO_DONE(-1);
3733
0
    if (prop1->del != NULL && prop2->del == NULL)
3734
0
        HGOTO_DONE(1);
3735
0
    if (prop1->del != prop2->del)
3736
0
        HGOTO_DONE(-1);
3737
3738
    /* Check if they both have the same 'copy' callback */
3739
0
    if (prop1->copy == NULL && prop2->copy != NULL)
3740
0
        HGOTO_DONE(-1);
3741
0
    if (prop1->copy != NULL && prop2->copy == NULL)
3742
0
        HGOTO_DONE(1);
3743
0
    if (prop1->copy != prop2->copy)
3744
0
        HGOTO_DONE(-1);
3745
3746
    /* Check if they both have the same 'compare' callback */
3747
0
    if (prop1->cmp == NULL && prop2->cmp != NULL)
3748
0
        HGOTO_DONE(-1);
3749
0
    if (prop1->cmp != NULL && prop2->cmp == NULL)
3750
0
        HGOTO_DONE(1);
3751
0
    if (prop1->cmp != prop2->cmp)
3752
0
        HGOTO_DONE(-1);
3753
3754
    /* Check if they both have the same 'close' callback */
3755
0
    if (prop1->close == NULL && prop2->close != NULL)
3756
0
        HGOTO_DONE(-1);
3757
0
    if (prop1->close != NULL && prop2->close == NULL)
3758
0
        HGOTO_DONE(1);
3759
0
    if (prop1->close != prop2->close)
3760
0
        HGOTO_DONE(-1);
3761
3762
    /* Check if they both have values allocated (or not allocated) */
3763
0
    if (prop1->value == NULL && prop2->value != NULL)
3764
0
        HGOTO_DONE(-1);
3765
0
    if (prop1->value != NULL && prop2->value == NULL)
3766
0
        HGOTO_DONE(1);
3767
0
    if (prop1->value != NULL) {
3768
        /* Prepare & restore library for user callback */
3769
0
        H5_BEFORE_USER_CB_NOCHECK
3770
0
            {
3771
                /* Call comparison routine */
3772
0
                cmp_value = prop1->cmp(prop1->value, prop2->value, prop1->size);
3773
0
            }
3774
0
        H5_AFTER_USER_CB_NOCHECK
3775
        /* Call comparison routine */
3776
0
        if (0 != cmp_value)
3777
0
            HGOTO_DONE(cmp_value);
3778
0
    } /* end if */
3779
3780
0
done:
3781
0
    FUNC_LEAVE_NOAPI(ret_value)
3782
0
} /* H5P__cmp_prop() */
3783
3784
/*--------------------------------------------------------------------------
3785
 NAME
3786
    H5P__cmp_class
3787
 PURPOSE
3788
    Internal routine to compare two generic property classes
3789
 USAGE
3790
    int H5P__cmp_class(pclass1, pclass2)
3791
        H5P_genclass_t *pclass1;    IN: 1st property class to compare
3792
        H5P_genclass_t *pclass2;    IN: 2nd property class to compare
3793
 RETURNS
3794
    Success: negative if class1 "less" than class2, positive if class1 "greater"
3795
        than class2, zero if class1 is "equal" to class2
3796
    Failure: can't fail
3797
 DESCRIPTION
3798
        This function compares two generic property classes together to see if
3799
    they are the same class.
3800
3801
 GLOBAL VARIABLES
3802
 COMMENTS, BUGS, ASSUMPTIONS
3803
 EXAMPLES
3804
 REVISION LOG
3805
--------------------------------------------------------------------------*/
3806
int
3807
H5P__cmp_class(const H5P_genclass_t *pclass1, const H5P_genclass_t *pclass2)
3808
1.16k
{
3809
1.16k
    H5SL_node_t *tnode1, *tnode2; /* Temporary pointer to property nodes */
3810
1.16k
    int          cmp_value;       /* Value from comparison */
3811
1.16k
    int          ret_value = 0;   /* Return value */
3812
3813
1.16k
    FUNC_ENTER_PACKAGE_NOERR
3814
3815
1.16k
    assert(pclass1);
3816
1.16k
    assert(pclass2);
3817
3818
    /* Use the revision number to quickly check for identical classes */
3819
1.16k
    if (pclass1->revision == pclass2->revision)
3820
1.16k
        HGOTO_DONE(0);
3821
3822
    /* Check the name */
3823
0
    if ((cmp_value = strcmp(pclass1->name, pclass2->name)) != 0)
3824
0
        HGOTO_DONE(cmp_value);
3825
3826
    /* Check the number of properties */
3827
0
    if (pclass1->nprops < pclass2->nprops)
3828
0
        HGOTO_DONE(-1);
3829
0
    if (pclass1->nprops > pclass2->nprops)
3830
0
        HGOTO_DONE(1);
3831
3832
    /* Check the number of property lists created from the class */
3833
0
    if (pclass1->plists < pclass2->plists)
3834
0
        HGOTO_DONE(-1);
3835
0
    if (pclass1->plists > pclass2->plists)
3836
0
        HGOTO_DONE(1);
3837
3838
    /* Check the number of classes derived from the class */
3839
0
    if (pclass1->classes < pclass2->classes)
3840
0
        HGOTO_DONE(-1);
3841
0
    if (pclass1->classes > pclass2->classes)
3842
0
        HGOTO_DONE(1);
3843
3844
    /* Check the number of ID references open on the class */
3845
0
    if (pclass1->ref_count < pclass2->ref_count)
3846
0
        HGOTO_DONE(-1);
3847
0
    if (pclass1->ref_count > pclass2->ref_count)
3848
0
        HGOTO_DONE(1);
3849
3850
    /* Check the property list types */
3851
0
    if (pclass1->type < pclass2->type)
3852
0
        HGOTO_DONE(-1);
3853
0
    if (pclass1->type > pclass2->type)
3854
0
        HGOTO_DONE(1);
3855
3856
    /* Check whether they are deleted or not */
3857
0
    if (pclass1->deleted < pclass2->deleted)
3858
0
        HGOTO_DONE(-1);
3859
0
    if (pclass1->deleted > pclass2->deleted)
3860
0
        HGOTO_DONE(1);
3861
3862
    /* Check whether they have creation callback functions & data */
3863
0
    if (pclass1->create_func == NULL && pclass2->create_func != NULL)
3864
0
        HGOTO_DONE(-1);
3865
0
    if (pclass1->create_func != NULL && pclass2->create_func == NULL)
3866
0
        HGOTO_DONE(1);
3867
0
    if (pclass1->create_func != pclass2->create_func)
3868
0
        HGOTO_DONE(-1);
3869
0
    if (pclass1->create_data < pclass2->create_data)
3870
0
        HGOTO_DONE(-1);
3871
0
    if (pclass1->create_data > pclass2->create_data)
3872
0
        HGOTO_DONE(1);
3873
3874
    /* Check whether they have close callback functions & data */
3875
0
    if (pclass1->close_func == NULL && pclass2->close_func != NULL)
3876
0
        HGOTO_DONE(-1);
3877
0
    if (pclass1->close_func != NULL && pclass2->close_func == NULL)
3878
0
        HGOTO_DONE(1);
3879
0
    if (pclass1->close_func != pclass2->close_func)
3880
0
        HGOTO_DONE(-1);
3881
0
    if (pclass1->close_data < pclass2->close_data)
3882
0
        HGOTO_DONE(-1);
3883
0
    if (pclass1->close_data > pclass2->close_data)
3884
0
        HGOTO_DONE(1);
3885
3886
    /* Cycle through the properties and compare them also */
3887
0
    tnode1 = H5SL_first(pclass1->props);
3888
0
    tnode2 = H5SL_first(pclass2->props);
3889
0
    while (tnode1 || tnode2) {
3890
0
        H5P_genprop_t *prop1, *prop2; /* Property for node */
3891
3892
        /* Check if they both have properties in this skip list node */
3893
0
        if (tnode1 == NULL && tnode2 != NULL)
3894
0
            HGOTO_DONE(-1);
3895
0
        if (tnode1 != NULL && tnode2 == NULL)
3896
0
            HGOTO_DONE(1);
3897
3898
        /* Compare the two properties */
3899
0
        prop1 = (H5P_genprop_t *)H5SL_item(tnode1);
3900
0
        prop2 = (H5P_genprop_t *)H5SL_item(tnode2);
3901
0
        if ((cmp_value = H5P__cmp_prop(prop1, prop2)) != 0)
3902
0
            HGOTO_DONE(cmp_value);
3903
3904
        /* Advance the pointers */
3905
0
        tnode1 = H5SL_next(tnode1);
3906
0
        tnode2 = H5SL_next(tnode2);
3907
0
    } /* end while */
3908
3909
1.16k
done:
3910
1.16k
    FUNC_LEAVE_NOAPI(ret_value)
3911
1.16k
} /* H5P__cmp_class() */
3912
3913
/*--------------------------------------------------------------------------
3914
 NAME
3915
    H5P__cmp_plist_cb
3916
 PURPOSE
3917
    Internal callback routine when iterating over properties in property list
3918
    to compare them for equality
3919
 USAGE
3920
    int H5P__cmp_plist_cb(prop, udata)
3921
        H5P_genprop_t *prop;        IN: Pointer to the property
3922
        void *udata;                IN/OUT: Pointer to iteration data from user
3923
 RETURNS
3924
    Success: Returns whether to continue (H5_ITER_CONT) or stop (H5_ITER_STOP)
3925
            iterating over the property lists.
3926
    Failure: Negative value (H5_ITER_ERROR)
3927
 DESCRIPTION
3928
    This routine compares a property from one property list (the one being
3929
    iterated over, to a property from the second property list (which is
3930
    looked up).  Iteration is stopped if the comparison is non-equal.
3931
 GLOBAL VARIABLES
3932
 COMMENTS, BUGS, ASSUMPTIONS
3933
 EXAMPLES
3934
 REVISION LOG
3935
--------------------------------------------------------------------------*/
3936
static int
3937
H5P__cmp_plist_cb(H5P_genprop_t *prop, void *_udata)
3938
0
{
3939
0
    H5P_plist_cmp_ud_t *udata = (H5P_plist_cmp_ud_t *)_udata; /* Pointer to user data */
3940
0
    htri_t              prop2_exist; /* Whether the property exists in the second property list */
3941
0
    int                 ret_value = H5_ITER_CONT; /* Return value */
3942
3943
0
    FUNC_ENTER_PACKAGE
3944
3945
    /* Sanity check */
3946
0
    assert(prop);
3947
0
    assert(udata);
3948
3949
    /* Check if the property exists in the second property list */
3950
0
    if ((prop2_exist = H5P_exist_plist(udata->plist2, prop->name)) < 0)
3951
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, H5_ITER_ERROR, "can't lookup existence of property?");
3952
0
    if (prop2_exist) {
3953
0
        const H5P_genprop_t *prop2; /* Pointer to property in second plist */
3954
3955
        /* Look up same property in second property list */
3956
0
        if (NULL == (prop2 = H5P__find_prop_plist(udata->plist2, prop->name)))
3957
0
            HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, H5_ITER_ERROR, "property doesn't exist");
3958
3959
        /* Compare the two properties */
3960
0
        if ((udata->cmp_value = H5P__cmp_prop(prop, prop2)) != 0)
3961
0
            HGOTO_DONE(H5_ITER_STOP);
3962
0
    } /* end if */
3963
0
    else {
3964
        /* Property exists in first list, but not second */
3965
0
        udata->cmp_value = 1;
3966
0
        HGOTO_DONE(H5_ITER_STOP);
3967
0
    } /* end else */
3968
3969
0
done:
3970
0
    FUNC_LEAVE_NOAPI(ret_value)
3971
0
} /* end H5P__cmp_plist_cb() */
3972
3973
/*--------------------------------------------------------------------------
3974
 NAME
3975
    H5P__cmp_plist
3976
 PURPOSE
3977
    Internal routine to compare two generic property lists
3978
 USAGE
3979
    herr_t H5P__cmp_plist(plist1, plist2, cmp_ret)
3980
        H5P_genplist_t *plist1;    IN: 1st property list to compare
3981
        H5P_genplist_t *plist2;    IN: 2nd property list to compare
3982
        int *cmp_ret;              OUT: Comparison value for two property lists
3983
                                        Negative if list1 "less" than list2,
3984
                                        positive if list1 "greater" than list2,
3985
                                        zero if list1 is "equal" to list2
3986
 RETURNS
3987
    Success: non-negative value
3988
    Failure: negative value
3989
 DESCRIPTION
3990
        This function compares two generic property lists together to see if
3991
    they are equal.
3992
 GLOBAL VARIABLES
3993
 COMMENTS, BUGS, ASSUMPTIONS
3994
 EXAMPLES
3995
 REVISION LOG
3996
--------------------------------------------------------------------------*/
3997
herr_t
3998
H5P__cmp_plist(const H5P_genplist_t *plist1, const H5P_genplist_t *plist2, int *cmp_ret)
3999
0
{
4000
0
    H5P_plist_cmp_ud_t udata;               /* User data for callback */
4001
0
    int                idx       = 0;       /* Index of property to begin with */
4002
0
    herr_t             ret_value = SUCCEED; /* Return value */
4003
4004
0
    FUNC_ENTER_PACKAGE
4005
4006
0
    assert(plist1);
4007
0
    assert(plist2);
4008
0
    assert(cmp_ret);
4009
4010
    /* Check the number of properties */
4011
0
    if (plist1->nprops < plist2->nprops) {
4012
0
        *cmp_ret = -1;
4013
0
        HGOTO_DONE(SUCCEED);
4014
0
    } /* end if */
4015
0
    if (plist1->nprops > plist2->nprops) {
4016
0
        *cmp_ret = 1;
4017
0
        HGOTO_DONE(SUCCEED);
4018
0
    } /* end if */
4019
4020
    /* Check whether they've been initialized */
4021
0
    if (plist1->class_init < plist2->class_init) {
4022
0
        *cmp_ret = -1;
4023
0
        HGOTO_DONE(SUCCEED);
4024
0
    } /* end if */
4025
0
    if (plist1->class_init > plist2->class_init) {
4026
0
        *cmp_ret = 1;
4027
0
        HGOTO_DONE(SUCCEED);
4028
0
    } /* end if */
4029
4030
    /* Set up iterator callback info */
4031
0
    udata.cmp_value = 0;
4032
0
    udata.plist2    = plist2;
4033
4034
    /* Iterate over properties in first property list */
4035
0
    if ((ret_value = H5P__iterate_plist(plist1, true, &idx, H5P__cmp_plist_cb, &udata)) < 0)
4036
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to iterate over list");
4037
0
    if (ret_value != 0) {
4038
0
        *cmp_ret = udata.cmp_value;
4039
0
        HGOTO_DONE(SUCCEED);
4040
0
    } /* end if */
4041
4042
    /* Check the parent classes */
4043
0
    if ((*cmp_ret = H5P__cmp_class(plist1->pclass, plist2->pclass)) != 0)
4044
0
        HGOTO_DONE(SUCCEED);
4045
4046
    /* Property lists must be equal, set comparison value to 0 */
4047
0
    *cmp_ret = 0;
4048
4049
0
done:
4050
0
    FUNC_LEAVE_NOAPI(ret_value)
4051
0
} /* H5P__cmp_plist() */
4052
4053
/*--------------------------------------------------------------------------
4054
 NAME
4055
    H5P_class_isa
4056
 PURPOSE
4057
    Internal routine to query whether a property class is the same as another
4058
    class.
4059
 USAGE
4060
    htri_t H5P_class_isa(pclass1, pclass2)
4061
        H5P_genclass_t *pclass1;   IN: Property class to check
4062
        H5P_genclass_t *pclass2;   IN: Property class to compare with
4063
 RETURNS
4064
    Success: true (1) or false (0)
4065
    Failure: negative value
4066
 DESCRIPTION
4067
    This routine queries whether a property class is the same as another class,
4068
    and walks up the hierarchy of derived classes, checking if the first class
4069
    is derived from the second class also.
4070
4071
 GLOBAL VARIABLES
4072
 COMMENTS, BUGS, ASSUMPTIONS
4073
 EXAMPLES
4074
 REVISION LOG
4075
--------------------------------------------------------------------------*/
4076
htri_t
4077
H5P_class_isa(const H5P_genclass_t *pclass1, const H5P_genclass_t *pclass2)
4078
1.16k
{
4079
1.16k
    htri_t ret_value = FAIL; /* Return value */
4080
4081
1.16k
    FUNC_ENTER_NOAPI(FAIL)
4082
4083
1.16k
    assert(pclass1);
4084
1.16k
    assert(pclass2);
4085
4086
    /* Compare property classes */
4087
1.16k
    if (H5P__cmp_class(pclass1, pclass2) == 0) {
4088
1.16k
        HGOTO_DONE(true);
4089
1.16k
    }
4090
0
    else {
4091
        /* Check if the class is derived, and walk up the chain, if so */
4092
0
        if (pclass1->parent != NULL)
4093
0
            ret_value = H5P_class_isa(pclass1->parent, pclass2);
4094
0
        else
4095
0
            HGOTO_DONE(false);
4096
0
    } /* end else */
4097
4098
1.16k
done:
4099
1.16k
    FUNC_LEAVE_NOAPI(ret_value)
4100
1.16k
} /* H5P_class_isa() */
4101
4102
/*--------------------------------------------------------------------------
4103
 NAME
4104
    H5P_isa_class
4105
 PURPOSE
4106
    Internal routine to query whether a property list is a certain class
4107
 USAGE
4108
    hid_t H5P_isa_class(plist_id, pclass_id)
4109
        hid_t plist_id;         IN: Property list to query
4110
        hid_t pclass_id;        IN: Property class to query
4111
 RETURNS
4112
    Success: true (1) or false (0)
4113
    Failure: negative
4114
 DESCRIPTION
4115
    This routine queries whether a property list is a member of the property
4116
    list class.
4117
4118
 GLOBAL VARIABLES
4119
 COMMENTS, BUGS, ASSUMPTIONS
4120
    This function is special in that it is an internal library function, but
4121
    accepts hid_t's as parameters.  Since it is used in basically the same way
4122
    as the H5I functions, this should be OK.  Don't make more library functions
4123
    which accept hid_t's without thorough discussion. -QAK
4124
 EXAMPLES
4125
 REVISION LOG
4126
--------------------------------------------------------------------------*/
4127
htri_t
4128
H5P_isa_class(hid_t plist_id, hid_t pclass_id)
4129
1.16k
{
4130
1.16k
    H5P_genplist_t *plist;            /* Property list to query */
4131
1.16k
    H5P_genclass_t *pclass;           /* Property list class */
4132
1.16k
    htri_t          ret_value = FAIL; /* Return value */
4133
4134
1.16k
    FUNC_ENTER_NOAPI(FAIL)
4135
4136
    /* Check arguments. */
4137
1.16k
    if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
4138
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
4139
1.16k
    if (NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
4140
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
4141
4142
    /* Compare the property list's class against the other class */
4143
1.16k
    if ((ret_value = H5P_class_isa(plist->pclass, pclass)) < 0)
4144
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to compare property list classes");
4145
4146
1.16k
done:
4147
1.16k
    FUNC_LEAVE_NOAPI(ret_value)
4148
1.16k
} /* H5P_isa_class() */
4149
4150
/*-------------------------------------------------------------------------
4151
 * Function:    H5P_is_default_plist
4152
 *
4153
 * Purpose:     Determine if the provided ID refers to a default property list.
4154
 *
4155
 * Return:      True if the ID refers to a default property list, false otherwise.
4156
 *
4157
 *-------------------------------------------------------------------------
4158
 */
4159
bool
4160
H5P_is_default_plist(hid_t plist_id)
4161
0
{
4162
0
    hid_t H5I_def_plists[] = {
4163
0
        H5P_LST_FILE_CREATE_ID_g,      H5P_LST_FILE_ACCESS_ID_g,      H5P_LST_DATASET_CREATE_ID_g,
4164
0
        H5P_LST_DATASET_ACCESS_ID_g,   H5P_LST_DATASET_XFER_ID_g,     H5P_LST_FILE_MOUNT_ID_g,
4165
0
        H5P_LST_GROUP_CREATE_ID_g,     H5P_LST_GROUP_ACCESS_ID_g,     H5P_LST_DATATYPE_CREATE_ID_g,
4166
0
        H5P_LST_DATATYPE_ACCESS_ID_g,  H5P_LST_MAP_CREATE_ID_g,       H5P_LST_MAP_ACCESS_ID_g,
4167
0
        H5P_LST_ATTRIBUTE_CREATE_ID_g, H5P_LST_ATTRIBUTE_ACCESS_ID_g, H5P_LST_OBJECT_COPY_ID_g,
4168
0
        H5P_LST_LINK_CREATE_ID_g,      H5P_LST_LINK_ACCESS_ID_g,      H5P_LST_VOL_INITIALIZE_ID_g,
4169
0
        H5P_LST_REFERENCE_ACCESS_ID_g};
4170
4171
0
    size_t num_default_plists = (size_t)(sizeof(H5I_def_plists) / sizeof(H5I_def_plists[0]));
4172
4173
0
    if (plist_id == H5P_DEFAULT)
4174
0
        return true;
4175
4176
0
    for (size_t i = 0; i < num_default_plists; i++) {
4177
0
        if (plist_id == H5I_def_plists[i])
4178
0
            return true;
4179
0
    }
4180
4181
0
    return false;
4182
0
}
4183
4184
/*--------------------------------------------------------------------------
4185
 NAME
4186
    H5P_object_verify
4187
 PURPOSE
4188
    Internal routine to query whether a property list is a certain class and
4189
        retrieve the property list object associated with it.
4190
 USAGE
4191
    void *H5P_object_verify(plist_id, pclass_id, allow_default)
4192
        hid_t plist_id;         IN: Property list to query
4193
        hid_t pclass_id;        IN: Property class to query
4194
        bool  allow_default;    IN: Whether to consider the default property lists valid
4195
 RETURNS
4196
    Success: valid pointer to a property list object
4197
    Failure: NULL
4198
 DESCRIPTION
4199
    This routine queries whether a property list is member of a certain class
4200
    and retrieves the property list object associated with it.
4201
4202
 GLOBAL VARIABLES
4203
 COMMENTS, BUGS, ASSUMPTIONS
4204
    This function is special in that it is an internal library function, but
4205
    accepts hid_t's as parameters.  Since it is used in basically the same way
4206
    as the H5I functions, this should be OK.  Don't make more library functions
4207
    which accept hid_t's without thorough discussion. -QAK
4208
4209
    This function is similar (in spirit) to H5I_object_verify()
4210
 EXAMPLES
4211
 REVISION LOG
4212
--------------------------------------------------------------------------*/
4213
H5P_genplist_t *
4214
H5P_object_verify(hid_t plist_id, hid_t pclass_id, bool allow_default)
4215
40
{
4216
40
    H5P_genplist_t *ret_value = NULL; /* Return value */
4217
4218
40
    FUNC_ENTER_NOAPI(NULL)
4219
4220
    /* Compare the property list's class against the other class */
4221
40
    if (H5P_isa_class(plist_id, pclass_id) != true)
4222
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOMPARE, NULL, "property list is not a member of the class");
4223
4224
40
    if (!allow_default && H5P_is_default_plist(plist_id)) {
4225
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOMPARE, NULL, "property list is a default list");
4226
0
    }
4227
4228
    /* Get the plist structure */
4229
40
    if (NULL == (ret_value = (H5P_genplist_t *)H5I_object(plist_id)))
4230
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, NULL, "can't find object for ID");
4231
4232
40
done:
4233
40
    FUNC_LEAVE_NOAPI(ret_value)
4234
40
} /* H5P_object_verify() */
4235
4236
/*--------------------------------------------------------------------------
4237
 NAME
4238
    H5P__iterate_plist_cb
4239
 PURPOSE
4240
    Internal callback routine when iterating over properties in property list
4241
 USAGE
4242
    int H5P__iterate_plist_cb(item, key, udata)
4243
        void *item;                 IN: Pointer to the property
4244
        void *key;                  IN: Pointer to the property's name
4245
        void *udata;            IN/OUT: Pointer to iteration data from user
4246
 RETURNS
4247
    Success: Returns the return value of the last call to ITER_FUNC
4248
 DESCRIPTION
4249
    This routine calls the actual callback routine for the property in the
4250
property list.
4251
 GLOBAL VARIABLES
4252
 COMMENTS, BUGS, ASSUMPTIONS
4253
 EXAMPLES
4254
 REVISION LOG
4255
--------------------------------------------------------------------------*/
4256
static int
4257
H5P__iterate_plist_cb(void *_item, void *_key, void *_udata)
4258
0
{
4259
0
    H5P_genprop_t       *item      = (H5P_genprop_t *)_item;        /* Pointer to the property */
4260
0
    char                *key       = (char *)_key;                  /* Pointer to the property's name */
4261
0
    H5P_iter_plist_ud_t *udata     = (H5P_iter_plist_ud_t *)_udata; /* Pointer to user data */
4262
0
    int                  ret_value = H5_ITER_CONT;                  /* Return value */
4263
4264
0
    FUNC_ENTER_PACKAGE
4265
4266
    /* Sanity check */
4267
0
    assert(item);
4268
0
    assert(key);
4269
4270
    /* Check if we've found the correctly indexed property */
4271
0
    if (*udata->curr_idx_ptr >= udata->prev_idx) {
4272
        /* Prepare & restore library for user callback */
4273
0
        H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR)
4274
0
            {
4275
                /* Call the callback function */
4276
0
                ret_value = (*udata->cb_func)(item, udata->udata);
4277
0
            }
4278
0
        H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR)
4279
0
        if (ret_value != 0)
4280
0
            HGOTO_DONE(ret_value);
4281
0
    } /* end if */
4282
4283
    /* Increment the current index */
4284
0
    (*udata->curr_idx_ptr)++;
4285
4286
    /* Add property name to 'seen' list */
4287
0
    if (H5SL_insert(udata->seen, key, key) < 0)
4288
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert property into 'seen' skip list");
4289
4290
0
done:
4291
0
    FUNC_LEAVE_NOAPI(ret_value)
4292
0
} /* end H5P__iterate_plist_cb() */
4293
4294
/*--------------------------------------------------------------------------
4295
 NAME
4296
    H5P__iterate_plist_pclass_cb
4297
 PURPOSE
4298
    Internal callback routine when iterating over properties in property class
4299
 USAGE
4300
    int H5P__iterate_plist_pclass_cb(item, key, udata)
4301
        void *item;                 IN: Pointer to the property
4302
        void *key;                  IN: Pointer to the property's name
4303
        void *udata;            IN/OUT: Pointer to iteration data from user
4304
 RETURNS
4305
    Success: Returns the return value of the last call to ITER_FUNC
4306
 DESCRIPTION
4307
    This routine verifies that the property hasn't already been seen or was
4308
deleted, and then chains to the property list callback.
4309
 GLOBAL VARIABLES
4310
 COMMENTS, BUGS, ASSUMPTIONS
4311
 EXAMPLES
4312
 REVISION LOG
4313
--------------------------------------------------------------------------*/
4314
static int
4315
H5P__iterate_plist_pclass_cb(void *_item, void *_key, void *_udata)
4316
0
{
4317
0
    H5P_genprop_t       *item      = (H5P_genprop_t *)_item;        /* Pointer to the property */
4318
0
    char                *key       = (char *)_key;                  /* Pointer to the property's name */
4319
0
    H5P_iter_plist_ud_t *udata     = (H5P_iter_plist_ud_t *)_udata; /* Pointer to user data */
4320
0
    int                  ret_value = H5_ITER_CONT;                  /* Return value */
4321
4322
0
    FUNC_ENTER_PACKAGE_NOERR
4323
4324
    /* Sanity check */
4325
0
    assert(item);
4326
0
    assert(key);
4327
4328
    /* Only call iterator callback for properties we haven't seen
4329
     * before and that haven't been deleted.
4330
     */
4331
0
    if (NULL == H5SL_search(udata->seen, key) && NULL == H5SL_search(udata->plist->del, key))
4332
0
        ret_value = H5P__iterate_plist_cb(item, key, udata);
4333
4334
0
    FUNC_LEAVE_NOAPI(ret_value)
4335
0
} /* end H5P__iterate_plist_pclass_cb() */
4336
4337
/*--------------------------------------------------------------------------
4338
 NAME
4339
    H5P__iterate_plist
4340
 PURPOSE
4341
    Internal routine to iterate over the properties in a property list
4342
 USAGE
4343
    int H5P__iterate_plist(plist, iter_all_prop, idx, cb_func, iter_data)
4344
        const H5P_genplist_t *plist; IN: Property list to iterate over
4345
        bool iter_all_prop;      IN: Whether to iterate over all properties
4346
                                        (true), or just non-default (i.e. changed)
4347
                                        properties (false).
4348
        int *idx;                   IN/OUT: Index of the property to begin with
4349
        H5P_iterate_t cb_func;    IN: Function pointer to function to be
4350
                                        called with each property iterated over.
4351
        void *iter_data;            IN/OUT: Pointer to iteration data from user
4352
 RETURNS
4353
    Success: Returns the return value of the last call to ITER_FUNC if it was
4354
                non-zero, or zero if all properties have been processed.
4355
    Failure: negative value
4356
 DESCRIPTION
4357
    This routine iterates over the properties in the property object specified
4358
with PLIST_ID.  For each property in the object, the ITER_DATA and some
4359
additional information, specified below, are passed to the ITER_FUNC function.
4360
The iteration begins with the IDX property in the object and the next element
4361
to be processed by the operator is returned in IDX.  If IDX is NULL, then the
4362
iterator starts at the first property; since no stopping point is returned in
4363
this case, the iterator cannot be restarted if one of the calls to its operator
4364
returns non-zero.
4365
4366
The prototype for H5P_iterate_t is:
4367
    typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data);
4368
The operation receives the property list or class identifier for the object
4369
being iterated over, ID, the name of the current property within the object,
4370
NAME, and the pointer to the operator data passed in to H5Piterate, ITER_DATA.
4371
4372
The return values from an operator are:
4373
    Zero causes the iterator to continue, returning zero when all properties
4374
        have been processed.
4375
    Positive causes the iterator to immediately return that positive value,
4376
        indicating short-circuit success. The iterator can be restarted at the
4377
        index of the next property.
4378
    Negative causes the iterator to immediately return that value, indicating
4379
        failure. The iterator can be restarted at the index of the next
4380
        property.
4381
4382
H5Piterate assumes that the properties in the object identified by ID remains
4383
unchanged through the iteration.  If the membership changes during the
4384
iteration, the function's behavior is undefined.
4385
4386
 GLOBAL VARIABLES
4387
 COMMENTS, BUGS, ASSUMPTIONS
4388
 EXAMPLES
4389
 REVISION LOG
4390
--------------------------------------------------------------------------*/
4391
int
4392
H5P__iterate_plist(const H5P_genplist_t *plist, bool iter_all_prop, int *idx, H5P_iterate_int_t cb_func,
4393
                   void *udata)
4394
0
{
4395
0
    H5P_genclass_t     *tclass;           /* Temporary class pointer */
4396
0
    H5P_iter_plist_ud_t udata_int;        /* User data for skip list iterator */
4397
0
    H5SL_t             *seen      = NULL; /* Skip list to hold names of properties already seen */
4398
0
    int                 curr_idx  = 0;    /* Current iteration index */
4399
0
    int                 ret_value = 0;    /* Return value */
4400
4401
0
    FUNC_ENTER_PACKAGE
4402
4403
    /* Sanity check */
4404
0
    assert(plist);
4405
0
    assert(idx);
4406
0
    assert(cb_func);
4407
4408
    /* Create the skip list to hold names of properties already seen */
4409
0
    if (NULL == (seen = H5SL_create(H5SL_TYPE_STR, NULL)))
4410
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "can't create skip list for seen properties");
4411
4412
    /* Set up iterator callback info */
4413
0
    udata_int.plist        = plist;
4414
0
    udata_int.cb_func      = cb_func;
4415
0
    udata_int.udata        = udata;
4416
0
    udata_int.seen         = seen;
4417
0
    udata_int.curr_idx_ptr = &curr_idx;
4418
0
    udata_int.prev_idx     = *idx;
4419
4420
    /* Iterate over properties in property list proper */
4421
    /* (Will be only the non-default (i.e. changed) properties) */
4422
0
    ret_value = H5SL_iterate(plist->props, H5P__iterate_plist_cb, &udata_int);
4423
0
    if (ret_value != 0)
4424
0
        HGOTO_DONE(ret_value);
4425
4426
    /* Check for iterating over all properties, or just non-default ones */
4427
0
    if (iter_all_prop) {
4428
        /* Walk up the class hierarchy */
4429
0
        tclass = plist->pclass;
4430
0
        while (tclass != NULL) {
4431
            /* Iterate over properties in property list class */
4432
0
            ret_value = H5SL_iterate(tclass->props, H5P__iterate_plist_pclass_cb, &udata_int);
4433
0
            if (ret_value != 0)
4434
0
                HGOTO_DONE(ret_value);
4435
4436
            /* Go up to parent class */
4437
0
            tclass = tclass->parent;
4438
0
        } /* end while */
4439
0
    }     /* end if */
4440
4441
0
done:
4442
    /* Set the index we stopped at */
4443
0
    *idx = curr_idx;
4444
4445
    /* Release the skip list of 'seen' properties */
4446
0
    if (seen != NULL)
4447
0
        H5SL_close(seen);
4448
4449
0
    FUNC_LEAVE_NOAPI(ret_value)
4450
0
} /* H5P__iterate_plist() */
4451
4452
/*--------------------------------------------------------------------------
4453
 NAME
4454
    H5P__iterate_pclass_cb
4455
 PURPOSE
4456
    Internal callback routine when iterating over properties in property list
4457
    class
4458
 USAGE
4459
    int H5P__iterate_pclass_cb(item, key, udata)
4460
        void *item;                 IN: Pointer to the property
4461
        void *key;                  IN: Pointer to the property's name
4462
        void *udata;            IN/OUT: Pointer to iteration data from user
4463
 RETURNS
4464
    Success: Returns the return value of the last call to ITER_FUNC
4465
 DESCRIPTION
4466
    This routine calls the actual callback routine for the property in the
4467
property list class.
4468
 GLOBAL VARIABLES
4469
 COMMENTS, BUGS, ASSUMPTIONS
4470
 EXAMPLES
4471
 REVISION LOG
4472
--------------------------------------------------------------------------*/
4473
static int
4474
H5P__iterate_pclass_cb(void *_item, void H5_ATTR_NDEBUG_UNUSED *_key, void *_udata)
4475
0
{
4476
0
    H5P_genprop_t        *item      = (H5P_genprop_t *)_item;         /* Pointer to the property */
4477
0
    H5P_iter_pclass_ud_t *udata     = (H5P_iter_pclass_ud_t *)_udata; /* Pointer to user data */
4478
0
    int                   ret_value = 0;                              /* Return value */
4479
4480
0
    FUNC_ENTER_PACKAGE_NOERR
4481
4482
    /* Sanity check */
4483
0
    assert(item);
4484
0
    assert((char *)_key);
4485
4486
    /* Check if we've found the correctly indexed property */
4487
0
    if (*udata->curr_idx_ptr >= udata->prev_idx) {
4488
        /* Prepare & restore library for user callback */
4489
0
        H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR)
4490
0
            {
4491
                /* Call the callback function */
4492
0
                ret_value = (*udata->cb_func)(item, udata->udata);
4493
0
            }
4494
0
        H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR)
4495
0
        if (ret_value != 0)
4496
0
            HGOTO_DONE(ret_value);
4497
0
    } /* end if */
4498
4499
    /* Increment the current index */
4500
0
    (*udata->curr_idx_ptr)++;
4501
4502
0
done:
4503
0
    FUNC_LEAVE_NOAPI(ret_value)
4504
0
} /* end H5P__iterate_pclass_cb() */
4505
4506
/*--------------------------------------------------------------------------
4507
 NAME
4508
    H5P__iterate_pclass
4509
 PURPOSE
4510
    Internal routine to iterate over the properties in a property class
4511
 USAGE
4512
    herr_t H5P__iterate_pclass(pclass, idx, cb_func, iter_data)
4513
        const H5P_genpclass_t *pclass; IN: Property list class to iterate over
4514
        int *idx;                   IN/OUT: Index of the property to begin with
4515
        H5P_iterate_t cb_func;    IN: Function pointer to function to be
4516
                                        called with each property iterated over.
4517
        void *iter_data;            IN/OUT: Pointer to iteration data from user
4518
 RETURNS
4519
    Success: Returns the return value of the last call to ITER_FUNC if it was
4520
                non-zero, or zero if all properties have been processed.
4521
    Failure: negative value
4522
 DESCRIPTION
4523
    This routine iterates over the properties in the property object specified
4524
with PCLASS_ID.  For each property in the object, the ITER_DATA and some
4525
additional information, specified below, are passed to the ITER_FUNC function.
4526
The iteration begins with the IDX property in the object and the next element
4527
to be processed by the operator is returned in IDX.  If IDX is NULL, then the
4528
iterator starts at the first property; since no stopping point is returned in
4529
this case, the iterator cannot be restarted if one of the calls to its operator
4530
returns non-zero.
4531
4532
The prototype for H5P_iterate_t is:
4533
    typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data);
4534
The operation receives the property list or class identifier for the object
4535
being iterated over, ID, the name of the current property within the object,
4536
NAME, and the pointer to the operator data passed in to H5Piterate, ITER_DATA.
4537
4538
The return values from an operator are:
4539
    Zero causes the iterator to continue, returning zero when all properties
4540
        have been processed.
4541
    Positive causes the iterator to immediately return that positive value,
4542
        indicating short-circuit success. The iterator can be restarted at the
4543
        index of the next property.
4544
    Negative causes the iterator to immediately return that value, indicating
4545
        failure. The iterator can be restarted at the index of the next
4546
        property.
4547
4548
H5Piterate assumes that the properties in the object identified by ID remains
4549
unchanged through the iteration.  If the membership changes during the
4550
iteration, the function's behavior is undefined.
4551
4552
 GLOBAL VARIABLES
4553
 COMMENTS, BUGS, ASSUMPTIONS
4554
 EXAMPLES
4555
 REVISION LOG
4556
--------------------------------------------------------------------------*/
4557
int
4558
H5P__iterate_pclass(const H5P_genclass_t *pclass, int *idx, H5P_iterate_int_t cb_func, void *udata)
4559
0
{
4560
0
    H5P_iter_pclass_ud_t udata_int;     /* User data for skip list iterator */
4561
0
    int                  curr_idx  = 0; /* Current iteration index */
4562
0
    int                  ret_value = 0; /* Return value */
4563
4564
0
    FUNC_ENTER_PACKAGE_NOERR
4565
4566
    /* Sanity check */
4567
0
    assert(pclass);
4568
0
    assert(idx);
4569
0
    assert(cb_func);
4570
4571
    /* Set up iterator callback info */
4572
0
    udata_int.cb_func      = cb_func;
4573
0
    udata_int.udata        = udata;
4574
0
    udata_int.curr_idx_ptr = &curr_idx;
4575
0
    udata_int.prev_idx     = *idx;
4576
4577
    /* Iterate over properties in property list class proper */
4578
0
    ret_value = H5SL_iterate(pclass->props, H5P__iterate_pclass_cb, &udata_int);
4579
0
    if (ret_value != 0)
4580
0
        HGOTO_DONE(ret_value);
4581
4582
0
done:
4583
    /* Set the index we stopped at */
4584
0
    *idx = curr_idx;
4585
4586
0
    FUNC_LEAVE_NOAPI(ret_value)
4587
0
} /* H5P__iterate_pclass() */
4588
4589
/*--------------------------------------------------------------------------
4590
 NAME
4591
    H5P__peek_cb
4592
 PURPOSE
4593
    Internal callback for H5P__do_prop, to peek at a property's value in a property list.
4594
 USAGE
4595
    herr_t H5P__peek_plist_cb(plist, name, value)
4596
        H5P_genplist_t *plist;  IN: Property list to peek property in
4597
        const char *name;       IN: Name of property to peek
4598
        H5P_genprop_t *prop;    IN: Property to peek
4599
        void *udata;            IN: User data for operation
4600
 RETURNS
4601
    Returns non-negative on success, negative on failure.
4602
 DESCRIPTION
4603
        Peeks at a new value for a property in a property list.
4604
 GLOBAL VARIABLES
4605
 COMMENTS, BUGS, ASSUMPTIONS
4606
    Called when the property is found in the property list and when it's found
4607
        for the property class.
4608
 EXAMPLES
4609
 REVISION LOG
4610
--------------------------------------------------------------------------*/
4611
static herr_t
4612
H5P__peek_cb(H5P_genplist_t H5_ATTR_NDEBUG_UNUSED *plist, const char H5_ATTR_NDEBUG_UNUSED *name,
4613
             H5P_genprop_t *prop, void *_udata)
4614
4.47k
{
4615
4.47k
    H5P_prop_get_ud_t *udata     = (H5P_prop_get_ud_t *)_udata; /* User data for callback */
4616
4.47k
    herr_t             ret_value = SUCCEED;                     /* Return value */
4617
4618
4.47k
    FUNC_ENTER_PACKAGE
4619
4620
    /* Sanity check */
4621
4.47k
    assert(plist);
4622
4.47k
    assert(name);
4623
4.47k
    assert(prop);
4624
4625
    /* Check for property size >0 */
4626
4.47k
    if (0 == prop->size)
4627
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
4628
4629
    /* Make a (shallow) copy of the value */
4630
4.47k
    H5MM_memcpy(udata->value, prop->value, prop->size);
4631
4632
4.47k
done:
4633
4.47k
    FUNC_LEAVE_NOAPI(ret_value)
4634
4.47k
} /* H5P__peek_cb() */
4635
4636
/*--------------------------------------------------------------------------
4637
 NAME
4638
    H5P_peek
4639
 PURPOSE
4640
    Internal routine to look at the value of a property in a property list.
4641
 USAGE
4642
    herr_t H5P_peek(plist, name, value)
4643
        H5P_genplist_t *plist;  IN: Property list to check
4644
        const char *name;       IN: Name of property to query
4645
        void *value;            OUT: Pointer to the buffer for the property value
4646
 RETURNS
4647
    Returns non-negative on success, negative on failure.
4648
 DESCRIPTION
4649
        Retrieves a "shallow" copy of the value for a property in a property
4650
    list.  The property name must exist or this routine will fail.  If there
4651
    is a 'get' callback routine registered for this property, it is _NOT_
4652
    called.
4653
 GLOBAL VARIABLES
4654
 COMMENTS, BUGS, ASSUMPTIONS
4655
        This routine may not be called for zero-sized properties and will
4656
    return an error in that case.
4657
 EXAMPLES
4658
 REVISION LOG
4659
--------------------------------------------------------------------------*/
4660
herr_t
4661
H5P_peek(H5P_genplist_t *plist, const char *name, void *value)
4662
4.47k
{
4663
4.47k
    H5P_prop_get_ud_t udata;               /* User data for callback */
4664
4.47k
    herr_t            ret_value = SUCCEED; /* Return value */
4665
4666
4.47k
    FUNC_ENTER_NOAPI(FAIL)
4667
4668
    /* Sanity check */
4669
4.47k
    assert(plist);
4670
4.47k
    assert(name);
4671
4.47k
    assert(value);
4672
4673
    /* Find the property and peek at the value */
4674
4.47k
    udata.value = value;
4675
4.47k
    if (H5P__do_prop(plist, name, H5P__peek_cb, H5P__peek_cb, &udata) < 0)
4676
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on plist to peek at value");
4677
4678
4.47k
done:
4679
4.47k
    FUNC_LEAVE_NOAPI(ret_value)
4680
4.47k
} /* H5P_peek() */
4681
4682
/*--------------------------------------------------------------------------
4683
 NAME
4684
    H5P__get_cb
4685
 PURPOSE
4686
    Internal callback for H5P__do_prop, to get a property's value in a property list.
4687
 USAGE
4688
    herr_t H5P__get_plist_cb(plist, name, value)
4689
        H5P_genplist_t *plist;  IN: Property list to get property in
4690
        const char *name;       IN: Name of property to get
4691
        H5P_genprop_t *prop;    IN: Property to get
4692
        void *udata;            IN: User data for operation
4693
 RETURNS
4694
    Returns non-negative on success, negative on failure.
4695
 DESCRIPTION
4696
        Gets a new value for a property in a property list.
4697
 GLOBAL VARIABLES
4698
 COMMENTS, BUGS, ASSUMPTIONS
4699
    Called when the property is found in the property list and when it's found
4700
        for the property class.
4701
 EXAMPLES
4702
 REVISION LOG
4703
--------------------------------------------------------------------------*/
4704
static herr_t
4705
H5P__get_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop, void *_udata)
4706
43.0k
{
4707
43.0k
    H5P_prop_get_ud_t *udata     = (H5P_prop_get_ud_t *)_udata; /* User data for callback */
4708
43.0k
    void              *tmp_value = NULL;                        /* Temporary value for property */
4709
43.0k
    herr_t             ret_value = SUCCEED;                     /* Return value */
4710
4711
43.0k
    FUNC_ENTER_PACKAGE
4712
4713
    /* Sanity check */
4714
43.0k
    assert(plist);
4715
43.0k
    assert(name);
4716
43.0k
    assert(prop);
4717
4718
    /* Check for property size >0 */
4719
43.0k
    if (0 == prop->size)
4720
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
4721
4722
    /* Call the 'get' callback, if there is one */
4723
43.0k
    if (NULL != prop->get) {
4724
        /* Make a copy of the current value, in case the callback fails */
4725
4
        if (NULL == (tmp_value = H5MM_malloc(prop->size)))
4726
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed temporary property value");
4727
4
        H5MM_memcpy(tmp_value, prop->value, prop->size);
4728
4729
        /* Prepare & restore library for user callback */
4730
4
        H5_BEFORE_USER_CB(FAIL)
4731
4
            {
4732
                /* Call user's callback */
4733
4
                ret_value = (*(prop->get))(plist->plist_id, name, prop->size, tmp_value);
4734
4
            }
4735
4
        H5_AFTER_USER_CB(FAIL)
4736
4
        if (ret_value < 0)
4737
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value");
4738
4739
        /* Copy new [possibly unchanged] value into return value */
4740
4
        H5MM_memcpy(udata->value, tmp_value, prop->size);
4741
4
    } /* end if */
4742
    /* No 'get' callback, just copy value */
4743
43.0k
    else
4744
43.0k
        H5MM_memcpy(udata->value, prop->value, prop->size);
4745
4746
43.0k
done:
4747
    /* Free the temporary value buffer */
4748
43.0k
    if (tmp_value)
4749
4
        H5MM_xfree(tmp_value);
4750
4751
43.0k
    FUNC_LEAVE_NOAPI(ret_value)
4752
43.0k
} /* H5P__get_cb() */
4753
4754
/*--------------------------------------------------------------------------
4755
 NAME
4756
    H5P_get
4757
 PURPOSE
4758
    Internal routine to query the value of a property in a property list.
4759
 USAGE
4760
    herr_t H5P_get(plist, name, value)
4761
        H5P_genplist_t *plist;  IN: Property list to check
4762
        const char *name;       IN: Name of property to query
4763
        void *value;            OUT: Pointer to the buffer for the property value
4764
 RETURNS
4765
    Returns non-negative on success, negative on failure.
4766
 DESCRIPTION
4767
        Retrieves a copy of the value for a property in a property list.  The
4768
    property name must exist or this routine will fail.  If there is a
4769
    'get' callback routine registered for this property, the copy of the
4770
    value of the property will first be passed to that routine and any changes
4771
    to the copy of the value will be used when returning the property value
4772
    from this routine.
4773
        If the 'get' callback routine returns an error, 'value' will not be
4774
    modified and this routine will return an error.  This routine may not be
4775
    called for zero-sized properties.
4776
4777
 GLOBAL VARIABLES
4778
 COMMENTS, BUGS, ASSUMPTIONS
4779
 EXAMPLES
4780
 REVISION LOG
4781
--------------------------------------------------------------------------*/
4782
herr_t
4783
H5P_get(H5P_genplist_t *plist, const char *name, void *value)
4784
43.0k
{
4785
43.0k
    H5P_prop_get_ud_t udata;               /* User data for callback */
4786
43.0k
    herr_t            ret_value = SUCCEED; /* Return value */
4787
4788
43.0k
    FUNC_ENTER_NOAPI(FAIL)
4789
4790
    /* Sanity check */
4791
43.0k
    assert(plist);
4792
43.0k
    assert(name);
4793
43.0k
    assert(value);
4794
4795
    /* Find the property and get the value */
4796
43.0k
    udata.value = value;
4797
43.0k
    if (H5P__do_prop(plist, name, H5P__get_cb, H5P__get_cb, &udata) < 0)
4798
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on plist to get value");
4799
4800
43.0k
done:
4801
43.0k
    FUNC_LEAVE_NOAPI(ret_value)
4802
43.0k
} /* H5P_get() */
4803
4804
/*--------------------------------------------------------------------------
4805
 NAME
4806
    H5P__del_plist_cb
4807
 PURPOSE
4808
    Internal callback for H5P__do_prop, to remove a property's value in a property list.
4809
 USAGE
4810
    herr_t H5P__del_plist_cb(plist, name, value)
4811
        H5P_genplist_t *plist;  IN: Property list to remove property from
4812
        const char *name;       IN: Name of property to remove
4813
        H5P_genprop_t *prop;    IN: Property to remove
4814
        void *udata;            IN: User data for operation
4815
 RETURNS
4816
    Returns non-negative on success, negative on failure.
4817
 DESCRIPTION
4818
        Remove a property in a property list.  Called when the
4819
    property is found in the property list.
4820
 GLOBAL VARIABLES
4821
 COMMENTS, BUGS, ASSUMPTIONS
4822
 EXAMPLES
4823
 REVISION LOG
4824
--------------------------------------------------------------------------*/
4825
static herr_t
4826
H5P__del_plist_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop, void H5_ATTR_UNUSED *_udata)
4827
0
{
4828
0
    char  *del_name  = NULL;    /* Pointer to deleted name */
4829
0
    herr_t ret_value = SUCCEED; /* Return value */
4830
4831
0
    FUNC_ENTER_PACKAGE
4832
4833
    /* Sanity check */
4834
0
    assert(plist);
4835
0
    assert(name);
4836
0
    assert(prop);
4837
4838
    /* Pass value to 'close' callback, if it exists */
4839
0
    if (NULL != prop->del) {
4840
        /* Prepare & restore library for user callback */
4841
0
        H5_BEFORE_USER_CB(FAIL)
4842
0
            {
4843
                /* Call user's callback */
4844
0
                ret_value = (*(prop->del))(plist->plist_id, name, prop->size, prop->value);
4845
0
            }
4846
0
        H5_AFTER_USER_CB(FAIL)
4847
0
        if (ret_value < 0)
4848
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't release property value");
4849
0
    } /* end if */
4850
4851
    /* Duplicate string for insertion into new deleted property skip list */
4852
0
    if (NULL == (del_name = H5MM_xstrdup(name)))
4853
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed");
4854
4855
    /* Insert property name into deleted list */
4856
0
    if (H5SL_insert(plist->del, del_name, del_name) < 0)
4857
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into deleted skip list");
4858
4859
    /* Remove the property from the skip list */
4860
0
    if (NULL == H5SL_remove(plist->props, prop->name))
4861
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't remove property from skip list");
4862
4863
    /* Free the property, ignoring return value, nothing we can do */
4864
0
    H5P__free_prop(prop);
4865
4866
    /* Decrement the number of properties in list */
4867
0
    plist->nprops--;
4868
4869
0
done:
4870
    /* Error cleanup */
4871
0
    if (ret_value < 0)
4872
0
        if (del_name)
4873
0
            H5MM_xfree(del_name);
4874
4875
0
    FUNC_LEAVE_NOAPI(ret_value)
4876
0
} /* H5P__del_plist_cb() */
4877
4878
/*--------------------------------------------------------------------------
4879
 NAME
4880
    H5P__del_pclass_cb
4881
 PURPOSE
4882
    Internal callback for H5P__do_prop, to remove a property's value in a property list.
4883
 USAGE
4884
    herr_t H5P__del_pclass_cb(plist, name, value)
4885
        H5P_genplist_t *plist;  IN: Property list to remove property from
4886
        const char *name;       IN: Name of property to remove
4887
        H5P_genprop_t *prop;    IN: Property to remove
4888
        void *udata;            IN: User data for operation
4889
 RETURNS
4890
    Returns non-negative on success, negative on failure.
4891
 DESCRIPTION
4892
        Remove a property in a property list.  Called when the
4893
    property is found in the property class.
4894
 GLOBAL VARIABLES
4895
 COMMENTS, BUGS, ASSUMPTIONS
4896
 EXAMPLES
4897
 REVISION LOG
4898
--------------------------------------------------------------------------*/
4899
static herr_t
4900
H5P__del_pclass_cb(H5P_genplist_t *plist, const char *name, H5P_genprop_t *prop, void H5_ATTR_UNUSED *_udata)
4901
0
{
4902
0
    char  *del_name  = NULL;    /* Pointer to deleted name */
4903
0
    void  *tmp_value = NULL;    /* Temporary value for property */
4904
0
    herr_t ret_value = SUCCEED; /* Return value */
4905
4906
0
    FUNC_ENTER_PACKAGE
4907
4908
    /* Sanity check */
4909
0
    assert(plist);
4910
0
    assert(name);
4911
0
    assert(prop);
4912
4913
    /* Pass value to 'del' callback, if it exists */
4914
0
    if (NULL != prop->del) {
4915
        /* Allocate space for a temporary copy of the property value */
4916
0
        if (NULL == (tmp_value = H5MM_malloc(prop->size)))
4917
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL,
4918
0
                        "memory allocation failed for temporary property value");
4919
0
        H5MM_memcpy(tmp_value, prop->value, prop->size);
4920
4921
        /* Prepare & restore library for user callback */
4922
0
        H5_BEFORE_USER_CB(FAIL)
4923
0
            {
4924
                /* Call user's callback */
4925
0
                ret_value = (*(prop->del))(plist->plist_id, name, prop->size, tmp_value);
4926
0
            }
4927
0
        H5_AFTER_USER_CB(FAIL)
4928
0
        if (ret_value < 0)
4929
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value");
4930
0
    } /* end if */
4931
4932
    /* Duplicate string for insertion into new deleted property skip list */
4933
0
    if (NULL == (del_name = H5MM_xstrdup(name)))
4934
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed");
4935
4936
    /* Insert property name into deleted list */
4937
0
    if (H5SL_insert(plist->del, del_name, del_name) < 0)
4938
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into deleted skip list");
4939
4940
    /* Decrement the number of properties in list */
4941
0
    plist->nprops--;
4942
4943
0
done:
4944
    /* Free the temporary value buffer */
4945
0
    if (tmp_value)
4946
0
        H5MM_xfree(tmp_value);
4947
4948
    /* Error cleanup */
4949
0
    if (ret_value < 0)
4950
0
        if (del_name)
4951
0
            H5MM_xfree(del_name);
4952
4953
0
    FUNC_LEAVE_NOAPI(ret_value)
4954
0
} /* H5P__del_pclass_cb() */
4955
4956
/*--------------------------------------------------------------------------
4957
 NAME
4958
    H5P_remove
4959
 PURPOSE
4960
    Internal routine to remove a property from a property list.
4961
 USAGE
4962
    herr_t H5P_remove(plist, name)
4963
        H5P_genplist_t *plist;  IN: Property list to modify
4964
        const char *name;       IN: Name of property to remove
4965
 RETURNS
4966
    Returns non-negative on success, negative on failure.
4967
 DESCRIPTION
4968
        Removes a property from a property list.  Both properties which were
4969
    in existence when the property list was created (i.e. properties registered
4970
    with H5Pregister2) and properties added to the list after it was created
4971
    (i.e. added with H5Pinsert2) may be removed from a property list.
4972
    Properties do not need to be removed a property list before the list itself
4973
    is closed, they will be released automatically when H5Pclose is called.
4974
    The 'close' callback for this property is called before the property is
4975
    release, if the callback exists.
4976
4977
 GLOBAL VARIABLES
4978
 COMMENTS, BUGS, ASSUMPTIONS
4979
 EXAMPLES
4980
 REVISION LOG
4981
--------------------------------------------------------------------------*/
4982
herr_t
4983
H5P_remove(H5P_genplist_t *plist, const char *name)
4984
0
{
4985
0
    herr_t ret_value = SUCCEED; /* Return value */
4986
4987
0
    FUNC_ENTER_NOAPI(FAIL)
4988
4989
    /* Sanity check */
4990
0
    assert(plist);
4991
0
    assert(name);
4992
4993
    /* Find the property and get the value */
4994
0
    if (H5P__do_prop(plist, name, H5P__del_plist_cb, H5P__del_pclass_cb, NULL) < 0)
4995
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTOPERATE, FAIL, "can't operate on plist to remove value");
4996
4997
0
done:
4998
0
    FUNC_LEAVE_NOAPI(ret_value)
4999
0
} /* H5P_remove() */
5000
5001
/*--------------------------------------------------------------------------
5002
 NAME
5003
    H5P__copy_prop_plist
5004
 PURPOSE
5005
    Internal routine to copy a property from one list to another
5006
 USAGE
5007
    herr_t H5P__copy_prop_plist(dst_plist, src_plist, name)
5008
        hid_t dst_id;               IN: ID of destination property list or class
5009
        hid_t src_id;               IN: ID of source property list or class
5010
        const char *name;           IN: Name of property to copy
5011
 RETURNS
5012
    Success: non-negative value.
5013
    Failure: negative value.
5014
 DESCRIPTION
5015
    Copies a property from one property list to another.
5016
5017
    If the property exists in the destination list, the property will be
5018
    first deleted from the destination list (generating a call to the 'del'
5019
    callback for the property, if one exists) and then the property is copied
5020
    from the source list to the destination list (generating a call to the
5021
    'copy' callback for the property, if one exists).
5022
5023
    If the property does not exist in the destination list, a new instance
5024
    of the property is created, the 'create' callback is called
5025
    (if such a callback exists for the property), and the new property is
5026
    inserted into the destination list.
5027
5028
 GLOBAL VARIABLES
5029
 COMMENTS, BUGS, ASSUMPTIONS
5030
 EXAMPLES
5031
 REVISION LOG
5032
--------------------------------------------------------------------------*/
5033
herr_t
5034
H5P__copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
5035
0
{
5036
0
    H5P_genplist_t *dst_plist;           /* Pointer to destination property list */
5037
0
    H5P_genplist_t *src_plist;           /* Pointer to source property list */
5038
0
    H5P_genprop_t  *prop;                /* Temporary property pointer */
5039
0
    H5P_genprop_t  *new_prop  = NULL;    /* Pointer to new property */
5040
0
    herr_t          ret_value = SUCCEED; /* return value */
5041
5042
0
    FUNC_ENTER_PACKAGE
5043
5044
0
    assert(name);
5045
5046
    /* Get the objects to operate on */
5047
0
    if (NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_id)) ||
5048
0
        NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_id)))
5049
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property object doesn't exist");
5050
5051
    /* Get the pointer to the source property */
5052
0
    if (NULL == (prop = H5P__find_prop_plist(src_plist, name)))
5053
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
5054
5055
    /* If the property exists in the destination already */
5056
0
    if (NULL != H5P__find_prop_plist(dst_plist, name)) {
5057
        /* Delete the property from the destination list, calling the 'del' callback if necessary */
5058
0
        if (H5P_remove(dst_plist, name) < 0)
5059
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
5060
5061
        /* Make a copy of the source property */
5062
0
        if ((new_prop = H5P__dup_prop(prop, H5P_PROP_WITHIN_LIST)) == NULL)
5063
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
5064
5065
        /* Call property copy callback, if it exists */
5066
0
        if (new_prop->copy) {
5067
            /* Prepare & restore library for user callback */
5068
0
            H5_BEFORE_USER_CB(FAIL)
5069
0
                {
5070
                    /* Call user's callback */
5071
0
                    ret_value = (new_prop->copy)(new_prop->name, new_prop->size, new_prop->value);
5072
0
                }
5073
0
            H5_AFTER_USER_CB(FAIL)
5074
0
            if (ret_value < 0)
5075
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property");
5076
0
        } /* end if */
5077
0
    }     /* end if */
5078
    /* If property doesn't exist in destination */
5079
0
    else {
5080
        /* Create property object from parameters. This is very similar to the property
5081
         * duplication call above, but the property's name is treated differently depending on
5082
         * whether the source property is defined on a plist or a plist class */
5083
0
        if (NULL ==
5084
0
            (new_prop = H5P__create_prop(prop->name, prop->size, H5P_PROP_WITHIN_LIST, prop->value,
5085
0
                                         prop->create, prop->set, prop->get, prop->encode, prop->decode,
5086
0
                                         prop->del, prop->copy, prop->cmp, prop->close)))
5087
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "Can't create property");
5088
5089
        /* Call property creation callback, if it exists */
5090
0
        if (new_prop->create) {
5091
            /* Prepare & restore library for user callback */
5092
0
            H5_BEFORE_USER_CB(FAIL)
5093
0
                {
5094
0
                    ret_value = (new_prop->create)(new_prop->name, new_prop->size, new_prop->value);
5095
0
                }
5096
0
            H5_AFTER_USER_CB(FAIL)
5097
0
            if (ret_value < 0)
5098
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "Can't initialize property");
5099
0
        } /* end if */
5100
0
    }     /* end else */
5101
5102
    /* Insert the initialized property into the property list */
5103
0
    if (H5P__add_prop(dst_plist->props, new_prop) < 0)
5104
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "Can't insert property into list");
5105
5106
    /* Increment the number of properties in list */
5107
0
    dst_plist->nprops++;
5108
5109
0
done:
5110
    /* Cleanup, if necessary */
5111
0
    if (ret_value < 0) {
5112
0
        if (new_prop != NULL)
5113
0
            H5P__free_prop(new_prop);
5114
0
    } /* end if */
5115
5116
0
    FUNC_LEAVE_NOAPI(ret_value)
5117
0
} /* H5P__copy_prop_plist() */
5118
5119
/*--------------------------------------------------------------------------
5120
 NAME
5121
    H5P__copy_prop_pclass
5122
 PURPOSE
5123
    Internal routine to copy a property from one class to another
5124
 USAGE
5125
    herr_t H5P__copy_prop_pclass(dst_pclass, src_pclass, name)
5126
        H5P_genclass_t  *dst_pclass;    IN: Pointer to destination class
5127
        H5P_genclass_t  *src_pclass;    IN: Pointer to source class
5128
        const char *name;               IN: Name of property to copy
5129
 RETURNS
5130
    Success: non-negative value.
5131
    Failure: negative value.
5132
 DESCRIPTION
5133
    Copies a property from one property class to another.
5134
5135
    If a property is copied from one class to another, all the property
5136
    information will be first deleted from the destination class and then the
5137
    property information will be copied from the source class into the
5138
    destination class.
5139
5140
    If the property does not exist in the destination class or list, this call
5141
    is equivalent to calling H5Pregister2.
5142
5143
 GLOBAL VARIABLES
5144
 COMMENTS, BUGS, ASSUMPTIONS
5145
 EXAMPLES
5146
 REVISION LOG
5147
--------------------------------------------------------------------------*/
5148
herr_t
5149
H5P__copy_prop_pclass(hid_t dst_id, hid_t src_id, const char *name)
5150
0
{
5151
0
    H5P_genclass_t *src_pclass;          /* Source property class, containing property to copy */
5152
0
    H5P_genclass_t *dst_pclass;          /* Destination property class */
5153
0
    H5P_genclass_t *orig_dst_pclass;     /* Original destination property class */
5154
0
    H5P_genprop_t  *prop;                /* Temporary property pointer */
5155
0
    herr_t          ret_value = SUCCEED; /* return value */
5156
5157
0
    FUNC_ENTER_PACKAGE
5158
5159
    /* Sanity check */
5160
0
    assert(name);
5161
5162
    /* Get property list classes */
5163
0
    if (NULL == (src_pclass = (H5P_genclass_t *)H5I_object(src_id)))
5164
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "source property class object doesn't exist");
5165
0
    if (NULL == (dst_pclass = (H5P_genclass_t *)H5I_object(dst_id)))
5166
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "destination property class object doesn't exist");
5167
5168
    /* Get the property from the source */
5169
0
    if (NULL == (prop = H5P__find_prop_pclass(src_pclass, name)))
5170
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to locate property");
5171
5172
    /* If the property exists in the destination already */
5173
0
    if (H5P__exist_pclass(dst_pclass, name)) {
5174
        /* Delete the old property from the destination class */
5175
0
        if (H5P__unregister(dst_pclass, name) < 0)
5176
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
5177
0
    } /* end if */
5178
5179
    /* Register the property into the destination */
5180
0
    orig_dst_pclass = dst_pclass;
5181
0
    if (H5P__register(&dst_pclass, name, prop->size, prop->value, prop->create, prop->set, prop->get,
5182
0
                      prop->encode, prop->decode, prop->del, prop->copy, prop->cmp, prop->close) < 0)
5183
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property");
5184
5185
    /* Check if the property class changed and needs to be substituted in the ID */
5186
0
    if (dst_pclass != orig_dst_pclass) {
5187
0
        H5P_genclass_t *old_dst_pclass; /* Old destination property class */
5188
5189
        /* Substitute the new destination property class in the ID */
5190
0
        if (NULL == (old_dst_pclass = (H5P_genclass_t *)H5I_subst(dst_id, dst_pclass)))
5191
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to substitute property class in ID");
5192
0
        assert(old_dst_pclass == orig_dst_pclass);
5193
5194
        /* Close the previous class */
5195
0
        if (H5P__close_class(old_dst_pclass) < 0)
5196
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTCLOSEOBJ, FAIL,
5197
0
                        "unable to close original property class after substitution");
5198
0
    } /* end if */
5199
5200
0
done:
5201
    /* Cleanup, if necessary */
5202
5203
0
    FUNC_LEAVE_NOAPI(ret_value)
5204
0
} /* H5P__copy_prop_pclass() */
5205
5206
/*--------------------------------------------------------------------------
5207
 NAME
5208
    H5P__unregister
5209
 PURPOSE
5210
    Internal routine to remove a property from a property list class.
5211
 USAGE
5212
    herr_t H5P__unregister(pclass, name)
5213
        H5P_genclass_t *pclass; IN: Property list class to modify
5214
        const char *name;       IN: Name of property to remove
5215
 RETURNS
5216
    Returns non-negative on success, negative on failure.
5217
 DESCRIPTION
5218
        Removes a property from a property list class.  Future property lists
5219
    created of that class will not contain this property.  Existing property
5220
    lists containing this property are not affected.
5221
5222
 GLOBAL VARIABLES
5223
 COMMENTS, BUGS, ASSUMPTIONS
5224
 EXAMPLES
5225
 REVISION LOG
5226
--------------------------------------------------------------------------*/
5227
herr_t
5228
H5P__unregister(H5P_genclass_t *pclass, const char *name)
5229
0
{
5230
0
    H5P_genprop_t *prop;                /* Temporary property pointer */
5231
0
    herr_t         ret_value = SUCCEED; /* Return value */
5232
5233
0
    FUNC_ENTER_PACKAGE
5234
5235
0
    assert(pclass);
5236
0
    assert(name);
5237
5238
    /* Get the property node from the skip list */
5239
0
    if ((prop = (H5P_genprop_t *)H5SL_search(pclass->props, name)) == NULL)
5240
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "can't find property in skip list");
5241
5242
    /* Remove the property from the skip list */
5243
0
    if (H5SL_remove(pclass->props, prop->name) == NULL)
5244
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "can't remove property from skip list");
5245
5246
    /* Free the property, ignoring return value, nothing we can do */
5247
0
    H5P__free_prop(prop);
5248
5249
    /* Decrement the number of registered properties in class */
5250
0
    pclass->nprops--;
5251
5252
    /* Update the revision for the class */
5253
0
    pclass->revision = H5P_GET_NEXT_REV;
5254
5255
0
done:
5256
0
    FUNC_LEAVE_NOAPI(ret_value)
5257
0
} /* H5P__unregister() */
5258
5259
/*--------------------------------------------------------------------------
5260
 NAME
5261
    H5P_close
5262
 PURPOSE
5263
    Internal routine to close a property list.
5264
 USAGE
5265
    herr_t H5P_close(plist)
5266
        H5P_genplist_t *plist;  IN: Property list to close
5267
 RETURNS
5268
    Returns non-negative on success, negative on failure.
5269
 DESCRIPTION
5270
        Closes a property list.  If a 'close' callback exists for the property
5271
    list class, it is called before the property list is destroyed.  If 'close'
5272
    callbacks exist for any individual properties in the property list, they are
5273
    called after the class 'close' callback.
5274
5275
 GLOBAL VARIABLES
5276
 COMMENTS, BUGS, ASSUMPTIONS
5277
        The property list class 'close' callback routine is not called from
5278
    here, it must have been checked for and called properly prior to this routine
5279
    being called.
5280
 EXAMPLES
5281
 REVISION LOG
5282
--------------------------------------------------------------------------*/
5283
herr_t
5284
H5P_close(H5P_genplist_t *plist)
5285
2.04k
{
5286
2.04k
    H5P_genclass_t *tclass;              /* Temporary class pointer */
5287
2.04k
    H5SL_t         *seen = NULL;         /* Skip list to hold names of properties already seen */
5288
2.04k
    size_t          nseen;               /* Number of items 'seen' */
5289
2.04k
    bool            has_parent_class;    /* Flag to indicate that this property list's class has a parent */
5290
2.04k
    size_t          ndel;                /* Number of items deleted */
5291
2.04k
    H5SL_node_t    *curr_node;           /* Current node in skip list */
5292
2.04k
    H5P_genprop_t  *tmp;                 /* Temporary pointer to properties */
5293
2.04k
    unsigned        make_cb   = 0;       /* Operator data for property free callback */
5294
2.04k
    herr_t          ret_value = SUCCEED; /* return value */
5295
5296
2.04k
    FUNC_ENTER_NOAPI_NOINIT
5297
5298
2.04k
    assert(plist);
5299
5300
    /* Make call to property list class close callback, if needed
5301
     * (up through chain of parent classes also)
5302
     */
5303
2.04k
    if (plist->class_init) {
5304
2.04k
        tclass = plist->pclass;
5305
9.29k
        while (NULL != tclass) {
5306
7.24k
            if (NULL != tclass->close_func) {
5307
                /* Prepare & restore library for user callback */
5308
0
                H5_BEFORE_USER_CB(FAIL)
5309
0
                    {
5310
                        /* Call user's "close" callback function, ignoring return value */
5311
0
                        (tclass->close_func)(plist->plist_id, tclass->close_data);
5312
0
                    }
5313
0
                H5_AFTER_USER_CB(FAIL)
5314
0
            } /* end if */
5315
5316
            /* Go up to parent class */
5317
7.24k
            tclass = tclass->parent;
5318
7.24k
        } /* end while */
5319
2.04k
    }     /* end if */
5320
5321
    /* Create the skip list to hold names of properties already seen
5322
     * (This prevents a property in the class hierarchy from having it's
5323
     * 'close' callback called, if a property in the class hierarchy has
5324
     * already been seen)
5325
     */
5326
2.04k
    if ((seen = H5SL_create(H5SL_TYPE_STR, NULL)) == NULL)
5327
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "can't create skip list for seen properties");
5328
2.04k
    nseen = 0;
5329
5330
    /* Walk through the changed properties in the list */
5331
2.04k
    if (H5SL_count(plist->props) > 0) {
5332
2.03k
        curr_node = H5SL_first(plist->props);
5333
14.1k
        while (curr_node != NULL) {
5334
            /* Get pointer to property from node */
5335
12.1k
            tmp = (H5P_genprop_t *)H5SL_item(curr_node);
5336
5337
            /* Call property close callback, if it exists */
5338
12.1k
            if (tmp->close) {
5339
                /* Prepare & restore library for user callback */
5340
4.78k
                H5_BEFORE_USER_CB(FAIL)
5341
4.78k
                    {
5342
                        /* Call user's callback */
5343
4.78k
                        (tmp->close)(tmp->name, tmp->size, tmp->value);
5344
4.78k
                    }
5345
4.78k
                H5_AFTER_USER_CB(FAIL)
5346
4.78k
            } /* end if */
5347
5348
            /* Add property name to "seen" list */
5349
12.1k
            if (H5SL_insert(seen, tmp->name, tmp->name) < 0)
5350
0
                HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into seen skip list");
5351
12.1k
            nseen++;
5352
5353
            /* Get the next property node in the skip list */
5354
12.1k
            curr_node = H5SL_next(curr_node);
5355
12.1k
        } /* end while */
5356
2.03k
    }     /* end if */
5357
5358
    /* Determine number of deleted items from property list */
5359
2.04k
    ndel = H5SL_count(plist->del);
5360
5361
    /*
5362
     * Check if we should remove class properties (up through list of parent classes also),
5363
     * initialize each with default value & make property 'remove' callback.
5364
     */
5365
2.04k
    tclass           = plist->pclass;
5366
2.04k
    has_parent_class = (bool)(tclass != NULL && tclass->parent != NULL && tclass->parent->nprops > 0);
5367
9.29k
    while (tclass != NULL) {
5368
7.24k
        if (tclass->nprops > 0) {
5369
            /* Walk through the properties in the class */
5370
5.18k
            curr_node = H5SL_first(tclass->props);
5371
39.7k
            while (curr_node != NULL) {
5372
                /* Get pointer to property from node */
5373
34.5k
                tmp = (H5P_genprop_t *)H5SL_item(curr_node);
5374
5375
                /* Only "delete" properties we haven't seen before
5376
                 * and that haven't already been deleted
5377
                 */
5378
34.5k
                if ((nseen == 0 || H5SL_search(seen, tmp->name) == NULL) &&
5379
22.4k
                    (ndel == 0 || H5SL_search(plist->del, tmp->name) == NULL)) {
5380
5381
                    /* Call property close callback, if it exists */
5382
22.4k
                    if (tmp->close) {
5383
29
                        void *tmp_value; /* Temporary value buffer */
5384
5385
                        /* Allocate space for a temporary copy of the property value */
5386
29
                        if (NULL == (tmp_value = H5MM_malloc(tmp->size)))
5387
0
                            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
5388
29
                                        "memory allocation failed for temporary property value");
5389
29
                        H5MM_memcpy(tmp_value, tmp->value, tmp->size);
5390
5391
                        /* Prepare & restore library for user callback */
5392
29
                        H5_BEFORE_USER_CB(FAIL)
5393
29
                            {
5394
                                /* Call user's callback */
5395
29
                                (tmp->close)(tmp->name, tmp->size, tmp_value);
5396
29
                            }
5397
29
                        H5_AFTER_USER_CB(FAIL)
5398
5399
                        /* Release the temporary value buffer */
5400
29
                        H5MM_xfree(tmp_value);
5401
29
                    } /* end if */
5402
5403
                    /* Add property name to "seen" list, if we have other classes to work on */
5404
22.4k
                    if (has_parent_class) {
5405
22.1k
                        if (H5SL_insert(seen, tmp->name, tmp->name) < 0)
5406
0
                            HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL,
5407
22.1k
                                        "can't insert property into seen skip list");
5408
22.1k
                        nseen++;
5409
22.1k
                    } /* end if */
5410
22.4k
                }     /* end if */
5411
5412
                /* Get the next property node in the skip list */
5413
34.5k
                curr_node = H5SL_next(curr_node);
5414
34.5k
            } /* end while */
5415
5.18k
        }     /* end if */
5416
5417
        /* Go up to parent class */
5418
7.24k
        tclass = tclass->parent;
5419
7.24k
    } /* end while */
5420
5421
    /* Decrement class's dependent property list value! */
5422
2.04k
    if (H5P__access_class(plist->pclass, H5P_MOD_DEC_LST) < 0)
5423
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "Can't decrement class ref count");
5424
5425
    /* Free the list of 'seen' properties */
5426
2.04k
    H5SL_close(seen);
5427
2.04k
    seen = NULL;
5428
5429
    /* Free the list of deleted property names */
5430
2.04k
    H5SL_destroy(plist->del, H5P__free_del_name_cb, NULL);
5431
5432
    /* Free the properties */
5433
2.04k
    H5SL_destroy(plist->props, H5P__free_prop_cb, &make_cb);
5434
5435
    /* Destroy property list object */
5436
2.04k
    plist = H5FL_FREE(H5P_genplist_t, plist);
5437
5438
2.04k
done:
5439
    /* Release the skip list of 'seen' properties */
5440
2.04k
    if (seen != NULL)
5441
0
        H5SL_close(seen);
5442
5443
2.04k
    FUNC_LEAVE_NOAPI(ret_value)
5444
2.04k
} /* H5P_close() */
5445
5446
/*--------------------------------------------------------------------------
5447
 NAME
5448
    H5P_get_class_name
5449
 PURPOSE
5450
    Internal routine to query the name of a generic property list class
5451
 USAGE
5452
    char *H5P_get_class_name(pclass)
5453
        H5P_genclass_t *pclass;    IN: Property list class to check
5454
 RETURNS
5455
    Success: Pointer to a malloc'ed string containing the class name
5456
    Failure: NULL
5457
 DESCRIPTION
5458
        This routine retrieves the name of a generic property list class.
5459
    The pointer to the name must be free'd by the user for successful calls.
5460
5461
 GLOBAL VARIABLES
5462
 COMMENTS, BUGS, ASSUMPTIONS
5463
 EXAMPLES
5464
 REVISION LOG
5465
--------------------------------------------------------------------------*/
5466
char *
5467
H5P_get_class_name(H5P_genclass_t *pclass)
5468
0
{
5469
0
    char *ret_value = NULL; /* Return value */
5470
5471
0
    FUNC_ENTER_NOAPI(NULL)
5472
5473
0
    assert(pclass);
5474
5475
    /* Get class name */
5476
0
    ret_value = H5MM_xstrdup(pclass->name);
5477
5478
0
done:
5479
0
    FUNC_LEAVE_NOAPI(ret_value)
5480
0
} /* H5P_get_class_name() */
5481
5482
/*--------------------------------------------------------------------------
5483
 NAME
5484
    H5P__get_class_path
5485
 PURPOSE
5486
    Internal routine to query the full path of a generic property list class
5487
 USAGE
5488
    char *H5P__get_class_name(pclass)
5489
        H5P_genclass_t *pclass;    IN: Property list class to check
5490
 RETURNS
5491
    Success: Pointer to a malloc'ed string containing the full path of class
5492
    Failure: NULL
5493
 DESCRIPTION
5494
        This routine retrieves the full path name of a generic property list
5495
    class, starting with the root of the class hierarchy.
5496
    The pointer to the name must be free'd by the user for successful calls.
5497
5498
 GLOBAL VARIABLES
5499
 COMMENTS, BUGS, ASSUMPTIONS
5500
 EXAMPLES
5501
 REVISION LOG
5502
--------------------------------------------------------------------------*/
5503
char *
5504
H5P__get_class_path(H5P_genclass_t *pclass)
5505
0
{
5506
0
    char *ret_value = NULL; /* Return value */
5507
5508
0
    FUNC_ENTER_PACKAGE
5509
5510
0
    assert(pclass);
5511
5512
    /* Recursively build the full path */
5513
0
    if (pclass->parent != NULL) {
5514
0
        char *par_path; /* Parent class's full path */
5515
5516
        /* Get the parent class's path */
5517
0
        par_path = H5P__get_class_path(pclass->parent);
5518
0
        if (par_path != NULL) {
5519
0
            size_t ret_str_len;
5520
5521
            /* Allocate enough space for the parent class's path, plus the '/'
5522
             * separator, this class's name and the string terminator
5523
             */
5524
0
            ret_str_len = strlen(par_path) + strlen(pclass->name) + 1 +
5525
0
                          3; /* Extra "+3" to quiet GCC warning - 2019/07/05, QAK */
5526
0
            if (NULL == (ret_value = (char *)H5MM_malloc(ret_str_len)))
5527
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for class name");
5528
5529
            /* Build the full path for this class */
5530
0
            snprintf(ret_value, ret_str_len, "%s/%s", par_path, pclass->name);
5531
5532
            /* Free the parent class's path */
5533
0
            H5MM_xfree(par_path);
5534
0
        } /* end if */
5535
0
        else
5536
0
            ret_value = H5MM_xstrdup(pclass->name);
5537
0
    } /* end if */
5538
0
    else
5539
0
        ret_value = H5MM_xstrdup(pclass->name);
5540
5541
0
done:
5542
0
    FUNC_LEAVE_NOAPI(ret_value)
5543
0
} /* H5P__get_class_path() */
5544
5545
/*--------------------------------------------------------------------------
5546
 NAME
5547
    H5P__open_class_path
5548
 PURPOSE
5549
    Internal routine to open [a copy of] a class with its full path name
5550
 USAGE
5551
    H5P_genclass_t *H5P__open_class_path(path)
5552
        const char *path;       IN: Full path name of class to open [copy of]
5553
 RETURNS
5554
    Success: Pointer to a generic property class object
5555
    Failure: NULL
5556
 DESCRIPTION
5557
    This routine opens [a copy] of the class indicated by the full path.
5558
5559
 GLOBAL VARIABLES
5560
 COMMENTS, BUGS, ASSUMPTIONS
5561
 EXAMPLES
5562
 REVISION LOG
5563
--------------------------------------------------------------------------*/
5564
H5P_genclass_t *
5565
H5P__open_class_path(const char *path)
5566
0
{
5567
0
    char             *tmp_path = NULL;  /* Temporary copy of the path */
5568
0
    char             *curr_name;        /* Pointer to current component of path name */
5569
0
    char             *delimit;          /* Pointer to path delimiter during traversal */
5570
0
    H5P_genclass_t   *curr_class;       /* Pointer to class during path traversal */
5571
0
    H5P_check_class_t check_info;       /* Structure to hold the information for checking duplicate names */
5572
0
    H5P_genclass_t   *ret_value = NULL; /* Return value */
5573
5574
0
    FUNC_ENTER_PACKAGE
5575
5576
0
    assert(path);
5577
5578
    /* Duplicate the path to use */
5579
0
    tmp_path = H5MM_xstrdup(path);
5580
0
    assert(tmp_path);
5581
5582
    /* Find the generic property class with this full path */
5583
0
    curr_name  = tmp_path;
5584
0
    curr_class = NULL;
5585
0
    while (NULL != (delimit = strchr(curr_name, '/'))) {
5586
        /* Change the delimiter to terminate the string */
5587
0
        *delimit = '\0';
5588
5589
        /* Set up the search structure */
5590
0
        check_info.parent    = curr_class;
5591
0
        check_info.name      = curr_name;
5592
0
        check_info.new_class = NULL;
5593
5594
        /* Find the class with this name & parent by iterating over the open classes */
5595
0
        if (H5I_iterate(H5I_GENPROP_CLS, H5P__open_class_path_cb, &check_info, false) < 0)
5596
0
            HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes");
5597
0
        else if (NULL == check_info.new_class)
5598
0
            HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class");
5599
5600
        /* Advance the pointer in the path to the start of the next component */
5601
0
        curr_class = check_info.new_class;
5602
0
        curr_name  = delimit + 1;
5603
0
    } /* end while */
5604
5605
    /* Should be pointing to the last component in the path name now... */
5606
5607
    /* Set up the search structure */
5608
0
    check_info.parent    = curr_class;
5609
0
    check_info.name      = curr_name;
5610
0
    check_info.new_class = NULL;
5611
5612
    /* Find the class with this name & parent by iterating over the open classes */
5613
0
    if (H5I_iterate(H5I_GENPROP_CLS, H5P__open_class_path_cb, &check_info, false) < 0)
5614
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes");
5615
0
    else if (NULL == check_info.new_class)
5616
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class");
5617
5618
    /* Copy it */
5619
0
    if (NULL == (ret_value = H5P__copy_pclass(check_info.new_class)))
5620
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class");
5621
5622
0
done:
5623
    /* Free the duplicated path */
5624
0
    H5MM_xfree(tmp_path);
5625
5626
0
    FUNC_LEAVE_NOAPI(ret_value)
5627
0
} /* H5P__open_class_path() */
5628
5629
/*--------------------------------------------------------------------------
5630
 NAME
5631
    H5P__get_class_parent
5632
 PURPOSE
5633
    Internal routine to query the parent class of a generic property class
5634
 USAGE
5635
    H5P_genclass_t *H5P__get_class_parent(pclass)
5636
        H5P_genclass_t *pclass;    IN: Property class to check
5637
 RETURNS
5638
    Success: Pointer to the parent class of a property class
5639
    Failure: NULL
5640
 DESCRIPTION
5641
    This routine retrieves a pointer to the parent class for a property class.
5642
5643
 GLOBAL VARIABLES
5644
 COMMENTS, BUGS, ASSUMPTIONS
5645
 EXAMPLES
5646
 REVISION LOG
5647
--------------------------------------------------------------------------*/
5648
H5P_genclass_t *
5649
H5P__get_class_parent(const H5P_genclass_t *pclass)
5650
0
{
5651
0
    H5P_genclass_t *ret_value = NULL; /* Return value */
5652
5653
0
    FUNC_ENTER_PACKAGE_NOERR
5654
5655
0
    assert(pclass);
5656
5657
    /* Get property size */
5658
0
    ret_value = pclass->parent;
5659
5660
0
    FUNC_LEAVE_NOAPI(ret_value)
5661
0
} /* H5P__get_class_parent() */
5662
5663
/*--------------------------------------------------------------------------
5664
 NAME
5665
    H5P__close_class
5666
 PURPOSE
5667
    Internal routine to close a property list class.
5668
 USAGE
5669
    herr_t H5P__close_class(class)
5670
        H5P_genclass_t *class;  IN: Property list class to close
5671
 RETURNS
5672
    Returns non-negative on success, negative on failure.
5673
 DESCRIPTION
5674
    Releases memory and de-attach a class from the property list class hierarchy.
5675
 GLOBAL VARIABLES
5676
 COMMENTS, BUGS, ASSUMPTIONS
5677
 EXAMPLES
5678
 REVISION LOG
5679
--------------------------------------------------------------------------*/
5680
herr_t
5681
H5P__close_class(H5P_genclass_t *pclass)
5682
22
{
5683
22
    herr_t ret_value = SUCCEED; /* Return value */
5684
5685
22
    FUNC_ENTER_PACKAGE
5686
5687
22
    assert(pclass);
5688
5689
    /* Decrement the reference count & check if the object should go away */
5690
22
    if (H5P__access_class(pclass, H5P_MOD_DEC_REF) < 0)
5691
0
        HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "can't decrement ID ref count");
5692
5693
22
done:
5694
22
    FUNC_LEAVE_NOAPI(ret_value)
5695
22
} /* H5P__close_class() */
5696
5697
/*-------------------------------------------------------------------------
5698
 * Function:       H5P__new_plist_of_type
5699
 *
5700
 * Purpose:        Create a new property list, of a given type
5701
 *
5702
 * Return:     Success: ID of new property list
5703
 *       Failure: H5I_INVALID_HID
5704
 *
5705
 *-------------------------------------------------------------------------
5706
 */
5707
hid_t
5708
H5P__new_plist_of_type(H5P_plist_type_t type)
5709
0
{
5710
0
    H5P_genclass_t *pclass;                      /* Class of property list to create */
5711
0
    hid_t           class_id;                    /* ID of class to create */
5712
0
    hid_t           ret_value = H5I_INVALID_HID; /* Return value */
5713
5714
0
    FUNC_ENTER_PACKAGE
5715
5716
    /* Sanity checks */
5717
0
    HDcompile_assert(H5P_TYPE_REFERENCE_ACCESS == (H5P_TYPE_MAX_TYPE - 1));
5718
0
    assert(type >= H5P_TYPE_USER && type <= H5P_TYPE_REFERENCE_ACCESS);
5719
5720
    /* Check arguments */
5721
0
    if (type == H5P_TYPE_USER)
5722
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, H5I_INVALID_HID, "can't create user property list");
5723
0
    if (type == H5P_TYPE_ROOT)
5724
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, H5I_INVALID_HID,
5725
0
                    "shouldn't be creating root class property list");
5726
5727
    /* Instantiate a property list of the proper type */
5728
0
    switch (type) {
5729
0
        case H5P_TYPE_OBJECT_CREATE:
5730
0
            class_id = H5P_CLS_OBJECT_CREATE_ID_g;
5731
0
            break;
5732
5733
0
        case H5P_TYPE_FILE_CREATE:
5734
0
            class_id = H5P_CLS_FILE_CREATE_ID_g;
5735
0
            break;
5736
5737
0
        case H5P_TYPE_FILE_ACCESS:
5738
0
            class_id = H5P_CLS_FILE_ACCESS_ID_g;
5739
0
            break;
5740
5741
0
        case H5P_TYPE_DATASET_CREATE:
5742
0
            class_id = H5P_CLS_DATASET_CREATE_ID_g;
5743
0
            break;
5744
5745
0
        case H5P_TYPE_DATASET_ACCESS:
5746
0
            class_id = H5P_CLS_DATASET_ACCESS_ID_g;
5747
0
            break;
5748
5749
0
        case H5P_TYPE_DATASET_XFER:
5750
0
            class_id = H5P_CLS_DATASET_XFER_ID_g;
5751
0
            break;
5752
5753
0
        case H5P_TYPE_FILE_MOUNT:
5754
0
            class_id = H5P_CLS_FILE_MOUNT_ID_g;
5755
0
            break;
5756
5757
0
        case H5P_TYPE_GROUP_CREATE:
5758
0
            class_id = H5P_CLS_GROUP_CREATE_ID_g;
5759
0
            break;
5760
5761
0
        case H5P_TYPE_GROUP_ACCESS:
5762
0
            class_id = H5P_CLS_GROUP_ACCESS_ID_g;
5763
0
            break;
5764
5765
0
        case H5P_TYPE_DATATYPE_CREATE:
5766
0
            class_id = H5P_CLS_DATATYPE_CREATE_ID_g;
5767
0
            break;
5768
5769
0
        case H5P_TYPE_DATATYPE_ACCESS:
5770
0
            class_id = H5P_CLS_DATATYPE_ACCESS_ID_g;
5771
0
            break;
5772
5773
0
        case H5P_TYPE_MAP_CREATE:
5774
0
            class_id = H5P_CLS_MAP_CREATE_ID_g;
5775
0
            break;
5776
5777
0
        case H5P_TYPE_MAP_ACCESS:
5778
0
            class_id = H5P_CLS_MAP_ACCESS_ID_g;
5779
0
            break;
5780
5781
0
        case H5P_TYPE_STRING_CREATE:
5782
0
            class_id = H5P_CLS_STRING_CREATE_ID_g;
5783
0
            break;
5784
5785
0
        case H5P_TYPE_ATTRIBUTE_CREATE:
5786
0
            class_id = H5P_CLS_ATTRIBUTE_CREATE_ID_g;
5787
0
            break;
5788
5789
0
        case H5P_TYPE_ATTRIBUTE_ACCESS:
5790
0
            class_id = H5P_CLS_ATTRIBUTE_ACCESS_ID_g;
5791
0
            break;
5792
5793
0
        case H5P_TYPE_OBJECT_COPY:
5794
0
            class_id = H5P_CLS_OBJECT_COPY_ID_g;
5795
0
            break;
5796
5797
0
        case H5P_TYPE_LINK_CREATE:
5798
0
            class_id = H5P_CLS_LINK_CREATE_ID_g;
5799
0
            break;
5800
5801
0
        case H5P_TYPE_LINK_ACCESS:
5802
0
            class_id = H5P_CLS_LINK_ACCESS_ID_g;
5803
0
            break;
5804
5805
0
        case H5P_TYPE_VOL_INITIALIZE:
5806
0
            class_id = H5P_CLS_VOL_INITIALIZE_ID_g;
5807
0
            break;
5808
5809
0
        case H5P_TYPE_REFERENCE_ACCESS:
5810
0
            class_id = H5P_CLS_REFERENCE_ACCESS_ID_g;
5811
0
            break;
5812
5813
0
        case H5P_TYPE_USER: /* shut compiler warnings up */
5814
0
        case H5P_TYPE_ROOT:
5815
0
        case H5P_TYPE_MAX_TYPE:
5816
0
        default:
5817
0
            HGOTO_ERROR(H5E_PLIST, H5E_BADRANGE, FAIL, "invalid property list type: %u\n", (unsigned)type);
5818
0
    } /* end switch */
5819
5820
    /* Get the class object */
5821
0
    if (NULL == (pclass = (H5P_genclass_t *)H5I_object(class_id)))
5822
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, H5I_INVALID_HID, "not a property class");
5823
5824
    /* Create the new property list */
5825
0
    if ((ret_value = H5P_create_id(pclass, true)) < 0)
5826
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create property list");
5827
5828
0
done:
5829
0
    FUNC_LEAVE_NOAPI(ret_value)
5830
0
} /* end H5P__new_plist_of_type() */
5831
5832
/*-------------------------------------------------------------------------
5833
 * Function:  H5P_get_plist_id
5834
 *
5835
 * Purpose: Quick and dirty routine to retrieve property list ID from
5836
 *    property list structure.
5837
 *          (Mainly added to stop non-file routines from poking about in the
5838
 *          H5P_genplist_t data structure)
5839
 *
5840
 * Return:      Success:        Non-negative ID of property list.
5841
 *              Failure:        H5I_INVALID_HID
5842
 *
5843
 *-------------------------------------------------------------------------
5844
 */
5845
hid_t
5846
H5P_get_plist_id(const H5P_genplist_t *plist)
5847
0
{
5848
    /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
5849
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
5850
5851
0
    assert(plist);
5852
5853
0
    FUNC_LEAVE_NOAPI(plist->plist_id)
5854
0
} /* end H5P_get_plist_id() */
5855
5856
/*-------------------------------------------------------------------------
5857
 * Function:  H5P_get_class
5858
 *
5859
 * Purpose: Quick and dirty routine to retrieve property list class from
5860
 *    property list structure.
5861
 *          (Mainly added to stop non-file routines from poking about in the
5862
 *          H5P_genplist_t data structure)
5863
 *
5864
 * Return:      Success:        Non-NULL class of property list.
5865
 *              Failure:        NULL
5866
 *
5867
 *-------------------------------------------------------------------------
5868
 */
5869
H5P_genclass_t *
5870
H5P_get_class(const H5P_genplist_t *plist)
5871
0
{
5872
    /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
5873
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
5874
5875
0
    assert(plist);
5876
5877
0
    FUNC_LEAVE_NOAPI(plist->pclass)
5878
0
} /* end H5P_get_class() */
5879
5880
/*-------------------------------------------------------------------------
5881
 * Function:       H5P_ignore_cmp
5882
 *
5883
 * Purpose:        Callback routine to ignore comparing property values.
5884
 *
5885
 * Return:         zero
5886
 *
5887
 *-------------------------------------------------------------------------
5888
 */
5889
int
5890
H5P_ignore_cmp(const void H5_ATTR_UNUSED *val1, const void H5_ATTR_UNUSED *val2, size_t H5_ATTR_UNUSED size)
5891
0
{
5892
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
5893
5894
0
    FUNC_LEAVE_NOAPI(0)
5895
0
} /* end H5P_ignore_cmp() */