diff options
-rw-r--r-- | tools/Makefile.in | 9 | ||||
-rw-r--r-- | tools/h5dump.c | 660 | ||||
-rw-r--r-- | tools/h5dump.h | 160 | ||||
-rw-r--r-- | tools/h5dumputil.c | 523 |
4 files changed, 1349 insertions, 3 deletions
diff --git a/tools/Makefile.in b/tools/Makefile.in index 2ab717a..e2c14c9 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -10,16 +10,16 @@ CPPFLAGS=-I../src -I. @CPPFLAGS@ # These are our main targets: -PROGS=h5debug h5import h5ls h5repart +PROGS=h5debug h5import h5ls h5repart h5dump LIB=libh5tools.a LIBS=../src/libhdf5.a libh5tools.a @LIBS@ # Source and object files for the library. -LIB_SRC=h5dump.c +LIB_SRC=h5tools.c LIB_OBJ=$(LIB_SRC:.c=.o) # Source and object files for programs... -PROG_SRC=h5debug.c h5import.c h5ls.c h5repart.c +PROG_SRC=h5debug.c h5import.c h5ls.c h5repart.c h5dump.c h5dumputil.c PROG_OBJ=$(PROG_SRC:.c=.o) PRIVATE_HDR=h5tools.h @@ -36,4 +36,7 @@ h5ls: h5ls.o $(LIB) ../src/libhdf5.a h5repart: h5repart.o $(LIB) ../src/libhdf5.a $(CC) $(CFLAGS) -o $@ h5repart.o $(LIBS) +h5dump: h5dump.o h5dumputil.o $(LIB) ../src/libhdf5.a + $(CC) $(CFLAGS) -o $@ h5dump.o h5dumputil.o $(LIBS) + @CONCLUDE@ diff --git a/tools/h5dump.c b/tools/h5dump.c new file mode 100644 index 0000000..a8a0a81 --- /dev/null +++ b/tools/h5dump.c @@ -0,0 +1,660 @@ +#include <h5dump.h> + +static int indent = 0; + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message about dumper + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +usage() +{ + +printf("Usage: dumper <filename>\n"); + +/* + printf(" Usage: h5dumper [OPTIONS] <file>\n"); + printf(" OPTIONS\n"); + printf(" -H Print a usage message \n"); + printf(" -nobb No boot block\n"); + printf(" -nodata No data\n"); + printf(" -g <name> Dump everything in the group with name <name>\n"); + printf(" -d <name> Dump everything in the dataset with name <name>\n"); + printf(" -l <name> Dump the target of the link with name <link>\n"); +*/ +} + + +/*------------------------------------------------------------------------- + * Function: indentation + * + * Purpose: Print spaces for indentation + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void indentation(int x) { + + while (x>0) { + printf(" "); + x--; + } + +} + + +/*------------------------------------------------------------------------- + * Function: datatype_name + * + * Purpose: Returns the name of data type. + * + * Return: Returns a pointer to a string. + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static char* +datatype_name(hid_t type) { + + switch (H5Tget_class(type)) { + + case H5T_INTEGER: + + if (H5Tequal(type, H5T_NATIVE_CHAR)) + return "H5T_NATIVE_CHAR"; + else if (H5Tequal(type, H5T_NATIVE_UCHAR)) + return "H5T_NATIVE_UCHAR"; + else if (H5Tequal(type, H5T_NATIVE_SHORT)) + return "H5T_NATIVE_SHORT"; + else if (H5Tequal(type, H5T_NATIVE_USHORT)) + return "H5T_NATIVE_USHORT"; + else if (H5Tequal(type, H5T_NATIVE_INT)) + return "H5T_NATIVE_INT"; + else if (H5Tequal(type, H5T_NATIVE_UINT)) + return "H5T_NATIVE_UINT"; + else if (H5Tequal(type, H5T_NATIVE_LONG)) + return "H5T_NATIVE_LONG"; + else if (H5Tequal(type, H5T_NATIVE_ULONG)) + return "H5T_NATIVE_ULONG"; + else if (H5Tequal(type, H5T_NATIVE_LLONG)) + return "H5T_NATIVE_LLONG"; + else if (H5Tequal(type, H5T_NATIVE_ULLONG)) + return "H5T_NATIVE_ULLONG"; + else if (H5Tequal(type, H5T_STD_I8BE)) + return "H5T_STD_I8BE"; + else if (H5Tequal(type, H5T_STD_I8LE)) + return "H5T_STD_I8LE"; + else if (H5Tequal(type, H5T_STD_I16BE)) + return "H5T_STD_I16BE"; + else if (H5Tequal(type, H5T_STD_I16LE)) + return "H5T_STD_I16LE"; + else if (H5Tequal(type, H5T_STD_I32BE)) + return "H5T_STD_I32BE"; + else if (H5Tequal(type, H5T_STD_I32LE)) + return "H5T_STD_I32LE"; + else if (H5Tequal(type, H5T_STD_I64BE)) + return "H5T_STD_I64BE"; + else if (H5Tequal(type, H5T_STD_I64LE)) + return "H5T_STD_I64LE"; + else if (H5Tequal(type, H5T_STD_U8BE)) + return "H5T_STD_U8BE"; + else if (H5Tequal(type, H5T_STD_U8LE)) + return "H5T_STD_U8LE"; + else if (H5Tequal(type, H5T_STD_U16BE)) + return "H5T_STD_U16BE"; + else if (H5Tequal(type, H5T_STD_U16LE)) + return "H5T_STD_U16LE"; + else if (H5Tequal(type, H5T_STD_U32BE)) + return "H5T_STD_U32BE"; + else if (H5Tequal(type, H5T_STD_U32LE)) + return "H5T_STD_U32LE"; + else if (H5Tequal(type, H5T_STD_U64BE)) + return "H5T_STD_U64BE"; + else if (H5Tequal(type, H5T_STD_U64LE)) + return "H5T_STD_U64LE"; + else return "unknown integer"; + + case H5T_FLOAT: + + if (H5Tequal(type, H5T_NATIVE_FLOAT)) + return "H5T_NATIVE_FLOAT"; + else if (H5Tequal(type, H5T_NATIVE_DOUBLE)) + return "H5T_NATIVE_DOUBLE"; + else if (H5Tequal(type, H5T_NATIVE_LDOUBLE)) + return "H5T_NATIVE_LDOUBLE"; + else if (H5Tequal(type, H5T_IEEE_F32BE)) + return "H5T_IEEE_F32BE"; + else if (H5Tequal(type, H5T_IEEE_F32LE)) + return "H5T_IEEE_F32LE"; + else if (H5Tequal(type, H5T_IEEE_F64BE)) + return "H5T_IEEE_F64BE"; + else if (H5Tequal(type, H5T_IEEE_F64LE)) + return "H5T_IEEE_F64LE"; + else return "unknown float"; + + case H5T_TIME: return "time: not yet implemented"; + + case H5T_STRING: + + if (H5Tequal(type,H5T_C_S1)) + return "H5T_C_S1"; + else if (H5Tequal(type,H5T_FORTRAN_S1)) + return "H5T_FORTRAN_S1"; + else return "unknown string"; + + case H5T_BITFIELD: + + if (H5Tequal(type, H5T_STD_B8BE)) + return "H5T_STD_B8BE"; + else if (H5Tequal(type, H5T_STD_B8LE)) + return "H5T_STD_B8LE"; + else if (H5Tequal(type, H5T_STD_B16BE)) + return "H5T_STD_B16BE"; + else if (H5Tequal(type, H5T_STD_B16LE)) + return "H5T_STD_B16LE"; + else if (H5Tequal(type, H5T_STD_B32BE)) + return "H5T_STD_B32BE"; + else if (H5Tequal(type, H5T_STD_B32LE)) + return "H5T_STD_B32LE"; + else if (H5Tequal(type, H5T_STD_B64BE)) + return "H5T_STD_B64BE"; + else if (H5Tequal(type, H5T_STD_B64LE)) + return "H5T_STD_B64LE"; + else return "unknown bitfield"; + + case H5T_OPAQUE: return "opaque: not yet implemented"; + + case H5T_COMPOUND: + + return "compound: not yet implemented"; + + default: + return "unknown data type"; + } + +} + + +/*------------------------------------------------------------------------- + * Function: dump_bb + * + * Purpose: Dump the boot block + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_bb() { + + printf ("%s %s %s\n", BOOT_BLOCK, BEGIN, END); + +} + + +/*------------------------------------------------------------------------- + * Function: dump_datatype + * + * Purpose: Dump the data type. Data type can be HDF5 predefined + * atomic data type, named data type or compound data type. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_datatype (hid_t type) { +char *pt; +char *fname ; +hid_t nmembers, mtype; +int i, ndims, perm[512]; +size_t dims[512]; + + indent += col; + indentation (indent); + pt = datatype_name(type); + printf ("%s %s \"%s\" %s\n", DATATYPE, BEGIN, pt, END); + indent -= col; +} + + +/*------------------------------------------------------------------------- + * Function: dump_dataspace + * + * Purpose: Dump the data space. Data space can be named data space, + * array, or others. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_dataspace (hid_t dataset_id, hid_t space) { +hsize_t size[64]; +hsize_t maxsize[64]; /* check max dims size */ +int ndims = H5Sextent_dims(space, size, maxsize); +int i; + + indent += col; + + indentation (indent); + + printf("%s ", DATASPACE); + + if (H5Sis_simple(space)) { + + HDfprintf (stdout, "%s %s ( %Hu",BEGIN, ARRAY, size[0]); + for (i = 1; i < ndims; i++) + HDfprintf (stdout, ", %Hu", size[i]); + printf(" ) "); + + if (maxsize[0]==H5S_UNLIMITED) + HDfprintf (stdout, "( %s", "H5S_UNLIMITED"); + else + HDfprintf (stdout, "( %Hu", maxsize[0]); + + for (i = 1; i < ndims; i++) + if (maxsize[i]==H5S_UNLIMITED) + HDfprintf (stdout, ", %s", "H5S_UNLIMITED"); + else + HDfprintf (stdout, ", %Hu", maxsize[i]); + + printf(" ) %s\n", END); + + } else + + printf("%s not yet implemented %s\n", BEGIN, END); + + indent -= col; + +} + + +/*------------------------------------------------------------------------- + * Function: dump_attr + * + * Purpose: dump the attribute + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static herr_t +dump_attr (hid_t attr, const char *attr_name, void __unused__ *op_data) +{ +hid_t attr_id, type, space; + + indentation(indent); + begin_obj (ATTRIBUTE, attr_name); + + if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) { + + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + dump_datatype(type); + dump_dataspace(attr_id, space); + dump_data(attr_id, ATTRIBUTE_DATA); + H5Tclose(type); + H5Sclose(space); + H5Aclose (attr_id); + + } else { + indent += col; + indentation (indent); + printf("Unable to open attribute.\n", attr_name); + indent -= col; + return FAIL; + } + + indentation (indent); + end_obj(); + + return SUCCEED; + +} + + +/*------------------------------------------------------------------------- + * Function: dump all + * + * Purpose: Dump everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static herr_t +dump_all (hid_t group, const char *name, void __unused__ *op_data) +{ +hid_t obj; +hid_t (*func)(void*); +void *edata; +char buf[512]; /* Is 512 large enough? */ + + /* Disable error reporting */ + H5Eget_auto (&func, &edata); + H5Eset_auto (NULL, NULL); + + + if (H5Gget_linkval (group, name, sizeof(buf), buf)>=0) { + + indentation (indent); + begin_obj(SOFTLINK, name); + indent += col; + indentation (indent); + printf ("linktarget \"%s\"\n", buf); + indent -= col; + indentation (indent); + end_obj(); + + } else if ((obj=H5Dopen (group, name))>=0) { + + dump_dataset (obj, name); + H5Dclose (obj); + + } else if ((obj=H5Gopen (group, name))>=0) { + + dump_group (obj, name); + H5Gclose (obj); + + } else if ((obj=H5Topen(group, name))>=0) { + + dump_named_datatype (obj, name); + H5Tclose(obj); + + } else { + + printf ("Unknown Object %s\n", name); + H5Eset_auto (func, edata); + return FAIL; + + } + + /* Restore error reporting */ + H5Eset_auto (func, edata); + + return SUCCEED; + +} + + +/*------------------------------------------------------------------------- + * Function: dump_named_datatype + * + * Purpose: Dump named data type + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_named_datatype (hid_t type_id, const char *name) { +char *fname ; +hid_t nmembers, mtype; +int i, ndims, perm[512]; /* dimensionality */ +size_t dims[512]; + + indentation (indent); + begin_obj(DATATYPE, name); + + indent += col; + indentation(indent); + printf("named data type: not yet implemented.\n"); + indent -= col; + + indentation (indent); + end_obj(); + +} + + +/*------------------------------------------------------------------------- + * Function: dump_group + * + * Purpose: Dump everything within the specified group + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_group (hid_t gid, const char *name) { + + indentation (indent); + begin_obj(GROUP, name); + indent += col; + H5Aiterate (gid, NULL, dump_attr, NULL); + H5Giterate (gid, ".", NULL, dump_all, NULL); + indent -= col; + indentation (indent); + end_obj(); + +} + + +/*------------------------------------------------------------------------- + * Function: dump_dataset + * + * Purpose: Dump the specified data set + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_dataset (hid_t did, const char *name) { +hid_t type, space; + + indentation (indent); + begin_obj(DATASET, name); + indent += col; + H5Aiterate (did, NULL, dump_attr, NULL); + indent -= col; + type = H5Dget_type (did); + space = H5Dget_space (did); + dump_datatype(type); + dump_dataspace(did, space); + + switch (H5Tget_class(type)) { + case H5T_INTEGER: + dump_data(did, DATASET_DATA); + break; + case H5T_FLOAT: + dump_data(did, DATASET_DATA); + break; + case H5T_TIME: + indent += col; + indentation (indent); + indent -= col; + printf("DATA{ not yet implemented.}\n"); + break; + case H5T_STRING: + indent += col; + indentation (indent); + indent -= col; + printf("DATA{ not yet implemented.}\n"); + break; + case H5T_BITFIELD: + indent += col; + indentation (indent); + indent -= col; + printf("DATA{ not yet implemented.}\n"); + break; + case H5T_OPAQUE: + indent += col; + indentation (indent); + indent -= col; + printf("DATA{ not yet implemented.}\n"); + break; + case H5T_COMPOUND: + indent += col; + indentation (indent); + indent -= col; + printf("DATA{ not yet implemented.}\n"); + break; + default: break; + } + + H5Tclose(type); + H5Sclose(space); + indentation (indent); + end_obj(); + +} + + +/*------------------------------------------------------------------------- + * Function: dump_data + * + * Purpose: Dump attribute or dataset data + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +static void +dump_data (hid_t obj_id, int obj_data) { + + hid_t f_type ; + size_t size ; + h5dump_t info; + + indent += col; + indentation (indent); + printf("%s %s", DATA, BEGIN); + + if (obj_data == DATASET_DATA) + f_type = H5Dget_type(obj_id); + else + f_type = H5Aget_type(obj_id); + + size = H5Tget_size(f_type); + + /* Set to all default values and then override */ + memset(&info, 0, sizeof info); + info.idx_fmt = " (%s) "; + info.line_ncols = 80; + + /* + * If the dataset is a 1-byte integer type then format it as an ASCI + * character string instead of integers. + */ + if (1==size && H5T_INTEGER==H5Tget_class(f_type)) { + info.elmt_suf1 = ""; + info.elmt_suf2 = ""; + info.idx_fmt = " (%s) \""; + info.line_suf = "\""; + printf("\""); + } + + + /* + * Print all the values. + */ + + if (h5dump1(stdout, &info, obj_id, -1, obj_data)<0) { + printf("Unable to print data."); + } + + if (1==size && H5T_INTEGER==H5Tget_class(f_type)) + printf("\""); + + printf("%s\n", END); + indent -= col; + + H5Tclose(f_type); + +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 dumper + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *-----------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) { +hid_t fid, gid; +hid_t plist=H5P_DEFAULT; +const char *fname = NULL; + + if (argc > 2 || argc <= 1) { + usage(); + exit(1); + } + + /* arguments */ + fname = argv[1]; + + /* open file */ + if ((fid = H5Fopen (fname, H5F_ACC_RDONLY, plist))<0) exit(1); + + begin_obj("HDF5", fname); + + gid = H5Gopen (fid, "/"); + + dump_group(gid, "/"); + + end_obj(); + + if (H5Gclose (gid) < 0) exit(1); + + if (H5Fclose (fid) < 0) exit(1); + + + return 0; + +} diff --git a/tools/h5dump.h b/tools/h5dump.h new file mode 100644 index 0000000..d537390 --- /dev/null +++ b/tools/h5dump.h @@ -0,0 +1,160 @@ +#ifndef _DUMPER_H +#define _DUMPER_H + +#include <hdf5.h> +#include <H5private.h> +#include <h5tools.h> + +#define BOOT_BLOCK "BOOT_BLOCK" +#define GROUP "GROUP" +#define DATASET "DATASET" +#define ATTRIBUTE "ATTRIBUTE" +#define DATATYPE "DATATYPE" +#define DATASPACE "DATASPACE" +#define DATA "DATA" +#define ARRAY "ARRAY" +#define OTHER "OTHER" +#define STORAGELAYOUT "STORAGELAYOUT" +#define COMPRESSION "COMPRESSION" +#define EXTERNAL "EXTERNAL" +#define HARDLINK "HARDLINK" +#define SOFTLINK "SOFTLINK" + +#define BEGIN "{" +#define END "}" + +#define ATTRIBUTE_DATA 0 +#define DATASET_DATA 1 + + +#define begin_obj(x,y) printf("%s \"%s\" %s\n", x, y, BEGIN) +#define end_obj() printf("%s\n", END); + +#define col 3; + +static void dump_group (hid_t , const char* ); +static void dump_dataset (hid_t, const char* ); +static void dump_data (hid_t, int); +static void dump_named_datatype (hid_t , const char *); + +#endif + + +/* + * 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 <stdio.h> + +/* + * Information about how to format output. + */ +typedef struct h5dump_t { + /* + * 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. + * + * suf: A strint to print at the end of each array. The default + * value is a right square bracket `]'. + */ + const char *arr_pre; + const char *arr_sep; + const char *arr_suf; + + /* + * Fields associated with compound data types. + * + * name: How the name of the struct member is printed in the + * values. By default the name is not printed, but a + * reasonable setting might be "%s=" which prints the name + * followed by an equal sign and then the value. + * + * sep: A string that separates one member from another. The + * default is a comma. + * + * pre: A string to print at the beginning of a compound type. + * The default is a left curly brace. + * + * suf: A string to print at the end of each compound type. The + * default is a right curly brace. + */ + const char *cmpd_name; + const char *cmpd_sep; + const char *cmpd_pre; + const char *cmpd_suf; + + /* + * 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 h5dump1(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type, int); + +#endif diff --git a/tools/h5dumputil.c b/tools/h5dumputil.c new file mode 100644 index 0000000..d0b3847 --- /dev/null +++ b/tools/h5dumputil.c @@ -0,0 +1,523 @@ +/* + * Note: this program is a modification of h5dump.c by Robb Matzke. + */ +#include <assert.h> +#include <ctype.h> +#include <h5dump.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)) +#define ALIGN(A,Z) ((((A)+(Z)-1)/(Z))*(Z)) + +#define DATASET_DATA 1 + +/*------------------------------------------------------------------------- + * 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, offset; + char temp[1024], *name; + hid_t memb; + int nmembs, j; + + 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)) { + switch (*((char*)vp)) { + case '\\': + strcpy(temp, "\\\\"); + break; + case '\b': + strcpy(temp, "\\b"); + break; + case '\f': + strcpy(temp, "\\f"); + break; + case '\n': + strcpy(temp, "\\n"); + break; + case '\r': + strcpy(temp, "\\r"); + break; + case '\t': + strcpy(temp, "\\t"); + break; + default: + if (isprint(*((char*)vp))) sprintf(temp, "%c", *((char*)vp)); + else sprintf(temp, "\\%03o", *((unsigned char*)vp)); + break; + } + } 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 if (H5T_COMPOUND==H5Tget_class(type)) { + nmembs = H5Tget_nmembers(type); + strcpy(temp, OPT(info->cmpd_pre, "{")); + for (j=0; j<nmembs; j++) { + if (j) strcat(temp, OPT(info->cmpd_sep, ",")); + + /* The name */ + name = H5Tget_member_name(type, j); + sprintf(temp+strlen(temp), OPT(info->cmpd_name, ""), name); + free(name); + + /* The value */ + offset = H5Tget_member_offset(type, j); + memb = H5Tget_member_type(type, j); + h5dump_sprint(temp+strlen(temp), info, memb, (char*)vp+offset); + H5Tclose(memb); + } + strcat(temp, OPT(info->cmpd_suf, "}")); + } 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, int obj_data) +{ + 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. + */ + if (obj_data == DATASET_DATA) + f_space = H5Dget_space(dset); + else + f_space = H5Aget_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); + + + if (obj_data == DATASET_DATA) + H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf); + else + H5Aread(dset, p_type, 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 (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); + */ + } + + /* 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_fixtype + * + * Purpose: Given a file data type choose a memory data type which is + * appropriate for printing the data. + * + * Return: Success: Memory data type + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, July 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hid_t +h5dump_fixtype(hid_t f_type) +{ + hid_t m_type=-1, f_memb; + hid_t *memb=NULL; + char **name=NULL; + int nmembs, i; + size_t size; + + size = H5Tget_size(f_type); + switch (H5Tget_class(f_type)) { + + case H5T_INTEGER: + /* + * Use the smallest native integer type of the same sign as the file + * such that the memory type is at least as large as the file type. + * If there is no memory type large enough then use the largest + * memory type available. + */ + if (size<=sizeof(char)) { + m_type = H5Tcopy(H5T_NATIVE_CHAR); + } else if (size<=sizeof(short)) { + m_type = H5Tcopy(H5T_NATIVE_SHORT); + } else if (size<=sizeof(int)) { + m_type = H5Tcopy(H5T_NATIVE_INT); + } else if (size<=sizeof(long)) { + m_type = H5Tcopy(H5T_NATIVE_LONG); + } else { + m_type = H5Tcopy(H5T_NATIVE_LLONG); + } + H5Tset_sign(m_type, H5Tget_size(f_type)); + break; + + case H5T_FLOAT: + /* + * Use the smallest native floating point type available such that + * its size is at least as large as the file type. If there is not + * native type large enough then use the largest native type. + */ + if (size<=sizeof(float)) { + m_type = H5Tcopy(H5T_NATIVE_FLOAT); + } else if (size<=sizeof(double)) { + m_type = H5Tcopy(H5T_NATIVE_DOUBLE); + } else { + m_type = H5Tcopy(H5T_NATIVE_LDOUBLE); + } + break; + + case H5T_COMPOUND: + nmembs = H5Tget_nmembers(f_type); + memb = calloc(nmembs, sizeof(hid_t)); + name = calloc(nmembs, sizeof(char*)); + + for (i=0, size=0; i<nmembs; i++) { + f_memb = H5Tget_member_type(f_type, i); + memb[i] = h5dump_fixtype(f_memb); + size = ALIGN(size, H5Tget_size(memb[i])) + H5Tget_size(memb[i]); + H5Tclose(f_memb); + name[i] = H5Tget_member_name(f_type, i); + if (memb[i]<0 || NULL==name[i]) goto done; + } + + m_type = H5Tcreate(H5T_COMPOUND, size); + for (i=0, size=0; i<nmembs; i++) { + H5Tinsert(m_type, name[i], size, memb[i]); + size = ALIGN(size, H5Tget_size(memb[i])) + H5Tget_size(memb[i]); + } + break; + + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + /* + * These type classes are not implemented yet. + */ + break; + + default: + /* What the heck? */ + break; + } + + done: + /* Clean up temp buffers */ + if (memb && name) { + for (i=0; i<nmembs; i++) { + if (memb[i]>=0) H5Tclose(memb[i]); + if (name[i]) free(name[i]); + } + free(memb); + free(name); + } + + return m_type; +} + + +/*------------------------------------------------------------------------- + * 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 +h5dump1(FILE *stream, const h5dump_t *info, hid_t dset, hid_t _p_type, int obj_data) +{ + hid_t f_space; + hid_t p_type = _p_type; + hid_t f_type; + int status; + + /* Check the data space */ + if (obj_data == DATASET_DATA) + f_space = H5Dget_space(dset); + else + f_space = H5Aget_space(dset); + + if (H5Sis_simple(f_space)<=0) return -1; + H5Sclose(f_space); + + /* + * Check the data type. If the caller didn't supply a data type then + * use an appropriate native data type. + */ + + if (obj_data == DATASET_DATA) + f_type = H5Dget_type(dset); + else + f_type = H5Aget_type(dset); + + if (p_type<0) { + p_type = h5dump_fixtype(f_type); + H5Tclose(f_type); + if (p_type<0) return -1; + } + + /* Print the data */ + status = h5dump_simple(stream, info, dset, p_type, obj_data); + if (p_type!=_p_type) H5Tclose(p_type); + return status; +} |