summaryrefslogtreecommitdiffstats
path: root/tools/h5tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/h5tools.c')
-rw-r--r--tools/h5tools.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/tools/h5tools.c b/tools/h5tools.c
new file mode 100644
index 0000000..ef1e954
--- /dev/null
+++ b/tools/h5tools.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright © 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, July 23, 1998
+ *
+ * Purpose: A library for displaying the values of a dataset in a human
+ * readable format.
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <h5tools.h>
+#include <hdf5.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * 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
+ * size of that temporary buffer in bytes. For efficiency's sake, choose the
+ * largest value suitable for your machine (for testing use a small value).
+ */
+#define H5DUMP_BUFSIZE 1024
+
+#define OPT(X,S) ((X)?(X):(S))
+#define MIN(X,Y) ((X)<(Y)?(X):(Y))
+#define NELMTS(X) (sizeof(X)/sizeof(*X))
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_prefix
+ *
+ * Purpose: Prints the prefix to show up at the begining of the line.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * 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[])
+{
+ hsize_t p_prod[8], p_idx[8];
+ hsize_t n, i;
+ char temp[1024];
+
+ /*
+ * Calculate the number of elements represented by a unit change in a
+ * certain index position.
+ */
+ for (i=ndims-1, p_prod[ndims-1]=1; i>0; --i) {
+ p_prod[i-1] = (max_idx[i]-min_idx[i]) * p_prod[i];
+ }
+
+ /*
+ * Calculate the index values from the element number.
+ */
+ for (i=0, n=elmtno; i<(hsize_t)ndims; i++) {
+ p_idx[i] = n / p_prod[i] + min_idx[i];
+ n %= p_prod[i];
+ }
+
+ /*
+ * 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]);
+ }
+
+ /*
+ * Add prefix and suffix to the index.
+ */
+ sprintf(s, OPT(info->idx_fmt, "%s: "), temp);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_sprint
+ *
+ * Purpose: Prints the value pointed to by VP into the string S assuming
+ * the data type of VP is TYPE.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
+{
+ size_t i, n;
+ char temp[1024];
+
+ if (H5Tequal(type, H5T_NATIVE_DOUBLE)) {
+ sprintf(temp, "%g", *((double*)vp));
+ } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) {
+ sprintf(temp, "%g", *((float*)vp));
+ } else if (H5Tequal(type, H5T_NATIVE_CHAR) ||
+ H5Tequal(type, H5T_NATIVE_UCHAR)) {
+ if ('\\'==*((char*)vp)) strcpy(temp, "\\\\");
+ else if (isprint(*((char*)vp))) sprintf(temp, "%c", *((char*)vp));
+ else sprintf(temp, "\\%03o", *((unsigned char*)vp));
+ } else if (H5Tequal(type, H5T_NATIVE_SHORT)) {
+ sprintf(temp, "%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));
+ } else if (H5Tequal(type, H5T_NATIVE_LONG)) {
+ sprintf(temp, "%ld", *((long*)vp));
+ } else if (H5Tequal(type, H5T_NATIVE_ULONG)) {
+ sprintf(temp, "%lu", *((unsigned long*)vp));
+ } else {
+ strcpy(temp, "0x");
+ n = H5Tget_size(type);
+ for (i=0; i<n; i++) {
+ sprintf(temp+strlen(temp), "%02x", ((unsigned char*)vp)[i]);
+ }
+ }
+
+ sprintf(s, OPT(info->elmt_fmt, "%s"), temp);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple
+ *
+ * Purpose: Print some values from a dataset with a simple data space.
+ * This is a special case of h5dump().
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+h5dump_simple(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 */
+
+ /* Print info */
+ hsize_t p_min_idx[8]; /*min selected index */
+ hsize_t p_max_idx[8]; /*max selected index */
+ size_t p_type_nbytes; /*size of memory type */
+ hsize_t p_nelmts; /*total selected elmts */
+ char p_buf[256]; /*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[8]; /*stripmine size */
+ hsize_t sm_nbytes; /*bytes per stripmine */
+ hsize_t sm_nelmts; /*elements per stripmine*/
+ unsigned char *sm_buf; /*buffer for raw data */
+ hid_t sm_space; /*stripmine data space */
+
+ /* Hyperslab info */
+ hssize_t hs_offset[8]; /*starting offset */
+ hsize_t hs_size[8]; /*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.
+ */
+ f_space = H5Dget_space(dset);
+ ndims = H5Sextent_ndims(f_space);
+ if ((size_t)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;
+ H5Sextent_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];
+ }
+
+ /*
+ * Determine the strip mine size and allocate a buffer. The strip mine is
+ * 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],
+ H5DUMP_BUFSIZE/sm_nbytes);
+ sm_nbytes *= sm_size[i-1];
+ assert(sm_nbytes>0);
+ }
+ sm_buf = malloc(sm_nbytes);
+ 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 */
+ 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]);
+ hs_nelmts *= hs_size[i];
+ }
+
+ /* Read the data */
+ H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL,
+ hs_size, NULL);
+ H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL,
+ &hs_nelmts, NULL);
+ H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf);
+
+ /* 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 (i+1<hs_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);
+ }
+
+ /* Calculate the next hyperslab offset */
+ for (i=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];
+ } else {
+ carry = 0;
+ }
+ }
+ }
+
+ if (p_column) {
+ fputs(OPT(info->line_suf, ""), stream);
+ putc('\n', stream);
+ fputs(OPT(info->line_sep, ""), stream);
+ }
+ H5Sclose(sm_space);
+ H5Sclose(f_space);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump
+ *
+ * Purpose: Print some values from a dataset. The values to print are
+ * determined by the P_SPACE argument and the format to use to
+ * print them is determined by the P_TYPE argument.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+h5dump(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type)
+{
+ hid_t f_space;
+
+ f_space = H5Dget_space(dset);
+ if (H5Sis_simple(f_space)<=0) return -1;
+ H5Sclose(f_space);
+
+ return h5dump_simple(stream, info, dset, p_type);
+}