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://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*-------------------------------------------------------------------------
15  *
16  * Created:		H5Pocpypl.c
17  *			Mar 13 2006
18  *			Peter Cao
19  *
20  * Purpose:		Object copying property list class routines
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5Pmodule.h" /* This source code file is part of the H5P module */
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"   /* Generic Functions			*/
35 #include "H5Eprivate.h"  /* Error handling		  	*/
36 #include "H5FLprivate.h" /* Free Lists                           */
37 #include "H5Iprivate.h"  /* IDs			  		*/
38 #include "H5MMprivate.h" /* Memory management                    */
39 #include "H5Oprivate.h"  /* Object headers		  	*/
40 #include "H5Ppkg.h"      /* Property lists		  	*/
41 
42 /****************/
43 /* Local Macros */
44 /****************/
45 
46 /* ========= Object Copy properties ============ */
47 /* Definitions for copy options */
48 #define H5O_CPY_OPTION_SIZE sizeof(unsigned)
49 #define H5O_CPY_OPTION_DEF  0
50 #define H5O_CPY_OPTION_ENC  H5P__encode_unsigned
51 #define H5O_CPY_OPTION_DEC  H5P__decode_unsigned
52 /* Definitions for merge committed dtype list */
53 #define H5O_CPY_MERGE_COMM_DT_LIST_SIZE  sizeof(H5O_copy_dtype_merge_list_t *)
54 #define H5O_CPY_MERGE_COMM_DT_LIST_DEF   NULL
55 #define H5O_CPY_MERGE_COMM_DT_LIST_SET   H5P__ocpy_merge_comm_dt_list_set
56 #define H5O_CPY_MERGE_COMM_DT_LIST_GET   H5P__ocpy_merge_comm_dt_list_get
57 #define H5O_CPY_MERGE_COMM_DT_LIST_ENC   H5P__ocpy_merge_comm_dt_list_enc
58 #define H5O_CPY_MERGE_COMM_DT_LIST_DEC   H5P__ocpy_merge_comm_dt_list_dec
59 #define H5O_CPY_MERGE_COMM_DT_LIST_DEL   H5P__ocpy_merge_comm_dt_list_del
60 #define H5O_CPY_MERGE_COMM_DT_LIST_COPY  H5P__ocpy_merge_comm_dt_list_copy
61 #define H5O_CPY_MERGE_COMM_DT_LIST_CMP   H5P__ocpy_merge_comm_dt_list_cmp
62 #define H5O_CPY_MERGE_COMM_DT_LIST_CLOSE H5P__ocpy_merge_comm_dt_list_close
63 /* Definitions for callback function when completing the search for a matching committed datatype from the
64  * committed dtype list */
65 #define H5O_CPY_MCDT_SEARCH_CB_SIZE sizeof(H5O_mcdt_cb_info_t)
66 #define H5O_CPY_MCDT_SEARCH_CB_DEF                                                                           \
67     {                                                                                                        \
68         NULL, NULL                                                                                           \
69     }
70 
71 /******************/
72 /* Local Typedefs */
73 /******************/
74 
75 /********************/
76 /* Package Typedefs */
77 /********************/
78 
79 /********************/
80 /* Local Prototypes */
81 /********************/
82 
83 /* General routines */
84 static H5O_copy_dtype_merge_list_t *H5P__free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list);
85 static herr_t                       H5P__copy_merge_comm_dt_list(H5O_copy_dtype_merge_list_t **value);
86 
87 /* Property class callbacks */
88 static herr_t H5P__ocpy_reg_prop(H5P_genclass_t *pclass);
89 
90 /* Property callbacks */
91 static herr_t H5P__ocpy_merge_comm_dt_list_set(hid_t prop_id, const char *name, size_t size, void *value);
92 static herr_t H5P__ocpy_merge_comm_dt_list_get(hid_t prop_id, const char *name, size_t size, void *value);
93 static herr_t H5P__ocpy_merge_comm_dt_list_enc(const void *value, void **_pp, size_t *size, void *udata);
94 static herr_t H5P__ocpy_merge_comm_dt_list_dec(const void **_pp, void *value);
95 static herr_t H5P__ocpy_merge_comm_dt_list_del(hid_t prop_id, const char *name, size_t size, void *value);
96 static herr_t H5P__ocpy_merge_comm_dt_list_copy(const char *name, size_t size, void *value);
97 static int    H5P__ocpy_merge_comm_dt_list_cmp(const void *value1, const void *value2, size_t size);
98 static herr_t H5P__ocpy_merge_comm_dt_list_close(const char *name, size_t size, void *value);
99 
100 /*********************/
101 /* Package Variables */
102 /*********************/
103 
104 /* Object copy property list class library initialization object */
105 const H5P_libclass_t H5P_CLS_OCPY[1] = {{
106     "object copy",        /* Class name for debugging     */
107     H5P_TYPE_OBJECT_COPY, /* Class type                   */
108 
109     &H5P_CLS_ROOT_g,           /* Parent class                 */
110     &H5P_CLS_OBJECT_COPY_g,    /* Pointer to class             */
111     &H5P_CLS_OBJECT_COPY_ID_g, /* Pointer to class ID          */
112     &H5P_LST_OBJECT_COPY_ID_g, /* Pointer to default property list ID */
113     H5P__ocpy_reg_prop,        /* Default property registration routine */
114 
115     NULL, /* Class creation callback      */
116     NULL, /* Class creation callback info */
117     NULL, /* Class copy callback          */
118     NULL, /* Class copy callback info     */
119     NULL, /* Class close callback         */
120     NULL  /* Class close callback info    */
121 }};
122 
123 /*****************************/
124 /* Library Private Variables */
125 /*****************************/
126 
127 /*******************/
128 /* Local Variables */
129 /*******************/
130 
131 /* Property value defaults */
132 static const unsigned H5O_def_ocpy_option_g = H5O_CPY_OPTION_DEF; /* Default object copy flags */
133 static const H5O_copy_dtype_merge_list_t *H5O_def_merge_comm_dtype_list_g =
134     H5O_CPY_MERGE_COMM_DT_LIST_DEF; /* Default merge committed dtype list */
135 static const H5O_mcdt_cb_info_t H5O_def_mcdt_cb_g =
136     H5O_CPY_MCDT_SEARCH_CB_DEF; /* Default callback before searching the global list of committed datatypes at
137                                    destination */
138 
139 /* Declare a free list to manage the H5O_copy_dtype_merge_list_t struct */
140 H5FL_DEFINE(H5O_copy_dtype_merge_list_t);
141 
142 /*-------------------------------------------------------------------------
143  * Function:    H5P__ocpy_reg_prop
144  *
145  * Purpose:     Initialize the object copy property list class
146  *
147  * Return:      Non-negative on success/Negative on failure
148  *
149  * Programmer:  Quincey Koziol
150  *              October 31, 2006
151  *-------------------------------------------------------------------------
152  */
153 static herr_t
H5P__ocpy_reg_prop(H5P_genclass_t * pclass)154 H5P__ocpy_reg_prop(H5P_genclass_t *pclass)
155 {
156     herr_t ret_value = SUCCEED; /* Return value */
157 
158     FUNC_ENTER_STATIC
159 
160     /* Register copy options property */
161     if (H5P__register_real(pclass, H5O_CPY_OPTION_NAME, H5O_CPY_OPTION_SIZE, &H5O_def_ocpy_option_g, NULL,
162                            NULL, NULL, H5O_CPY_OPTION_ENC, H5O_CPY_OPTION_DEC, NULL, NULL, NULL, NULL) < 0)
163         HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
164 
165     /* Register merge named dtype list property */
166     if (H5P__register_real(pclass, H5O_CPY_MERGE_COMM_DT_LIST_NAME, H5O_CPY_MERGE_COMM_DT_LIST_SIZE,
167                            &H5O_def_merge_comm_dtype_list_g, NULL, H5O_CPY_MERGE_COMM_DT_LIST_SET,
168                            H5O_CPY_MERGE_COMM_DT_LIST_GET, H5O_CPY_MERGE_COMM_DT_LIST_ENC,
169                            H5O_CPY_MERGE_COMM_DT_LIST_DEC, H5O_CPY_MERGE_COMM_DT_LIST_DEL,
170                            H5O_CPY_MERGE_COMM_DT_LIST_COPY, H5O_CPY_MERGE_COMM_DT_LIST_CMP,
171                            H5O_CPY_MERGE_COMM_DT_LIST_CLOSE) < 0)
172         HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
173 
174     /* Register property for callback when completing the search for a matching named datatype from the named
175      * dtype list */
176     /* (Note: this property should not have an encode/decode callback -QAK) */
177     if (H5P__register_real(pclass, H5O_CPY_MCDT_SEARCH_CB_NAME, H5O_CPY_MCDT_SEARCH_CB_SIZE,
178                            &H5O_def_mcdt_cb_g, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
179         HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
180 
181 done:
182     FUNC_LEAVE_NOAPI(ret_value)
183 } /* end H5P__ocpy_reg_prop() */
184 
185 /*-------------------------------------------------------------------------
186  * Function:    H5P__free_merge_comm_dtype_list
187  *
188  * Purpose:     Frees the provided merge named dtype list
189  *
190  * Return:      NULL
191  *
192  * Programmer:  Neil Fortner
193  *              October 27, 2011
194  *
195  *-------------------------------------------------------------------------
196  */
197 static H5O_copy_dtype_merge_list_t *
H5P__free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t * dt_list)198 H5P__free_merge_comm_dtype_list(H5O_copy_dtype_merge_list_t *dt_list)
199 {
200     FUNC_ENTER_STATIC_NOERR
201 
202     /* Free the list */
203     while (dt_list) {
204         H5O_copy_dtype_merge_list_t *tmp_node;
205 
206         tmp_node = dt_list->next;
207 
208         (void)H5MM_xfree(dt_list->path);
209         (void)H5FL_FREE(H5O_copy_dtype_merge_list_t, dt_list);
210 
211         dt_list = tmp_node;
212     } /* end while */
213 
214     FUNC_LEAVE_NOAPI(NULL);
215 } /* H5P__free_merge_comm_dtype_list */
216 
217 /*--------------------------------------------------------------------------
218  * Function:	H5P__copy_merge_comm_dt_list
219  *
220  * Purpose:	Copy a merge committed datatype list
221  *
222  * Return:	Success:	Non-negative
223  * 		Failure:	Negative
224  *
225  * Programmer:	Quincey Koziol
226  *		Wednesday, September 2, 2015
227  *
228  *--------------------------------------------------------------------------
229  */
230 static herr_t
H5P__copy_merge_comm_dt_list(H5O_copy_dtype_merge_list_t ** value)231 H5P__copy_merge_comm_dt_list(H5O_copy_dtype_merge_list_t **value)
232 {
233     const H5O_copy_dtype_merge_list_t *src_dt_list;             /* Source merge named datatype lists */
234     H5O_copy_dtype_merge_list_t *      dst_dt_list      = NULL; /* Destination merge named datatype lists */
235     H5O_copy_dtype_merge_list_t *      dst_dt_list_tail = NULL,
236                                 *tmp_dt_list            = NULL; /* temporary merge named datatype lists */
237     herr_t ret_value                                    = SUCCEED;
238 
239     FUNC_ENTER_STATIC
240 
241     /* Sanity check */
242     HDassert(value);
243 
244     /* Make copy of merge committed dtype list */
245     src_dt_list = *value;
246     while (src_dt_list) {
247         /* Copy src_dt_list */
248         if (NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t)))
249             HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
250         if (NULL == (tmp_dt_list->path = H5MM_strdup(src_dt_list->path)))
251             HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
252 
253         /* Add copied node to dest dtype list */
254         if (dst_dt_list_tail) {
255             dst_dt_list_tail->next = tmp_dt_list;
256             dst_dt_list_tail       = tmp_dt_list;
257         } /* end if */
258         else {
259             dst_dt_list      = tmp_dt_list;
260             dst_dt_list_tail = tmp_dt_list;
261         } /* end else */
262         tmp_dt_list = NULL;
263 
264         /* Advance src_dt_list pointer */
265         src_dt_list = src_dt_list->next;
266     } /* end while */
267 
268     /* Set the merge named dtype list property for the destination property list */
269     *value = dst_dt_list;
270 
271 done:
272     if (ret_value < 0) {
273         dst_dt_list = H5P__free_merge_comm_dtype_list(dst_dt_list);
274         if (tmp_dt_list) {
275             tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path);
276             tmp_dt_list       = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list);
277         } /* end if */
278     }     /* end if */
279 
280     FUNC_LEAVE_NOAPI(ret_value)
281 } /* end H5P__copy_merge_comm_dt_list() */
282 
283 /*-------------------------------------------------------------------------
284  * Function:    H5P__ocpy_merge_comm_dt_list_set
285  *
286  * Purpose:     Copies a merge committed datatype list property when it's set for a property list
287  *
288  * Return:      Success:        Non-negative
289  *              Failure:        Negative
290  *
291  * Programmer:  Quincey Koziol
292  *              Wednesday, Sept 2, 2015
293  *
294  *-------------------------------------------------------------------------
295  */
296 static herr_t
H5P__ocpy_merge_comm_dt_list_set(hid_t H5_ATTR_UNUSED prop_id,const char H5_ATTR_UNUSED * name,size_t H5_ATTR_UNUSED size,void * value)297 H5P__ocpy_merge_comm_dt_list_set(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
298                                  size_t H5_ATTR_UNUSED size, void *value)
299 {
300     herr_t ret_value = SUCCEED; /* Return value */
301 
302     FUNC_ENTER_STATIC
303 
304     /* Sanity check */
305     HDassert(value);
306 
307     /* Make copy of merge committed dtype list */
308     if (H5P__copy_merge_comm_dt_list((H5O_copy_dtype_merge_list_t **)value) < 0)
309         HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy merge committed dtype list")
310 
311 done:
312     FUNC_LEAVE_NOAPI(ret_value)
313 } /* end H5P__ocpy_merge_comm_dt_list_set() */
314 
315 /*-------------------------------------------------------------------------
316  * Function:    H5P__ocpy_merge_comm_dt_list_get
317  *
318  * Purpose:     Copies a merge committed datatype list property when it's retrieved from a property list
319  *
320  * Return:      Success:        Non-negative
321  *              Failure:        Negative
322  *
323  * Programmer:  Quincey Koziol
324  *              Wednesday, Sept 2, 2015
325  *
326  *-------------------------------------------------------------------------
327  */
328 static herr_t
H5P__ocpy_merge_comm_dt_list_get(hid_t H5_ATTR_UNUSED prop_id,const char H5_ATTR_UNUSED * name,size_t H5_ATTR_UNUSED size,void * value)329 H5P__ocpy_merge_comm_dt_list_get(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
330                                  size_t H5_ATTR_UNUSED size, void *value)
331 {
332     herr_t ret_value = SUCCEED; /* Return value */
333 
334     FUNC_ENTER_STATIC
335 
336     /* Sanity check */
337     HDassert(value);
338 
339     /* Make copy of merge committed dtype list */
340     if (H5P__copy_merge_comm_dt_list((H5O_copy_dtype_merge_list_t **)value) < 0)
341         HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy merge committed dtype list")
342 
343 done:
344     FUNC_LEAVE_NOAPI(ret_value)
345 } /* end H5P__ocpy_merge_comm_dt_list_get() */
346 
347 /*-------------------------------------------------------------------------
348  * Function:       H5P__ocpy_merge_comm_dt_list_enc
349  *
350  * Purpose:        Callback routine which is called whenever the common
351  *		   datatype property in the object copy property list is
352  *                 decoded.
353  *
354  * Return:	   Success:	Non-negative
355  *		   Failure:	Negative
356  *
357  * Programmer:     Quincey Koziol
358  *                 Friday, August 31, 2012
359  *
360  *-------------------------------------------------------------------------
361  */
362 static herr_t
H5P__ocpy_merge_comm_dt_list_enc(const void * value,void ** _pp,size_t * size,void * udata)363 H5P__ocpy_merge_comm_dt_list_enc(const void *value, void **_pp, size_t *size, void* udata)
364 {
365     const H5O_copy_dtype_merge_list_t *const *dt_list_ptr = (const H5O_copy_dtype_merge_list_t *const *)value;
366     uint8_t **                                pp          = (uint8_t **)_pp;
367     const H5O_copy_dtype_merge_list_t *       dt_list; /* Pointer to merge named datatype list */
368     size_t                                    len;     /* Length of path component */
369     (void)udata;
370 
371     FUNC_ENTER_STATIC_NOERR
372 
373     HDassert(dt_list_ptr);
374     HDassert(size);
375 
376     /* Iterate over merge committed dtype list */
377     dt_list = *dt_list_ptr;
378     while (dt_list) {
379         /* Get length of encoded path */
380         len = HDstrlen(dt_list->path) + 1;
381 
382         /* Encode merge committed dtype list */
383         if (*pp) {
384             H5MM_memcpy(*(char **)pp, dt_list->path, len);
385             *pp += len;
386         } /* end if */
387 
388         /* Increment the size of the buffer */
389         *size += len;
390 
391         /* Advance to the next node */
392         dt_list = dt_list->next;
393     } /* end while */
394 
395     /* Encode the terminator for the string sequence */
396     if (*pp)
397         *(*pp)++ = (uint8_t)'\0';
398 
399     /* Account for the string sequence terminator */
400     *size += 1;
401 
402     FUNC_LEAVE_NOAPI(SUCCEED)
403 } /* end H5P__ocpy_merge_comm_dt_list_enc() */
404 
405 /*-------------------------------------------------------------------------
406  * Function:       H5P__ocpy_merge_comm_dt_list_dec
407  *
408  * Purpose:        Callback routine which is called whenever the common
409  *                 datatype property in the dataset access property list is
410  *                 decoded.
411  *
412  * Return:	   Success:	Non-negative
413  *		   Failure:	Negative
414  *
415  * Programmer:     Quincey Koziol
416  *                 Friday, August 31, 2012
417  *
418  *-------------------------------------------------------------------------
419  */
420 static herr_t
H5P__ocpy_merge_comm_dt_list_dec(const void ** _pp,void * _value)421 H5P__ocpy_merge_comm_dt_list_dec(const void **_pp, void *_value)
422 {
423     H5O_copy_dtype_merge_list_t **dt_list =
424         (H5O_copy_dtype_merge_list_t **)_value; /* Pointer to merge named datatype list */
425     const uint8_t **             pp           = (const uint8_t **)_pp;
426     H5O_copy_dtype_merge_list_t *dt_list_tail = NULL,
427                                 *tmp_dt_list  = NULL; /* temporary merge named datatype lists */
428     size_t len;                                       /* Length of path component */
429     herr_t ret_value = SUCCEED;                       /* Return value */
430 
431     FUNC_ENTER_STATIC
432 
433     /* Sanity check */
434     HDassert(pp);
435     HDassert(*pp);
436     HDassert(dt_list);
437 
438     /* Start off with NULL (default value) */
439     *dt_list = NULL;
440 
441     /* Decode the string sequence */
442     len = HDstrlen(*(const char **)pp);
443     while (len > 0) {
444         /* Create new node & duplicate string */
445         if (NULL == (tmp_dt_list = H5FL_CALLOC(H5O_copy_dtype_merge_list_t)))
446             HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
447         if (NULL == (tmp_dt_list->path = H5MM_strdup(*(const char **)pp)))
448             HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
449         *pp += len + 1;
450         HDassert(len == HDstrlen(tmp_dt_list->path));
451 
452         /* Add copied node to dtype list */
453         if (dt_list_tail) {
454             dt_list_tail->next = tmp_dt_list;
455             dt_list_tail       = tmp_dt_list;
456         } /* end if */
457         else {
458             *dt_list     = tmp_dt_list;
459             dt_list_tail = tmp_dt_list;
460         } /* end else */
461         tmp_dt_list = NULL;
462 
463         /* Compute length of next string */
464         len = HDstrlen(*(const char **)pp);
465     } /* end while */
466 
467     /* Advance past terminator for string sequence */
468     *pp += 1;
469 
470 done:
471     if (ret_value < 0) {
472         *dt_list = H5P__free_merge_comm_dtype_list(*dt_list);
473         if (tmp_dt_list) {
474             tmp_dt_list->path = (char *)H5MM_xfree(tmp_dt_list->path);
475             tmp_dt_list       = H5FL_FREE(H5O_copy_dtype_merge_list_t, tmp_dt_list);
476         } /* end if */
477     }     /* end if */
478 
479     FUNC_LEAVE_NOAPI(ret_value)
480 } /* H5P__ocpy_merge_comm_dt_list_dec() */
481 
482 /*--------------------------------------------------------------------------
483  * Function:	H5P__ocpy_merge_comm_dt_list_del
484  *
485  * Purpose:     Frees memory used to store the merge committed datatype list property
486  *
487  * Return:	Success:	Non-negative
488  * 		Failure:	Negative
489  *
490  * Programmer:	Quincey Koziol
491  *		Wednesday, September 2, 2015
492  *
493  *--------------------------------------------------------------------------
494  */
495 static herr_t
H5P__ocpy_merge_comm_dt_list_del(hid_t H5_ATTR_UNUSED prop_id,const char H5_ATTR_UNUSED * name,size_t H5_ATTR_UNUSED size,void * value)496 H5P__ocpy_merge_comm_dt_list_del(hid_t H5_ATTR_UNUSED prop_id, const char H5_ATTR_UNUSED *name,
497                                  size_t H5_ATTR_UNUSED size, void *value)
498 {
499     FUNC_ENTER_STATIC_NOERR
500 
501     /* Sanity check */
502     HDassert(value);
503 
504     /* Free the merge named dtype list */
505     H5P__free_merge_comm_dtype_list(*(H5O_copy_dtype_merge_list_t **)value);
506 
507     FUNC_LEAVE_NOAPI(SUCCEED)
508 } /* end H5P__ocpy_merge_comm_dt_list_del() */
509 
510 /*--------------------------------------------------------------------------
511  * Function:	H5P__ocpy_merge_comm_dt_list_copy
512  *
513  * Purpose:	Copy the merge committed datatype list
514  *
515  * Return:	Success:	Non-negative
516  * 		Failure:	Negative
517  *
518  * Programmer:	Quincey Koziol
519  *		Friday, August 31, 2012
520  *
521  *--------------------------------------------------------------------------
522  */
523 static herr_t
H5P__ocpy_merge_comm_dt_list_copy(const char H5_ATTR_UNUSED * name,size_t H5_ATTR_UNUSED size,void * value)524 H5P__ocpy_merge_comm_dt_list_copy(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
525 {
526     herr_t ret_value = SUCCEED;
527 
528     FUNC_ENTER_STATIC
529 
530     /* Sanity check */
531     HDassert(value);
532 
533     /* Make copy of merge committed dtype list */
534     if (H5P__copy_merge_comm_dt_list((H5O_copy_dtype_merge_list_t **)value) < 0)
535         HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy merge committed dtype list")
536 
537 done:
538     FUNC_LEAVE_NOAPI(ret_value)
539 } /* end H5P__ocpy_merge_comm_dt_list_copy() */
540 
541 /*-------------------------------------------------------------------------
542  * Function:       H5P__ocpy_merge_comm_dt_list_cmp
543  *
544  * Purpose:        Callback routine which is called whenever the merge
545  *                 named dtype property in the object copy property list
546  *                 is compared.
547  *
548  * Return:         positive if VALUE1 is greater than VALUE2, negative if
549  *                      VALUE2 is greater than VALUE1 and zero if VALUE1 and
550  *                      VALUE2 are equal.
551  *
552  * Programmer:     Neil Fortner
553  *                 Friday, October 28, 2011
554  *
555  *-------------------------------------------------------------------------
556  */
557 static int
H5P__ocpy_merge_comm_dt_list_cmp(const void * _dt_list1,const void * _dt_list2,size_t H5_ATTR_UNUSED size)558 H5P__ocpy_merge_comm_dt_list_cmp(const void *_dt_list1, const void *_dt_list2, size_t H5_ATTR_UNUSED size)
559 {
560     const H5O_copy_dtype_merge_list_t *dt_list1 = *(H5O_copy_dtype_merge_list_t *const *)
561                                                       _dt_list1, /* Create local aliases for values */
562         *dt_list2    = *(H5O_copy_dtype_merge_list_t *const *)_dt_list2;
563     herr_t ret_value = 0; /* Return value */
564 
565     FUNC_ENTER_STATIC_NOERR
566 
567     /* Sanity check */
568     HDassert(_dt_list1);
569     HDassert(_dt_list2);
570     HDassert(size == sizeof(H5O_copy_dtype_merge_list_t *));
571 
572     /* Walk through the lists, comparing each path.  For the lists to be the
573      * same, the paths must be in the same order. */
574     while (dt_list1 && dt_list2) {
575         HDassert(dt_list1->path);
576         HDassert(dt_list2->path);
577 
578         /* Compare paths */
579         ret_value = HDstrcmp(dt_list1->path, dt_list2->path);
580         if (ret_value != 0)
581             HGOTO_DONE(ret_value)
582 
583         /* Advance to next node */
584         dt_list1 = dt_list1->next;
585         dt_list2 = dt_list2->next;
586     } /* end while */
587 
588     /* Check if one list is longer than the other */
589     if (dt_list1)
590         HGOTO_DONE(1)
591     if (dt_list2)
592         HGOTO_DONE(-1)
593 
594 done:
595     FUNC_LEAVE_NOAPI(ret_value)
596 } /* end H5P__ocpy_merge_comm_dt_list_cmp() */
597 
598 /*--------------------------------------------------------------------------
599  * Function:	H5P__ocpy_merge_comm_dt_list_close
600  *
601  * Purpose:	Close the merge common datatype list property
602  *
603  * Return:	Success:	Non-negative
604  * 		Failure:	Negative
605  *
606  * Programmer:	Quincey Koziol
607  *		Friday, August 31, 2012
608  *
609  *---------------------------------------------------------------------------
610  */
611 static herr_t
H5P__ocpy_merge_comm_dt_list_close(const char H5_ATTR_UNUSED * name,size_t H5_ATTR_UNUSED size,void * value)612 H5P__ocpy_merge_comm_dt_list_close(const char H5_ATTR_UNUSED *name, size_t H5_ATTR_UNUSED size, void *value)
613 {
614     FUNC_ENTER_STATIC_NOERR
615 
616     HDassert(value);
617 
618     /* Free the merge named dtype list */
619     H5P__free_merge_comm_dtype_list(*(H5O_copy_dtype_merge_list_t **)value);
620 
621     FUNC_LEAVE_NOAPI(SUCCEED)
622 } /* end H5P__ocpy_merge_comm_dt_list_close() */
623 
624 /*-------------------------------------------------------------------------
625  * Function:    H5Pset_copy_object
626  *
627  * Purpose:     Set properties when copying an object (group, dataset, and datatype)
628  *              from one location to another
629  *
630  * Usage:       H5Pset_copy_group(plist_id, cpy_option)
631  *              hid_t plist_id;			IN: Property list to copy object
632  *              unsigned cpy_option; 		IN: Options to copy object such as
633  *                  H5O_COPY_SHALLOW_HIERARCHY_FLAG    -- Copy only immediate members
634  *                  H5O_COPY_EXPAND_SOFT_LINK_FLAG     -- Expand soft links into new objects/
635  *                  H5O_COPY_EXPAND_EXT_LINK_FLAG      -- Expand external links into new objects
636  *                  H5O_COPY_EXPAND_REFERENCE_FLAG -- Copy objects that are pointed by references
637  *                  H5O_COPY_WITHOUT_ATTR_FLAG         -- Copy object without copying attributes
638  *
639  * Return:      Non-negative on success/Negative on failure
640  *
641  * Programmer:  Peter Cao
642  *              March 13, 2006
643  *-------------------------------------------------------------------------
644  */
645 herr_t
H5Pset_copy_object(hid_t plist_id,unsigned cpy_option)646 H5Pset_copy_object(hid_t plist_id, unsigned cpy_option)
647 {
648     H5P_genplist_t *plist;               /* Property list pointer */
649     herr_t          ret_value = SUCCEED; /* Return value */
650 
651     FUNC_ENTER_API(FAIL)
652     H5TRACE2("e", "iIu", plist_id, cpy_option);
653 
654     /* Check parameters */
655     if (cpy_option & ~H5O_COPY_ALL)
656         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown option specified")
657 
658     /* Get the plist structure */
659     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
660         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
661 
662     /* Set value */
663     if (H5P_set(plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0)
664         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set copy object flag")
665 
666 done:
667     FUNC_LEAVE_API(ret_value)
668 } /* end H5Pset_copy_object() */
669 
670 /*-------------------------------------------------------------------------
671  * Function:    H5Pget_copy_object
672  *
673  * Purpose:     Returns the cpy_option, which is set for H5Ocopy(hid_t loc_id,
674  *              const char* name, ... ) for copying objects
675  *
676  * Return:      Non-negative on success/Negative on failure
677  *
678  * Programmer:  Peter Cao
679  *              March 13, 2006
680  *-------------------------------------------------------------------------
681  */
682 herr_t
H5Pget_copy_object(hid_t plist_id,unsigned * cpy_option)683 H5Pget_copy_object(hid_t plist_id, unsigned *cpy_option /*out*/)
684 {
685     H5P_genplist_t *plist;               /* Property list pointer */
686     herr_t          ret_value = SUCCEED; /* return value */
687 
688     FUNC_ENTER_API(FAIL)
689     H5TRACE2("e", "ix", plist_id, cpy_option);
690 
691     /* Get the plist structure */
692     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
693         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
694 
695     /* Get values */
696     if (cpy_option)
697         if (H5P_get(plist, H5O_CPY_OPTION_NAME, cpy_option) < 0)
698             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag")
699 
700 done:
701     FUNC_LEAVE_API(ret_value)
702 } /* end H5Pget_copy_object() */
703 
704 /*-------------------------------------------------------------------------
705  * Function:    H5Padd_merge_committed_dtype_path
706  *
707  * Purpose:     Adds path to the list of paths to search first in the
708  *              target file when merging committed datatypes during H5Ocopy
709  *              (i.e. when using the H5O_COPY_MERGE_COMMITTED_DTYPE_FLAG flag
710  *              as set by H5Pset_copy_object).  If the source named
711  *              dataype is not found in the list of paths created by this
712  *              function, the entire file will be searched.
713  *
714  * Usage:       H5Padd_merge_committed_dtype_path(plist_id, path)
715  *              hid_t plist_id;                 IN: Property list to copy object
716  *              const char *path;               IN: Path to add to list
717  *
718  * Return:      Non-negative on success/Negative on failure
719  *
720  * Programmer:  Neil Fortner
721  *              October 27, 2011
722  *-------------------------------------------------------------------------
723  */
724 herr_t
H5Padd_merge_committed_dtype_path(hid_t plist_id,const char * path)725 H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path)
726 {
727     H5P_genplist_t *             plist;               /* Property list pointer */
728     H5O_copy_dtype_merge_list_t *old_list;            /* Merge committed dtype list currently present */
729     H5O_copy_dtype_merge_list_t *new_obj   = NULL;    /* New object to add to list */
730     herr_t                       ret_value = SUCCEED; /* Return value */
731 
732     FUNC_ENTER_API(FAIL)
733     H5TRACE2("e", "i*s", plist_id, path);
734 
735     /* Check parameters */
736     if (!path)
737         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no path specified")
738     if (path[0] == '\0')
739         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "path is empty string")
740 
741     /* Get the plist structure */
742     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
743         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
744 
745     /* Get dtype list */
746     if (H5P_peek(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &old_list) < 0)
747         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge named dtype list")
748 
749     /* Add the new path to the list */
750     if (NULL == (new_obj = H5FL_CALLOC(H5O_copy_dtype_merge_list_t)))
751         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
752     if (NULL == (new_obj->path = H5MM_strdup(path)))
753         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
754     new_obj->next = old_list;
755 
756     /* Update the list stored in the property list */
757     if (H5P_poke(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &new_obj) < 0)
758         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge named dtype list")
759 
760 done:
761     if (ret_value < 0)
762         if (new_obj) {
763             new_obj->path = (char *)H5MM_xfree(new_obj->path);
764             new_obj       = H5FL_FREE(H5O_copy_dtype_merge_list_t, new_obj);
765         } /* end if */
766 
767     FUNC_LEAVE_API(ret_value)
768 } /* end H5Padd_merge_committed_dtype_path() */
769 
770 /*-------------------------------------------------------------------------
771  * Function:    H5Pfree_merge_committed_dtype_paths
772  *
773  * Purpose:     Frees and clears the list of paths created by
774  *              H5Padd_merge_committed_dtype_path.  A new list may then be
775  *              created by calling H5Padd_merge_committed_dtype_path again.
776  *
777  * Usage:       H5Pfree_merge_committed_dtype_paths(plist_id)
778  *              hid_t plist_id;                 IN: Property list to copy object
779  *
780  * Return:      Non-negative on success/Negative on failure
781  *
782  * Programmer:  Neil Fortner
783  *              October 27, 2011
784  *-------------------------------------------------------------------------
785  */
786 herr_t
H5Pfree_merge_committed_dtype_paths(hid_t plist_id)787 H5Pfree_merge_committed_dtype_paths(hid_t plist_id)
788 {
789     H5P_genplist_t *             plist;               /* Property list pointer */
790     H5O_copy_dtype_merge_list_t *dt_list;             /* Merge committed dtype list currently present */
791     herr_t                       ret_value = SUCCEED; /* Return value */
792 
793     FUNC_ENTER_API(FAIL)
794     H5TRACE1("e", "i", plist_id);
795 
796     /* Get the plist structure */
797     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
798         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
799 
800     /* Get dtype list */
801     if (H5P_peek(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
802         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get merge committed dtype list")
803 
804     /* Free dtype list */
805     dt_list = H5P__free_merge_comm_dtype_list(dt_list);
806 
807     /* Update the list stored in the property list (to NULL) */
808     if (H5P_poke(plist, H5O_CPY_MERGE_COMM_DT_LIST_NAME, &dt_list) < 0)
809         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set merge committed dtype list")
810 
811 done:
812     FUNC_LEAVE_API(ret_value)
813 } /* end H5Pfree_merge_committed_dtype_paths() */
814 
815 /*-------------------------------------------------------------------------
816  * Function:    H5Pset_mcdt_search_cb
817  *
818  * Purpose:     Set the callback function when a matching committed datatype is not found
819  *		from the list of paths stored in the object copy property list.
820  * 		H5Ocopy will invoke this callback before searching all committed datatypes
821  *		at destination.
822  *
823  * Usage:       H5Pset_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t func, void *op_data)
824  *              hid_t plist_id;                 IN: Property list to copy object
825  *              H5O_mcdt_search_cb_t func;      IN: The callback function
826  *              void *op_data;      		IN: The user data
827  *
828  * Return:      Non-negative on success/Negative on failure
829  *
830  * Programmer:  Vailin Choi; November 28, 2011
831  *-------------------------------------------------------------------------
832  */
833 herr_t
H5Pset_mcdt_search_cb(hid_t plist_id,H5O_mcdt_search_cb_t func,void * op_data)834 H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, void *op_data)
835 {
836     H5P_genplist_t *   plist;               /* Property list pointer */
837     H5O_mcdt_cb_info_t cb_info;             /* Callback info struct */
838     herr_t             ret_value = SUCCEED; /* Return value */
839 
840     FUNC_ENTER_API(FAIL)
841     H5TRACE3("e", "ix*x", plist_id, func, op_data);
842 
843     /* Check if the callback function is NULL and the user data is non-NULL.
844      * This is almost certainly an error as the user data will not be used. */
845     if (!func && op_data)
846         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback is NULL while user data is not")
847 
848     /* Get the plist structure */
849     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
850         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
851 
852     /* Populate the callback info struct */
853     cb_info.func      = func;
854     cb_info.user_data = op_data;
855 
856     /* Set callback info */
857     if (H5P_set(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0)
858         HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set callback info")
859 
860 done:
861     FUNC_LEAVE_API(ret_value)
862 } /* end H5Pset_mcdt_search_cb() */
863 
864 /*-------------------------------------------------------------------------
865  * Function:    H5Pget_mcdt_search_cb
866  *
867  * Purpose:     Retrieves the callback function and user data from the specified
868  *		object copy property list.
869  *
870  * Usage:       H5Pget_mcdt_search_cb(plist_id, H5O_mcdt_search_cb_t *func, void **op_data)
871  *              hid_t plist_id;                 IN: Property list to copy object
872  *		H5O_mcdt_search_cb_t *func;	OUT: The callback function
873  *		void **op_data;			OUT: The user data
874  *
875  * Return:      Non-negative on success/Negative on failure
876  *
877  * Programmer:  Vailin Choi; November 29, 2011
878  *
879  *-------------------------------------------------------------------------
880  */
881 herr_t
H5Pget_mcdt_search_cb(hid_t plist_id,H5O_mcdt_search_cb_t * func,void ** op_data)882 H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data)
883 {
884     H5P_genplist_t *   plist;               /* Property list pointer */
885     H5O_mcdt_cb_info_t cb_info;             /* Callback info struct */
886     herr_t             ret_value = SUCCEED; /* Return value */
887 
888     FUNC_ENTER_API(FAIL)
889     H5TRACE3("e", "i*x**x", plist_id, func, op_data);
890 
891     /* Get the plist structure */
892     if (NULL == (plist = H5P_object_verify(plist_id, H5P_OBJECT_COPY)))
893         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
894 
895     /* Get callback info */
896     if (H5P_get(plist, H5O_CPY_MCDT_SEARCH_CB_NAME, &cb_info) < 0)
897         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get callback info")
898 
899     if (func)
900         *func = cb_info.func;
901 
902     if (op_data)
903         *op_data = cb_info.user_data;
904 
905 done:
906     FUNC_LEAVE_API(ret_value)
907 } /* end H5Pget_mcdt_search_cb() */
908