From 847be78dbec1116c5b9be6207dba5253b75da323 Mon Sep 17 00:00:00 2001 From: Dana Robinson Date: Mon, 5 Apr 2021 20:40:06 -0700 Subject: Brings H5RS changes from develop --- MANIFEST | 1 + src/H5Gname.c | 282 ++++++++++------------------- src/H5RS.c | 524 ++++++++++++++++++++++++++++++++++++++++++------------ src/H5RSmodule.h | 32 ++++ src/H5RSprivate.h | 6 +- test/trefstr.c | 246 +++++++++++++++++++++---- 6 files changed, 746 insertions(+), 345 deletions(-) create mode 100644 src/H5RSmodule.h diff --git a/MANIFEST b/MANIFEST index bc8ac15..12ffa30 100644 --- a/MANIFEST +++ b/MANIFEST @@ -949,6 +949,7 @@ ./src/H5UC.c ./src/H5UCprivate.h ./src/H5RS.c +./src/H5RSmodule.h ./src/H5RSprivate.h ./src/H5S.c ./src/H5Sall.c diff --git a/src/H5Gname.c b/src/H5Gname.c index 8020d86..fd63cbb 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -77,22 +77,16 @@ typedef struct H5G_gnba_iter_t { /* Local Prototypes */ /********************/ -static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r); -static H5RS_str_t *H5G_build_fullpath(const char *prefix, const char *name); -#ifdef NOT_YET -static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r); -#endif /* NOT_YET */ -static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, - const char *dst_path); -static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key); +static htri_t H5G__common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r); +static H5RS_str_t *H5G__build_fullpath(const char *prefix, const char *name); +static herr_t H5G__name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, + const char *dst_path); +static int H5G__name_replace_cb(void *obj_ptr, hid_t obj_id, void *key); /*********************/ /* Package Variables */ /*********************/ -/* Declare extern the PQ free list for the wrapped strings */ -H5FL_BLK_EXTERN(str_buf); - /*****************************/ /* Library Private Variables */ /*****************************/ @@ -197,7 +191,7 @@ done: } /* end H5G_normalize() */ /*------------------------------------------------------------------------- - * Function: H5G_common_path + * Function: H5G__common_path * * Purpose: Determine if one path is a valid prefix of another path * @@ -211,14 +205,14 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) +H5G__common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) { const char *fullpath; /* Pointer to actual fullpath string */ const char *prefix; /* Pointer to actual prefix string */ size_t nchars1, nchars2; /* Number of characters in components */ htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Get component of each name */ fullpath = H5RS_get_str(fullpath_r); @@ -259,10 +253,10 @@ H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_common_path() */ +} /* end H5G__common_path() */ /*------------------------------------------------------------------------- - * Function: H5G_build_fullpath + * Function: H5G__build_fullpath * * Purpose: Build a full path from a prefix & base pair of strings * @@ -275,51 +269,26 @@ done: *------------------------------------------------------------------------- */ static H5RS_str_t * -H5G_build_fullpath(const char *prefix, const char *name) +H5G__build_fullpath(const char *prefix, const char *name) { - char * full_path; /* Full user path built */ - size_t orig_path_len; /* Original length of the path */ - size_t path_len; /* Length of the path */ - size_t name_len; /* Length of the name */ - unsigned need_sep; /* Flag to indicate if separator is needed */ H5RS_str_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Sanity check */ HDassert(prefix); HDassert(name); - /* Get the length of the prefix */ - orig_path_len = path_len = HDstrlen(prefix); - - /* Determine if there is a trailing separator in the name */ - if (prefix[path_len - 1] == '/') - need_sep = 0; - else - need_sep = 1; - - /* Add in the length needed for the '/' separator and the relative path */ - name_len = HDstrlen(name); - path_len += name_len + need_sep; - - /* Allocate space for the path */ - if (NULL == (full_path = (char *)H5FL_BLK_MALLOC(str_buf, path_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Build full path */ - HDstrncpy(full_path, prefix, orig_path_len + 1); - if (need_sep) - HDstrncat(full_path, "/", (size_t)1); - HDstrncat(full_path, name, name_len); - - /* Create reference counted string for path */ - if (NULL == (ret_value = H5RS_own(full_path))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + /* Create full path */ + if (NULL == (ret_value = H5RS_create(prefix))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, NULL, "can't create ref-counted string") + if (prefix[HDstrlen(prefix) - 1] != '/') + H5RS_aputc(ret_value, '/'); /* Add separator, if the prefix doesn't end in one */ + H5RS_acat(ret_value, name); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_build_fullpath() */ +} /* end H5G__build_fullpath() */ /*------------------------------------------------------------------------- * Function: H5G_build_fullpath_refstr_str @@ -350,49 +319,11 @@ H5G_build_fullpath_refstr_str(H5RS_str_t *prefix_r, const char *name) HDassert(prefix); /* Create reference counted string for path */ - ret_value = H5G_build_fullpath(prefix, name); + ret_value = H5G__build_fullpath(prefix, name); FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_build_fullpath_refstr_str() */ -#ifdef NOT_YET - -/*------------------------------------------------------------------------- - * Function: H5G_name_build_refstr_refstr - * - * Purpose: Build a full path from a prefix & base pair of reference counted - * strings - * - * Return: Pointer to reference counted string on success, NULL on error - * - * Programmer: Quincey Koziol - * - * Date: August 19, 2005 - * - *------------------------------------------------------------------------- - */ -static H5RS_str_t * -H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r) -{ - const char *prefix; /* Pointer to raw string of prefix */ - const char *name; /* Pointer to raw string of name */ - H5RS_str_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - /* Get the pointer to the prefix */ - prefix = H5RS_get_str(prefix_r); - - /* Get the pointer to the raw src user path */ - name = H5RS_get_str(name_r); - - /* Create reference counted string for path */ - ret_value = H5G_build_fullpath(prefix, name); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_build_fullpath_refstr_refstr() */ -#endif /* NOT_YET */ - /*------------------------------------------------------------------------- * Function: H5G__name_init * @@ -643,7 +574,7 @@ H5G_name_free(H5G_name_t *name) } /* end H5G_name_free() */ /*------------------------------------------------------------------------- - * Function: H5G_name_move_path + * Function: H5G__name_move_path * * Purpose: Update a user or canonical path after an object moves * @@ -656,15 +587,15 @@ H5G_name_free(H5G_name_t *name) *------------------------------------------------------------------------- */ static herr_t -H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, - const char *dst_path) +H5G__name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path, + const char *dst_path) { const char *path; /* Path to update */ size_t path_len; /* Length of path */ size_t full_suffix_len; /* Length of full suffix */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check arguments */ HDassert(path_r_ptr && *path_r_ptr); @@ -681,27 +612,23 @@ H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char path_len = HDstrlen(path); if (full_suffix_len < path_len) { const char *dst_suffix; /* Destination suffix that changes */ - size_t dst_suffix_len; /* Length of destination suffix */ const char *src_suffix; /* Source suffix that changes */ size_t path_prefix_len; /* Length of path prefix */ const char *path_prefix2; /* 2nd prefix for path */ size_t path_prefix2_len; /* Length of 2nd path prefix */ - const char *common_prefix; /* Common prefix for src & dst paths */ size_t common_prefix_len; /* Length of common prefix */ - char * new_path; /* Pointer to new path */ - size_t new_path_len; /* Length of new path */ + H5RS_str_t *rs; /* Ref-counted string for new path */ - /* Compute path prefix before full suffix*/ + /* Compute path prefix before full suffix */ path_prefix_len = path_len - full_suffix_len; /* Determine the common prefix for src & dst paths */ - common_prefix = src_path; common_prefix_len = 0; /* Find first character that is different */ while (*(src_path + common_prefix_len) == *(dst_path + common_prefix_len)) common_prefix_len++; /* Back up to previous '/' */ - while (*(common_prefix + common_prefix_len) != '/') + while (*(src_path + common_prefix_len) != '/') common_prefix_len--; /* Include '/' */ common_prefix_len++; @@ -710,41 +637,36 @@ H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char src_suffix = src_path + (common_prefix_len - 1); /* Determine destination suffix */ - dst_suffix = dst_path + (common_prefix_len - 1); - dst_suffix_len = HDstrlen(dst_suffix); + dst_suffix = dst_path + (common_prefix_len - 1); - /* Compute path prefix before src suffix*/ + /* Compute path prefix before src suffix */ path_prefix2 = path; path_prefix2_len = path_prefix_len - HDstrlen(src_suffix); - /* Allocate space for the new path */ - new_path_len = path_prefix2_len + dst_suffix_len + full_suffix_len; - if (NULL == (new_path = (char *)H5FL_BLK_MALLOC(str_buf, new_path_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + /* Allocate new ref-counted string */ + if (NULL == (rs = H5RS_create(NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create ref-counted string") /* Create the new path */ - if (path_prefix2_len > 0) { - HDstrncpy(new_path, path_prefix2, path_prefix2_len + 1); - HDstrncpy(new_path + path_prefix2_len, dst_suffix, dst_suffix_len + 1); - } /* end if */ - else - HDstrncpy(new_path, dst_suffix, dst_suffix_len + 1); + if (path_prefix2_len > 0) + H5RS_ancat(rs, path_prefix2, path_prefix2_len); + H5RS_acat(rs, dst_suffix); if (full_suffix_len > 0) - HDstrncat(new_path, full_suffix, full_suffix_len); + H5RS_acat(rs, full_suffix); /* Release previous path */ H5RS_decr(*path_r_ptr); /* Take ownership of the new full path */ - *path_r_ptr = H5RS_own(new_path); + *path_r_ptr = rs; } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_name_move_path() */ +} /* end H5G__name_move_path() */ /*------------------------------------------------------------------------- - * Function: H5G_name_replace_cb + * Function: H5G__name_replace_cb * * Purpose: H5I_iterate callback function to replace group entry names * @@ -757,7 +679,7 @@ done: *------------------------------------------------------------------------- */ static int -H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) +H5G__name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) { const H5G_names_t *names = (const H5G_names_t *)key; /* Get operation's information */ H5O_loc_t * oloc; /* Object location for object that the ID refers to */ @@ -766,7 +688,7 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) hbool_t obj_in_child = FALSE; /* Flag to indicate that the object is in the child mount hier. */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC HDassert(obj_ptr); @@ -853,39 +775,30 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) case H5G_NAME_MOUNT: /* Check if object is in child mount hier. */ if (obj_in_child) { - const char *full_path; /* Full path of current object */ - const char *src_path; /* Full path of source object */ - size_t src_path_len; /* Length of source full path */ - char * new_full_path; /* New full path of object */ - size_t new_full_len; /* Length of new full path */ + const char *full_path; /* Full path of current object */ + const char *src_path; /* Full path of source object */ + H5RS_str_t *rs; /* Ref-counted string for new path */ /* Get pointers to paths of interest */ - full_path = H5RS_get_str(obj_path->full_path_r); - src_path = H5RS_get_str(names->src_full_path_r); - src_path_len = HDstrlen(src_path); - - /* Build new full path */ - - /* Allocate space for the new full path */ - new_full_len = src_path_len + HDstrlen(full_path); - if (NULL == (new_full_path = (char *)H5FL_BLK_MALLOC(str_buf, new_full_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + full_path = H5RS_get_str(obj_path->full_path_r); + src_path = H5RS_get_str(names->src_full_path_r); - /* Create the new full path */ - HDstrncpy(new_full_path, src_path, src_path_len + 1); - HDstrncat(new_full_path, full_path, new_full_len); + /* Create new full path */ + if (NULL == (rs = H5RS_create(src_path))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create ref-counted string") + H5RS_acat(rs, full_path); /* Release previous full path */ H5RS_decr(obj_path->full_path_r); /* Take ownership of the new full path */ - obj_path->full_path_r = H5RS_own(new_full_path); + obj_path->full_path_r = rs; } /* end if */ /* Object must be in parent mount file hier. */ else { /* Check if the source is along the entry's path */ /* (But not actually the entry itself) */ - if (H5G_common_path(obj_path->full_path_r, names->src_full_path_r) && + if (H5G__common_path(obj_path->full_path_r, names->src_full_path_r) && H5RS_cmp(obj_path->full_path_r, names->src_full_path_r)) { /* Hide the user path */ (obj_path->obj_hidden)++; @@ -899,36 +812,30 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) */ case H5G_NAME_UNMOUNT: if (obj_in_child) { - const char *full_path; /* Full path of current object */ - const char *full_suffix; /* Full path after source path */ - size_t full_suffix_len; /* Length of full path after source path */ - const char *src_path; /* Full path of source object */ - char * new_full_path; /* New full path of object */ + const char *full_path; /* Full path of current object */ + const char *full_suffix; /* Full path after source path */ + const char *src_path; /* Full path of source object */ + H5RS_str_t *rs; /* Ref-counted string for new path */ /* Get pointers to paths of interest */ full_path = H5RS_get_str(obj_path->full_path_r); src_path = H5RS_get_str(names->src_full_path_r); /* Construct full path suffix */ - full_suffix = full_path + HDstrlen(src_path); - full_suffix_len = HDstrlen(full_suffix); + full_suffix = full_path + HDstrlen(src_path); - /* Build new full path */ - - /* Create the new full path */ - if (NULL == (new_full_path = (char *)H5FL_BLK_MALLOC(str_buf, full_suffix_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDstrncpy(new_full_path, full_suffix, full_suffix_len + 1); + /* Create new full path suffix */ + if (NULL == (rs = H5RS_create(full_suffix))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create ref-counted string") /* Release previous full path */ H5RS_decr(obj_path->full_path_r); /* Take ownership of the new full path */ - obj_path->full_path_r = H5RS_own(new_full_path); + obj_path->full_path_r = rs; /* Check if the object's user path should be invalidated */ - if (obj_path->user_path_r && - HDstrlen(new_full_path) < (size_t)H5RS_len(obj_path->user_path_r)) { + if (obj_path->user_path_r && H5RS_len(rs) < H5RS_len(obj_path->user_path_r)) { /* Free user path */ H5RS_decr(obj_path->user_path_r); obj_path->user_path_r = NULL; @@ -936,7 +843,7 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) } /* end if */ else { /* Check if file being unmounted was hiding the object */ - if (H5G_common_path(obj_path->full_path_r, names->src_full_path_r) && + if (H5G__common_path(obj_path->full_path_r, names->src_full_path_r) && H5RS_cmp(obj_path->full_path_r, names->src_full_path_r)) { /* Un-hide the user path */ (obj_path->obj_hidden)--; @@ -950,7 +857,7 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) */ case H5G_NAME_DELETE: /* Check if the location being unlinked is in the path for the current object */ - if (H5G_common_path(obj_path->full_path_r, names->src_full_path_r)) { + if (H5G__common_path(obj_path->full_path_r, names->src_full_path_r)) { /* Free paths for object */ H5G_name_free(obj_path); } /* end if */ @@ -962,54 +869,43 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) */ case H5G_NAME_MOVE: /* Link move case, check for relative names case */ /* Check if the src object moved is in the current object's path */ - if (H5G_common_path(obj_path->full_path_r, names->src_full_path_r)) { - const char *full_path; /* Full path of current object */ - const char *full_suffix; /* Suffix of full path, after src_path */ - size_t full_suffix_len; /* Length of suffix of full path after src_path*/ - char * new_full_path; /* New full path of object */ - size_t new_full_len; /* Length of new full path */ - const char *src_path; /* Full path of source object */ - const char *dst_path; /* Full path of destination object */ - size_t dst_path_len; /* Length of destination's full path */ + if (H5G__common_path(obj_path->full_path_r, names->src_full_path_r)) { + const char *full_path; /* Full path of current object */ + const char *full_suffix; /* Suffix of full path, after src_path */ + const char *src_path; /* Full path of source object */ + const char *dst_path; /* Full path of destination object */ + H5RS_str_t *rs; /* Ref-counted string for new path */ /* Sanity check */ HDassert(names->dst_full_path_r); /* Get pointers to paths of interest */ - full_path = H5RS_get_str(obj_path->full_path_r); - src_path = H5RS_get_str(names->src_full_path_r); - dst_path = H5RS_get_str(names->dst_full_path_r); - dst_path_len = HDstrlen(dst_path); + full_path = H5RS_get_str(obj_path->full_path_r); + src_path = H5RS_get_str(names->src_full_path_r); + dst_path = H5RS_get_str(names->dst_full_path_r); /* Make certain that the source and destination names are full (not relative) paths */ HDassert(*src_path == '/'); HDassert(*dst_path == '/'); /* Get pointer to "full suffix" */ - full_suffix = full_path + HDstrlen(src_path); - full_suffix_len = HDstrlen(full_suffix); + full_suffix = full_path + HDstrlen(src_path); /* Update the user path, if one exists */ if (obj_path->user_path_r) - if (H5G_name_move_path(&(obj_path->user_path_r), full_suffix, src_path, dst_path) < 0) + if (H5G__name_move_path(&(obj_path->user_path_r), full_suffix, src_path, dst_path) < 0) HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build user path name") - /* Build new full path */ - - /* Allocate space for the new full path */ - new_full_len = dst_path_len + full_suffix_len; - if (NULL == (new_full_path = (char *)H5FL_BLK_MALLOC(str_buf, new_full_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Create the new full path */ - HDstrncpy(new_full_path, dst_path, dst_path_len + 1); - HDstrncat(new_full_path, full_suffix, full_suffix_len); + /* Create new full path */ + if (NULL == (rs = H5RS_create(dst_path))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create ref-counted string") + H5RS_acat(rs, full_suffix); /* Release previous full path */ H5RS_decr(obj_path->full_path_r); /* Take ownership of the new full path */ - obj_path->full_path_r = H5RS_own(new_full_path); + obj_path->full_path_r = rs; } /* end if */ break; @@ -1019,7 +915,7 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5G_name_replace_cb() */ +} /* end H5G__name_replace_cb() */ /*------------------------------------------------------------------------- * Function: H5G_name_replace @@ -1144,17 +1040,17 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file, H5RS /* Search through group IDs */ if (search_group) - if (H5I_iterate(H5I_GROUP, H5G_name_replace_cb, &names, FALSE) < 0) + if (H5I_iterate(H5I_GROUP, H5G__name_replace_cb, &names, FALSE) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over groups") /* Search through dataset IDs */ if (search_dataset) - if (H5I_iterate(H5I_DATASET, H5G_name_replace_cb, &names, FALSE) < 0) + if (H5I_iterate(H5I_DATASET, H5G__name_replace_cb, &names, FALSE) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datasets") /* Search through datatype IDs */ if (search_datatype) - if (H5I_iterate(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE) < 0) + if (H5I_iterate(H5I_DATATYPE, H5G__name_replace_cb, &names, FALSE) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datatypes") } /* end if */ } /* end if */ @@ -1164,7 +1060,7 @@ done: } /* end H5G_name_replace() */ /*------------------------------------------------------------------------- - * Function: H5G_get_name_by_addr_cb + * Function: H5G__get_name_by_addr_cb * * Purpose: Callback for retrieving object's name by address * @@ -1178,7 +1074,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info2_t *linfo, void *_udata) +H5G__get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info2_t *linfo, void *_udata) { H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */ H5G_loc_t obj_loc; /* Location of object */ @@ -1187,7 +1083,7 @@ H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info2_t *linfo, v hbool_t obj_found = FALSE; /* Object at 'path' found */ herr_t ret_value = H5_ITER_CONT; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Sanity check */ HDassert(path); @@ -1237,7 +1133,7 @@ done: HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_get_name_by_addr_cb() */ +} /* end H5G__get_name_by_addr_cb() */ /*------------------------------------------------------------------------- * Function: H5G_get_name_by_addr @@ -1285,7 +1181,7 @@ H5G_get_name_by_addr(H5F_t *f, const H5O_loc_t *loc, char *name, size_t size) udata.path = NULL; /* Visit all the links in the file */ - if ((status = H5G_visit(&root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G_get_name_by_addr_cb, + if ((status = H5G_visit(&root_loc, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G__get_name_by_addr_cb, &udata)) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADITER, (-1), "group traversal failed while looking for object name") else if (status > 0) diff --git a/src/H5RS.c b/src/H5RS.c index 77fa414..96d55e7 100644 --- a/src/H5RS.c +++ b/src/H5RS.c @@ -15,37 +15,89 @@ * Reference counted string algorithms. * * These are used for various internal strings which get copied multiple times. + * They also efficiently handle dynamically allocations and appends. * */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free lists */ -#include "H5RSprivate.h" /* Reference-counted strings */ +/****************/ +/* Module Setup */ +/****************/ + +#include "H5RSmodule.h" /* This source code file is part of the H5RS module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5RSprivate.h" /* Reference-counted strings */ + +/****************/ +/* Local Macros */ +/****************/ + +/* Initial buffer size to allocate */ +#define H5RS_ALLOC_SIZE 256 + +/******************/ +/* Local Typedefs */ +/******************/ /* Private typedefs & structs */ struct H5RS_str_t { char * s; /* String to be reference counted */ - unsigned wrapped; /* Indicates that the string to be ref-counted is not copied */ + char * end; /* Pointer to terminating NUL character at the end of the string */ + size_t len; /* Current length of the string */ + size_t max; /* Size of allocated buffer */ + hbool_t wrapped; /* Indicates that the string to be ref-counted is not copied */ unsigned n; /* Reference count of number of pointers sharing string */ }; +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5RS__xstrdup(H5RS_str_t *rs, const char *s); +static herr_t H5RS__prepare_for_append(H5RS_str_t *rs); +static herr_t H5RS__resize_for_append(H5RS_str_t *rs, size_t len); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Package initialization variable */ +hbool_t H5_PKG_INIT_VAR = FALSE; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + /* Declare a free list to manage the H5RS_str_t struct */ H5FL_DEFINE_STATIC(H5RS_str_t); /* Declare the PQ free list for the wrapped strings */ -H5FL_BLK_DEFINE(str_buf); +H5FL_BLK_DEFINE_STATIC(str_buf); /*-------------------------------------------------------------------------- NAME - H5RS_xstrdup + H5RS__xstrdup PURPOSE Duplicate the string being reference counted USAGE - char *H5RS_xstrdup(s) + herr_t H5RS__xstrdup(rs, s) + H5RS_str_t *rs; IN/OUT: Ref-counted string to hold duplicated string const char *s; IN: String to duplicate RETURNS - Returns a pointer to a new string on success, NULL on failure. + Non-negative on success/Negative on failure DESCRIPTION Duplicate a string buffer being reference counted. Use this instead of [H5MM_][x]strdup, in order to use the free-list memory routines. @@ -54,25 +106,145 @@ H5FL_BLK_DEFINE(str_buf); EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static char * -H5RS_xstrdup(const char *s) +static herr_t +H5RS__xstrdup(H5RS_str_t *rs, const char *s) { - char *ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(rs); if (s) { - size_t len = HDstrlen(s) + 1; + size_t len = HDstrlen(s); + + /* Determine size of buffer to allocate */ + rs->max = H5RS_ALLOC_SIZE; + while ((len + 1) > rs->max) + rs->max *= 2; + + /* Allocate the underlying string */ + if (NULL == (rs->s = (char *)H5FL_BLK_MALLOC(str_buf, rs->max))) + HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, FAIL, "memory allocation failed") + if (len) + HDmemcpy(rs->s, s, len); + rs->end = rs->s + len; + *rs->end = '\0'; + rs->len = len; + } /* end if */ + else { + /* Free previous string, if one */ + if (rs->s) { + H5FL_BLK_FREE(str_buf, rs->s); + rs->s = rs->end = NULL; + rs->max = rs->len = 0; + } /* end if */ + else { + /* Sanity checks */ + HDassert(NULL == rs->end); + HDassert(0 == rs->max); + HDassert(0 == rs->len); + } /* end else */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS__xstrdup() */ - ret_value = (char *)H5FL_BLK_MALLOC(str_buf, len); - HDassert(ret_value); - HDstrncpy(ret_value, s, len); +/*-------------------------------------------------------------------------- + NAME + H5RS__prepare_for_append + PURPOSE + Prepare a ref-counted string for an append + USAGE + herr_t H5RS__prepare_for_append(rs) + H5RS_str_t *rs; IN/OUT: Ref-counted string to hold duplicated string + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Allocate space for a string, or duplicate a wrapped string, in preparation + for appending another string. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5RS__prepare_for_append(H5RS_str_t *rs) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(rs); + + if (NULL == rs->s) { + rs->max = H5RS_ALLOC_SIZE; + if (NULL == (rs->s = (char *)H5FL_BLK_MALLOC(str_buf, rs->max))) + HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, FAIL, "memory allocation failed") + rs->end = rs->s; + *rs->s = '\0'; + rs->len = 0; } /* end if */ - else - ret_value = NULL; + else { + /* If the ref-counted string started life as a wrapper around an + * existing string, duplicate the string now, so we can modify it. + */ + if (rs->wrapped) { + if (H5RS__xstrdup(rs, rs->s) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTCOPY, FAIL, "can't copy string") + rs->wrapped = FALSE; + } /* end if */ + } /* end else */ +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5RS_xstrdup() */ +} /* end H5RS__prepare_for_append() */ + +/*-------------------------------------------------------------------------- + NAME + H5RS__resize_for_append + PURPOSE + Resize ref-counted string buffer to accommodate appending another string + USAGE + herr_t H5RS__resize_for_append(rs, len) + H5RS_str_t *rs; IN/OUT: Ref-counted string to hold duplicated string + size_t len; IN: Additional length to accommodate + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Resize a ref-counted string buffer to be large enough to accommodate + another string of a specified length. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5RS__resize_for_append(H5RS_str_t *rs, size_t len) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(rs); + + /* Check if buffer should be re-allocated */ + if (len >= (rs->max - rs->len)) { + /* Allocate a large enough buffer */ + while (len >= (rs->max - rs->len)) + rs->max *= 2; + if (NULL == (rs->s = (char *)H5FL_BLK_REALLOC(str_buf, rs->s, rs->max))) + HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, FAIL, "memory allocation failed") + rs->end = rs->s + rs->len; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS__resize() */ /*-------------------------------------------------------------------------- NAME @@ -96,18 +268,19 @@ H5RS_xstrdup(const char *s) H5RS_str_t * H5RS_create(const char *s) { - H5RS_str_t *ret_value; /* Return value */ + H5RS_str_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) /* Allocate ref-counted string structure */ - if (NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) - HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") + if (NULL == (ret_value = H5FL_CALLOC(H5RS_str_t))) + HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->s = H5RS_xstrdup(s); - ret_value->wrapped = 0; - ret_value->n = 1; + if (s) + if (H5RS__xstrdup(ret_value, s) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTCOPY, NULL, "can't copy string") + ret_value->n = 1; done: FUNC_LEAVE_NOAPI(ret_value) @@ -135,63 +308,233 @@ done: H5RS_str_t * H5RS_wrap(const char *s) { - H5RS_str_t *ret_value; /* Return value */ + H5RS_str_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) /* Allocate ref-counted string structure */ if (NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) - HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR(H5E_RS, H5E_CANTALLOC, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->s = (char *)s; - ret_value->wrapped = 1; + ret_value->s = (char *)s; + ret_value->len = HDstrlen(s); + ret_value->end = ret_value->s + ret_value->len; + + ret_value->wrapped = TRUE; + ret_value->max = 0; /* Wrapped, not allocated */ ret_value->n = 1; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_wrap() */ -/*-------------------------------------------------------------------------- - NAME - H5RS_own - PURPOSE - Transfer ownership of a regular string to a reference counted string - USAGE - H5RS_str_t *H5RS_own(s) - const char *s; IN: String to transfer ownership of +/*------------------------------------------------------------------------- + * Function: H5RS_asprintf_cat + * + * Purpose: This function appends formatted output to a ref-counted string, + * allocating the managed string if necessary. The formatting + * string is printf() compatible. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, September 18, 2020 + * + *------------------------------------------------------------------------- + */ +/* Disable warning for "format not a string literal" here -QAK */ +/* + * This pragma only needs to surround the sprintf() calls with + * format_templ in the code below, but early (4.4.7, at least) gcc only + * allows diagnostic pragmas to be toggled outside of functions. + */ +H5_GCC_DIAG_OFF("format-nonliteral") +H5_ATTR_FORMAT(printf, 2, 3) +herr_t +H5RS_asprintf_cat(H5RS_str_t *rs, const char *fmt, ...) +{ + va_list args1, args2; + size_t out_len; + herr_t ret_value = SUCCEED; /* Return value */ - RETURNS - Returns a pointer to a new ref-counted string on success, NULL on failure. - DESCRIPTION - Transfer ownership of a dynamically allocated string to a reference counted - string. The routine which passed in the string should not attempt to free - it, the reference counting string routines will do that when the reference - count drops to zero. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -H5RS_str_t * -H5RS_own(char *s) + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(rs); + HDassert(fmt); + + /* Prepare the [possibly wrapped or empty] ref-counted string for an append */ + if (H5RS__prepare_for_append(rs) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTINIT, FAIL, "can't initialize ref-counted string") + + /* Attempt to write formatted output into the managed string */ + HDva_start(args1, fmt); + HDva_copy(args2, args1); + while ((out_len = (size_t)HDvsnprintf(rs->end, (rs->max - rs->len), fmt, args1)) >= (rs->max - rs->len)) { + /* Allocate a large enough buffer */ + if (H5RS__resize_for_append(rs, out_len) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTRESIZE, FAIL, "can't resize ref-counted string buffer") + + /* Restart the va_list */ + HDva_end(args1); + HDva_copy(args1, args2); + } /* end while */ + + /* Increment the size & end of the string */ + rs->len += out_len; + rs->end += out_len; + + /* Finish access to varargs */ + HDva_end(args1); + HDva_end(args2); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS_asprintf_cat() */ +H5_GCC_DIAG_ON("format-nonliteral") + +/*------------------------------------------------------------------------- + * Function: H5RS_acat + * + * Purpose: This function appends a character string to a ref-counted string, + * allocating the managed string if necessary. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, September 18, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RS_acat(H5RS_str_t *rs, const char *s) { - H5RS_str_t *ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI(FAIL) - /* Allocate ref-counted string structure */ - if (NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) - HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") + /* Sanity checks */ + HDassert(rs); + HDassert(s); - /* Set the internal fields */ - ret_value->s = s; - ret_value->wrapped = 0; - ret_value->n = 1; + /* Concatenate the provided string on to the managed string */ + if (*s) { + size_t len = HDstrlen(s); + + /* Allocate the underlying string, if necessary */ + if (H5RS__prepare_for_append(rs) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTINIT, FAIL, "can't initialize ref-counted string") + + /* Increase the managed string's buffer size if necessary */ + if ((rs->len + len) >= rs->max) + if (H5RS__resize_for_append(rs, len) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTRESIZE, FAIL, "can't resize ref-counted string buffer") + + /* Append the string */ + HDmemcpy(rs->end, s, len); + rs->end += len; + *rs->end = '\0'; + rs->len += len; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5RS_own() */ +} /* end H5RS_acat() */ + +/*------------------------------------------------------------------------- + * Function: H5RS_ancat + * + * Purpose: This function appends at most 'n' characters from a string + * to a ref-counted string, allocating the managed string if + * necessary. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, September 18, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RS_ancat(H5RS_str_t *rs, const char *s, size_t n) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(rs); + HDassert(s); + + /* Concatenate the provided string on to the managed string */ + if (n && *s) { + size_t len = HDstrlen(s); + + /* Limit characters to copy to the minimum of 'n' and 'len' */ + n = MIN(len, n); + + /* Allocate the underlying string, if necessary */ + if (H5RS__prepare_for_append(rs) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTINIT, FAIL, "can't initialize ref-counted string") + + /* Increase the managed string's buffer size if necessary */ + if ((rs->len + n) >= rs->max) + if (H5RS__resize_for_append(rs, n) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTRESIZE, FAIL, "can't resize ref-counted string buffer") + + /* Append the string */ + HDmemcpy(rs->end, s, n); + rs->end += n; + *rs->end = '\0'; + rs->len += n; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS_ancat() */ + +/*------------------------------------------------------------------------- + * Function: H5RS_aputc + * + * Purpose: This function appends a character to a ref-counted string, + * allocating the managed string if necessary. + * + * Return: SUCCEED / FAIL + * + * Programmer: Quincey Koziol + * Friday, September 18, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RS_aputc(H5RS_str_t *rs, int c) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(rs); + HDassert(c); + + /* Allocate the underlying string, if necessary */ + if (H5RS__prepare_for_append(rs) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTINIT, FAIL, "can't initialize ref-counted string") + + /* Increase the managed string's buffer size if necessary */ + if ((rs->len + 1) >= rs->max) + if (H5RS__resize_for_append(rs, 1) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTRESIZE, FAIL, "can't resize ref-counted string buffer") + + /* Append the current character */ + *rs->end++ = (char)c; + rs->len++; + *rs->end = '\0'; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS_aputc() */ /*-------------------------------------------------------------------------- NAME @@ -252,7 +595,9 @@ H5RS_decr(H5RS_str_t *rs) herr_t H5RS_incr(H5RS_str_t *rs) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) /* Sanity check */ HDassert(rs); @@ -263,14 +608,16 @@ H5RS_incr(H5RS_str_t *rs) * scope appropriately. */ if (rs->wrapped) { - rs->s = H5RS_xstrdup(rs->s); - rs->wrapped = 0; + if (H5RS__xstrdup(rs, rs->s) < 0) + HGOTO_ERROR(H5E_RS, H5E_CANTCOPY, FAIL, "can't copy string") + rs->wrapped = FALSE; } /* end if */ /* Increment reference count for string */ rs->n++; - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_incr() */ /*-------------------------------------------------------------------------- @@ -307,53 +654,6 @@ H5RS_dup(H5RS_str_t *ret_value) /*-------------------------------------------------------------------------- NAME - H5RS_dup_str - PURPOSE - "Duplicate" a regular string into a ref-counted string - USAGE - H5RS_str_t H5RS_dup_str(s) - const char *s; IN: Regular string to duplicate - - RETURNS - Returns a pointer to ref-counted string on success, NULL on failure. - DESCRIPTION - Duplicate a regular string into a ref-counted string. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -H5RS_str_t * -H5RS_dup_str(const char *s) -{ - char * new_str; /* Duplicate of string */ - size_t path_len; /* Length of the path */ - H5RS_str_t *ret_value; - - FUNC_ENTER_NOAPI(NULL) - - /* Sanity check */ - HDassert(s); - - /* Get the length of the string */ - path_len = HDstrlen(s); - - /* Allocate space for the string */ - if (NULL == (new_str = (char *)H5FL_BLK_MALLOC(str_buf, path_len + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Copy name for full path */ - HDstrncpy(new_str, s, (path_len + 1)); - - /* Create reference counted string for path */ - ret_value = H5RS_own(new_str); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5RS_dup_str() */ - -/*-------------------------------------------------------------------------- - NAME H5RS_cmp PURPOSE Compare two ref-counted strings diff --git a/src/H5RSmodule.h b/src/H5RSmodule.h new file mode 100644 index 0000000..17977c7 --- /dev/null +++ b/src/H5RSmodule.h @@ -0,0 +1,32 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol + * Saturday, October 10, 2020 + * + * Purpose: This file contains declarations which define macros for the + * H5RS package. Including this header means that the source file + * is part of the H5RS package. + */ +#ifndef H5RSmodule_H +#define H5RSmodule_H + +/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error + * reporting macros. + */ +#define H5RS_MODULE +#define H5_MY_PKG H5RS +#define H5_MY_PKG_ERR H5E_RS +#define H5_MY_PKG_INIT NO + +#endif /* H5RSmodule_H */ diff --git a/src/H5RSprivate.h b/src/H5RSprivate.h index 32e1dc6..7d2b728 100644 --- a/src/H5RSprivate.h +++ b/src/H5RSprivate.h @@ -45,11 +45,13 @@ typedef struct H5RS_str_t H5RS_str_t; /********************/ H5_DLL H5RS_str_t *H5RS_create(const char *s); H5_DLL H5RS_str_t *H5RS_wrap(const char *s); -H5_DLL H5RS_str_t *H5RS_own(char *s); H5_DLL herr_t H5RS_decr(H5RS_str_t *rs); H5_DLL herr_t H5RS_incr(H5RS_str_t *rs); H5_DLL H5RS_str_t *H5RS_dup(H5RS_str_t *s); -H5_DLL H5RS_str_t *H5RS_dup_str(const char *s); +H5_DLL herr_t H5RS_asprintf_cat(H5RS_str_t *rs, const char *fmt, ...) H5_ATTR_FORMAT(printf, 2, 3); +H5_DLL herr_t H5RS_acat(H5RS_str_t *rs, const char *s); +H5_DLL herr_t H5RS_ancat(H5RS_str_t *rs, const char *s, size_t len); +H5_DLL herr_t H5RS_aputc(H5RS_str_t *rs, int c); H5_DLL int H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2); H5_DLL ssize_t H5RS_len(const H5RS_str_t *rs); H5_DLL char * H5RS_get_str(const H5RS_str_t *rs); diff --git a/test/trefstr.c b/test/trefstr.c index 049384f..a3f568a 100644 --- a/test/trefstr.c +++ b/test/trefstr.c @@ -265,7 +265,9 @@ test_refstr_wrap(void) /* Get pointer to raw string in ref-counted string */ s = H5RS_get_str(rs); CHECK_PTR(s, "H5RS_get_str"); - CHECK(s, buf, "wrapping"); + if (s == buf) + TestErrPrintf("%d: Should not have gotten the same pointer from reference-counted string!\n", + __LINE__); cmp = HDstrcmp(s, buf); if (cmp <= 0) TestErrPrintf("%d: string comparison incorrect!\n", __LINE__); @@ -280,60 +282,225 @@ test_refstr_wrap(void) /**************************************************************** ** -** test_refstr_own(): Test basic H5RS (ref-counted strings) code. -** Tests transferring ownership of dynamically allocated strings -** to ref-counted strings. +** test_refstr_asprintf_cat(): Test basic H5RS (ref-counted strings) code. +** Tests appending printf-formatted output to ref-counted strings. ** ****************************************************************/ static void -test_refstr_own(void) +test_refstr_asprintf_cat(void) { - H5RS_str_t *rs; /* Ref-counted string created */ - char * s; /* Pointer to string to transfer */ - const char *t; /* Temporary pointers to string */ - int cmp; /* Comparison value */ - herr_t ret; /* Generic return value */ + H5RS_str_t *rs; /* Ref-counted string created */ + const char *s; /* Pointer to raw string in ref-counted string */ + char buf[256]; /* Buffer to compare against */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ /* Output message about test being performed */ - MESSAGE(5, ("Testing Transferring Ref-Counted Strings\n")); + MESSAGE(5, ("Testing Printf-formatted Output to Ref-Counted Strings\n")); - /* Initialize buffer */ - s = (char *)H5FL_BLK_MALLOC(str_buf, HDstrlen("foo") + 1); - CHECK_PTR(s, "H5FL_BLK_MALLOC"); - HDstrcpy(s, "foo"); + /* Wrap ref-counted string around existing buffer */ + rs = H5RS_create(NULL); + CHECK_PTR(rs, "H5RS_create"); - /* Transfer ownership of dynamically allocated string to ref-counted string */ - rs = H5RS_own(s); - CHECK_PTR(rs, "H5RS_own"); + /* Print initial output to ref-counted string */ + ret = H5RS_asprintf_cat(rs, "%d-%s", (int)10, "foo"); + CHECK(ret, FAIL, "H5RS_asprintf_cat"); /* Get pointer to raw string in ref-counted string */ - t = H5RS_get_str(rs); - CHECK_PTR(t, "H5RS_get_str"); - CHECK_PTR_EQ(t, s, "transferring"); - cmp = HDstrcmp(s, t); + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDsprintf(buf, "%d-%s", (int)10, "foo"); + cmp = HDstrcmp(s, buf); VERIFY(cmp, 0, "HDstrcmp"); - /* Increment reference count (should NOT duplicate string) */ - ret = H5RS_incr(rs); - CHECK(ret, FAIL, "H5RS_incr"); + /* Append more output to ref-counted string */ + ret = H5RS_asprintf_cat(rs, "-%f", (double)20.0); + CHECK(ret, FAIL, "H5RS_asprintf_cat"); - /* Change the buffer initially wrapped */ - *s = 'F'; + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDsprintf(buf, "%d-%s-%f", (int)10, "foo", (double)20.0); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Decrement reference count for string */ + ret = H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); + +} /* end test_refstr_asprintf_cat() */ + +/**************************************************************** +** +** test_refstr_acat(): Test basic H5RS (ref-counted strings) code. +** Tests appending strings to ref-counted strings. +** +****************************************************************/ +static void +test_refstr_acat(void) +{ + H5RS_str_t *rs; /* Ref-counted string created */ + const char *s; /* Pointer to raw string in ref-counted string */ + char buf[256]; /* Buffer to compare against */ + char * large_str, *large_str2; /* Large strings to append */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Appending Strings to Ref-Counted Strings\n")); + + /* Wrap ref-counted string around existing buffer */ + rs = H5RS_create(NULL); + CHECK_PTR(rs, "H5RS_create"); + + /* Append first string to ref-counted string */ + ret = H5RS_acat(rs, "foo"); + CHECK(ret, FAIL, "H5RS_acat"); /* Get pointer to raw string in ref-counted string */ - t = H5RS_get_str(rs); - CHECK_PTR(t, "H5RS_get_str"); - CHECK_PTR_EQ(t, s, "transferring"); - cmp = HDstrcmp(t, s); + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDsprintf(buf, "%s", "foo"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Append another string to ref-counted string */ + ret = H5RS_acat(rs, "bar"); + CHECK(ret, FAIL, "H5RS_acat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDsprintf(buf, "%s", "foobar"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Append a large string to ref-counted string */ + large_str = HDmalloc(1024); + CHECK_PTR(large_str, "HDmalloc"); + HDmemset(large_str, 'a', 1024); + large_str[1023] = '\0'; + ret = H5RS_acat(rs, large_str); + CHECK(ret, FAIL, "H5RS_acat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDsprintf(buf, "%s", "foobar"); + large_str2 = HDmalloc(1024 + 6); + CHECK_PTR(large_str2, "HDmalloc"); + HDstrcpy(large_str2, "foobar"); + HDmemset(&large_str2[6], 'a', 1024); + large_str2[1029] = '\0'; + cmp = HDstrcmp(s, large_str2); VERIFY(cmp, 0, "HDstrcmp"); /* Decrement reference count for string */ ret = H5RS_decr(rs); CHECK(ret, FAIL, "H5RS_decr"); + + /* Free large strings */ + HDfree(large_str); + HDfree(large_str2); +} /* end test_refstr_acat() */ + +/**************************************************************** +** +** test_refstr_ancat(): Test basic H5RS (ref-counted strings) code. +** Tests appending length-limited strings to ref-counted strings. +** +****************************************************************/ +static void +test_refstr_ancat(void) +{ + H5RS_str_t *rs; /* Ref-counted string created */ + const char *s; /* Pointer to raw string in ref-counted string */ + char buf[256]; /* Buffer to compare against */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Appending Strings to Ref-Counted Strings\n")); + + /* Wrap ref-counted string around existing buffer */ + rs = H5RS_create(NULL); + CHECK_PTR(rs, "H5RS_create"); + + /* Append first string to ref-counted string */ + ret = H5RS_ancat(rs, "foo", 2); + CHECK(ret, FAIL, "H5RS_ancat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDstrcpy(buf, "fo"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Append another string to ref-counted string */ + ret = H5RS_ancat(rs, "bar", 2); + CHECK(ret, FAIL, "H5RS_ancat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDstrcpy(buf, "foba"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Decrement reference count for string */ ret = H5RS_decr(rs); CHECK(ret, FAIL, "H5RS_decr"); +} /* end test_refstr_ancat() */ + +/**************************************************************** +** +** test_refstr_aputc(): Test basic H5RS (ref-counted strings) code. +** Tests appending characters to ref-counted strings. +** +****************************************************************/ +static void +test_refstr_aputc(void) +{ + H5RS_str_t *rs; /* Ref-counted string created */ + const char *s; /* Pointer to raw string in ref-counted string */ + char buf[256]; /* Buffer to compare against */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Appending Strings to Ref-Counted Strings\n")); -} /* end test_refstr_own() */ + /* Wrap ref-counted string around existing buffer */ + rs = H5RS_create(NULL); + CHECK_PTR(rs, "H5RS_create"); + + /* Append first character to ref-counted string */ + ret = H5RS_aputc(rs, 'f'); + CHECK(ret, FAIL, "H5RS_ancat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDstrcpy(buf, "f"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Append another character to ref-counted string */ + ret = H5RS_aputc(rs, 'o'); + CHECK(ret, FAIL, "H5RS_ancat"); + + /* Get pointer to raw string in ref-counted string */ + s = H5RS_get_str(rs); + CHECK_PTR(s, "H5RS_get_str"); + HDstrcpy(buf, "fo"); + cmp = HDstrcmp(s, buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Decrement reference count for string */ + ret = H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); +} /* end test_refstr_aputc() */ /**************************************************************** ** @@ -361,12 +528,15 @@ test_refstr(void) test_refstr_init(); /* Actual ref-counted strings tests */ - test_refstr_create(); /* Test ref-counted string creation */ - test_refstr_count(); /* Test ref-counted string counting */ - test_refstr_dup(); /* Test ref-counted string duplication */ - test_refstr_cmp(); /* Test ref-counted string comparison */ - test_refstr_wrap(); /* Test ref-counted string wrapping */ - test_refstr_own(); /* Test ref-counted string ownership transfer */ + test_refstr_create(); /* Test ref-counted string creation */ + test_refstr_count(); /* Test ref-counted string counting */ + test_refstr_dup(); /* Test ref-counted string duplication */ + test_refstr_cmp(); /* Test ref-counted string comparison */ + test_refstr_wrap(); /* Test ref-counted string wrapping */ + test_refstr_asprintf_cat(); /* Test ref-counted string printf-formatted output */ + test_refstr_acat(); /* Test ref-counted string appends */ + test_refstr_ancat(); /* Test ref-counted length-limited string appends */ + test_refstr_aputc(); /* Test ref-counted character appends */ /* Finalize ref-counted strings testing data */ test_refstr_finalize(); -- cgit v0.12