From 7e5d420349ddab3b5e8b8e35293433d5b452a977 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 8 Oct 2002 09:08:10 -0500 Subject: [svn-r5963] Purpose: New internal feature. Description: Need some way to determine the "full path" for a generic property class, i.e. where is this class in the class hierarchy, in relation to its parent class, etc. Solution: Added an internal function "H5P_get_class_path" and a testing function "H5Pget_class_path_test" that builds the full path of a generic property class back to the top of its class hierarchy. This implementation uses '/' characters to delimit the components of the class path, but no special cases are currently supported for having a '/' character as part of the actual class name. Should this become an issue, code to support (and test) it will need to be added. Platforms tested: FreeBSD 4.6 (sleipnir) (not major enough to justify triple-test) --- src/H5P.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/H5Pprivate.h | 1 + src/H5Ppublic.h | 3 ++ test/tgenprop.c | 71 +++++++++++++++++++++++++++++++- 4 files changed, 188 insertions(+), 9 deletions(-) diff --git a/src/H5P.c b/src/H5P.c index 8713b4e..964d627 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -196,7 +196,7 @@ H5P_init_interface(void) /* Allocate the root class */ assert(H5P_CLS_NO_CLASS_g==(-1)); - if (NULL==(root_class = H5P_create_class (NULL,"none",H5P_NO_CLASS_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL))) + if (NULL==(root_class = H5P_create_class (NULL,"root",H5P_NO_CLASS_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the root class */ @@ -618,7 +618,7 @@ H5P_dup_prop(H5P_genprop_t *oprop) HDmemcpy(prop,oprop,sizeof(H5P_genprop_t)); /* Duplicate name */ - prop->name = HDstrdup(oprop->name); + prop->name = H5MM_xstrdup(oprop->name); /* Duplicate current value, if it exists */ if(oprop->value!=NULL) { @@ -710,7 +710,7 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value, /* Set the property initial values */ prop->xor_val = H5P_xor_name(name); /* Generate the XOR'd value for the name */ - prop->name = HDstrdup(name); /* Duplicate name */ + prop->name = H5MM_xstrdup(name); /* Duplicate name */ prop->size=size; /* Duplicate value, if it exists */ @@ -1146,7 +1146,7 @@ H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned hashsize, /* Set class state */ pclass->parent = par_class; - pclass->name = HDstrdup(name); + pclass->name = H5MM_xstrdup(name); pclass->nprops = 0; /* Classes are created without properties initially */ pclass->hashsize = hashsize; pclass->plists = 0; /* No properties lists of this class yet */ @@ -4612,7 +4612,7 @@ done: Internal routine to query the name of a generic property list class USAGE char *H5P_get_class_name(pclass) - H5P_genclass_t *pclass; IN: Property list to check + H5P_genclass_t *pclass; IN: Property list class to check RETURNS Success: Pointer to a malloc'ed string containing the class name Failure: NULL @@ -4633,8 +4633,8 @@ char *H5P_get_class_name(H5P_genclass_t *pclass) assert(pclass); - /* Get property size */ - ret_value=HDstrdup(pclass->name); + /* Get class name */ + ret_value=H5MM_xstrdup(pclass->name); done: FUNC_LEAVE (ret_value); @@ -4683,6 +4683,114 @@ done: /*-------------------------------------------------------------------------- NAME + H5P_get_class_path + PURPOSE + Internal routine to query the full path of a generic property list class + USAGE + char *H5P_get_class_name(pclass) + H5P_genclass_t *pclass; IN: Property list class to check + RETURNS + Success: Pointer to a malloc'ed string containing the full path of class + Failure: NULL + DESCRIPTION + This routine retrieves the full path name of a generic property list + class, starting with the root of the class hierarchy. + The pointer to the name must be free'd by the user for successful calls. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +char *H5P_get_class_path(H5P_genclass_t *pclass) +{ + char *par_path; /* Parent class's full path */ + size_t par_path_len;/* Parent class's full path's length */ + size_t my_path_len; /* This class's name's length */ + char *ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5P_get_class_path, NULL); + + assert(pclass); + + /* Recursively build the full path */ + if(pclass->parent!=NULL) { + /* Get the parent class's path */ + par_path=H5P_get_class_path(pclass->parent); + if(par_path!=NULL) { + /* Get the string lengths we need to allocate space */ + par_path_len=HDstrlen(par_path); + my_path_len=HDstrlen(pclass->name); + + /* Allocate enough space for the parent class's path, plus the '/' + * separator, this class's name and the string terminator + */ + if(NULL==(ret_value=H5MM_malloc(par_path_len+1+my_path_len+1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for class name"); + + /* Build the full path for this class */ + HDstrcpy(ret_value,par_path); + HDstrcat(ret_value,"/"); + HDstrcat(ret_value,pclass->name); + + /* Free the parent class's path */ + H5MM_xfree(par_path); + } /* end if */ + else + ret_value=H5MM_xstrdup(pclass->name); + } /* end if */ + else + ret_value=H5MM_xstrdup(pclass->name); + +done: + FUNC_LEAVE (ret_value); +} /* H5P_get_class_path() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Pget_class_path + PURPOSE + Routine to query the full path of a generic property list class + USAGE + char *H5Pget_class_name(pclass_id) + hid_t pclass_id; IN: Property class to query + RETURNS + Success: Pointer to a malloc'ed string containing the full path of class + Failure: NULL + DESCRIPTION + This routine retrieves the full path name of a generic property list + class, starting with the root of the class hierarchy. + The pointer to the name must be free'd by the user for successful calls. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING H5P_get_class_path() + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +char *H5Pget_class_path_test(hid_t pclass_id) +{ + H5P_genclass_t *pclass; /* Property class to query */ + char *ret_value; /* return value */ + + FUNC_ENTER_API(H5Pget_class_path_test, NULL); + + /* Check arguments. */ + if (NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property class"); + + /* Get the property list class path */ + if ((ret_value=H5P_get_class_path(pclass))==NULL) + HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "unable to query full path of class"); + +done: + FUNC_LEAVE (ret_value); +} /* H5Pget_class_path_test() */ + + +/*-------------------------------------------------------------------------- + NAME H5P_get_class_parent PURPOSE Internal routine to query the parent class of a generic property class diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 156943c..b0de67a 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -40,6 +40,7 @@ H5_DLL herr_t H5P_insert(H5P_genplist_t *plist, const char *name, size_t size, H5_DLL herr_t H5P_remove(hid_t plist_id, H5P_genplist_t *plist, const char *name); H5_DLL htri_t H5P_exist_plist(H5P_genplist_t *plist, const char *name); H5_DLL char *H5P_get_class_name(H5P_genclass_t *pclass); +H5_DLL char *H5P_get_class_path(H5P_genclass_t *pclass); H5_DLL herr_t H5P_get_nprops_pclass(H5P_genclass_t *pclass, size_t *nprops); H5_DLL herr_t H5P_register(H5P_genclass_t *pclass, const char *name, size_t size, void *def_value, H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 07cbec2..d2ab774 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -115,6 +115,9 @@ H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data); H5_DLL char *H5Pget_class_name(hid_t pclass_id); +#ifdef H5P_TESTING +H5_DLL char *H5Pget_class_path_test(hid_t pclass_id); +#endif /* H5P_TESTING */ H5_DLL hid_t H5Pcreate(hid_t cls_id); H5_DLL herr_t H5Pregister(hid_t cls_id, const char *name, size_t size, void *def_value, H5P_prp_create_func_t prp_create, diff --git a/test/tgenprop.c b/test/tgenprop.c index 93cc3ff..a12b1e9 100644 --- a/test/tgenprop.c +++ b/test/tgenprop.c @@ -20,17 +20,22 @@ * *************************************************************/ +/* Define this macro to indicate that the testing APIs should be available */ +#define H5P_TESTING + #include "testhdf5.h" #include "hdf5.h" -#include "H5Dprivate.h" /* For Datset creation property list names */ +#include "H5Dprivate.h" /* For Dataset creation property list names */ #define FILENAME "tgenprop.h5" /* Property definitions */ #define CLASS1_NAME "Class 1" +#define CLASS1_PATH "root/Class 1" #define CLASS1_HASHSIZE 25 #define CLASS2_NAME "Class 2" +#define CLASS2_PATH "root/Class 1/Class 2" #define CLASS2_HASHSIZE 25 /* Property definitions */ @@ -1371,7 +1376,7 @@ test_genprop_class_addprop(void) /**************************************************************** ** -** test_genprop_list_equal(): Test basic generic property list code. +** test_genprop_equal(): Test basic generic property list code. ** More tests for H5Pequal() ** ****************************************************************/ @@ -1419,6 +1424,67 @@ test_genprop_equal(void) /**************************************************************** ** +** test_genprop_path(): Test basic generic property list code. +** Tests for class paths +** +****************************************************************/ +static void +test_genprop_path(void) +{ + hid_t cid1; /* Generic Property class ID */ + hid_t cid2; /* Generic Property class ID */ + char *path; /* Class path */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Generic Property List Class Path Functionality\n")); + + /* Create a new generic class, derived from the root of the class hierarchy */ + cid1 = H5Pcreate_class(H5P_NO_CLASS,CLASS1_NAME,CLASS1_HASHSIZE,NULL,NULL,NULL,NULL,NULL,NULL); + CHECK_I(cid1, "H5Pcreate_class"); + + /* Insert first property into class (with no callbacks) */ + ret = H5Pregister(cid1,PROP1_NAME,PROP1_SIZE,PROP1_DEF_VALUE,NULL,NULL,NULL,NULL,NULL,NULL); + CHECK_I(ret, "H5Pregister"); + + /* Get full path for first class */ + path=H5Pget_class_path_test(cid1); + CHECK_PTR(path, "H5Pget_class_path_test"); + if(HDstrcmp(path,CLASS1_PATH)!=0) { + num_errs++; + printf("Class names don't match!, path=%s, CLASS1_PATH=%s\n",path,CLASS1_PATH); + } /* end if */ + free(path); + + /* Create another new generic class, derived from first class */ + cid2 = H5Pcreate_class(cid1,CLASS2_NAME,CLASS2_HASHSIZE,NULL,NULL,NULL,NULL,NULL,NULL); + CHECK_I(cid2, "H5Pcreate_class"); + + /* Insert second property into class (with no callbacks) */ + ret = H5Pregister(cid2,PROP2_NAME,PROP2_SIZE,PROP2_DEF_VALUE,NULL,NULL,NULL,NULL,NULL,NULL); + CHECK_I(ret, "H5Pregister"); + + /* Get full path for second class */ + path=H5Pget_class_path_test(cid2); + CHECK_PTR(path, "H5Pget_class_path_test"); + if(HDstrcmp(path,CLASS2_PATH)!=0) { + num_errs++; + printf("Class names don't match!, path=%s, CLASS2_PATH=%s\n",path,CLASS2_PATH); + } /* end if */ + free(path); + + /* Close class */ + ret = H5Pclose_class(cid1); + CHECK_I(ret, "H5Pclose_class"); + + /* Close class */ + ret = H5Pclose_class(cid2); + CHECK_I(ret, "H5Pclose_class"); + +} /* ent test_genprop_path() */ + +/**************************************************************** +** ** test_genprop(): Main generic property testing routine. ** ****************************************************************/ @@ -1443,6 +1509,7 @@ test_genprop(void) test_genprop_class_addprop(); /* Test adding properties to HDF5 property class */ test_genprop_equal(); /* Tests for more H5Pequal verification */ + test_genprop_path(); /* Tests for class path verification */ } /* test_genprop() */ -- cgit v0.12