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