From 8846157e5985458fd0a3ddb47658a14d10fb97b2 Mon Sep 17 00:00:00 2001 From: Pedro Vicente Nunes Date: Mon, 26 Jun 2006 09:41:59 -0500 Subject: [svn-r12437] Purpose: new feature. h5dump output of binary data Description: a new switch -b FILE_NAME that dumps the contents of memory data to file FILE_NAME in binary form new program binread.c that reads the contents of this file and outputs it to stdout added a test for the h5dump shell script that does a run of -b the binread.c program reads the data used in this run, usage is ./binread FILE_NAME Solution: Platforms tested: linux solaris AIX Misc. update: --- MANIFEST | 3 + tools/h5dump/Makefile.am | 2 +- tools/h5dump/Makefile.in | 20 +- tools/h5dump/binread.c | 100 +++++++++ tools/h5dump/h5dump.c | 62 ++++-- tools/h5dump/testh5dump.sh.in | 3 + tools/lib/h5tools.c | 477 +++++++++++++++++++++++++++++++++++++++- tools/lib/h5tools.h | 4 +- tools/testfiles/tbin.ddl | 11 + tools/testfiles/tnofilename.ddl | 1 + 10 files changed, 650 insertions(+), 33 deletions(-) create mode 100644 tools/h5dump/binread.c create mode 100644 tools/testfiles/tbin.ddl diff --git a/MANIFEST b/MANIFEST index f29ad6c..89cb160 100644 --- a/MANIFEST +++ b/MANIFEST @@ -778,6 +778,8 @@ ./tools/h5dump/h5dumpgentest.c ./tools/h5dump/testh5dump.sh.in ./tools/h5dump/testh5dumpxml.sh.in +./tools/h5dump/binread.c + ./tools/h5import/Makefile.am ./tools/h5import/Makefile.in @@ -1072,6 +1074,7 @@ ./tools/testfiles/tvms.ddl ./tools/testfiles/tldouble.h5 ./tools/testfiles/tvms.h5 +./tools/testfiles/tbin.ddl # Expected output from h5ls tests diff --git a/tools/h5dump/Makefile.am b/tools/h5dump/Makefile.am index 0cdc47b..94a6d73 100644 --- a/tools/h5dump/Makefile.am +++ b/tools/h5dump/Makefile.am @@ -26,7 +26,7 @@ INCLUDES=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib TEST_PROG=h5dumpgentest TEST_SCRIPT=testh5dump.sh testh5dumpxml.sh -check_PROGRAMS=$(TEST_PROG) +check_PROGRAMS=$(TEST_PROG) binread check_SCRIPTS=$(TEST_SCRIPT) SCRIPT_DEPEND=h5dump$(EXEEXT) diff --git a/tools/h5dump/Makefile.in b/tools/h5dump/Makefile.in index 897ad53..3c78e7e 100644 --- a/tools/h5dump/Makefile.in +++ b/tools/h5dump/Makefile.in @@ -30,7 +30,7 @@ # HDF5 Library Makefile(.in) # -SOURCES = h5dump.c h5dumpgentest.c +SOURCES = binread.c h5dump.c h5dumpgentest.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -58,7 +58,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/testh5dump.sh.in $(srcdir)/testh5dumpxml.sh.in \ $(top_srcdir)/config/commence.am \ $(top_srcdir)/config/conclude.am -check_PROGRAMS = $(am__EXEEXT_1) +check_PROGRAMS = $(am__EXEEXT_1) binread$(EXEEXT) bin_PROGRAMS = h5dump$(EXEEXT) subdir = tools/h5dump ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -72,11 +72,15 @@ am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) am__EXEEXT_1 = h5dumpgentest$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) +binread_SOURCES = binread.c +binread_OBJECTS = binread.$(OBJEXT) +binread_LDADD = $(LDADD) +am__DEPENDENCIES_1 = $(top_builddir)/tools/lib/libh5tools.la +am__DEPENDENCIES_2 = $(top_builddir)/src/libhdf5.la +binread_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) h5dump_SOURCES = h5dump.c h5dump_OBJECTS = h5dump.$(OBJEXT) h5dump_LDADD = $(LDADD) -am__DEPENDENCIES_1 = $(top_builddir)/tools/lib/libh5tools.la -am__DEPENDENCIES_2 = $(top_builddir)/src/libhdf5.la h5dump_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) h5dumpgentest_SOURCES = h5dumpgentest.c h5dumpgentest_OBJECTS = h5dumpgentest.$(OBJEXT) @@ -94,8 +98,8 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = h5dump.c h5dumpgentest.c -DIST_SOURCES = h5dump.c h5dumpgentest.c +SOURCES = binread.c h5dump.c h5dumpgentest.c +DIST_SOURCES = binread.c h5dump.c h5dumpgentest.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -434,6 +438,9 @@ clean-checkPROGRAMS: echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done +binread$(EXEEXT): $(binread_OBJECTS) $(binread_DEPENDENCIES) + @rm -f binread$(EXEEXT) + $(LINK) $(binread_LDFLAGS) $(binread_OBJECTS) $(binread_LDADD) $(LIBS) h5dump$(EXEEXT): $(h5dump_OBJECTS) $(h5dump_DEPENDENCIES) @rm -f h5dump$(EXEEXT) $(LINK) $(h5dump_LDFLAGS) $(h5dump_OBJECTS) $(h5dump_LDADD) $(LIBS) @@ -447,6 +454,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5dumpgentest.Po@am__quote@ diff --git a/tools/h5dump/binread.c b/tools/h5dump/binread.c new file mode 100644 index 0000000..d3b43a9 --- /dev/null +++ b/tools/h5dump/binread.c @@ -0,0 +1,100 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +/* + This program reads binary output from h5dump (-b option). + To use change the following 3 symbols accordingly. + For example, to read 6 elements of a float type from a file "out.dat", define + + #define NELMTS 6 + #define TYPE float + #define FORMAT "%f " + +*/ + +#define NELMTS 2 +#define TYPE int +#define FORMAT "%d " + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Prints a usage message on stderr and then returns. + * + * Return: void + * + * Programmer: Pedro Vicente Nunes + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage (void) +{ + fprintf(stderr, "\ + usage: binread FILE_NAME\n"); +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: main program. + * + *------------------------------------------------------------------------- + */ + +int +main (int argc, const char *argv[]) +{ + FILE *stream; + int numread; + TYPE buf[NELMTS]; + size_t i, nelmts = NELMTS; + char *fname=NULL; + + if (argc != 2) + { + usage(); + exit(1); + } + + fname = strdup(argv[1]); + + if( (stream = fopen(fname, "rb" )) != NULL ) + { + numread = fread( buf, sizeof( TYPE ), nelmts, stream ); + printf( "Number of items read = %d\n", numread ); + + for (i = 0; i < nelmts; i++) + { + printf(FORMAT,buf[i]); + } + printf("\n"); + + fclose( stream ); + } + else + printf( "File %s could not be opened\n",fname ); + + free(fname); + + return 0; +} + diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index 2a6b33a..c2bc761 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -351,7 +351,7 @@ struct handler_t { * parameters. The long-named ones can be partially spelled. When * adding more, make sure that they don't clash with each other. */ -static const char *s_opts = "hnpeyBHirVa:c:d:f:g:k:l:t:w:xD:uX:o:s:S:A"; +static const char *s_opts = "hnpeyBHirVa:c:d:f:g:k:l:t:w:xD:uX:o:b:s:S:A"; static struct long_options l_opts[] = { { "help", no_arg, 'h' }, { "hel", no_arg, 'h' }, @@ -600,6 +600,7 @@ usage(const char *prog) fprintf(stdout, " -g P, --group=P Print the specified group and all members\n"); fprintf(stdout, " -l P, --soft-link=P Print the value(s) of the specified soft link\n"); fprintf(stdout, " -o F, --output=F Output raw data into file F\n"); + fprintf(stdout, " -b F Output raw data into file F in binary form (use with -d)\n"); fprintf(stdout, " -t P, --datatype=P Print the specified named data type\n"); fprintf(stdout, " -w N, --width=N Set the number of columns of output\n"); fprintf(stdout, " -x, --xml Output in XML using Schema\n"); @@ -1952,7 +1953,7 @@ dump_subsetting_header(struct subset_t *sset, int dims) *------------------------------------------------------------------------- */ static void -dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int pindex) +dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int display_ai) { h5tool_format_t *outputformat = &dataformat; int status = -1; @@ -1967,7 +1968,7 @@ dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int pindex) outputformat->line_ncols = nCols; outputformat->do_escape=display_escape; /* print the matrix indices */ - outputformat->pindex=pindex; + outputformat->pindex=display_ai; if (outputformat->pindex) { outputformat->idx_fmt = "(%s): "; outputformat->idx_n_fmt = "%lu"; @@ -2001,7 +2002,7 @@ dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int pindex) /* Print all the values. */ if (obj_data == DATASET_DATA) { - hid_t f_type = H5Dget_type(obj_id); + hid_t f_type = H5Dget_type(obj_id); char string_prefix[64]; h5tool_format_t string_dataformat; @@ -2665,21 +2666,40 @@ static void dump_fcontents(hid_t fid) * Programmer: Albert Cheng, 2000/09/30 * * Modifications: + * pvn June, 1, 2006. Add a switch for binary output * *------------------------------------------------------------------------- */ static int -set_output_file(const char *fname) +set_output_file(const char *fname, int is_bin) { - FILE *f; /* temporary holding place for the stream pointer - * so that rawdatastream is changed only when succeeded */ - - if ((f = fopen(fname, "w")) != NULL) { - rawdatastream = f; - return 0; - } - - return -1; + FILE *f; /* temporary holding place for the stream pointer +* so that rawdatastream is changed only when succeeded */ + + if (rawdatastream && rawdatastream != stdout) { + if (fclose(rawdatastream)) + perror("closing rawdatastream"); + else + rawdatastream = NULL; + } + + /* binary output */ + if (is_bin) + { + if ((f = fopen(fname, "wb")) != NULL) { + rawdatastream = f; + return 0; + } + } + else + { + if ((f = fopen(fname, "w")) != NULL) { + rawdatastream = f; + return 0; + } + } + + return -1; } /*------------------------------------------------------------------------- @@ -3110,6 +3130,7 @@ handle_datatypes(hid_t fid, char *type, void UNUSED * data) * Tuesday, 20. February 2001 * * Modifications: + * pvn June, 1, 2006. Add a switch for binary output * *------------------------------------------------------------------------- */ @@ -3234,7 +3255,7 @@ parse_start: last_was_dset = FALSE; break; case 'o': - if (set_output_file(opt_arg) < 0){ + if (set_output_file(opt_arg, 0) < 0){ /* failed to set output file */ usage(progname); leave(EXIT_FAILURE); @@ -3244,6 +3265,17 @@ parse_start: last_was_dset = FALSE; break; + case 'b': + if (set_output_file(opt_arg, 1) < 0){ + /* failed to set output file */ + usage(progname); + leave(EXIT_FAILURE); + } + + bin_output = TRUE; + last_was_dset = FALSE; + break; + /** begin XML parameters **/ case 'x': /* select XML output */ diff --git a/tools/h5dump/testh5dump.sh.in b/tools/h5dump/testh5dump.sh.in index c23651b..f390110 100644 --- a/tools/h5dump/testh5dump.sh.in +++ b/tools/h5dump/testh5dump.sh.in @@ -320,6 +320,9 @@ TOOLTEST tlonglinks.ddl tlonglinks.h5 # test for vms TOOLTEST tvms.ddl tvms.h5 +# test for binary output +TOOLTEST tbin.ddl -d integer -b out.bin test1.h5 + if test $nerrors -eq 0 ; then echo "All $DUMPER tests passed." fi diff --git a/tools/lib/h5tools.c b/tools/lib/h5tools.c index 01f0fca..a38a435 100644 --- a/tools/lib/h5tools.c +++ b/tools/lib/h5tools.c @@ -46,6 +46,11 @@ /* global variables */ int compound_data; FILE *rawdatastream; /* should initialize to stdout but gcc moans about it */ +int bin_output; /* binary output */ + +/* local prototypes */ +static int do_bin_output(FILE *stream, hsize_t nelmts, hid_t tid, void *_mem); +static int render_bin_output(FILE *stream, hid_t tid, void *_mem); /* module-scoped variables */ static int h5tools_init_g; /* if h5tools lib has been initialized */ @@ -558,16 +563,24 @@ h5tools_dump_simple_data(FILE *stream, const h5tool_format_t *info, hid_t contai *break after we see a number equal *to the ctx->size_last_dim. */ - /* Setup */ - memset(&buffer, 0, sizeof(h5tools_str_t)); - size = H5Tget_size(type); - - if (info->line_ncols > 0) - ncols = info->line_ncols; - - h5tools_simple_prefix(stream, info, ctx, (hsize_t)0, 0); - - for (i = 0; i < nelmts; i++, ctx->cur_elmt++, elmt_counter++) { + /* binary dump */ + if (bin_output) + { + do_bin_output(stream,nelmts,type,_mem); + bin_output=0; + } + else + { + /* Setup */ + memset(&buffer, 0, sizeof(h5tools_str_t)); + size = H5Tget_size(type); + + if (info->line_ncols > 0) + ncols = info->line_ncols; + + h5tools_simple_prefix(stream, info, ctx, (hsize_t)0, 0); + + for (i = 0; i < nelmts; i++, ctx->cur_elmt++, elmt_counter++) { /* Render the element */ h5tools_str_reset(&buffer); h5tools_str_sprint(&buffer, info, container, type, mem + i * size, ctx); @@ -688,6 +701,9 @@ h5tools_dump_simple_data(FILE *stream, const h5tool_format_t *info, hid_t contai } h5tools_str_close(&buffer); + + }/* else bin */ + } /*------------------------------------------------------------------------- @@ -1284,3 +1300,444 @@ void init_acc_pos(h5tools_context_t *ctx, hsize_t *dims) ctx->pos[i]=0; } + +/*------------------------------------------------------------------------- + * Function: do_bin_output + * + * Purpose: Dump memory buffer to a binary file stream + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Pedro Vicente Nunes + * Friday, June 2, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static +int do_bin_output(FILE *stream, hsize_t nelmts, hid_t tid, void *_mem) +{ + unsigned char *mem = (unsigned char*)_mem; + size_t size; /* datum size */ + hsize_t i; /* element counter */ + + size = H5Tget_size(tid); + + for (i = 0; i < nelmts; i++) + { + if (render_bin_output(stream,tid,mem + i * size)<0) + { + printf("\nError in writing binary stream\n"); + return FAIL; + } + } + + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: render_bin_output + * + * Purpose: Write one element of memory buffer to a binary file stream + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Pedro Vicente Nunes + * Friday, June 2, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static +int render_bin_output(FILE *stream, hid_t tid, void *_mem) +{ +#if 0 + #define DEBUG_H5DUMP_BIN 1 +#endif + unsigned char *mem = (unsigned char*)_mem; + size_t size; /* datum size */ + float tempfloat; + double tempdouble; + unsigned long_long tempullong; + long_long templlong; + unsigned long tempulong; + long templong; + unsigned int tempuint; + int tempint; + unsigned short tempushort; + short tempshort; + unsigned char tempuchar; + char tempschar; +#if H5_SIZEOF_LONG_DOUBLE !=0 + long double templdouble; +#endif +#if DEBUG_H5DUMP_BIN + static char fmt_llong[8], fmt_ullong[8]; + if (!fmt_llong[0]) { + sprintf(fmt_llong, "%%%sd", H5_PRINTF_LL_WIDTH); + sprintf(fmt_ullong, "%%%su", H5_PRINTF_LL_WIDTH); + } +#endif + + size = H5Tget_size(tid); + + if (H5Tequal(tid, H5T_NATIVE_FLOAT)) + { + memcpy(&tempfloat, mem, sizeof(float)); +#if DEBUG_H5DUMP_BIN + fprintf(stream, "%g ", tempfloat); +#else + if (1 != fwrite(&tempfloat, size, 1, stream)) + return FAIL; +#endif + } + else if (H5Tequal(tid, H5T_NATIVE_DOUBLE)) + { + memcpy(&tempdouble, mem, sizeof(double)); +#if DEBUG_H5DUMP_BIN + fprintf(stream, "%g ", tempdouble); +#else + if (1 != fwrite(&tempdouble, size, 1, stream)) + return FAIL; +#endif + } +#if H5_SIZEOF_LONG_DOUBLE !=0 + else if (H5Tequal(tid, H5T_NATIVE_LDOUBLE)) + { + memcpy(&templdouble, mem, sizeof(long double)); +#if DEBUG_H5DUMP_BIN + fprintf(stream, "%Lf ", templdouble); +#else + if (1 != fwrite(&templdouble, size, 1, stream)) + return FAIL; +#endif + } +#endif + else if (H5T_STRING == H5Tget_class(tid)) + { + unsigned int i; + H5T_str_t pad; + char *s; + + pad = H5Tget_strpad(tid); + + if(H5Tis_variable_str(tid)) + { + s = *(char**)mem; + if(s!=NULL) + size = HDstrlen(s); + } + else + { + s = mem; + size = H5Tget_size(tid); + } + for (i=0; i= 1 && ndims <= H5S_MAX_RANK); + + /* calculate the number of array elements */ + for (k = 0, nelmts = 1; k < ndims; k++) + { + temp_nelmts = nelmts; + temp_nelmts *= dims[k]; + nelmts = (size_t)temp_nelmts; + } + + /* dump the array element */ + for (i = 0; i < nelmts; i++) + { + if (render_bin_output(stream,memb,mem + i * size)<0) + return FAIL; + } + + H5Tclose(memb); + } + else if (H5Tget_class(tid) == H5T_VLEN) + { + unsigned int i; + hsize_t nelmts; + hid_t memb; + + /* get the VL sequences's base datatype for each element */ + memb = H5Tget_super(tid); + size = H5Tget_size(memb); + + /* Get the number of sequence elements */ + nelmts = ((hvl_t *)mem)->len; + + for (i = 0; i < nelmts; i++) + { + /* dump the array element */ + if (render_bin_output(stream,memb,((char *)(((hvl_t *)mem)->p)) + i * size)<0) + return FAIL; + } + H5Tclose(memb); + } + else + { + /* all other types get printed as hexadecimal */ + size_t i; + if (1==size) + { +#if DEBUG_H5DUMP_BIN + fprintf(stream, "0x%02x", mem[0]); +#else + if (1 != fwrite(&mem[0], size, 1, stream)) + return FAIL; +#endif + } + else + { + for (i = 0; i < size; i++) + { +#if DEBUG_H5DUMP_BIN + fprintf(stream, "%s%02x", i?":":"", mem[i]); +#else + if (1 != fwrite(&mem[i], sizeof(char), 1, stream)) + return FAIL; +#endif + } /*i*/ + }/*else 1 */ + } + + + return SUCCEED; +} + diff --git a/tools/lib/h5tools.h b/tools/lib/h5tools.h index 4bbc2d6..861c474 100644 --- a/tools/lib/h5tools.h +++ b/tools/lib/h5tools.h @@ -352,7 +352,9 @@ struct subset_t { hsize_t *block; }; -extern FILE *rawdatastream; /*output stream for raw data */ +extern FILE *rawdatastream; /* output stream for raw data */ +extern int bin_output; /* binary output */ + /* Strings for output */ #define GROUP "GROUP" diff --git a/tools/testfiles/tbin.ddl b/tools/testfiles/tbin.ddl new file mode 100644 index 0000000..0ffebb8 --- /dev/null +++ b/tools/testfiles/tbin.ddl @@ -0,0 +1,11 @@ +############################# +Expected output for 'h5dump -d integer -b out.bin test1.h5' +############################# +HDF5 "test1.h5" { +DATASET "integer" { + DATATYPE H5T_STD_I32LE + DATASPACE SIMPLE { ( 2 ) / ( 2 ) } + DATA { + } +} +} diff --git a/tools/testfiles/tnofilename.ddl b/tools/testfiles/tnofilename.ddl index 36cbcad..2b9107a 100644 --- a/tools/testfiles/tnofilename.ddl +++ b/tools/testfiles/tnofilename.ddl @@ -20,6 +20,7 @@ usage: h5dump [OPTIONS] file -g P, --group=P Print the specified group and all members -l P, --soft-link=P Print the value(s) of the specified soft link -o F, --output=F Output raw data into file F + -b F Output raw data into file F in binary form (use with -d) -t P, --datatype=P Print the specified named data type -w N, --width=N Set the number of columns of output -x, --xml Output in XML using Schema -- cgit v0.12