summaryrefslogtreecommitdiffstats
path: root/src/H5RS.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@lbl.gov>2020-11-26 02:44:34 (GMT)
committerGitHub <noreply@github.com>2020-11-26 02:44:34 (GMT)
commit1bb2bdbcf84b31ee3d098063d081b940aab8f751 (patch)
tree5a4b05c052c49d4ccf687f9d9059e7fe94eeddbf /src/H5RS.c
parent3ebcfb8bf3cc18d9adddba86c47e647fd4eec842 (diff)
downloadhdf5-1bb2bdbcf84b31ee3d098063d081b940aab8f751.zip
hdf5-1bb2bdbcf84b31ee3d098063d081b940aab8f751.tar.gz
hdf5-1bb2bdbcf84b31ee3d098063d081b940aab8f751.tar.bz2
Enhance API tracing (#120)
Enhance API tracing to handle more types, and to put tracing info in a string, allowing it to be used when reporting errors. Also refactor ref-counted strings (H5RS) module to add capabilities needed for the tracing. Refactored H5Gname.c routines to use new H5RS routines also. Added /*out*/ tags to API routines that are returning information to the application. Updated H5TRACE macros from running updated trace script over library code. Added tests for new H5RS routines.
Diffstat (limited to 'src/H5RS.c')
-rw-r--r--src/H5RS.c481
1 files changed, 375 insertions, 106 deletions
diff --git a/src/H5RS.c b/src/H5RS.c
index 0e8ab27..6ab5334 100644
--- a/src/H5RS.c
+++ b/src/H5RS.c
@@ -15,9 +15,16 @@
* Reference counted string algorithms.
*
* These are used for various internal strings which get copied multiple times.
+ * They also efficiently handle dynamically allocations and appends.
*
*/
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5RSmodule.h" /* This source code file is part of the H5RS module */
+
/***********/
/* Headers */
/***********/
@@ -30,6 +37,9 @@
/* Local Macros */
/****************/
+/* Initial buffer size to allocate */
+#define H5RS_ALLOC_SIZE 256
+
/******************/
/* Local Typedefs */
/******************/
@@ -37,7 +47,10 @@
/* 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 */
};
@@ -48,10 +61,17 @@ struct H5RS_str_t {
/********************/
/* 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 */
/*****************************/
@@ -64,7 +84,7 @@ struct H5RS_str_t {
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
@@ -72,11 +92,12 @@ H5FL_BLK_DEFINE(str_buf);
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.
@@ -85,28 +106,148 @@ 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_STATIC_NOERR
+ FUNC_ENTER_STATIC
- if (s) {
- size_t len = HDstrlen(s) + 1;
+ /* Sanity check */
+ HDassert(rs);
- ret_value = (char *)H5FL_BLK_MALLOC(str_buf, len);
- HDassert(ret_value);
- HDstrncpy(ret_value, s, len);
+ if (s) {
+ 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
- ret_value = NULL;
+ 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() */
/*--------------------------------------------------------------------------
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 {
+ /* 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__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
H5RS_create
PURPOSE
Create a reference counted string
@@ -127,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)
@@ -175,54 +317,224 @@ H5RS_wrap(const char *s)
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_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_own() */
+} /* end H5RS_aputc() */
/*--------------------------------------------------------------------------
NAME
@@ -283,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);
@@ -294,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() */
/*--------------------------------------------------------------------------
@@ -338,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