summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/conclude.in3
-rwxr-xr-xconfigure4
-rw-r--r--configure.in2
-rw-r--r--src/H5.c35
-rw-r--r--src/H5A.c2
-rw-r--r--src/H5D.c2
-rw-r--r--src/H5F.c5
-rw-r--r--src/H5G.c2
-rw-r--r--src/H5I.c42
-rw-r--r--src/H5Iprivate.h2
-rw-r--r--src/H5P.c2
-rw-r--r--src/H5R.c2
-rw-r--r--src/H5RA.c2
-rw-r--r--src/H5S.c2
-rw-r--r--src/H5T.c133
-rw-r--r--src/H5TB.c2
-rw-r--r--src/H5config.h.in3
-rw-r--r--src/H5private.h6
-rw-r--r--tools/h5ls.c36
-rw-r--r--tools/h5tools.c934
-rw-r--r--tools/h5tools.h125
21 files changed, 1021 insertions, 325 deletions
diff --git a/config/conclude.in b/config/conclude.in
index 51cf691..63bd512 100644
--- a/config/conclude.in
+++ b/config/conclude.in
@@ -98,7 +98,8 @@ uninstall:
#
mostlyclean:
-$(RM) $(LIB_OBJ) $(LIB_OBJ:.lo=.o)
- -$(RM) $(TEST_OBJ) $(PROG_OBJ) $(MOSTLYCLEAN)
+ -$(RM) $(TEST_OBJ) $(TEST_OBJ:.lo=.o)
+ -$(RM) $(PROG_OBJ) $(PROG_OBJ:.lo=.o) $(MOSTLYCLEAN)
# Like `mostlyclean' except it also removes the final targets: things like
# libraries and executables. This target doesn't remove any file that
diff --git a/configure b/configure
index 32cb3c1..d71bd89 100755
--- a/configure
+++ b/configure
@@ -1300,7 +1300,7 @@ case "$host" in
esac
# Actually configure libtool. ac_aux_dir is where install-sh is found.
-AR="$AR" CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \
$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
@@ -4143,7 +4143,7 @@ else
fi
done
-for ac_func in gettimeofday BSDgettimeofday difftime snprintf
+for ac_func in gettimeofday BSDgettimeofday difftime snprintf vsnprintf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:4150: checking for $ac_func" >&5
diff --git a/configure.in b/configure.in
index ca76701..0505781 100644
--- a/configure.in
+++ b/configure.in
@@ -417,7 +417,7 @@ dnl ----------------------------------------------------------------------
dnl Check for functions.
dnl
AC_CHECK_FUNCS(getpwuid gethostname system getrusage fork waitpid)
-AC_CHECK_FUNCS(gettimeofday BSDgettimeofday difftime snprintf)
+AC_CHECK_FUNCS(gettimeofday BSDgettimeofday difftime snprintf vsnprintf)
AC_CHECK_FUNCS(compress2 setsysinfo longjmp signal sigaction)
AC_TRY_COMPILE([#include<sys/types.h>],
[off64_t n = 0;],
diff --git a/src/H5.c b/src/H5.c
index c2ce573..d096a16 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -471,6 +471,41 @@ HDsnprintf(char *buf, size_t UNUSED size, const char *fmt, ...)
}
#endif /* HAVE_SNPRINTF */
+#ifndef HAVE_VSNPRINTF
+
+
+/*-------------------------------------------------------------------------
+ * Function: HDvsnprintf
+ *
+ * Purpose: The same as HDsnprintf() except the variable arguments are
+ * passed as a va_list.
+ *
+ * Note: This function is for compatibility on systems that don't have
+ * vsnprintf(3). It doesn't actually check for overflow like the
+ * real vsnprintf() would.
+ *
+ * Return: Success: Number of characters stored, not including
+ * the terminating null. If this value equals
+ * SIZE then there was not enough space in BUF
+ * for all the output.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+HDvsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+{
+ return vsprintf(buf, fmt, ap);
+}
+#endif /* HAVE_VSNPRINTF */
+
+
/*-------------------------------------------------------------------------
* Function: HDfprintf
diff --git a/src/H5A.c b/src/H5A.c
index 624a9fd..b7bb4c3 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -100,7 +100,7 @@ H5A_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_ATTR))) {
- H5I_clear_group(H5I_ATTR);
+ H5I_clear_group(H5I_ATTR, FALSE);
} else {
H5I_destroy_group(H5I_ATTR);
interface_initialize_g = 0;
diff --git a/src/H5D.c b/src/H5D.c
index 9f6c253..7a4a148 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -126,7 +126,7 @@ H5D_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_DATASET))) {
- H5I_clear_group(H5I_DATASET);
+ H5I_clear_group(H5I_DATASET, FALSE);
} else {
H5I_destroy_group(H5I_DATASET);
interface_initialize_g = 0;
diff --git a/src/H5F.c b/src/H5F.c
index 0b30f27..6fa808a 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -338,7 +338,10 @@ herr_t
H5F_close_all(void)
{
FUNC_ENTER(H5F_close_all, FAIL);
- H5I_clear_group(H5I_FILE);
+ if (H5I_clear_group(H5I_FILE, FALSE)<0) {
+ HRETURN_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL,
+ "unable to close one or more files");
+ }
FUNC_LEAVE(SUCCEED);
}
diff --git a/src/H5G.c b/src/H5G.c
index 003bcc5..8e488d9 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -726,7 +726,7 @@ H5G_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_GROUP))) {
- H5I_clear_group(H5I_GROUP);
+ H5I_clear_group(H5I_GROUP, FALSE);
} else {
/* Empty the object type table */
for (i=0; i<H5G_ntypes_g; i++) {
diff --git a/src/H5I.c b/src/H5I.c
index b7e73b5..46bd3e4 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -364,14 +364,18 @@ H5I_nmembers(H5I_type_t grp)
* Wednesday, March 24, 1999
*
* Modifications:
+ * Robb Matzke, 1999-04-27
+ * If FORCE is zero then any item for which the free callback
+ * failed is not removed. This function returns failure if
+ * items could not be removed.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5I_clear_group(H5I_type_t grp)
+H5I_clear_group(H5I_type_t grp, hbool_t force)
{
H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */
- H5I_id_info_t *cur=NULL, *next=NULL;
+ H5I_id_info_t *cur=NULL, *next=NULL, *prev=NULL;
intn ret_value = SUCCEED;
uintn i;
@@ -401,26 +405,35 @@ H5I_clear_group(H5I_type_t grp)
/*
* Call free method for all objects in group regardless of their reference
* counts. Ignore the return value from from the free method and remove
- * object from group regardless.
+ * object from group regardless if FORCE is non-zero.
*/
for (i=0; i<grp_ptr->hash_size; i++) {
for (cur=grp_ptr->id_list[i]; cur; cur=next) {
/* Free the object regardless of reference count */
if (grp_ptr->free_func && (grp_ptr->free_func)(cur->obj_ptr)<0) {
+ if (force) {
#if H5I_DEBUG
- if (H5DEBUG(I)) {
- fprintf(H5DEBUG(I), "H5I: free grp=%d obj=0x%08lx "
- "failure ignored\n", (int)grp,
- (unsigned long)(cur->obj_ptr));
- }
+ if (H5DEBUG(I)) {
+ fprintf(H5DEBUG(I), "H5I: free grp=%d obj=0x%08lx "
+ "failure ignored\n", (int)grp,
+ (unsigned long)(cur->obj_ptr));
+ }
#endif /*H5I_DEBUG*/
+ /* Add ID struct to free list */
+ next = cur->next;
+ H5I_release_id_node(cur);
+ } else {
+ if (prev) prev->next = cur;
+ else grp_ptr->id_list[i] = cur;
+ prev = cur;
+ }
+ } else {
+ /* Add ID struct to free list */
+ next = cur->next;
+ H5I_release_id_node(cur);
}
-
- /* Add ID struct to free list */
- next = cur->next;
- H5I_release_id_node(cur);
}
- grp_ptr->id_list[i]=NULL;
+ if (!prev) grp_ptr->id_list[i]=NULL;
}
done:
@@ -472,7 +485,8 @@ H5I_destroy_group(H5I_type_t grp)
* free function is invoked for each atom being freed.
*/
if (1==grp_ptr->count) {
- H5I_clear_group(grp);
+ H5I_clear_group(grp, TRUE);
+ H5E_clear(); /*don't care about errors*/
H5MM_xfree(grp_ptr->id_list);
HDmemset (grp_ptr, 0, sizeof(*grp_ptr));
} else {
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index 99b6628..dbe5078 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -74,7 +74,7 @@ typedef struct {
__DLL__ intn H5I_init_group(H5I_type_t grp, size_t hash_size, uintn reserved,
H5I_free_t func);
__DLL__ intn H5I_nmembers(H5I_type_t grp);
-__DLL__ herr_t H5I_clear_group(H5I_type_t grp);
+__DLL__ herr_t H5I_clear_group(H5I_type_t grp, hbool_t force);
__DLL__ herr_t H5I_destroy_group(H5I_type_t grp);
__DLL__ hid_t H5I_register(H5I_type_t grp, void *object);
__DLL__ void *H5I_object(hid_t id);
diff --git a/src/H5P.c b/src/H5P.c
index 3a7f221..0f33e95 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -111,7 +111,7 @@ H5P_term_interface(void)
}
if (n) {
for (i=0; i<H5P_NCLASSES; i++) {
- H5I_clear_group((H5I_type_t)(H5I_TEMPLATE_0+i));
+ H5I_clear_group((H5I_type_t)(H5I_TEMPLATE_0+i), FALSE);
}
} else {
for (i=0; i<H5P_NCLASSES; i++) {
diff --git a/src/H5R.c b/src/H5R.c
index 1ed1632..274b69f 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -94,7 +94,7 @@ H5R_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_REFERENCE))) {
- H5I_clear_group(H5I_REFERENCE);
+ H5I_clear_group(H5I_REFERENCE, FALSE);
} else {
H5I_destroy_group(H5I_REFERENCE);
interface_initialize_g = 0;
diff --git a/src/H5RA.c b/src/H5RA.c
index 389e8dc..3690a50 100644
--- a/src/H5RA.c
+++ b/src/H5RA.c
@@ -125,7 +125,7 @@ H5RA_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_RAGGED))) {
- H5I_clear_group(H5I_RAGGED);
+ H5I_clear_group(H5I_RAGGED, FALSE);
} else {
H5T_close(H5RA_meta_type_g);
H5RA_meta_type_g = NULL;
diff --git a/src/H5S.c b/src/H5S.c
index d9e5c49..b2874ce06 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -122,7 +122,7 @@ H5S_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_DATASPACE))) {
- H5I_clear_group(H5I_DATASPACE);
+ H5I_clear_group(H5I_DATASPACE, FALSE);
} else {
#ifdef H5S_DEBUG
/*
diff --git a/src/H5T.c b/src/H5T.c
index 4919617..2ccdcb1 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -1113,50 +1113,46 @@ H5T_term_interface(void)
H5T_path_t *path = NULL;
if (interface_initialize_g) {
- if ((n=H5I_nmembers(H5I_DATATYPE))) {
- H5I_clear_group(H5I_DATATYPE);
- } else {
- /* Unregister all conversion functions */
- for (i=0; i<H5T_g.npaths; i++) {
- path = H5T_g.path[i];
- assert (path);
-
- if (path->func) {
- H5T_print_stats(path, &nprint/*in,out*/);
- path->cdata.command = H5T_CONV_FREE;
- if ((path->func)(FAIL, FAIL, &(path->cdata),
- 0, NULL, NULL)<0) {
+ /* Unregister all conversion functions */
+ for (i=0; i<H5T_g.npaths; i++) {
+ path = H5T_g.path[i];
+ assert (path);
+
+ if (path->func) {
+ H5T_print_stats(path, &nprint/*in,out*/);
+ path->cdata.command = H5T_CONV_FREE;
+ if ((path->func)(FAIL, FAIL, &(path->cdata),
+ 0, NULL, NULL)<0) {
#ifdef H5T_DEBUG
- if (H5DEBUG(T)) {
- fprintf (H5DEBUG(T), "H5T: conversion function "
- "0x%08lx failed to free private data for "
- "%s (ignored)\n",
- (unsigned long)(path->func), path->name);
- }
-#endif
- H5E_clear(); /*ignore the error*/
+ if (H5DEBUG(T)) {
+ fprintf (H5DEBUG(T), "H5T: conversion function "
+ "0x%08lx failed to free private data for "
+ "%s (ignored)\n",
+ (unsigned long)(path->func), path->name);
}
+#endif
+ H5E_clear(); /*ignore the error*/
}
- H5T_close (path->src);
- H5T_close (path->dst);
- H5MM_xfree (path);
- H5T_g.path[i] = NULL;
}
+ H5T_close (path->src);
+ H5T_close (path->dst);
+ H5MM_xfree (path);
+ H5T_g.path[i] = NULL;
+ }
- /* Clear conversion tables */
- H5T_g.path = H5MM_xfree(H5T_g.path);
- H5T_g.npaths = H5T_g.apaths = 0;
- H5T_g.soft = H5MM_xfree(H5T_g.soft);
- H5T_g.nsoft = H5T_g.asoft = 0;
+ /* Clear conversion tables */
+ H5T_g.path = H5MM_xfree(H5T_g.path);
+ H5T_g.npaths = H5T_g.apaths = 0;
+ H5T_g.soft = H5MM_xfree(H5T_g.soft);
+ H5T_g.nsoft = H5T_g.asoft = 0;
- /* Unlock all datatypes, then free them */
- H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL);
- H5I_destroy_group(H5I_DATATYPE);
+ /* Unlock all datatypes, then free them */
+ H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL);
+ H5I_destroy_group(H5I_DATATYPE);
- /* Mark interface as closed */
- interface_initialize_g = 0;
- n = 1; /*H5I*/
- }
+ /* Mark interface as closed */
+ interface_initialize_g = 0;
+ n = 1; /*H5I*/
}
return n;
}
@@ -4551,6 +4547,8 @@ H5T_lock (H5T_t *dt, hbool_t immutable)
* Monday, December 8, 1997
*
* Modifications:
+ * Robb Matzke, 1999-04-27
+ * This function fails if the datatype state is IMMUTABLE.
*
*-------------------------------------------------------------------------
*/
@@ -4558,9 +4556,9 @@ herr_t
H5T_close(H5T_t *dt)
{
intn i;
+ H5T_t *parent = dt->parent;
FUNC_ENTER(H5T_close, FAIL);
-
assert(dt);
/*
@@ -4575,41 +4573,44 @@ H5T_close(H5T_t *dt)
dt->state = H5T_STATE_NAMED;
}
- /* Close the parent */
- if (dt->parent && H5T_close(dt->parent)<0) {
- HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
- "unable to close parent data type");
- }
-
/*
- * Don't free locked datatypes unless we are shutting down the
- * interface.
+ * Don't free locked datatypes.
*/
- if (H5T_STATE_IMMUTABLE!=dt->state) {
- switch (dt->type) {
- case H5T_COMPOUND:
- for (i=0; i<dt->u.compnd.nmembs; i++) {
- H5MM_xfree(dt->u.compnd.memb[i].name);
- H5T_close(dt->u.compnd.memb[i].type);
- }
- H5MM_xfree(dt->u.compnd.memb);
- H5MM_xfree(dt);
- break;
+ if (H5T_STATE_IMMUTABLE==dt->state) {
+ HRETURN_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL,
+ "unable to close immutable datatype");
+ }
- case H5T_ENUM:
- for (i=0; i<dt->u.enumer.nmembs; i++) {
- H5MM_xfree(dt->u.enumer.name[i]);
- }
- H5MM_xfree(dt->u.enumer.name);
- H5MM_xfree(dt->u.enumer.value);
- H5MM_xfree(dt);
- break;
+ /* Close the datatype */
+ switch (dt->type) {
+ case H5T_COMPOUND:
+ for (i=0; i<dt->u.compnd.nmembs; i++) {
+ H5MM_xfree(dt->u.compnd.memb[i].name);
+ H5T_close(dt->u.compnd.memb[i].type);
+ }
+ H5MM_xfree(dt->u.compnd.memb);
+ H5MM_xfree(dt);
+ break;
- default:
- H5MM_xfree(dt);
+ case H5T_ENUM:
+ for (i=0; i<dt->u.enumer.nmembs; i++) {
+ H5MM_xfree(dt->u.enumer.name[i]);
}
+ H5MM_xfree(dt->u.enumer.name);
+ H5MM_xfree(dt->u.enumer.value);
+ H5MM_xfree(dt);
+ break;
+
+ default:
+ H5MM_xfree(dt);
}
+ /* Close the parent */
+ if (parent && H5T_close(parent)<0) {
+ HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
+ "unable to close parent data type");
+ }
+
FUNC_LEAVE(SUCCEED);
}
diff --git a/src/H5TB.c b/src/H5TB.c
index 19d400e..4b6bf25 100644
--- a/src/H5TB.c
+++ b/src/H5TB.c
@@ -117,7 +117,7 @@ H5TB_term_interface(void)
if (interface_initialize_g) {
if ((n=H5I_nmembers(H5I_TEMPBUF))) {
- H5I_clear_group(H5I_TEMPBUF);
+ H5I_clear_group(H5I_TEMPBUF, FALSE);
} else {
/* Free group and buffers */
H5I_destroy_group(H5I_TEMPBUF);
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 0b8340e..cdb3fb2 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -194,6 +194,9 @@
/* Define if you have the system function. */
#undef HAVE_SYSTEM
+/* Define if you have the vsnprintf function. */
+#undef HAVE_VSNPRINTF
+
/* Define if you have the waitpid function. */
#undef HAVE_WAITPID
diff --git a/src/H5private.h b/src/H5private.h
index 539e93c..6c80e2b 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -689,6 +689,9 @@ __DLL__ int64_t HDstrtoll (const char *s, const char **rest, int base);
#define HDvfprintf(F,FMT,A) vfprintf(F,FMT,A)
#define HDvprintf(FMT,A) vprintf(FMT,A)
#define HDvsprintf(S,FMT,A) vsprintf(S,FMT,A)
+#ifdef HAVE_VSNPRINTF
+# define HDvsnprintf(S,N,FMT,A) vsnprintf(S,N,FMT,A)
+#endif
#define HDwait(W) wait(W)
#define HDwaitpid(P,W,O) waitpid(P,W,O)
#define HDwcstombs(S,P,Z) wcstombs(S,P,Z)
@@ -704,6 +707,9 @@ char *strdup(const char *s);
#ifndef HAVE_SNPRINTF
__DLL__ int HDsnprintf(char *buf, size_t size, const char *fmt, ...);
#endif
+#ifndef HAVE_VSNPRINTF
+__DLL__ int HDvsnprintf(char *buf, size_t size, const char *fmt, va_list ap);
+#endif
/*
* These macros check whether debugging has been requested for a certain
diff --git a/tools/h5ls.c b/tools/h5ls.c
index 1648620..6073738 100644
--- a/tools/h5ls.c
+++ b/tools/h5ls.c
@@ -983,8 +983,9 @@ dump_dataset_values(hid_t dset)
/* Set to all default values and then override */
memset(&info, 0, sizeof info);
- info.idx_fmt = " (%s) ";
+ info.idx_fmt = "(%s)";
info.line_ncols = width_g;
+ info.line_multi_new = 1;
if (label_g) info.cmpd_name = "%s=";
/*
@@ -996,10 +997,16 @@ dump_dataset_values(hid_t dset)
info.ascii = TRUE;
info.elmt_suf1 = "";
info.elmt_suf2 = "";
- info.idx_fmt = " (%s) \"";
+ info.line_pre =" %s \"";
info.line_suf = "\"";
}
+ /*
+ * If a compound datatype is split across multiple lines then add an
+ * ellipsis to the beginning of the continuation line.
+ */
+ info.line_pre = " %s ";
+ info.line_cont = " %s ";
/*
* Print all the values.
@@ -1066,10 +1073,17 @@ list_attr (hid_t obj, const char *attr_name, void UNUSED *op_data)
/* Data */
memset(&info, 0, sizeof info);
+ info.line_multi_new = 1;
if (nelmts<5) {
- info.idx_fmt = " Data: ";
+ info.idx_fmt = "";
+ info.line_1st = " Data: ";
+ info.line_pre = " ";
+ info.line_cont = " ";
+
} else {
- info.idx_fmt = " (%s) ";
+ info.idx_fmt = "(%s)";
+ info.line_pre = " %s ";
+ info.line_cont = " %s ";
}
info.line_ncols = width_g;
if (label_g) info.cmpd_name = "%s=";
@@ -1078,7 +1092,8 @@ list_attr (hid_t obj, const char *attr_name, void UNUSED *op_data)
info.ascii = TRUE;
info.elmt_suf1 = "";
info.elmt_suf2 = "";
- info.idx_fmt = " (%s) \"";
+ info.idx_fmt = "(%s)";
+ info.line_pre = " %s \"";
info.line_suf = "\"";
}
if ((p_type=h5dump_fixtype(type))>=0) {
@@ -1191,6 +1206,7 @@ dataset_list2(hid_t dset, const char UNUSED *name)
hsize_t chsize[64]; /*chunk size in elements */
int ndims; /*dimensionality */
int n, max_len; /*max extern file name length */
+ double utilization; /*percent utilization of storage*/
int i;
if (verbose_g>0) {
@@ -1218,6 +1234,16 @@ dataset_list2(hid_t dset, const char UNUSED *name)
(unsigned long)used, 1==used?"":"s",
(unsigned long)total, 1==total?"":"s");
if (total>0) {
+#ifdef WIN32
+ hsize_t mask = (hsize_1)1 << (8*sizeof(hsize_t)-1);
+ if ((used & mask) || (total & mask)) {
+ total = 0; /*prevent utilization printing*/
+ } else {
+ utilization = (hssize_t)used*100.0 /(hssize_t)total;
+ }
+#else
+ utilization = (used*100.0)/total;
+#endif
printf(", %1.2f%% utilization", (used*100.0)/total);
}
putchar('\n');
diff --git a/tools/h5tools.c b/tools/h5tools.c
index 1067494..9b5dab5 100644
--- a/tools/h5tools.c
+++ b/tools/h5tools.c
@@ -16,6 +16,21 @@
#include <stdlib.h>
#include <string.h>
#include <H5private.h>
+
+/*
+ * If REPEAT_VERBOSE is defined then character strings will be printed so
+ * that repeated character sequences like "AAAAAAAAAA" are displayed as
+ *
+ * 'A' repeates 9 times
+ *
+ * Otherwise the format is more Perl-like
+ *
+ * 'A'*10
+ *
+ */
+#define REPEAT_VERBOSE
+
+
/*
* The output functions need a temporary buffer to hold a piece of the
* dataset while it's being printed. This constant sets the limit on the
@@ -30,30 +45,267 @@
#define OPT(X,S) ((X)?(X):(S))
#define ALIGN(A,Z) ((((A)+(Z)-1)/(Z))*(Z))
+#define START_OF_DATA 0x0001
+#define END_OF_DATA 0x0002
+
+/* Variable length string datatype */
+#define STR_INIT_LEN 4096 /*initial length */
+typedef struct h5dump_str_t {
+ char *s; /*allocate string */
+ size_t len; /*length of actual value */
+ size_t nalloc; /*allocated size of string */
+} h5dump_str_t;
+
+/* Special strings embedded in the output */
+#define OPTIONAL_LINE_BREAK "\001"
+/* Output variables */
+typedef struct h5dump_context_t {
+ size_t cur_column; /*current column for output */
+ int need_prefix; /*is line prefix needed? */
+ int ndims; /*dimensionality */
+ hsize_t p_min_idx[H5S_MAX_RANK]; /*min selected index */
+ hsize_t p_max_idx[H5S_MAX_RANK]; /*max selected index */
+ int prev_multiline; /*was prev datum multiline? */
+ size_t prev_prefix_len;/*length of previous prefix */
+} h5dump_context_t;
+
/*-------------------------------------------------------------------------
- * Function: h5dump_prefix
+ * Function: h5dump_str_close
*
- * Purpose: Prints the prefix to show up at the begining of the line.
+ * Purpose: Closes a string by releasing it's memory and setting the size
+ * information to zero.
*
* Return: void
*
* Programmer: Robb Matzke
- * Thursday, July 23, 1998
+ * Monday, April 26, 1999
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void
-h5dump_prefix(char *s/*out*/, const h5dump_t *info, hsize_t elmtno, int ndims,
- hsize_t min_idx[], hsize_t max_idx[])
+h5dump_str_close(h5dump_str_t *str)
+{
+ if (str && str->nalloc) {
+ free(str->s);
+ memset(str, 0, sizeof(h5dump_str_t));
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_str_len
+ *
+ * Purpose: Returns the length of the string, not counting the null
+ * terminator.
+ *
+ * Return: Success: Length of string
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+h5dump_str_len(h5dump_str_t *str)
+{
+ return str->len;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_str_append
+ *
+ * Purpose: Formats variable arguments according to printf() format
+ * string and appends the result to variable length string STR.
+ *
+ * Return: Success: Pointer to buffer containing result.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_str_append(h5dump_str_t *str/*in,out*/, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ /* Make sure we have some memory into which to print */
+ if (!str->s || str->nalloc<=0) {
+ str->nalloc = STR_INIT_LEN;
+ str->s = malloc(str->nalloc);
+ assert(str->s);
+ str->s[0] = '\0';
+ str->len = 0;
+ }
+
+ while (1) {
+ size_t avail = str->nalloc - str->len;
+ size_t nchars = HDvsnprintf(str->s+str->len, avail, fmt, ap);
+ if (nchars<avail) {
+ /* success */
+ str->len += nchars;
+ break;
+ }
+ /* Try again with twice as much space */
+ str->nalloc *= 2;
+ str->s = realloc(str->s, str->nalloc);
+ assert(str->s);
+ }
+
+ va_end(ap);
+ return str->s;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_str_reset
+ *
+ * Purpose: Reset the string to the empty value. If no memory is
+ * allocated yet then initialize the h5dump_str_t struct.
+ *
+ * Return: Success: Ptr to the buffer which contains a null
+ * character as the first element.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_str_reset(h5dump_str_t *str/*in,out*/)
+{
+ if (!str->s || str->nalloc<=0) {
+ str->nalloc = STR_INIT_LEN;
+ str->s = malloc(str->nalloc);
+ assert(str->s);
+ }
+
+ str->s[0] = '\0';
+ str->len = 0;
+ return str->s;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_str_trunc
+ *
+ * Purpose: Truncate a string to be at most SIZE characters.
+ *
+ * Return: Success: Pointer to the string
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_str_trunc(h5dump_str_t *str/*in,out*/, size_t size)
+{
+ if (size<str->len) {
+ str->len = size;
+ str->s[size] = '\0';
+ }
+ return str->s;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_str_fmt
+ *
+ * Purpose: Reformat a string contents beginning at character START
+ * according to printf format FMT. FMT should contain no format
+ * specifiers except possibly the `%s' variety. For example, if
+ * the input string is `hello' and the format is "<<%s>>" then
+ * the output value will be "<<hello>>".
+ *
+ * Return: Success: A pointer to the resulting string.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_str_fmt(h5dump_str_t *str/*in,out*/, size_t start, const char *fmt)
+{
+ char _temp[1024], *temp=_temp;
+
+ /* If the format string is simply "%s" then don't bother doing anything */
+ if (!strcmp(fmt, "%s")) return str->s;
+
+ /*
+ * Save the input value if there is a `%' anywhere in FMT. Otherwise
+ * don't bother because we don't need a temporary copy.
+ */
+ if (strchr(fmt, '%')) {
+ if ((str->len-start)+1>sizeof _temp) {
+ temp = malloc((str->len-start)+1);
+ assert(temp);
+ }
+ strcpy(temp, str->s+start);
+ }
+
+ /* Reset the output string and append a formatted version */
+ h5dump_str_trunc(str, start);
+ h5dump_str_append(str, fmt, temp);
+
+ /* Free the temp buffer if we allocated one */
+ if (temp != _temp) free(temp);
+ return str->s;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_prefix
+ *
+ * Purpose: Renders the line prefix value into string STR.
+ *
+ * Return: Success: Pointer to the prefix.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_prefix(h5dump_str_t *str/*in,out*/, const h5dump_t *info,
+ hsize_t elmtno, int ndims, hsize_t min_idx[], hsize_t max_idx[])
{
hsize_t p_prod[H5S_MAX_RANK], p_idx[H5S_MAX_RANK];
hsize_t n, i=0;
- char temp[1024];
+ h5dump_str_reset(str);
if (ndims>0) {
/*
* Calculate the number of elements represented by a unit change in a
@@ -74,92 +326,179 @@ h5dump_prefix(char *s/*out*/, const h5dump_t *info, hsize_t elmtno, int ndims,
/*
* Print the index values.
*/
- *temp = '\0';
for (i=0; i<(hsize_t)ndims; i++) {
- if (i) strcat(temp, OPT(info->idx_sep, ","));
- sprintf(temp+strlen(temp), OPT(info->idx_n_fmt, "%lu"),
- (unsigned long)p_idx[i]);
+ if (i) h5dump_str_append(str, "%s", OPT(info->idx_sep, ","));
+ h5dump_str_append(str, OPT(info->idx_n_fmt, "%lu"),
+ (unsigned long)p_idx[i]);
}
} else {
/* Scalar */
- sprintf(temp, OPT(info->idx_n_fmt, "%lu"), (unsigned long)0);
+ h5dump_str_append(str, OPT(info->idx_n_fmt, "%lu"), (unsigned long)0);
}
/*
* Add prefix and suffix to the index.
*/
- sprintf(s, OPT(info->idx_fmt, "%s: "), temp);
+ return h5dump_str_fmt(str, 0, OPT(info->idx_fmt, "%s: "));
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_escape
+ *
+ * Purpose: Changes all "funny" characters in S into standard C escape
+ * sequences. If ESCAPE_SPACES is non-zero then spaces are
+ * escaped by prepending a backslash.
+ *
+ * Return: Success: S
+ *
+ * Failure: NULL if the buffer would overflow. The
+ * buffer has as many left-to-right escapes as
+ * possible before overflow would have happened.
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5dump_escape(char *s/*in,out*/, size_t size, int escape_spaces)
+{
+ size_t n = strlen(s);
+ size_t i;
+ const char *escape;
+ char octal[8];
+
+ for (i=0; i<n; i++) {
+ switch (s[i]) {
+ case '"':
+ escape = "\\\"";
+ break;
+ case '\\':
+ escape = "\\\\";
+ break;
+ case '\b':
+ escape = "\\b";
+ break;
+ case '\f':
+ escape = "\\f";
+ break;
+ case '\n':
+ escape = "\\n";
+ break;
+ case '\r':
+ escape = "\\r";
+ break;
+ case '\t':
+ escape = "\\t";
+ break;
+ case ' ':
+ escape = escape_spaces ? "\\ " : NULL;
+ break;
+ default:
+ if (!isprint(*s)) {
+ sprintf(octal, "\\%03o", (unsigned char)(s[i]));
+ escape = octal;
+ } else {
+ escape = NULL;
+ }
+ break;
+ }
+
+ if (escape) {
+ size_t esc_size = strlen(escape);
+ if (n+esc_size+1>size) return NULL; /*would overflow*/
+ memmove(s+i+esc_size, s+i, (n-i)+1); /*make room*/
+ memcpy(s+i, escape, esc_size); /*insert*/
+ n += esc_size;
+ i += esc_size - 1;
+ }
+ }
+ return s;
}
/*-------------------------------------------------------------------------
* Function: h5dump_sprint
*
- * Purpose: Prints the value pointed to by VP into the string S assuming
- * the data type of VP is TYPE.
+ * Purpose: Renders the value pointed to by VP of type TYPE into variable
+ * length string STR.
*
- * Return: void
+ * Return: A pointer to memory containing the result or NULL on error.
*
* Programmer: Robb Matzke
* Thursday, July 23, 1998
*
* Modifications:
+ * Robb Matzke, 1999-04-26
+ * Made this function safe from overflow problems by allowing it
+ * to reallocate the output string.
*
*-------------------------------------------------------------------------
*/
-static void
-h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
+static char *
+h5dump_sprint(h5dump_str_t *str/*in,out*/, const h5dump_t *info,
+ hid_t type, void *vp)
{
- size_t i, n, offset, size, dims[H5S_MAX_RANK], nelmts;
-#ifndef NDEBUG
- unsigned overflow = 0xaaaaaaaa;
-#endif
- char temp[8192];
+ size_t i, n, offset, size, dims[H5S_MAX_RANK], nelmts, start;
char *name, quote='\0';
hid_t memb;
int nmembs, j, k, ndims;
const int repeat_threshold = 8;
-
+ static char fmt_llong[8], fmt_ullong[8];
+
+ /* Build default formats for long long types */
+ if (!fmt_llong[0]) {
+ sprintf(fmt_llong, "%%%sd", PRINTF_LL_WIDTH);
+ sprintf(fmt_ullong, "%%%su", PRINTF_LL_WIDTH);
+ }
+
+ /* Append value depending on data type */
+ start = h5dump_str_len(str);
if (H5Tequal(type, H5T_NATIVE_DOUBLE)) {
- sprintf(temp, "%g", *((double*)vp));
+ h5dump_str_append(str, OPT(info->fmt_double, "%g"), *((double*)vp));
} else if (H5Tequal(type, H5T_NATIVE_FLOAT)) {
- sprintf(temp, "%g", *((float*)vp));
+ h5dump_str_append(str, OPT(info->fmt_double, "%g"), *((float*)vp));
} else if (info->ascii &&
(H5Tequal(type, H5T_NATIVE_SCHAR) ||
H5Tequal(type, H5T_NATIVE_UCHAR))) {
switch (*((char*)vp)) {
case '"':
- strcpy(temp, "\\\"");
+ h5dump_str_append(str, "\\\"");
break;
case '\\':
- strcpy(temp, "\\\\");
+ h5dump_str_append(str, "\\\\");
break;
case '\b':
- strcpy(temp, "\\b");
+ h5dump_str_append(str, "\\b");
break;
case '\f':
- strcpy(temp, "\\f");
+ h5dump_str_append(str, "\\f");
break;
case '\n':
- strcpy(temp, "\\n");
+ h5dump_str_append(str, "\\n");
break;
case '\r':
- strcpy(temp, "\\r");
+ h5dump_str_append(str, "\\r");
break;
case '\t':
- strcpy(temp, "\\t");
+ h5dump_str_append(str, "\\t");
break;
default:
- if (isprint(*((char*)vp))) sprintf(temp, "%c", *((char*)vp));
- else sprintf(temp, "\\%03o", *((unsigned char*)vp));
+ if (isprint(*((char*)vp))) {
+ h5dump_str_append(str, "%c", *((char*)vp));
+ } else {
+ h5dump_str_append(str, "\\%03o", *((unsigned char*)vp));
+ }
break;
}
} else if (H5T_STRING==H5Tget_class(type)) {
size = H5Tget_size(type);
- temp[0] = '\0';
quote = '\0';
for (i=0; i<size; i++) {
@@ -175,115 +514,134 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
* repeated is in it's own quote.
*/
if (j>repeat_threshold) {
- if (quote) sprintf(temp+strlen(temp), "%c", quote);
+ if (quote) h5dump_str_append(str, "%c", quote);
quote = '\'';
- sprintf(temp+strlen(temp), "%s%c", i?" ":"", quote);
+ h5dump_str_append(str, "%s%c", i?" ":"", quote);
} else if (!quote) {
quote = '"';
- sprintf(temp+strlen(temp), "%s%c", i?" ":"", quote);
+ h5dump_str_append(str, "%s%c", i?" ":"", quote);
}
/* Print the character */
switch (((char*)vp)[i]) {
case '"':
- strcat(temp, "\\\"");
+ h5dump_str_append(str, "\\\"");
break;
case '\\':
- strcat(temp, "\\\\");
+ h5dump_str_append(str, "\\\\");
break;
case '\b':
- strcat(temp, "\\b");
+ h5dump_str_append(str, "\\b");
break;
case '\f':
- strcat(temp, "\\f");
+ h5dump_str_append(str, "\\f");
break;
case '\n':
- strcat(temp, "\\n");
+ h5dump_str_append(str, "\\n");
break;
case '\r':
- strcat(temp, "\\r");
+ h5dump_str_append(str, "\\r");
break;
case '\t':
- strcat(temp, "\\t");
+ h5dump_str_append(str, "\\t");
break;
default:
if (isprint(((char*)vp)[i])) {
- sprintf(temp+strlen(temp), "%c", ((char*)vp)[i]);
+ h5dump_str_append(str, "%c", ((char*)vp)[i]);
} else {
- sprintf(temp+strlen(temp), "\\%03o",
- ((unsigned char*)vp)[i]);
+ h5dump_str_append(str, "\\%03o", ((unsigned char*)vp)[i]);
}
break;
}
/* Print the repeat count */
if (j>repeat_threshold) {
- sprintf(temp+strlen(temp), "%c repeats %d times", quote, j-1);
+#ifdef REPEAT_VERBOSE
+ h5dump_str_append(str, "%c repeats %d times", quote, j-1);
+#else
+ h5dump_str_append(str, "%c*%d", quote, j-1);
+#endif
quote = '\0';
i += j-1;
}
}
- if (quote) sprintf(temp+strlen(temp), "%c", quote);
+ if (quote) h5dump_str_append(str, "%c", quote);
+
+ } else if (H5Tequal(type, H5T_NATIVE_INT)) {
+ h5dump_str_append(str, OPT(info->fmt_int, "%d"),
+ *((int*)vp));
+
+ } else if (H5Tequal(type, H5T_NATIVE_UINT)) {
+ h5dump_str_append(str, OPT(info->fmt_uint, "%u"),
+ *((unsigned*)vp));
} else if (H5Tequal(type, H5T_NATIVE_SCHAR)) {
- sprintf(temp, "%d", *((signed char*)vp));
+ h5dump_str_append(str, OPT(info->fmt_schar, "%d"),
+ *((signed char*)vp));
} else if (H5Tequal(type, H5T_NATIVE_UCHAR)) {
- sprintf(temp, "%u", *((unsigned char*)vp));
+ h5dump_str_append(str, OPT(info->fmt_uchar, "%u"),
+ *((unsigned char*)vp));
} else if (H5Tequal(type, H5T_NATIVE_SHORT)) {
- sprintf(temp, "%d", *((short*)vp));
+ h5dump_str_append(str, OPT(info->fmt_short, "%d"),
+ *((short*)vp));
} else if (H5Tequal(type, H5T_NATIVE_USHORT)) {
- sprintf(temp, "%u", *((unsigned short*)vp));
-
- } else if (H5Tequal(type, H5T_NATIVE_INT)) {
- sprintf(temp, "%d", *((int*)vp));
-
- } else if (H5Tequal(type, H5T_NATIVE_UINT)) {
- sprintf(temp, "%u", *((unsigned*)vp));
+ h5dump_str_append(str, OPT(info->fmt_ushort, "%u"),
+ *((unsigned short*)vp));
} else if (H5Tequal(type, H5T_NATIVE_LONG)) {
- sprintf(temp, "%ld", *((long*)vp));
+ h5dump_str_append(str, OPT(info->fmt_long, "%ld"),
+ *((long*)vp));
} else if (H5Tequal(type, H5T_NATIVE_ULONG)) {
- sprintf(temp, "%lu", *((unsigned long*)vp));
+ h5dump_str_append(str, OPT(info->fmt_ulong, "%lu"),
+ *((unsigned long*)vp));
+
+ } else if (H5Tequal(type, H5T_NATIVE_LLONG)) {
+ h5dump_str_append(str, OPT(info->fmt_llong, fmt_llong),
+ *((long_long*)vp));
+
+ } else if (H5Tequal(type, H5T_NATIVE_ULLONG)) {
+ h5dump_str_append(str, OPT(info->fmt_ullong, fmt_ullong),
+ *((unsigned long_long*)vp));
} else if (H5Tequal(type, H5T_NATIVE_HSSIZE)) {
if (sizeof(hssize_t)==sizeof(int)) {
- sprintf(temp, "%d", *((int*)vp));
+ h5dump_str_append(str, OPT(info->fmt_int, "%d"),
+ *((int*)vp));
} else if (sizeof(hssize_t)==sizeof(long)) {
- sprintf(temp, "%ld", *((long*)vp));
+ h5dump_str_append(str, OPT(info->fmt_long, "%ld"),
+ *((long*)vp));
} else {
- char fmt[8];
- strcpy(fmt, "%");
- strcat(fmt, PRINTF_LL_WIDTH);
- strcat(fmt, "d");
- sprintf(temp, fmt, *((int64_t*)vp));
+ h5dump_str_append(str, OPT(info->fmt_llong, fmt_llong),
+ *((int64_t*)vp));
}
} else if (H5Tequal(type, H5T_NATIVE_HSIZE)) {
if (sizeof(hsize_t)==sizeof(int)) {
- sprintf(temp, "%u", *((unsigned*)vp));
+ h5dump_str_append(str, OPT(info->fmt_uint, "%u"),
+ *((unsigned*)vp));
} else if (sizeof(hsize_t)==sizeof(long)) {
- sprintf(temp, "%lu", *((unsigned long*)vp));
+ h5dump_str_append(str, OPT(info->fmt_ulong, "%lu"),
+ *((unsigned long*)vp));
} else {
- char fmt[8];
- strcpy(fmt, "%");
- strcat(fmt, PRINTF_LL_WIDTH);
- strcat(fmt, "u");
- sprintf(temp, fmt, *((uint64_t*)vp));
+ h5dump_str_append(str, OPT(info->fmt_ullong, fmt_ullong),
+ *((uint64_t*)vp));
}
} else if (H5T_COMPOUND==H5Tget_class(type)) {
nmembs = H5Tget_nmembers(type);
- strcpy(temp, OPT(info->cmpd_pre, "{"));
+ h5dump_str_append(str, "%s", OPT(info->cmpd_pre, "{"));
for (j=0; j<nmembs; j++) {
- if (j) strcat(temp, OPT(info->cmpd_sep, ","));
+ if (j) h5dump_str_append(str, "%s",
+ OPT(info->cmpd_sep,
+ ", " OPTIONAL_LINE_BREAK));
/* The name */
name = H5Tget_member_name(type, j);
- sprintf(temp+strlen(temp), OPT(info->cmpd_name, ""), name);
+ h5dump_str_append(str, OPT(info->cmpd_name, ""), name);
free(name);
/* The value */
@@ -294,45 +652,264 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
assert(ndims>=0 && ndims<=H5S_MAX_RANK);
for (k=0, nelmts=1; k<ndims; k++) nelmts *= dims[k];
- if (nelmts>1) strcat(temp, OPT(info->arr_pre, "["));
+ if (nelmts>1) {
+ h5dump_str_append(str, "%s", OPT(info->arr_pre, "["));
+ }
for (i=0; i<nelmts; i++) {
- if (i) strcat(temp, OPT(info->arr_sep, ","));
- h5dump_sprint(temp+strlen(temp), info, memb,
- (char*)vp+offset+i*size);
+ if (i) {
+ h5dump_str_append(str, "%s",
+ OPT(info->arr_sep,
+ "," OPTIONAL_LINE_BREAK));
+ }
+ h5dump_sprint(str, info, memb, (char*)vp+offset+i*size);
+ }
+ if (nelmts>1) {
+ h5dump_str_append(str, "%s", OPT(info->arr_suf, "]"));
}
- if (nelmts>1) strcat(temp, OPT(info->arr_suf, "]"));
H5Tclose(memb);
}
- strcat(temp, OPT(info->cmpd_suf, "}"));
+ h5dump_str_append(str, "%s", OPT(info->cmpd_suf, "}"));
} else if (H5T_ENUM==H5Tget_class(type)) {
- if (H5Tenum_nameof(type, vp, temp, sizeof temp)<0) {
- strcpy(temp, "0x");
+ char enum_name[1024];
+ if (H5Tenum_nameof(type, vp, enum_name, sizeof enum_name)>=0) {
+ h5dump_escape(enum_name, sizeof enum_name, TRUE);
+ } else {
+ h5dump_str_append(str, "0x");
n = H5Tget_size(type);
for (i=0; i<n; i++) {
- sprintf(temp+strlen(temp), "%02x", ((unsigned char*)vp)[i]);
+ h5dump_str_append(str, "%02x", ((unsigned char*)vp)[i]);
}
}
} else {
- strcpy(temp, "0x");
+ h5dump_str_append(str, "0x");
n = H5Tget_size(type);
for (i=0; i<n; i++) {
- sprintf(temp+strlen(temp), "%02x", ((unsigned char*)vp)[i]);
+ h5dump_str_append(str, "%02x", ((unsigned char*)vp)[i]);
}
}
- sprintf(s, OPT(info->elmt_fmt, "%s"), temp);
+ return h5dump_str_fmt(str, start, OPT(info->elmt_fmt, "%s"));
+}
- /*
- * We should really fix this so it's not possible to overflow the `temp'
- * buffer.
- */
- assert(overflow==0xaaaaaaaa);
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_ncols
+ *
+ * Purpose: Count the number of columns in a string. This is the number
+ * of characters in the string not counting line-control
+ * characters.
+ *
+ * Return: Success: Width of string.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, April 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+h5dump_ncols(const char *s)
+{
+ size_t i;
+
+ for (i=0; *s; s++) if (*s>=' ') i++;
+ return i;
}
/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_prefix
+ *
+ * Purpose: If ctx->need_prefix is set then terminate the current line
+ * (if applicable), calculate the prefix string, and display it
+ * at the start of a line.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_simple_prefix(FILE *stream, const h5dump_t *info,
+ h5dump_context_t *ctx, hsize_t elmtno, int secnum)
+{
+ h5dump_str_t prefix;
+
+ memset(&prefix, 0, sizeof(h5dump_str_t));
+ if (!ctx->need_prefix) return;
+
+ /* Terminate previous line, if any */
+ if (ctx->cur_column) {
+ fputs(OPT(info->line_suf, ""), stream);
+ putc('\n', stream);
+ fputs(OPT(info->line_sep, ""), stream);
+ }
+
+ /* Calculate new prefix */
+ h5dump_prefix(&prefix, info, elmtno, ctx->ndims,
+ ctx->p_min_idx, ctx->p_max_idx);
+
+ /* Write new prefix to output */
+ if (0==elmtno && 0==secnum && info->line_1st) {
+ fputs(h5dump_str_fmt(&prefix, 0, info->line_1st),
+ stream);
+ } else if (secnum && info->line_cont) {
+ fputs(h5dump_str_fmt(&prefix, 0, info->line_cont),
+ stream);
+ } else {
+ fputs(h5dump_str_fmt(&prefix, 0, info->line_pre),
+ stream);
+ }
+ ctx->cur_column = ctx->prev_prefix_len = h5dump_str_len(&prefix);
+ ctx->need_prefix = 0;
+
+ /* Free string */
+ h5dump_str_close(&prefix);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_data
+ *
+ * Purpose: Prints some (NELMTS) data elements to output STREAM. The
+ * elements are stored in _MEM as type TYPE and are printed
+ * according to the format described in INFO. The CTX struct
+ * contains context information shared between calls to this
+ * function. The FLAGS is a bit field that indicates whether
+ * the data supplied in this call falls at the beginning or end
+ * of the total data to be printed (START_OF_DATA and
+ * END_OF_DATA).
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_simple_data(FILE *stream, const h5dump_t *info,
+ h5dump_context_t *ctx/*in,out*/, unsigned flags,
+ hsize_t nelmts, hid_t type, void *_mem)
+{
+ unsigned char *mem = (unsigned char*)_mem;
+ hsize_t i; /*element counter */
+ char *s, *section; /*a section of output */
+ int secnum; /*section sequence number */
+ size_t size; /*size of each datum */
+ size_t ncols=80; /*available output width */
+ h5dump_str_t buffer; /*string into which to render */
+ int multiline; /*datum was multiline */
+
+ /* Setup */
+ memset(&buffer, 0, sizeof(h5dump_str_t));
+ size = H5Tget_size(type);
+ if (info->line_ncols>0) ncols = info->line_ncols;
+ h5dump_simple_prefix(stream, info, ctx, 0, 0);
+
+ for (i=0; i<nelmts; i++) {
+
+ /* Render the element */
+ h5dump_str_reset(&buffer);
+ h5dump_sprint(&buffer, info, type, mem+i*size);
+ if (i+1<nelmts || 0==(flags & END_OF_DATA)) {
+ h5dump_str_append(&buffer, "%s", OPT(info->elmt_suf1, ","));
+ }
+ s = h5dump_str_fmt(&buffer, 0, "%s");
+
+ /*
+ * If the element would split on multiple lines if printed at our
+ * current location...
+ */
+ if (1==info->line_multi_new &&
+ (ctx->cur_column + h5dump_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols) {
+ if (ctx->prev_multiline) {
+ /*
+ * ... and the previous element also occupied more than one
+ * line, then start this element at the beginning of a line.
+ */
+ ctx->need_prefix = TRUE;
+ } else if ((ctx->prev_prefix_len + h5dump_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) <= ncols) {
+ /*
+ * ...but *could* fit on one line otherwise, then we
+ * should end the current line and start this element on its
+ * own line.
+ */
+ ctx->need_prefix = TRUE;
+ }
+ }
+
+ /*
+ * If the previous element occupied multiple lines and this element
+ * is too long to fit on a line then start this element at the
+ * beginning of the line.
+ */
+ if (1==info->line_multi_new &&
+ ctx->prev_multiline &&
+ (ctx->cur_column + h5dump_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols) {
+ ctx->need_prefix = TRUE;
+ }
+
+ /*
+ * Each OPTIONAL_LINE_BREAK embedded in the rendered string can cause
+ * the data to split across multiple lines. We display the sections
+ * one-at a time.
+ */
+ for (secnum=0, multiline=0;
+ (section=strtok(secnum?NULL:s, OPTIONAL_LINE_BREAK));
+ secnum++) {
+ /*
+ * If the current section plus possible suffix and end-of-line
+ * information would cause the output to wrap then we need to
+ * start a new line.
+ */
+ if ((ctx->cur_column + strlen(section) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols) {
+ ctx->need_prefix = 1;
+ }
+
+ /*
+ * Print the prefix or separate the beginning of this element
+ * from the previous element.
+ */
+ if (ctx->need_prefix) {
+ if (secnum) multiline++;
+ h5dump_simple_prefix(stream, info, ctx, i, secnum);
+ } else if (i && 0==secnum) {
+ fputs(OPT(info->elmt_suf2, " "), stream);
+ ctx->cur_column += strlen(OPT(info->elmt_suf2, " "));
+ }
+
+ /* Print the section */
+ fputs(section, stream);
+ ctx->cur_column += strlen(section);
+ }
+ ctx->prev_multiline = multiline;
+ }
+ h5dump_str_close(&buffer);
+}
+
+
+
+/*-------------------------------------------------------------------------
* Function: h5dump_simple_dset
*
* Purpose: Print some values from a dataset with a simple data space.
@@ -354,21 +931,15 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
hid_t p_type)
{
hid_t f_space; /*file data space */
- int ndims; /*dimensionality */
hsize_t elmtno, i; /*counters */
int carry; /*counter carry value */
hssize_t zero[8]; /*vector of zeros */
- int need_prefix=1; /*indices need printing */
+ unsigned flags; /*buffer extent flags */
/* Print info */
- hsize_t p_min_idx[H5S_MAX_RANK];/*min selected index */
- hsize_t p_max_idx[H5S_MAX_RANK];/*max selected index */
+ h5dump_context_t ctx; /*print context */
size_t p_type_nbytes; /*size of memory type */
hsize_t p_nelmts; /*total selected elmts */
- char p_buf[8192]; /*output string */
- size_t p_column=0; /*output column */
- size_t p_ncolumns=80; /*default num columns */
- char p_prefix[1024]; /*line prefix string */
/* Stripmine info */
hsize_t sm_size[H5S_MAX_RANK]; /*stripmine size */
@@ -382,20 +953,24 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
hsize_t hs_size[H5S_MAX_RANK]; /*size this pass */
hsize_t hs_nelmts; /*elements in request */
+
+
/*
* Check that everything looks okay. The dimensionality must not be too
* great and the dimensionality of the items selected for printing must
* match the dimensionality of the dataset.
*/
+ memset(&ctx, 0, sizeof ctx);
+ ctx.need_prefix = 1;
f_space = H5Dget_space(dset);
- ndims = H5Sget_simple_extent_ndims(f_space);
- if ((size_t)ndims>NELMTS(sm_size)) return -1;
+ ctx.ndims = H5Sget_simple_extent_ndims(f_space);
+ if ((size_t)(ctx.ndims)>NELMTS(sm_size)) return -1;
/* Assume entire data space to be printed */
- for (i=0; i<(hsize_t)ndims; i++) p_min_idx[i] = 0;
- H5Sget_simple_extent_dims(f_space, p_max_idx, NULL);
- for (i=0, p_nelmts=1; i<(hsize_t)ndims; i++) {
- p_nelmts *= p_max_idx[i]-p_min_idx[i];
+ for (i=0; i<(hsize_t)(ctx.ndims); i++) ctx.p_min_idx[i] = 0;
+ H5Sget_simple_extent_dims(f_space, ctx.p_max_idx, NULL);
+ for (i=0, p_nelmts=1; i<(hsize_t)(ctx.ndims); i++) {
+ p_nelmts *= ctx.p_max_idx[i]-ctx.p_min_idx[i];
}
if (0==p_nelmts) return 0; /*nothing to print*/
@@ -404,8 +979,8 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
* a hyperslab whose size is manageable.
*/
p_type_nbytes = H5Tget_size(p_type);
- for (i=ndims, sm_nbytes=p_type_nbytes; i>0; --i) {
- sm_size[i-1] = MIN (p_max_idx[i-1]-p_min_idx[i-1],
+ for (i=ctx.ndims, sm_nbytes=p_type_nbytes; i>0; --i) {
+ sm_size[i-1] = MIN (ctx.p_max_idx[i-1] - ctx.p_min_idx[i-1],
H5DUMP_BUFSIZE/sm_nbytes);
sm_nbytes *= sm_size[i-1];
assert(sm_nbytes>0);
@@ -414,18 +989,15 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
sm_nelmts = sm_nbytes/p_type_nbytes;
sm_space = H5Screate_simple(1, &sm_nelmts, NULL);
- /* Local things */
- if (info->line_ncols>0) p_ncolumns = info->line_ncols;
-
/* The stripmine loop */
memset(hs_offset, 0, sizeof hs_offset);
memset(zero, 0, sizeof zero);
for (elmtno=0; elmtno<p_nelmts; elmtno+=hs_nelmts) {
/* Calculate the hyperslab size */
- if (ndims>0) {
- for (i=0, hs_nelmts=1; i<(hsize_t)ndims; i++) {
- hs_size[i] = MIN(sm_size[i], p_max_idx[i]-hs_offset[i]);
+ if (ctx.ndims>0) {
+ for (i=0, hs_nelmts=1; i<(hsize_t)(ctx.ndims); i++) {
+ hs_size[i] = MIN(ctx.p_max_idx[i]-hs_offset[i], sm_size[i]);
hs_nelmts *= hs_size[i];
}
H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL,
@@ -442,54 +1014,26 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
if (H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf)<0) {
return -1;
}
-
- /* Print the data */
- for (i=0; i<hs_nelmts; i++) {
- /* Render the element */
- h5dump_sprint(p_buf, info, p_type, sm_buf+i*p_type_nbytes);
- if (elmtno+i+1<p_nelmts) {
- strcat(p_buf, OPT(info->elmt_suf1, ","));
- }
- /* Print the prefix */
- if ((p_column +
- strlen(p_buf) +
- strlen(OPT(info->elmt_suf2, " ")) +
- strlen(OPT(info->line_suf, ""))) > p_ncolumns) {
- need_prefix = 1;
- }
- if (need_prefix) {
- h5dump_prefix(p_prefix, info, elmtno+i, ndims,
- p_min_idx, p_max_idx);
- if (p_column) {
- fputs(OPT(info->line_suf, ""), stream);
- putc('\n', stream);
- fputs(OPT(info->line_sep, ""), stream);
- }
- fputs(p_prefix, stream);
- p_column = strlen(p_prefix);
- need_prefix = 0;
- } else {
- fputs(OPT(info->elmt_suf2, " "), stream);
- p_column += strlen(OPT(info->elmt_suf2, " "));
- }
-
- fputs(p_buf, stream);
- p_column += strlen(p_buf);
- }
+ /* Print the data */
+ flags = ((0==elmtno?START_OF_DATA:0) |
+ (elmtno+hs_nelmts>=p_nelmts?END_OF_DATA:0));
+ h5dump_simple_data(stream, info, &ctx, flags, hs_nelmts, p_type,
+ sm_buf);
/* Calculate the next hyperslab offset */
- for (i=ndims, carry=1; i>0 && carry; --i) {
+ for (i=ctx.ndims, carry=1; i>0 && carry; --i) {
hs_offset[i-1] += hs_size[i-1];
- if (hs_offset[i-1]==(hssize_t)p_max_idx[i-1]) {
- hs_offset[i-1] = p_min_idx[i-1];
+ if (hs_offset[i-1]==(hssize_t)(ctx.p_max_idx[i-1])) {
+ hs_offset[i-1] = ctx.p_min_idx[i-1];
} else {
carry = 0;
}
}
}
- if (p_column) {
+ /* Terminate the output */
+ if (ctx.cur_column) {
fputs(OPT(info->line_suf, ""), stream);
putc('\n', stream);
fputs(OPT(info->line_sep, ""), stream);
@@ -520,81 +1064,43 @@ h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
*/
static int
h5dump_simple_mem(FILE *stream, const h5dump_t *info, hid_t type,
- hid_t space, void *_mem)
+ hid_t space, void *mem)
{
- unsigned char *mem = (unsigned char*)_mem;
- int ndims; /*dimensionality */
hsize_t i; /*counters */
- int need_prefix=1; /*indices need printing */
-
- /* Print info */
- hsize_t p_min_idx[H5S_MAX_RANK];/*min selected index */
- hsize_t p_max_idx[H5S_MAX_RANK];/*max selected index */
- size_t p_type_nbytes; /*size of memory type */
- hsize_t p_nelmts; /*total selected elmts */
- char p_buf[8192]; /*output string */
- size_t p_column=0; /*output column */
- size_t p_ncolumns=80; /*default num columns */
- char p_prefix[1024]; /*line prefix string */
+ size_t size; /*size of each element */
+ hsize_t nelmts; /*total selected elmts */
+ h5dump_context_t ctx; /*printing context */
/*
* Check that everything looks okay. The dimensionality must not be too
* great and the dimensionality of the items selected for printing must
* match the dimensionality of the dataset.
*/
- ndims = H5Sget_simple_extent_ndims(space);
- if ((size_t)ndims>NELMTS(p_min_idx)) return -1;
+ memset(&ctx, 0, sizeof ctx);
+ ctx.need_prefix = 1;
+ ctx.ndims = H5Sget_simple_extent_ndims(space);
+ if ((size_t)(ctx.ndims)>NELMTS(ctx.p_min_idx)) return -1;
/* Assume entire data space to be printed */
- for (i=0; i<(hsize_t)ndims; i++) p_min_idx[i] = 0;
- H5Sget_simple_extent_dims(space, p_max_idx, NULL);
- for (i=0, p_nelmts=1; i<(hsize_t)ndims; i++) {
- p_nelmts *= p_max_idx[i]-p_min_idx[i];
+ for (i=0; i<(hsize_t)(ctx.ndims); i++) ctx.p_min_idx[i] = 0;
+ H5Sget_simple_extent_dims(space, ctx.p_max_idx, NULL);
+ for (i=0, nelmts=1; i<(hsize_t)(ctx.ndims); i++) {
+ nelmts *= ctx.p_max_idx[i] - ctx.p_min_idx[i];
}
- if (0==p_nelmts) return 0; /*nothing to print*/
- p_type_nbytes = H5Tget_size(type);
-
- /* Local things */
- if (info->line_ncols>0) p_ncolumns = info->line_ncols;
+ if (0==nelmts) return 0; /*nothing to print*/
+ size = H5Tget_size(type);
- for (i=0; i<p_nelmts; i++) {
- /* Render the element */
- h5dump_sprint(p_buf, info, type, mem+i*p_type_nbytes);
- if (i+1<p_nelmts) {
- strcat(p_buf, OPT(info->elmt_suf1, ","));
- }
+ /* Print it */
+ h5dump_simple_data(stream, info, &ctx, START_OF_DATA|END_OF_DATA,
+ nelmts, type, mem);
- /* Print the prefix */
- if ((p_column +
- strlen(p_buf) +
- strlen(OPT(info->elmt_suf2, " ")) +
- strlen(OPT(info->line_suf, ""))) > p_ncolumns) {
- need_prefix = 1;
- }
- if (need_prefix) {
- h5dump_prefix(p_prefix, info, i, ndims, p_min_idx, p_max_idx);
- if (p_column) {
- fputs(OPT(info->line_suf, ""), stream);
- putc('\n', stream);
- fputs(OPT(info->line_sep, ""), stream);
- }
- fputs(p_prefix, stream);
- p_column = strlen(p_prefix);
- need_prefix = 0;
- } else {
- fputs(OPT(info->elmt_suf2, " "), stream);
- p_column += strlen(OPT(info->elmt_suf2, " "));
- }
-
- fputs(p_buf, stream);
- p_column += strlen(p_buf);
- }
-
- if (p_column) {
+ /* Terminate the output */
+ if (ctx.cur_column) {
fputs(OPT(info->line_suf, ""), stream);
putc('\n', stream);
fputs(OPT(info->line_sep, ""), stream);
}
+
return 0;
}
diff --git a/tools/h5tools.h b/tools/h5tools.h
index 8b5cbfe..a6ed864 100644
--- a/tools/h5tools.h
+++ b/tools/h5tools.h
@@ -18,15 +18,84 @@
*/
typedef struct h5dump_t {
/*
+ * Fields associated with formatting numeric data. If a datatype matches
+ * multiple formats based on its size, then the first applicable format
+ * from this list is used.
+ *
+ * fmt_int: The printf() format to use when rendering data which is
+ * typed `int'. The default is `%d'.
+ *
+ * fmt_uint: The printf() format to use when rendering data which is
+ * typed `unsigned'. The default is `%u'.
+ *
+ * fmt_schar: The printf() format to use when rendering data which is
+ * typed `signed char'. The default is `%d'. This format is
+ * used ony if the `ascii' field is zero.
+ *
+ * fmt_uchar: The printf() format to use when rendering data which is
+ * typed `unsigned char'. The default is `%u'. This format
+ * is used only if the `ascii' field is zero.
+ *
+ * fmt_short: The printf() format to use when rendering data which is
+ * typed `short'. The default is `%d'.
+ *
+ * fmt_ushort: The printf() format to use when rendering data which is
+ * typed `unsigned short'. The default is `%u'.
+ *
+ * fmt_long: The printf() format to use when rendering data which is
+ * typed `long'. The default is `%ld'.
+ *
+ * fmt_ulong: The printf() format to use when rendering data which is
+ * typed `unsigned long'. The default is `%lu'.
+ *
+ * fmt_llong: The printf() format to use when rendering data which is
+ * typed `long long'. The default depends on what printf()
+ * format is available to print this datatype.
+ *
+ * fmt_ullong: The printf() format to use when rendering data which is
+ * typed `unsigned long long'. The default depends on what
+ * printf() format is available to print this datatype.
+ *
+ * fmt_double: The printf() format to use when rendering data which is
+ * typed `double'. The default is `%g'.
+ *
+ * fmt_float: The printf() format to use when rendering data which is
+ * typed `float'. The default is `%g'.
+ *
+ * ascii: If set then print 1-byte integer values as an ASCII
+ * character (no quotes). If the character is one of the
+ * standard C escapes then print the escaped version. If
+ * the character is unprintable then print a 3-digit octal
+ * escape. If `ascii' is zero then then 1-byte integers are
+ * printed as numeric values. The default is zero.
+ *
+ * Numeric data is also subject to the formats for individual elements.
+ */
+ const char *fmt_int;
+ const char *fmt_uint;
+ const char *fmt_schar;
+ const char *fmt_uchar;
+ const char *fmt_short;
+ const char *fmt_ushort;
+ const char *fmt_long;
+ const char *fmt_ulong;
+ const char *fmt_llong;
+ const char *fmt_ullong;
+ const char *fmt_double;
+ const char *fmt_float;
+ int ascii;
+
+ /*
* Fields associated with compound array members.
*
* pre: A string to print at the beginning of each array. The
* default value is the left square bracket `['.
*
* sep: A string to print between array values. The default
- * value is a comma.
+ * value is a ",\001" ("\001" indicates an optional line
+ * break).
*
- * suf: A strint to print at the end of each array. The default
+ * suf: A string to print at the end of each array. The default
* value is a right square bracket `]'.
*/
const char *arr_pre;
@@ -42,7 +111,9 @@ typedef struct h5dump_t {
* followed by an equal sign and then the value.
*
* sep: A string that separates one member from another. The
- * default is a comma.
+ * default is ", \001" (the \001 indicates an optional
+ * line break to allow structs to span multiple lines of
+ * output).
*
* pre: A string to print at the beginning of a compound type.
* The default is a left curly brace.
@@ -58,13 +129,6 @@ typedef struct h5dump_t {
/*
* Fields associated with the individual elements.
*
- * ascii: If set then print 1-byte integer values as an ASCII
- * character (no quotes). If the character is one of the
- * standard C escapes then print the escaped version. If
- * the character is unprintable then print a 3-digit octal
- * escape. If `ascii' is zero then then 1-byte integers are
- * printed as numeric values. The default is zero.
- *
* fmt: A printf(3c) format to use to print the value string
* after it has been rendered. The default is "%s".
*
@@ -76,7 +140,6 @@ typedef struct h5dump_t {
* are followed on the same line by another element. The
* default is a single space.
*/
- int ascii;
const char *elmt_fmt;
const char *elmt_suf1;
const char *elmt_suf2;
@@ -107,6 +170,22 @@ typedef struct h5dump_t {
*
* ncols: Number of columns per line defaults to 80.
*
+ * pre: Each line of output contains an optional prefix area
+ * before the data. This area can contain the index for the
+ * first datum (represented by `%s') as well as other
+ * constant text. The default value is `%s'.
+ *
+ * 1st: This is the format to print at the beginning of the first
+ * line of output. The default value is the current value of
+ * `pre' described above.
+ *
+ * cont: This is the format to print at the beginning of each line
+ * which was continued because the line was split onto
+ * multiple lines. This often happens with compound
+ * data which is longer than one line of output. The default
+ * value is the current value of the `pre' field
+ * described above.
+ *
* suf: This character string will be appended to each line of
* output. It should not contain line feeds. The default
* is the empty string.
@@ -114,11 +193,33 @@ typedef struct h5dump_t {
* sep: A character string to be printed after every line feed
* defaulting to the empty string. It should end with a
* line feed.
+ *
+ * multi_new: Indicates the algorithm to use when data elements tend to
+ * occupy more than one line of output. The possible values
+ * are (zero is the default):
+ *
+ * 0: No consideration. Each new element is printed
+ * beginning where the previous element ended.
+ *
+ * 1: Print the current element beginning where the
+ * previous element left off. But if that would result
+ * in the element occupying more than one line and it
+ * would only occupy one line if it started at the
+ * beginning of a line, then it is printed at the
+ * beginning of the next line.
+ *
+ * multi_new: If an element is continued onto additional lines then
+ * should the following element begin on the next line? The
+ * default is to start the next element on the same line
+ * unless it wouldn't fit.
*/
int line_ncols; /*columns of output */
+ const char *line_pre; /*prefix at front of each line */
+ const char *line_1st; /*alternate pre. on first line */
+ const char *line_cont; /*alternate pre. on continuation*/
const char *line_suf; /*string to append to each line */
const char *line_sep; /*separates lines */
-
+ int line_multi_new; /*split multi-line outputs? */
} h5dump_t;