diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.in | 25 | ||||
-rw-r--r-- | tools/h5ls.c | 129 | ||||
-rw-r--r-- | tools/h5tools.c | 327 | ||||
-rw-r--r-- | tools/h5tools.h | 81 |
4 files changed, 520 insertions, 42 deletions
diff --git a/tools/Makefile.in b/tools/Makefile.in index 1f93b00..2ab717a 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -7,26 +7,33 @@ @COMMENCE@ # Add include directory to the C preprocessor flags. -CPPFLAGS=-I../src @CPPFLAGS@ +CPPFLAGS=-I../src -I. @CPPFLAGS@ # These are our main targets: PROGS=h5debug h5import h5ls h5repart +LIB=libh5tools.a +LIBS=../src/libhdf5.a libh5tools.a @LIBS@ + +# Source and object files for the library. +LIB_SRC=h5dump.c +LIB_OBJ=$(LIB_SRC:.c=.o) # Source and object files for programs... PROG_SRC=h5debug.c h5import.c h5ls.c h5repart.c PROG_OBJ=$(PROG_SRC:.c=.o) +PRIVATE_HDR=h5tools.h # How to build the programs... -h5debug: h5debug.o ../src/libhdf5.a - $(CC) $(CFLAGS) -o $@ h5debug.o ../src/libhdf5.a $(LIBS) +h5debug: h5debug.o $(LIB) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ h5debug.o $(LIBS) -h5import: h5import.o ../src/libhdf5.a - $(CC) $(CFLAGS) -o $@ h5import.o ../src/libhdf5.a $(LIBS) +h5import: h5import.o $(LIB) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ h5import.o $(LIBS) -h5ls: h5ls.o ../src/libhdf5.a - $(CC) $(CFLAGS) -o $@ h5ls.o ../src/libhdf5.a $(LIBS) +h5ls: h5ls.o $(LIB) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ h5ls.o $(LIBS) -h5repart: h5repart.o ../src/libhdf5.a - $(CC) $(CFLAGS) -o $@ h5repart.o ../src/libhdf5.a $(LIBS) +h5repart: h5repart.o $(LIB) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ h5repart.o $(LIBS) @CONCLUDE@ diff --git a/tools/h5ls.c b/tools/h5ls.c index 8127d13..93a756a 100644 --- a/tools/h5ls.c +++ b/tools/h5ls.c @@ -6,6 +6,7 @@ * Monday, March 23, 1998 */ #include <ctype.h> +#include <h5tools.h> #include <hdf5.h> #include <stdio.h> #include <stdlib.h> @@ -20,8 +21,10 @@ # define __unused__ __attribute__((unused)) #endif -/* Verbosity level */ +/* Command-line switches */ static int verbose_g = 0; +static int dump_g = 0; +static int width_g = 80; /*------------------------------------------------------------------------- @@ -45,6 +48,8 @@ usage (const char *progname) usage: %s [OPTIONS] FILE [GROUP]\n\ OPTIONS\n\ -h, -?, --help Print a usage message and exit\n\ + -d, --dump Print the values of datasets\n\ + -wN, --width=N Set the number of columns of output\n\ -v, --verbose Generate more verbose output\n\ -V, --version Print version number and exit\n\ FILE\n\ @@ -73,41 +78,72 @@ usage: %s [OPTIONS] FILE [GROUP]\n\ static void dump_dataset_values(hid_t dset) { - hid_t file_space, mem_space, type; - hsize_t file_nelmts, mem_nelmts; - hssize_t start, zero=0; - unsigned char buf[1024]; - hsize_t i; + hid_t f_type, m_type=-1; + h5dump_t info; + size_t size; - file_space = H5Dget_space(dset); - type = H5Dget_type(dset); + /* Set to all default values and then override */ + memset(&info, 0, sizeof info); + info.idx_fmt = " (%s) "; + info.line_ncols = width_g; - if (H5Tequal(type, H5T_NATIVE_CHAR)) { - printf("%*svalue = \"", 26, ""); - file_nelmts = H5Sextent_npoints(file_space); - mem_nelmts = sizeof(buf); - mem_space = H5Screate_simple(1, &mem_nelmts, NULL); - for (start=0; - start<(hssize_t)file_nelmts; - start+=(hssize_t)mem_nelmts) { - mem_nelmts = MIN(mem_nelmts, file_nelmts-(hsize_t)start); - H5Sselect_hyperslab(file_space, H5S_SELECT_SET, &start, NULL, - &mem_nelmts, NULL); - H5Sselect_hyperslab(mem_space, H5S_SELECT_SET, &zero, NULL, - &mem_nelmts, NULL); - H5Dread(dset, H5T_NATIVE_CHAR, mem_space, file_space, H5P_DEFAULT, - buf); - for (i=0; i<mem_nelmts; i++) { - if (isprint(buf[i])) putchar(buf[i]); - else printf("\\%03o", buf[i]); - } + /* + * Decide which data type to use for printing the values and make any + * necessary adjustments to the way the values will be formatted. + */ + f_type = H5Dget_type(dset); + size = H5Tget_size(f_type); + switch (H5Tget_class(f_type)) { + case H5T_INTEGER: + if (1==size) { + /* + * Assume that the dataset is being used to hold character values + * and print the values as strings. + */ + info.elmt_suf1 = ""; + info.elmt_suf2 = ""; + info.idx_fmt = " (%s) \""; + info.line_suf = "\""; } - H5Sclose(mem_space); - printf("\"\n"); - } - H5Sclose(file_space); - H5Tclose(type); + /* + * For printing use an integer which is the same width and sign as + * the file but in native byte order. + */ + m_type = H5Tcopy(H5T_NATIVE_INT); + H5Tset_offset(m_type, 0); + H5Tset_precision(m_type, size*8); + H5Tset_size(m_type, size); + H5Tset_sign(m_type, H5Tget_sign(f_type)); + break; + + case H5T_FLOAT: + if (size==sizeof(float)) { + m_type = H5Tcopy(H5T_NATIVE_FLOAT); + } else { + m_type = H5Tcopy(H5T_NATIVE_DOUBLE); + } + break; + + case H5T_COMPOUND: + printf(" Data: printing of compound data types is not implemented " + "yet\n"); + break; + + default: + /*unable to print*/ + printf(" Data: [unable to print]\n"); + break; + } + H5Tclose(f_type); + if (m_type<0) return; /*not printable*/ + + /* + * Print all the values. + */ + printf(" Data:\n"); + h5dump(stdout, &info, dset, m_type); + H5Tclose(m_type); } @@ -209,7 +245,7 @@ list (hid_t group, const char *name, void __unused__ *op_data) printf ("}\n"); H5Dclose (space); H5Aiterate (obj, NULL, list_attr, NULL); - dump_dataset_values(obj); + if (dump_g) dump_dataset_values(obj); H5Dclose (obj); } else if ((obj=H5Gopen (group, name))>=0) { printf ("Group\n"); @@ -229,6 +265,7 @@ list (hid_t group, const char *name, void __unused__ *op_data) } /* Display the comment if the object has one */ + comment[0] = '\0'; H5Gget_comment(group, name, sizeof(comment), comment); strcpy(comment+sizeof(comment)-4, "..."); if (comment[0]) printf("%26s%s\n", "", comment); @@ -264,6 +301,7 @@ main (int argc, char *argv[]) const char *gname = "/"; const char *progname; const char *s; + char *rest; int argno; /* Name of this program without the path */ @@ -279,12 +317,34 @@ main (int argc, char *argv[]) } else if (!strcmp(argv[argno], "--help")) { usage(progname); exit(0); + } else if (!strcmp(argv[argno], "--dump")) { + dump_g++; + } else if (!strncmp(argv[argno], "--width=", 8)) { + width_g = strtol(argv[argno]+8, &rest, 0); + if (width_g<=0 || *rest) { + usage(progname); + exit(1); + } } else if (!strcmp(argv[argno], "--verbose")) { verbose_g++; } else if (!strcmp(argv[argno], "--version")) { printf("This is %s version %u.%u release %u\n", progname, H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE); exit(0); + } else if (!strncmp(argv[argno], "-w", 2)) { + if (argv[argno][2]) { + s = argv[argno]+2; + } else if (argno+1>=argc) { + usage(progname); + exit(1); + } else { + s = argv[++argno]; + } + width_g = strtol(s, &rest, 0); + if (width_g<=0 || *rest) { + usage(progname); + exit(1); + } } else if ('-'!=argv[argno][1]) { /* Single-letter switches */ for (s=argv[argno]+1; *s; s++) { @@ -293,6 +353,9 @@ main (int argc, char *argv[]) case 'h': /* --help */ usage(progname); exit(0); + case 'd': /* --dump */ + dump_g++; + break; case 'v': /* --verbose */ verbose_g++; break; 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); +} diff --git a/tools/h5tools.h b/tools/h5tools.h new file mode 100644 index 0000000..966eaff --- /dev/null +++ b/tools/h5tools.h @@ -0,0 +1,81 @@ +/* + * Copyright © 1998 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke <matzke@llnl.gov> + * Thursday, July 23, 1998 + * + * Purpose: Support functions for the various tools. + */ +#ifndef _H5TOOLS_H +#define _H5TOOLS_H + +#include <hdf5.h> +#include <stdio.h> + +/* + * Information about how to format output. + */ +typedef struct h5dump_t { + /* + * Fields associated with the individual elements. + * + * fmt: A printf(3c) format to use to print the value string + * after it has been rendered. The default is "%s". + * + * suf1: This string is appended to elements which are followed by + * another element whether the following element is on the + * same line or the next line. The default is a comma. + * + * suf2: This string is appended (after `suf1') to elements which + * are followed on the same line by another element. The + * default is a single space. + */ + const char *elmt_fmt; + const char *elmt_suf1; + const char *elmt_suf2; + + /* + * Fields associated with the index values printed at the left edge of + * each line of output. + * + * n_fmt: Each index value is printed according to this printf(3c) + * format string which should include a format for a long + * integer. The default is "%lu". + * + * sep: Each integer in the index list will be separated from the + * others by this string, which defaults to a comma. + * + * fmt: After the index values are formated individually and + * separated from one another by some string, the entire + * resulting string will be formated according to this + * printf(3c) format which should include a format for a + * character string. The default is "%s". + */ + const char *idx_n_fmt; /*index number format */ + const char *idx_sep; /*separator between numbers */ + const char *idx_fmt; /*entire index format */ + + /* + * Fields associated with entire lines. + * + * ncols: Number of columns per line defaults to 80. + * + * suf: This character string will be appended to each line of + * output. It should not contain line feeds. The default + * is the empty string. + * + * sep: A character string to be printed after every line feed + * defaulting to the empty string. It should end with a + * line feed. + */ + int line_ncols; /*columns of output */ + const char *line_suf; /*string to append to each line */ + const char *line_sep; /*separates lines */ + +} h5dump_t; + + +int h5dump(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type); + +#endif |