diff options
author | Allen Byrne <byrn@hdfgroup.org> | 2016-10-27 15:06:00 (GMT) |
---|---|---|
committer | Allen Byrne <byrn@hdfgroup.org> | 2016-10-27 15:06:00 (GMT) |
commit | 2c6dbbf2129c4997606be4b130346d42fe12eae3 (patch) | |
tree | db8430aa5757b32f3bd46928798cc2b686a72bfb /tools/src/h5dump | |
parent | 5b562d9ce9b2945d0378b9c03e01f42923da80f4 (diff) | |
download | hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.zip hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.tar.gz hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.tar.bz2 |
Split tools into src and test - add folders
Diffstat (limited to 'tools/src/h5dump')
-rw-r--r-- | tools/src/h5dump/CMakeLists.txt | 43 | ||||
-rw-r--r-- | tools/src/h5dump/Makefile.am | 38 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump.c | 1802 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump.h | 115 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_ddl.c | 2178 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_ddl.h | 52 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_defines.h | 56 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_extern.h | 114 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_xml.c | 4567 | ||||
-rw-r--r-- | tools/src/h5dump/h5dump_xml.h | 39 |
10 files changed, 9004 insertions, 0 deletions
diff --git a/tools/src/h5dump/CMakeLists.txt b/tools/src/h5dump/CMakeLists.txt new file mode 100644 index 0000000..ab310db --- /dev/null +++ b/tools/src/h5dump/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5DUMP) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5dump executables +# -------------------------------------------------------------------- +add_executable (h5dump + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump.c + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump_ddl.c + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump_xml.c +) +TARGET_NAMING (h5dump STATIC) +TARGET_C_PROPERTIES (h5dump STATIC " " " ") +target_link_libraries (h5dump ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5dump PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5dump") + +set (H5_DEP_EXECUTABLES h5dump) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5dump ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5dump + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5dump/Makefile.am b/tools/src/h5dump/Makefile.am new file mode 100644 index 0000000..dc43065 --- /dev/null +++ b/tools/src/h5dump/Makefile.am @@ -0,0 +1,38 @@ +# +# Copyright by The HDF Group. +# 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include files in /src directory and /tools/lib directory +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# Our main target, the h5dump tool. +bin_PROGRAMS=h5dump + +# Add h5dump specific linker flags here +h5dump_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All the programs depend on the hdf5 and h5tools libraries +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +# Source files for the program +h5dump_SOURCES=h5dump.c h5dump_ddl.c h5dump_xml.c + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5dump/h5dump.c b/tools/src/h5dump/h5dump.c new file mode 100644 index 0000000..562cfd5 --- /dev/null +++ b/tools/src/h5dump/h5dump.c @@ -0,0 +1,1802 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "h5dump.h" +#include "h5dump_ddl.h" +#include "h5dump_xml.h" + +/* Name of tool */ +#define PROGRAMNAME "h5dump" + +static const char *driver = NULL; /* The driver to open the file with. */ +const char *outfname=NULL; +static int doxml = 0; +static int useschema = 1; +static const char *xml_dtd_uri = NULL; + +/* module-scoped variables for XML option */ +#define DEFAULT_XSD "http://www.hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd" +#define DEFAULT_DTD "http://www.hdfgroup.org/HDF5/XML/DTD/HDF5-File.dtd" + +/* Standard DDL output */ +static const dump_functions ddl_function_table = { + dump_group, + dump_named_datatype, + dump_dataset, + dump_dataspace, + dump_datatype, + dump_attr_cb, + dump_data +}; + +/* XML output */ +static const dump_functions xml_function_table = { + xml_dump_group, + xml_dump_named_datatype, + xml_dump_dataset, + xml_dump_dataspace, + xml_dump_datatype, + xml_dump_attr, + xml_dump_data +}; + +/* internal functions */ +static void init_prefix(char **prfx, size_t prfx_len); + +/* a structure for handling the order command-line parameters come in */ +struct handler_t { + void (*func)(hid_t, const char *, void *, int, const char *); + char *obj; + struct subset_t *subset_info; +}; + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +/* The following initialization makes use of C language cancatenating */ +/* "xxx" "yyy" into "xxxyyy". */ +static const char *s_opts = "hn*peyBHirVa:c:d:f:g:k:l:t:w:xD:uX:o*b*F:s:S:A*q:z:m:RECM:O*N:vG:"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h' }, + { "contents", optional_arg, 'n' }, + { "properties", no_arg, 'p' }, + { "superblock", no_arg, 'B' }, + { "boot-block", no_arg, 'B' }, + { "boot-bloc", no_arg, 'B' }, + { "boot-blo", no_arg, 'B' }, + { "boot-bl", no_arg, 'B' }, + { "boot-b", no_arg, 'B' }, + { "boot", no_arg, 'B' }, + { "boo", no_arg, 'B' }, + { "bo", no_arg, 'B' }, + { "header", no_arg, 'H' }, + { "heade", no_arg, 'H' }, + { "head", no_arg, 'H' }, + { "hea", no_arg, 'H' }, + { "object-ids", no_arg, 'i' }, + { "object-id", no_arg, 'i' }, + { "object-i", no_arg, 'i' }, + { "object", no_arg, 'i' }, + { "objec", no_arg, 'i' }, + { "obje", no_arg, 'i' }, + { "obj", no_arg, 'i' }, + { "ob", no_arg, 'i' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "ver", no_arg, 'V' }, + { "ve", no_arg, 'V' }, + { "attribute", require_arg, 'a' }, + { "attribut", require_arg, 'a' }, + { "attribu", require_arg, 'a' }, + { "attrib", require_arg, 'a' }, + { "attri", require_arg, 'a' }, + { "attr", require_arg, 'a' }, + { "att", require_arg, 'a' }, + { "at", require_arg, 'a' }, + { "block", require_arg, 'k' }, + { "bloc", require_arg, 'k' }, + { "blo", require_arg, 'k' }, + { "bl", require_arg, 'k' }, + { "count", require_arg, 'c' }, + { "coun", require_arg, 'c' }, + { "cou", require_arg, 'c' }, + { "co", require_arg, 'c' }, + { "dataset", require_arg, 'd' }, + { "datase", require_arg, 'd' }, + { "datas", require_arg, 'd' }, + { "datatype", require_arg, 't' }, + { "datatyp", require_arg, 't' }, + { "dataty", require_arg, 't' }, + { "datat", require_arg, 't' }, + { "filedriver", require_arg, 'f' }, + { "filedrive", require_arg, 'f' }, + { "filedriv", require_arg, 'f' }, + { "filedri", require_arg, 'f' }, + { "filedr", require_arg, 'f' }, + { "filed", require_arg, 'f' }, + { "file", require_arg, 'f' }, + { "fil", require_arg, 'f' }, + { "fi", require_arg, 'f' }, + { "group", require_arg, 'g' }, + { "grou", require_arg, 'g' }, + { "gro", require_arg, 'g' }, + { "gr", require_arg, 'g' }, + { "output", optional_arg, 'o' }, + { "outpu", optional_arg, 'o' }, + { "outp", optional_arg, 'o' }, + { "out", optional_arg, 'o' }, + { "ou", optional_arg, 'o' }, + { "soft-link", require_arg, 'l' }, + { "soft-lin", require_arg, 'l' }, + { "soft-li", require_arg, 'l' }, + { "soft-l", require_arg, 'l' }, + { "soft", require_arg, 'l' }, + { "sof", require_arg, 'l' }, + { "start", require_arg, 's' }, + { "star", require_arg, 's' }, + { "sta", require_arg, 's' }, + { "stride", require_arg, 'S' }, + { "strid", require_arg, 'S' }, + { "string", no_arg, 'r' }, + { "strin", no_arg, 'r' }, + { "use-dtd", no_arg, 'u' }, + { "use-dt", no_arg, 'u' }, + { "use-d", no_arg, 'u' }, + { "use-", no_arg, 'u' }, + { "use", no_arg, 'u' }, + { "us", no_arg, 'u' }, + { "u", no_arg, 'u' }, + { "width", require_arg, 'w' }, + { "widt", require_arg, 'w' }, + { "wid", require_arg, 'w' }, + { "wi", require_arg, 'w' }, + { "xml-dtd", require_arg, 'D' }, + { "xml-dt", require_arg, 'D' }, + { "xml-d", require_arg, 'D' }, + { "xml-ns", require_arg, 'X' }, + { "xml-n", require_arg, 'X' }, + { "xml", no_arg, 'x' }, + { "xm", no_arg, 'x' }, + { "onlyattr", optional_arg, 'A' }, + { "escape", no_arg, 'e' }, + { "noindex", no_arg, 'y' }, + { "binary", optional_arg, 'b' }, + { "form", require_arg, 'F' }, + { "sort_by", require_arg, 'q' }, + { "sort_order", require_arg, 'z' }, + { "format", require_arg, 'm' }, + { "region", no_arg, 'R' }, + { "enable-error-stack", no_arg, 'E' }, + { "packed-bits", require_arg, 'M' }, + { "no-compact-subset", no_arg, 'C' }, + { "ddl", optional_arg, 'O' }, + { "any_path", require_arg, 'N' }, + { "vds-view-first-missing", no_arg, 'v' }, + { "vds-gap-size", require_arg, 'G' }, + { NULL, 0, '\0' } +}; + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown MPI & HDF5 and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol + * Saturday, 31. January 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + h5tools_close(); + + HDexit(ret); +} + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message about dumper + * + * Return: void + *------------------------------------------------------------------------- + */ +static void +usage(const char *prog) +{ + FLUSHSTREAM(rawoutstream); + PRINTSTREAM(rawoutstream, "usage: %s [OPTIONS] files\n", prog); + PRINTVALSTREAM(rawoutstream, " OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -h, --help Print a usage message and exit\n"); + PRINTVALSTREAM(rawoutstream, " -V, --version Print version number and exit\n"); + PRINTVALSTREAM(rawoutstream, "--------------- File Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -n, --contents Print a list of the file contents and exit\n"); + PRINTVALSTREAM(rawoutstream, " Optional value 1 also prints attributes.\n"); + PRINTVALSTREAM(rawoutstream, " -B, --superblock Print the content of the super block\n"); + PRINTVALSTREAM(rawoutstream, " -H, --header Print the header only; no data is displayed\n"); + PRINTVALSTREAM(rawoutstream, " -f D, --filedriver=D Specify which driver to open the file with\n"); + PRINTVALSTREAM(rawoutstream, " -o F, --output=F Output raw data into file F\n"); + PRINTVALSTREAM(rawoutstream, " -b B, --binary=B Binary file output, of form B\n"); + PRINTVALSTREAM(rawoutstream, " -O F, --ddl=F Output ddl text into file F\n"); + PRINTVALSTREAM(rawoutstream, " Use blank(empty) filename F to suppress ddl display\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Object Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -a P, --attribute=P Print the specified attribute\n"); + PRINTVALSTREAM(rawoutstream, " If an attribute name contains a slash (/), escape the\n"); + PRINTVALSTREAM(rawoutstream, " slash with a preceding backslash (\\).\n"); + PRINTVALSTREAM(rawoutstream, " (See example section below.)\n"); + PRINTVALSTREAM(rawoutstream, " -d P, --dataset=P Print the specified dataset\n"); + PRINTVALSTREAM(rawoutstream, " -g P, --group=P Print the specified group and all members\n"); + PRINTVALSTREAM(rawoutstream, " -l P, --soft-link=P Print the value(s) of the specified soft link\n"); + PRINTVALSTREAM(rawoutstream, " -t P, --datatype=P Print the specified named datatype\n"); + PRINTVALSTREAM(rawoutstream, " -N P, --any_path=P Print any attribute, dataset, group, datatype, or link that matches P\n"); + PRINTVALSTREAM(rawoutstream, " P can be the absolute path or just a relative path.\n"); + PRINTVALSTREAM(rawoutstream, " -A, --onlyattr Print the header and value of attributes\n"); + PRINTVALSTREAM(rawoutstream, " Optional value 0 suppresses printing attributes.\n"); + PRINTVALSTREAM(rawoutstream, " --vds-view-first-missing Set the VDS bounds to first missing mapped elements.\n"); + PRINTVALSTREAM(rawoutstream, " --vds-gap-size=N Set the missing file gap size, N=non-negative integers\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Object Property Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -i, --object-ids Print the object ids\n"); + PRINTVALSTREAM(rawoutstream, " -p, --properties Print dataset filters, storage layout and fill value\n"); + PRINTVALSTREAM(rawoutstream, " -M L, --packedbits=L Print packed bits as unsigned integers, using mask\n"); + PRINTVALSTREAM(rawoutstream, " format L for an integer dataset specified with\n"); + PRINTVALSTREAM(rawoutstream, " option -d. L is a list of offset,length values,\n"); + PRINTVALSTREAM(rawoutstream, " separated by commas. Offset is the beginning bit in\n"); + PRINTVALSTREAM(rawoutstream, " the data value and length is the number of bits of\n"); + PRINTVALSTREAM(rawoutstream, " the mask.\n"); + PRINTVALSTREAM(rawoutstream, " -R, --region Print dataset pointed by region references\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Formatting Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -e, --escape Escape non printing characters\n"); + PRINTVALSTREAM(rawoutstream, " -r, --string Print 1-byte integer datasets as ASCII\n"); + PRINTVALSTREAM(rawoutstream, " -y, --noindex Do not print array indices with the data\n"); + PRINTVALSTREAM(rawoutstream, " -m T, --format=T Set the floating point output format\n"); + PRINTVALSTREAM(rawoutstream, " -q Q, --sort_by=Q Sort groups and attributes by index Q\n"); + PRINTVALSTREAM(rawoutstream, " -z Z, --sort_order=Z Sort groups and attributes by order Z\n"); + PRINTVALSTREAM(rawoutstream, " --enable-error-stack Prints messages from the HDF5 error stack as they\n"); + PRINTVALSTREAM(rawoutstream, " occur.\n"); + PRINTVALSTREAM(rawoutstream, " --no-compact-subset Disable compact form of subsetting and allow the use\n"); + PRINTVALSTREAM(rawoutstream, " of \"[\" in dataset names.\n"); + PRINTVALSTREAM(rawoutstream, " -w N, --width=N Set the number of columns of output. A value of 0 (zero)\n"); + PRINTVALSTREAM(rawoutstream, " sets the number of columns to the maximum (65535).\n"); + PRINTVALSTREAM(rawoutstream, " Default width is 80 columns.\n"); + PRINTVALSTREAM(rawoutstream, "--------------- XML Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -x, --xml Output in XML using Schema\n"); + PRINTVALSTREAM(rawoutstream, " -u, --use-dtd Output in XML using DTD\n"); + PRINTVALSTREAM(rawoutstream, " -D U, --xml-dtd=U Use the DTD or schema at U\n"); + PRINTVALSTREAM(rawoutstream, " -X S, --xml-ns=S (XML Schema) Use qualified names n the XML\n"); + PRINTVALSTREAM(rawoutstream, " \":\": no namespace, default: \"hdf5:\"\n"); + PRINTVALSTREAM(rawoutstream, " E.g., to dump a file called `-f', use h5dump -- -f\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Subsetting Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " Subsetting is available by using the following options with a dataset\n"); + PRINTVALSTREAM(rawoutstream, " option. Subsetting is done by selecting a hyperslab from the data.\n"); + PRINTVALSTREAM(rawoutstream, " Thus, the options mirror those for performing a hyperslab selection.\n"); + PRINTVALSTREAM(rawoutstream, " One of the START, COUNT, STRIDE, or BLOCK parameters are mandatory if you do subsetting.\n"); + PRINTVALSTREAM(rawoutstream, " The STRIDE, COUNT, and BLOCK parameters are optional and will default to 1 in\n"); + PRINTVALSTREAM(rawoutstream, " each dimension. START is optional and will default to 0 in each dimension.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " -s START, --start=START Offset of start of subsetting selection\n"); + PRINTVALSTREAM(rawoutstream, " -S STRIDE, --stride=STRIDE Hyperslab stride\n"); + PRINTVALSTREAM(rawoutstream, " -c COUNT, --count=COUNT Number of blocks to include in selection\n"); + PRINTVALSTREAM(rawoutstream, " -k BLOCK, --block=BLOCK Size of block in hyperslab\n"); + PRINTVALSTREAM(rawoutstream, " START, COUNT, STRIDE, and BLOCK - is a list of integers the number of which are equal to the\n"); + PRINTVALSTREAM(rawoutstream, " number of dimensions in the dataspace being queried\n"); + PRINTVALSTREAM(rawoutstream, " (Alternate compact form of subsetting is described in the Reference Manual)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Option Argument Conventions ---------------\n"); + PRINTVALSTREAM(rawoutstream, " D - is the file driver to use in opening the file. Acceptable values\n"); + PRINTVALSTREAM(rawoutstream, " are \"sec2\", \"family\", \"split\", \"multi\", \"direct\", and \"stream\". Without\n"); + PRINTVALSTREAM(rawoutstream, " the file driver flag, the file will be opened with each driver in\n"); + PRINTVALSTREAM(rawoutstream, " turn and in the order specified above until one driver succeeds\n"); + PRINTVALSTREAM(rawoutstream, " in opening the file.\n"); + PRINTVALSTREAM(rawoutstream, " See examples below for family, split, and multi driver special file name usage.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " F - is a filename.\n"); + PRINTVALSTREAM(rawoutstream, " P - is the full path from the root group to the object.\n"); + PRINTVALSTREAM(rawoutstream, " N - is an integer greater than 1.\n"); + PRINTVALSTREAM(rawoutstream, " T - is a string containing the floating point format, e.g '%%.3f'\n"); + PRINTVALSTREAM(rawoutstream, " U - is a URI reference (as defined in [IETF RFC 2396],\n"); + PRINTVALSTREAM(rawoutstream, " updated by [IETF RFC 2732])\n"); + PRINTVALSTREAM(rawoutstream, " B - is the form of binary output: NATIVE for a memory type, FILE for the\n"); + PRINTVALSTREAM(rawoutstream, " file type, LE or BE for pre-existing little or big endian types.\n"); + PRINTVALSTREAM(rawoutstream, " Must be used with -o (output file) and it is recommended that\n"); + PRINTVALSTREAM(rawoutstream, " -d (dataset) is used. B is an optional argument, defaults to NATIVE\n"); + PRINTVALSTREAM(rawoutstream, " Q - is the sort index type. It can be \"creation_order\" or \"name\" (default)\n"); + PRINTVALSTREAM(rawoutstream, " Z - is the sort order type. It can be \"descending\" or \"ascending\" (default)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Examples ---------------\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 1) Attribute foo of the group /bar_none in file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -a /bar_none/foo quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Attribute \"high/low\" of the group /bar_none in the file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -a \"/bar_none/high\\/low\" quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 2) Selecting a subset from dataset /foo in file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -s \"0,1\" -S \"1,1\" -c \"2,3\" -k \"2,2\" quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 3) Saving dataset 'dset' in file quux.h5 to binary file 'out.bin'\n"); + PRINTVALSTREAM(rawoutstream, " using a little-endian type\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /dset -b LE -o out.bin quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 4) Display two packed bits (bits 0-1 and bits 4-6) in the dataset /dset\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /dset -M 0,1,4,3 quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 5) Dataset foo in files file1.h5 file2.h5 file3.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo file1.h5 file2.h5 file3.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 6) Dataset foo in split files splitfile-m.h5 splitfile-r.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f split splitfile\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 7) Dataset foo in multi files mf-s.h5, mf-b.h5, mf-r.h5, mf-g.h5, mf-l.h5 and mf-o.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f multi mf\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 8) Dataset foo in family files fam00000.h5 fam00001.h5 and fam00002.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f family fam%%05d.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); +} + + +/*------------------------------------------------------------------------- + * Function: table_list_add + * + * Purpose: Add a new set of tables + * + * Return: index of added table on success, -1 on failure + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * Adapted from trav_addr_add in h5trav.c by Quincey Koziol + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +ssize_t +table_list_add(hid_t oid, unsigned long file_no) +{ + size_t idx; /* Index of table to use */ + find_objs_t info; + + /* Allocate space if necessary */ + if(table_list.nused == table_list.nalloc) { + h5dump_table_items_t *tmp_ptr; + + table_list.nalloc = MAX(1, table_list.nalloc * 2); + if(NULL == (tmp_ptr = (h5dump_table_items_t *)HDrealloc(table_list.tables, table_list.nalloc * sizeof(table_list.tables[0])))) + return -1; + table_list.tables = tmp_ptr; + } /* end if */ + + /* Append it */ + idx = table_list.nused++; + table_list.tables[idx].fileno = file_no; + table_list.tables[idx].oid = oid; + if(H5Iinc_ref(oid) < 0) { + table_list.nused--; + return -1; + } + if(init_objs(oid, &info, &table_list.tables[idx].group_table, + &table_list.tables[idx].dset_table, &table_list.tables[idx].type_table) < 0) { + H5Idec_ref(oid); + table_list.nused--; + return -1; + } + +#ifdef H5DUMP_DEBUG + dump_tables(&info); +#endif /* H5DUMP_DEBUG */ + + return((ssize_t) idx); +} /* end table_list_add() */ + + +/*------------------------------------------------------------------------- + * Function: table_list_visited + * + * Purpose: Check if a table already exists for the specified fileno + * + * Return: The index of the matching table, or -1 if no matches found + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * Adapted from trav_addr_visited in h5trav.c by Quincey Koziol + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +H5_ATTR_PURE ssize_t +table_list_visited(unsigned long file_no) +{ + size_t u; /* Local index variable */ + + /* Look for table */ + for(u = 0; u < table_list.nused; u++) + /* Check for fileno value already in array */ + if(table_list.tables[u].fileno == file_no) + return((ssize_t) u); + + /* Didn't find table */ + return(-1); +} /* end table_list_visited() */ + + +/*------------------------------------------------------------------------- + * Function: table_list_free + * + * Purpose: Frees the table list + * + * Return: void + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +static void +table_list_free(void) +{ + size_t u; /* Local index variable */ + + /* Iterate over tables */ + for(u = 0; u < table_list.nused; u++) { + /* Release object id */ + if(H5Idec_ref(table_list.tables[u].oid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + /* Free each table */ + free_table(table_list.tables[u].group_table); + HDfree(table_list.tables[u].group_table); + free_table(table_list.tables[u].dset_table); + HDfree(table_list.tables[u].dset_table); + free_table(table_list.tables[u].type_table); + HDfree(table_list.tables[u].type_table); + } + + /* Free the table list */ + HDfree(table_list.tables); + table_list.tables = NULL; + table_list.nalloc = table_list.nused = 0; +} /* end table_list_free() */ + +/*------------------------------------------------------------------------- + * Function: set_binary_form + * + * Purpose: set the binary form of output by translating from a string input + * parameter to a integer return value + * + * Return: integer form of binary output or -1 if none found + * + * Programmer: Pedro Vicente Nunes + * June 28, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +set_binary_form(const char *form) +{ + int bform = -1; + + if (HDstrcmp(form,"NATIVE") == 0 || HDstrcmp(form,"MEMORY") == 0) { + /* native form */ + bform = 0; + } + else if (HDstrcmp(form,"FILE") == 0) /* file type form */ + bform = 1; + else if (HDstrcmp(form,"LE") == 0) /* convert to little endian */ + bform = 2; + else if (HDstrcmp(form,"BE") == 0) /* convert to big endian */ + bform = 3; + + return bform; +} + +/*------------------------------------------------------------------------- + * Function: set_sort_by + * + * Purpose: set the "by" form of sorting by translating from a string input + * parameter to a H5_index_t return value + * current sort values are [creation_order | name] + * + * Return: H5_index_t form of sort or H5_INDEX_UNKNOWN if none found + * + * Programmer: Pedro Vicente Nunes + * October 1, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5_index_t +set_sort_by(const char *form) +{ + H5_index_t idx_type = H5_INDEX_UNKNOWN; + + if (HDstrcmp(form,"name")==0) /* H5_INDEX_NAME */ + idx_type = H5_INDEX_NAME; + else if (HDstrcmp(form,"creation_order")==0) /* H5_INDEX_CRT_ORDER */ + idx_type = H5_INDEX_CRT_ORDER; + + return idx_type; +} + +/*------------------------------------------------------------------------- + * Function: set_sort_order + * + * Purpose: set the order of sorting by translating from a string input + * parameter to a H5_iter_order_t return value + * current order values are [ascending | descending ] + * + * Return: H5_iter_order_t form of order or H5_ITER_UNKNOWN if none found + * + * Programmer: Pedro Vicente Nunes + * October 1, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5_iter_order_t +set_sort_order(const char *form) +{ + H5_iter_order_t iter_order = H5_ITER_UNKNOWN; + + if (HDstrcmp(form,"ascending")==0) /* H5_ITER_INC */ + iter_order = H5_ITER_INC; + else if (HDstrcmp(form,"descending")==0) /* H5_ITER_DEC */ + iter_order = H5_ITER_DEC; + + return iter_order; +} + +/*------------------------------------------------------------------------- + * Function: parse_hsize_list + * + * Purpose: Parse a list of comma or space separated integers and return + * them in a list. The string being passed into this function + * should be at the start of the list you want to parse. You are + * responsible for freeing the array returned from here. + * + * Lists in the so-called "terse" syntax are separated by + * semicolons (;). The lists themselves can be separated by + * either commas (,) or white spaces. + * + * Return: <none> + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + *------------------------------------------------------------------------- + */ +static void +parse_hsize_list(const char *h_list, subset_d *d) +{ + hsize_t *p_list; + const char *ptr; + unsigned int size_count = 0; + unsigned int i = 0; + unsigned int last_digit = 0; + + if (!h_list || !*h_list || *h_list == ';') + return; + + /* count how many integers do we have */ + for (ptr = h_list; ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if (HDisdigit(*ptr)) { + if (!last_digit) + /* the last read character wasn't a digit */ + size_count++; + + last_digit = 1; + } + else + last_digit = 0; + + if (size_count == 0) + /* there aren't any integers to read */ + return; + + /* allocate an array for the integers in the list */ + p_list = (hsize_t *)HDcalloc(size_count, sizeof(hsize_t)); + + for (ptr = h_list; i < size_count && ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if(HDisdigit(*ptr)) { + /* we should have an integer now */ + p_list[i++] = (hsize_t)HDstrtoull(ptr, NULL, 0); + + while (HDisdigit(*ptr)) + /* scroll to end of integer */ + ptr++; + } + d->data = p_list; + d->len = size_count; +} + +/*------------------------------------------------------------------------- + * Function: parse_subset_params + * + * Purpose: Parse the so-called "terse" syntax for specifying subsetting + * parameters. + * + * Return: Success: struct subset_t object + * Failure: NULL + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static struct subset_t * +parse_subset_params(char *dset) +{ + struct subset_t *s = NULL; + char *brace; + + if (!disable_compact_subset && ((brace = HDstrrchr(dset, '[')) != NULL)) { + *brace++ = '\0'; + + s = (struct subset_t *)HDcalloc(1, sizeof(struct subset_t)); + parse_hsize_list(brace, &s->start); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->stride); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->count); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->block); + } + + return s; +} + +/*------------------------------------------------------------------------- + * Function: parse_mask_list + * + * Purpose: Parse a list of comma or space separated integers and fill + * the packed_bits list and counter. The string being passed into this function + * should be at the start of the list you want to parse. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static int +parse_mask_list(const char *h_list) +{ + int soffset_value; + unsigned offset_value; + int slength_value; + unsigned length_value; + unsigned long long temp_mask; + const char *ptr = NULL; + + /* sanity check */ + HDassert(h_list); + + HDmemset(packed_mask,0,sizeof(packed_mask)); + + packed_bits_num = 0; + /* scan in pair of offset,length separated by commas. */ + ptr = h_list; + while (*ptr) { + /* scan for an offset which is an unsigned int */ + if (!HDisdigit(*ptr)) { + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + soffset_value = HDatoi(ptr); + offset_value = (unsigned)soffset_value; + if (soffset_value < 0 || offset_value >= PACKED_BITS_SIZE_MAX) { + error_msg("Packed Bit offset value(%d) must be between 0 and %u\n", + soffset_value, (unsigned)(PACKED_BITS_SIZE_MAX - 1)); + return FAIL; + } + + /* skip to end of integer */ + while (HDisdigit(*++ptr)) + ; + /* Look for the common separator */ + if (*ptr++ != ',') { + error_msg("Bad mask list(%s), missing expected comma separator.\n", h_list); + return FAIL; + } + + /* scan for a length which is a positive int */ + if (!HDisdigit(*ptr)) { + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + slength_value = HDatoi(ptr); + if (slength_value <= 0) { + error_msg("Packed Bit length value(%d) must be positive.\n", slength_value); + return FAIL; + } + length_value = (unsigned)slength_value; + if ((offset_value + length_value) > PACKED_BITS_SIZE_MAX) { + error_msg("Packed Bit offset+length value(%u) too large. Max is %u\n", + offset_value+length_value, (unsigned)PACKED_BITS_SIZE_MAX); + return FAIL; + } + + /* skip to end of int */ + while (HDisdigit(*++ptr)) + ; + + /* store the offset,length pair */ + if (packed_bits_num >= PACKED_BITS_MAX) { + /* too many requests */ + error_msg("Too many masks requested (max. %d). Mask list(%s)\n", PACKED_BITS_MAX, h_list); + return FAIL; + } + packed_offset[packed_bits_num] = offset_value; + packed_length[packed_bits_num] = length_value; + /* create the bit mask by left shift 1's by length, then negate it. */ + /* After packed_mask is calculated, packed_length is not needed but */ + /* keep it for debug purpose. */ + temp_mask = ~0ULL; + if(length_value < (int)(8 *sizeof(unsigned long long))) { + temp_mask = temp_mask << length_value; + packed_mask[packed_bits_num] = ~temp_mask; + } + else + packed_mask[packed_bits_num] = temp_mask; + packed_bits_num++; + + /* skip a possible comma separator */ + if (*ptr == ',') { + if (!(*++ptr)) { + /* unexpected end of string */ + error_msg("Bad mask list(%s), unexpected end of string.\n", h_list); + return FAIL; + } + } + } + HDassert(packed_bits_num <= PACKED_BITS_MAX); + if (packed_bits_num == 0) { + /* got no masks! */ + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: free_handler + * + * Purpose: Convenience function to free the handler_t structures. Needs a + * length variable (LEN) to know how many in the array it needs + * to free + * + * Return: Nothing + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +free_handler(struct handler_t *hand, int len) +{ + int i; + + if(hand) { + for (i = 0; i < len; i++) { + if(hand[i].obj) { + HDfree(hand[i].obj); + hand[i].obj=NULL; + } + + if (hand[i].subset_info) { + if(hand[i].subset_info->start.data) + HDfree(hand[i].subset_info->start.data); + if(hand[i].subset_info->stride.data) + HDfree(hand[i].subset_info->stride.data); + if(hand[i].subset_info->count.data) + HDfree(hand[i].subset_info->count.data); + if(hand[i].subset_info->block.data) + HDfree(hand[i].subset_info->block.data); + + HDfree(hand[i].subset_info); + hand[i].subset_info=NULL; + } + } + + HDfree(hand); + } +} + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parse the command line for the h5dumper. + * + * Return: Success: A pointer to an array of handler_t structures. + * These contain all the information needed to dump + * the necessary object. + * + * Failure: Exits program with EXIT_FAILURE value. + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * pvn June, 1, 2006. Add a switch for binary output + * + *------------------------------------------------------------------------- + */ +static struct handler_t * +parse_command_line(int argc, const char *argv[]) +{ + struct handler_t *hand = NULL; + struct handler_t *last_dset = NULL; + int i; + int opt; + int last_was_dset = FALSE; + + /* no arguments */ + if (argc == 1) { + usage(h5tools_getprogname()); + goto error; + } + + /* this will be plenty big enough to hold the info */ + if((hand = (struct handler_t *)HDcalloc((size_t)argc, sizeof(struct handler_t)))==NULL) { + goto error; + } + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { +parse_start: + switch ((char)opt) { + case 'R': + display_region = TRUE; + region_output = TRUE; + break; + case 'B': + display_bb = TRUE; + last_was_dset = FALSE; + break; + case 'n': + display_fi = TRUE; + last_was_dset = FALSE; + if ( opt_arg != NULL) { + h5trav_set_verbose(HDatoi(opt_arg)); + } + break; + case 'p': + display_dcpl = TRUE; + break; + case 'y': + display_ai = FALSE; + break; + case 'e': + display_escape = TRUE; + break; + case 'H': + display_data = FALSE; + display_attr_data = FALSE; + last_was_dset = FALSE; + break; + case 'A': + if ( opt_arg != NULL) { + if(0 == HDatoi(opt_arg)) include_attrs = FALSE; + } + else { + display_data = FALSE; + display_attr_data = TRUE; + last_was_dset = FALSE; + } + break; + case 'i': + display_oid = TRUE; + last_was_dset = FALSE; + break; + case 'r': + display_char = TRUE; + break; + case 'V': + print_version(h5tools_getprogname()); + free_handler(hand, argc); + hand = NULL; + h5tools_setstatus(EXIT_SUCCESS); + goto done; + break; + case 'w': + { + int sh5tools_nCols = HDatoi(opt_arg); + + if (sh5tools_nCols <= 0) + h5tools_nCols = 65535; + else + h5tools_nCols = (unsigned)sh5tools_nCols; + last_was_dset = FALSE; + } + break; + case 'N': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_paths; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'a': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_attributes; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'd': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datasets; + hand[i].obj = HDstrdup(opt_arg); + hand[i].subset_info = parse_subset_params(hand[i].obj); + last_dset = &hand[i]; + break; + } + + last_was_dset = TRUE; + break; + case 'f': + driver = opt_arg; + break; + case 'g': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_groups; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'l': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_links; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 't': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datatypes; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + + case 'O': + if (h5tools_set_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'o': + if ( bin_output ) { + if (h5tools_set_data_output_file(opt_arg, 1) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + else { + if(display_attr_data && !display_data) { + if (h5tools_set_attr_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + if(display_data || display_all) { + if (h5tools_set_data_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + } + + usingdasho = TRUE; + last_was_dset = FALSE; + outfname = opt_arg; + break; + + case 'b': + if ( opt_arg != NULL) { + if ( ( bin_form = set_binary_form(opt_arg)) < 0) { + /* failed to set binary form */ + usage(h5tools_getprogname()); + goto error; + } + } + bin_output = TRUE; + if (outfname!=NULL) { + if (h5tools_set_data_output_file(outfname, 1) < 0) { + /* failed to set output file */ + usage(h5tools_getprogname()); + goto error; + } + + last_was_dset = FALSE; + } + break; + + case 'q': + if ( ( sort_by = set_sort_by(opt_arg)) < 0) { + /* failed to set "sort by" form */ + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'z': + if ( ( sort_order = set_sort_order(opt_arg)) < 0) { + /* failed to set "sort order" form */ + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'M': + if (!last_was_dset) { + error_msg("option `-%c' can only be used after --dataset option\n", opt); + goto error; + } + if (parse_mask_list(opt_arg) != SUCCEED){ + usage(h5tools_getprogname()); + goto error; + } + display_packed_bits = TRUE; + break; + case 'v': + display_vds_first = TRUE; + break; + case 'G': + vds_gap_size = HDatoi(opt_arg); + if (vds_gap_size < 0) { + usage(h5tools_getprogname()); + goto error; + } + break; + + /** begin XML parameters **/ + case 'x': + /* select XML output */ + doxml = TRUE; + useschema = TRUE; + h5tools_dump_header_format = NULL; + dump_function_table = &xml_function_table; + h5tools_nCols = 0; + break; + case 'u': + doxml = TRUE; + useschema = FALSE; + xmlnsprefix = ""; + h5tools_dump_header_format = NULL; + dump_function_table = &xml_function_table; + h5tools_nCols = 0; + break; + case 'D': + /* specify alternative XML DTD or schema */ + /* To Do: check format of this value? */ + xml_dtd_uri = opt_arg; + h5tools_nCols = 0; + break; + + case 'm': + /* specify alternative floating point printing format */ + fp_format = opt_arg; + h5tools_nCols = 0; + break; + + case 'X': + /* specify XML namespace (default="hdf5:"), or none */ + /* To Do: check format of this value? */ + if (!useschema) { + usage(h5tools_getprogname()); + goto error; + } + if (HDstrcmp(opt_arg,":") == 0) + xmlnsprefix = ""; + else + xmlnsprefix = opt_arg; + h5tools_nCols = 0; + break; + /** end XML parameters **/ + + /** begin subsetting parameters **/ + case 's': + case 'S': + case 'c': + case 'k': { + struct subset_t *s; + + if (!last_was_dset) { + error_msg("option `-%c' can only be used after --dataset option\n", opt); + goto error; + } + + if (last_dset->subset_info) { + /* + * This overrides the "terse" syntax if they actually mixed + * the two. + */ + s = last_dset->subset_info; + } + else { + last_dset->subset_info = s = (struct subset_t *)HDcalloc(1, sizeof(struct subset_t)); + } + + /* + * slightly convoluted, but...we are only interested in options + * for subsetting: "--start", "--stride", "--count", and "--block" + * which can come in any order. If we run out of parameters (EOF) + * or run into one which isn't a subsetting parameter (NOT s, S, + * c, or K), then we exit the do-while look, set the subset_info + * to the structure we've been filling. If we've reached the end + * of the options, we exit the parsing (goto parse_end) otherwise, + * since we've "read" the next option, we need to parse it. So we + * jump to the beginning of the switch statement (goto parse_start). + */ + do { + switch ((char)opt) { + case 's': + if (s->start.data) { + HDfree(s->start.data); + s->start.data = NULL; + } + parse_hsize_list(opt_arg, &s->start); + break; + case 'S': + if (s->stride.data) { + HDfree(s->stride.data); + s->stride.data = NULL; + } + parse_hsize_list(opt_arg, &s->stride); + break; + case 'c': + if (s->count.data) { + HDfree(s->count.data); + s->count.data = NULL; + } + parse_hsize_list(opt_arg, &s->count); + break; + case 'k': + if (s->block.data) { + HDfree(s->block.data); + s->block.data = NULL; + } + parse_hsize_list(opt_arg, &s->block); + break; + default: + goto end_collect; + } + } while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF); + +end_collect: + last_was_dset = FALSE; + + if (opt != EOF) + goto parse_start; + else + goto parse_end; + } + /** end subsetting parameters **/ + + case 'E': + enable_error_stack = TRUE; + break; + case 'C': + disable_compact_subset = TRUE; + break; + case 'h': + usage(h5tools_getprogname()); + free_handler(hand, argc); + hand = NULL; + h5tools_setstatus(EXIT_SUCCESS); + goto done; + case '?': + default: + usage(h5tools_getprogname()); + goto error; + } + } + +parse_end: + /* check for file name to be processed */ + if (argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + goto error; + } +done: + return hand; + +error: + if (hand) { + free_handler(hand, argc); + hand = NULL; + } + h5tools_setstatus(EXIT_FAILURE); + + return hand; +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 dumper + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Albert Cheng + * 30. September 2000 + * Add the -o option--output file for datasets raw data + * + * REMcG + * November 2000 + * Changes to support XML. + * + * Bill Wendling + * Wednesday, 10. January 2001 + * Modified the way command line parameters are interpreted. They go + * through one function call now (get_option). + * + * Bill Wendling + * Tuesday, 20. February 2001 + * Moved command line parsing to separate function. Made various + * "display_*" flags global. + * + * REMcG + * August 2003 + * Major upgrade to XML support. + * + * Pedro Vicente + * September 2007 + * list objects in requested order (creation order or alphabetically) + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + hid_t fid = -1; + hid_t gid = -1; + H5E_auto2_t func; + H5E_auto2_t tools_func; + H5O_info_t oi; + struct handler_t *hand = NULL; + int i; + unsigned u; + void *edata; + void *tools_edata; + char *fname = NULL; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + h5tools_dump_header_format = &h5tools_standardformat; + dump_function_table = &ddl_function_table; + dump_indent = 0; + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Disable tools error reporting */ + H5Eget_auto2(H5tools_ERR_STACK_g, &tools_func, &tools_edata); + H5Eset_auto2(H5tools_ERR_STACK_g, NULL, NULL); + + if((hand = parse_command_line(argc, argv))==NULL) { + goto done; + } + + if (bin_output && outfname == NULL) { + error_msg("binary output requires a file name, use -o <filename>\n"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + if (enable_error_stack) { + H5Eset_auto2(H5E_DEFAULT, func, edata); + H5Eset_auto2(H5tools_ERR_STACK_g, tools_func, tools_edata); + } + + /* Check for conflicting options */ + if (doxml) { + if (!display_all) { + error_msg("option \"%s\" not available for XML\n", + "to display selected objects"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_bb) { + error_msg("option \"%s\" not available for XML\n", "--boot-block"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_oid == 1) { + error_msg("option \"%s\" not available for XML\n", "--object-ids"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_char == TRUE) { + error_msg("option \"%s\" not available for XML\n", "--string"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (usingdasho) { + error_msg("option \"%s\" not available for XML\n", "--output"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + else { + if (xml_dtd_uri) { + warn_msg("option \"%s\" only applies with XML: %s\n", "--xml-dtd", xml_dtd_uri); + } + } + + if (argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + /* Initialize indexing options */ + h5trav_set_index(sort_by, sort_order); + + while(opt_ind < argc) { + fname = HDstrdup(argv[opt_ind++]); + + fid = h5tools_fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT, driver, NULL, 0); + + if (fid < 0) { + error_msg("unable to open file \"%s\"\n", fname); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* allocate and initialize internal data structure */ + init_prefix(&prefix, prefix_len); + + /* Prepare to find objects that might be targets of a reference */ + fill_ref_path_table(fid); + + if(doxml) { + /* initialize XML */ + /* reset prefix! */ + HDstrcpy(prefix, ""); + + /* make sure the URI is initialized to something */ + if (xml_dtd_uri == NULL) { + if (useschema) { + xml_dtd_uri = DEFAULT_XSD; + } + else { + xml_dtd_uri = DEFAULT_DTD; + xmlnsprefix = ""; + } + } + else { + if (useschema && HDstrcmp(xmlnsprefix,"")) { + error_msg("Cannot set Schema URL for a qualified namespace--use -X or -U option with -D \n"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + } + + /* Get object info for root group */ + if(H5Oget_info_by_name(fid, "/", &oi, H5P_DEFAULT) < 0) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* Initialize object tables */ + if(table_list_add(fid, oi.fileno) < 0) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + group_table = table_list.tables[0].group_table; + dset_table = table_list.tables[0].dset_table; + type_table = table_list.tables[0].type_table; + + /* does there exist unamed committed datatype */ + for (u = 0; u < type_table->nobjs; u++) + if (!type_table->objs[u].recorded) { + unamedtype = 1; + break; + } /* end if */ + + /* start to dump - display file header information */ + if (!doxml) { + begin_obj(h5tools_dump_header_format->filebegin, fname, h5tools_dump_header_format->fileblockbegin); + } + else { + PRINTVALSTREAM(rawoutstream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + + /* alternative first element, depending on schema or DTD. */ + if (useschema) { + if (HDstrcmp(xmlnsprefix,"") == 0) { + PRINTSTREAM(rawoutstream, "<HDF5-File xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"%s\">\n", + xml_dtd_uri); + } + else { + /* TO DO: make -url option work in this case (may need new option) */ + char *ns; + char *indx; + + ns = HDstrdup(xmlnsprefix); + indx = HDstrrchr(ns,(int)':'); + if (indx) *indx = '\0'; + + PRINTSTREAM(rawoutstream, "<%sHDF5-File xmlns:%s=\"http://hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xsi:schemaLocation=\"http://hdfgroup.org/HDF5/XML/schema/HDF5-File " + "http://www.hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd\">\n",xmlnsprefix,ns); + HDfree(ns); + } + } + else { + PRINTSTREAM(rawoutstream, "<!DOCTYPE HDF5-File PUBLIC \"HDF5-File.dtd\" \"%s\">\n", xml_dtd_uri); + PRINTVALSTREAM(rawoutstream, "<HDF5-File>\n"); + } + } + + if (!doxml) { + if (display_fi) { + PRINTVALSTREAM(rawoutstream, "\n"); + dump_fcontents(fid); + end_obj(h5tools_dump_header_format->fileend,h5tools_dump_header_format->fileblockend); + PRINTVALSTREAM(rawoutstream, "\n"); + goto done; + } + + if (display_bb) + dump_fcpl(fid); + } + + if(display_all) { + if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) { + error_msg("unable to open root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + if (!doxml) + dump_indent += COL; + dump_function_table->dump_group_function(gid, "/" ); + if (!doxml) + dump_indent -= COL; + PRINTVALSTREAM(rawoutstream, "\n"); + } + + if(H5Gclose(gid) < 0) { + error_msg("unable to close root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + } + else { + /* Note: this option is not supported for XML */ + if(doxml) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } /* end if */ + + for(i = 0; i < argc; i++) { + if(hand[i].func) { + hand[i].func(fid, hand[i].obj, hand[i].subset_info, 1, NULL); + } + } + PRINTVALSTREAM(rawoutstream, "\n"); + } + + if (!doxml) { + end_obj(h5tools_dump_header_format->fileend, h5tools_dump_header_format->fileblockend); + PRINTVALSTREAM(rawoutstream, "\n"); + } + else { + PRINTSTREAM(rawoutstream, "</%sHDF5-File>\n", xmlnsprefix); + } + /* Free tables for objects */ + table_list_free(); + + if(fid >=0) + if (H5Fclose(fid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + if(prefix) { + HDfree(prefix); + prefix = NULL; + } + if(fname) { + HDfree(fname); + fname = NULL; + } + } /* end while */ + + if(hand) + free_handler(hand, argc); + + /* To Do: clean up XML table */ + + leave(h5tools_getstatus()); + +done: + /* Free tables for objects */ + table_list_free(); + + if(fid >=0) + if (H5Fclose(fid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + if(prefix) { + HDfree(prefix); + prefix = NULL; + } + if(fname) { + HDfree(fname); + fname = NULL; + } + + if(hand) + free_handler(hand, argc); + + /* To Do: clean up XML table */ + + H5Eset_auto2(H5E_DEFAULT, func, edata); + + leave(h5tools_getstatus()); +} + +/*------------------------------------------------------------------------- + * Function: h5_fileaccess + * + * Purpose: Returns a file access template which is the default template + * but with a file driver set according to the constant or + * environment variable HDF5_DRIVER + * + * Return: Success: A file access property list + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, November 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +h5_fileaccess(void) +{ + static const char *multi_letters = "msbrglo"; + const char *val = NULL; + const char *name; + char s[1024]; + hid_t fapl = -1; + + /* First use the environment variable, then the constant */ + val = HDgetenv("HDF5_DRIVER"); +#ifdef HDF5_DRIVER + if (!val) val = HDF5_DRIVER; +#endif + + if ((fapl=H5Pcreate(H5P_FILE_ACCESS))<0) return -1; + if (!val || !*val) return fapl; /*use default*/ + + HDstrncpy(s, val, sizeof s); + s[sizeof(s)-1] = '\0'; + if (NULL==(name=HDstrtok(s, " \t\n\r"))) return fapl; + + if (!HDstrcmp(name, "sec2")) { + /* Unix read() and write() system calls */ + if (H5Pset_fapl_sec2(fapl)<0) return -1; + } + else if (!HDstrcmp(name, "stdio")) { + /* Standard C fread() and fwrite() system calls */ + if (H5Pset_fapl_stdio(fapl)<0) return -1; + } + else if (!HDstrcmp(name, "core")) { + /* In-core temporary file with 1MB increment */ + if (H5Pset_fapl_core(fapl, 1024*1024, FALSE)<0) return -1; + } + else if (!HDstrcmp(name, "split")) { + /* Split meta data and raw data each using default driver */ + if (H5Pset_fapl_split(fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT) < 0) + return -1; + } + else if (!HDstrcmp(name, "multi")) { + /* Multi-file driver, general case of the split driver */ + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + hid_t memb_fapl[H5FD_MEM_NTYPES]; + const char *memb_name[H5FD_MEM_NTYPES]; + char sv[H5FD_MEM_NTYPES][1024]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + H5FD_mem_t mt; + + HDmemset(memb_map, 0, sizeof memb_map); + HDmemset(memb_fapl, 0, sizeof memb_fapl); + HDmemset(memb_name, 0, sizeof memb_name); + HDmemset(memb_addr, 0, sizeof memb_addr); + + HDassert(HDstrlen(multi_letters)==H5FD_MEM_NTYPES); + for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,mt)) { + memb_fapl[mt] = H5P_DEFAULT; + memb_map[mt] = mt; + sprintf(sv[mt], "%%s-%c.h5", multi_letters[mt]); + memb_name[mt] = sv[mt]; + memb_addr[mt] = (haddr_t)MAX(mt - 1, 0) * (HADDR_MAX / 10); + } + + if (H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, FALSE) < 0) + return -1; + } + else if (!HDstrcmp(name, "family")) { + hsize_t fam_size = 100*1024*1024; /*100 MB*/ + + /* Family of files, each 1MB and using the default driver */ + if ((val=HDstrtok(NULL, " \t\n\r"))) + fam_size = (hsize_t)(HDstrtod(val, NULL) * 1024*1024); + if (H5Pset_fapl_family(fapl, fam_size, H5P_DEFAULT)<0) + return -1; + } + else if (!HDstrcmp(name, "log")) { + long log_flags = H5FD_LOG_LOC_IO; + + /* Log file access */ + if ((val = HDstrtok(NULL, " \t\n\r"))) + log_flags = HDstrtol(val, NULL, 0); + + if (H5Pset_fapl_log(fapl, NULL, (unsigned)log_flags, 0) < 0) + return -1; + } + else if (!HDstrcmp(name, "direct")) { + /* Substitute Direct I/O driver with sec2 driver temporarily because + * some output has sec2 driver as the standard. */ + if (H5Pset_fapl_sec2(fapl)<0) return -1; + } + else { + /* Unknown driver */ + return -1; + } + + return fapl; +} + + +/*------------------------------------------------------------------------- + * Function: init_prefix + * + * Purpose: allocate and initialize prefix + * + * Return: void + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +init_prefix(char **prfx, size_t prfx_len) +{ + HDassert(prfx_len > 0); + *prfx = (char *)HDcalloc(prfx_len, 1); +} + + +/*------------------------------------------------------------------------- + * Function: add_prefix + * + * Purpose: Add object to prefix + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +add_prefix(char **prfx, size_t *prfx_len, const char *name) +{ + size_t new_len = HDstrlen(*prfx) + HDstrlen(name) + 2; + + /* Check if we need more space */ + if(*prfx_len <= new_len) { + *prfx_len = new_len + 1; + *prfx = (char *)HDrealloc(*prfx, *prfx_len); + } + + /* Append object name to prefix */ + HDstrcat(HDstrcat(*prfx, "/"), name); +} /* end add_prefix */ + diff --git a/tools/src/h5dump/h5dump.h b/tools/src/h5dump/h5dump.h new file mode 100644 index 0000000..8224c02 --- /dev/null +++ b/tools/src/h5dump/h5dump.h @@ -0,0 +1,115 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_H__ +#define H5DUMP_H__ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_defines.h" + +/** + ** This is the global dispatch table for the dump functions. + **/ +/* the table of dump functions */ +typedef struct dump_functions_t { + void (*dump_group_function) (hid_t, const char *); + void (*dump_named_datatype_function) (hid_t, const char *); + void (*dump_dataset_function) (hid_t, const char *, struct subset_t *); + void (*dump_dataspace_function) (hid_t); + void (*dump_datatype_function) (hid_t); + herr_t (*dump_attribute_function) (hid_t, const char *, const H5A_info_t *, void *); + void (*dump_data_function) (hid_t, int, struct subset_t *, int); +} dump_functions; + +/* List of table structures. There is one table structure for each file */ +typedef struct h5dump_table_items_t { + unsigned long fileno; /* File number that these tables refer to */ + hid_t oid; /* ID of an object in this file, held open so fileno is consistent */ + table_t *group_table; /* Table of groups */ + table_t *dset_table; /* Table of datasets */ + table_t *type_table; /* Table of datatypes */ +} h5dump_table_items_t; +typedef struct h5dump_table_list_t { + size_t nalloc; + size_t nused; + h5dump_table_items_t *tables; +} h5dump_table_list_t; + +h5dump_table_list_t table_list = {0, 0, NULL}; +table_t *group_table = NULL, *dset_table = NULL, *type_table = NULL; +unsigned dump_indent = 0; /*how far in to indent the line */ + +int unamedtype = 0; /* shared datatype with no name */ +hbool_t hit_elink = FALSE; /* whether we have traversed an external link */ +size_t prefix_len = 1024; +char *prefix = NULL; +const char *fp_format = NULL; + +/* things to display or which are set via command line parameters */ +int display_all = TRUE; +int display_oid = FALSE; +int display_data = TRUE; +int display_attr_data = TRUE; +int display_char = FALSE; /*print 1-byte numbers as ASCII */ +int usingdasho = FALSE; +int display_bb = FALSE; /*superblock */ +int display_dcpl = FALSE; /*dcpl */ +int display_fi = FALSE; /*file index */ +int display_ai = TRUE; /*array index */ +int display_escape = FALSE; /*escape non printable characters */ +int display_region = FALSE; /*print region reference data */ +int disable_compact_subset= FALSE; /* disable compact form of subset notation */ +int display_packed_bits = FALSE; /*print 1-8 byte numbers as packed bits*/ +int include_attrs = TRUE; /* Display attributes */ +int display_vds_first = FALSE; /* vds display to all by default*/ +int vds_gap_size = 0; /* vds skip missing files default is none */ + +/* sort parameters */ +H5_index_t sort_by = H5_INDEX_NAME; /*sort_by [creation_order | name] */ +H5_iter_order_t sort_order = H5_ITER_INC; /*sort_order [ascending | descending] */ + +#define PACKED_BITS_MAX 8 /* Maximum number of packed-bits to display */ +#define PACKED_BITS_SIZE_MAX (8*sizeof(long long)) /* Maximum bits size of integer types of packed-bits */ +/* mask list for packed bits */ +unsigned long long packed_mask[PACKED_BITS_MAX]; /* packed bits are restricted to 8*sizeof(llong) bytes */ + +/* packed bits display parameters */ +unsigned packed_offset[PACKED_BITS_MAX]; +unsigned packed_length[PACKED_BITS_MAX]; + +/* + * The global table is set to either ddl_function_table or + * xml_function_table in the initialization. + */ +const dump_functions *dump_function_table; + +#ifdef __cplusplus +"C" { +#endif + +void add_prefix(char **prfx, size_t *prfx_len, const char *name); +hid_t h5_fileaccess(void); +ssize_t table_list_add(hid_t oid, unsigned long file_no); +ssize_t table_list_visited(unsigned long file_no); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_H__ */ diff --git a/tools/src/h5dump/h5dump_ddl.c b/tools/src/h5dump/h5dump_ddl.c new file mode 100644 index 0000000..182d570 --- /dev/null +++ b/tools/src/h5dump/h5dump_ddl.c @@ -0,0 +1,2178 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_dump.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_extern.h" +#include "h5dump_ddl.h" + +typedef struct { + hid_t fid; /* File ID being traversed */ + const char *op_name; /* Object name wanted */ +} trav_handle_udata_t; + +typedef struct { + const char *path; /* Path of object being searched */ + const char *op_name; /* Object name wanted */ +} trav_attr_udata_t; + +/* callback function used by H5Literate() */ +static herr_t dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void *op_data); +static int dump_extlink(hid_t group, const char *linkname, const char *objname); + +/*------------------------------------------------------------------------- + * Function: dump_datatype + * + * Purpose: Dump the datatype. Datatype can be HDF5 predefined + * atomic datatype or committed/transient datatype. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_datatype(hid_t type) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + h5dump_type_table = type_table; + h5tools_dump_datatype(rawoutstream, outputformat, &ctx, type); + h5dump_type_table = NULL; +} + +/*------------------------------------------------------------------------- + * Function: dump_dataspace + * + * Purpose: Dump the dataspace. Dataspace can be named dataspace, + * array, or others. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_dataspace(hid_t space) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + h5tools_dump_dataspace(rawoutstream, outputformat, &ctx, space); +} + + +/*------------------------------------------------------------------------- + * Function: dump_attr_cb + * + * Purpose: attribute function callback called by H5Aiterate2, displays the attribute + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: Pedro Vicente, October 4, 2007 + * Added H5A_info_t parameter to conform with H5Aiterate2 + * + *------------------------------------------------------------------------- + */ +herr_t +dump_attr_cb(hid_t oid, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *info, void H5_ATTR_UNUSED *_op_data) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + + hid_t attr_id; + herr_t ret = SUCCEED; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + attr_id = H5Aopen(oid, attr_name, H5P_DEFAULT); + oid_output = display_oid; + data_output = display_data; + attr_data_output = display_attr_data; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + h5dump_type_table = type_table; + h5tools_dump_attribute(rawoutstream, outputformat, &ctx, attr_name, attr_id, display_ai, display_char); + h5dump_type_table = NULL; + + if(attr_id < 0) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + + return ret; +} + + +/*------------------------------------------------------------------------- + * Function: dump_all_cb + * + * Purpose: function callback called by H5Literate, + * displays everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * RMcG, November 2000 + * Added XML support. Also, optionally checks the op_data argument + * + * PVN, May 2008 + * Dump external links + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void H5_ATTR_UNUSED *op_data) +{ + hid_t obj; + hid_t dapl_id = H5P_DEFAULT; /* dataset access property list ID */ + herr_t ret = SUCCEED; + char *obj_path = NULL; /* Full path of object */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + /* Build the object's path name */ + obj_path = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + if(!obj_path) { + ret = FAIL; + goto done; + } + + HDstrcpy(obj_path, prefix); + HDstrcat(obj_path, "/"); + HDstrcat(obj_path, name); + + if(linfo->type == H5L_TYPE_HARD) { + H5O_info_t oinfo; + + /* Stat the object */ + if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) { + error_msg("unable to get object information for \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + goto done; + } /* end if */ + + switch(oinfo.type) { + case H5O_TYPE_GROUP: + if((obj = H5Gopen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump group \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + char *old_prefix; /* Pointer to previous prefix */ + + /* Keep copy of prefix before iterating into group */ + old_prefix = HDstrdup(prefix); + HDassert(old_prefix); + + /* Append group name to prefix */ + add_prefix(&prefix, &prefix_len, name); + + /* Iterate into group */ + dump_function_table->dump_group_function(obj, name); + + /* Restore old prefix name */ + HDstrcpy(prefix, old_prefix); + HDfree(old_prefix); + + /* Close group */ + H5Gclose(obj); + } + break; + + case H5O_TYPE_DATASET: + if(display_data) { + if ((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0) { + error_msg("error in creating default access property list ID\n"); + } + if (display_vds_first) { + if(H5Pset_virtual_view(dapl_id, H5D_VDS_FIRST_MISSING) < 0) + error_msg("error in setting access property list ID, virtual_view\n"); + } + if (vds_gap_size > 0) { + if(H5Pset_virtual_printf_gap(dapl_id, (hsize_t)vds_gap_size) < 0) + error_msg("error in setting access property list ID, virtual_printf_gap\n"); + } + } + if((obj = H5Dopen2(group, name, dapl_id)) >= 0) { + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj == NULL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + goto done; + } + else if(found_obj->displayed) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + goto done; + } + else { + found_obj->displayed = TRUE; + } + } /* end if */ + + dump_function_table->dump_dataset_function(obj, name, NULL); + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + } + else { + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + error_msg("unable to dump dataset \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + break; + + case H5O_TYPE_NAMED_DATATYPE: + if((obj = H5Topen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump datatype \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + dump_function_table->dump_named_datatype_function(obj, name); + H5Tclose(obj); + } + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + } /* end if */ + else { + char *targbuf; + + switch(linfo->type) { + case H5L_TYPE_SOFT: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->softlinkbegin, name, + h5tools_dump_header_format->softlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + /* print the value of a soft link */ + /* Standard DDL: no modification */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "LINKTARGET \"%s\"", targbuf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->softlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->softlinkblockend); + if(HDstrlen(h5tools_dump_header_format->softlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->softlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->softlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(targbuf); + break; + + case H5L_TYPE_EXTERNAL: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->extlinkbegin, name, + h5tools_dump_header_format->extlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + indentation(dump_indent); + error_msg("unable to get external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + const char *filename; + const char *targname; + + if(H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &targname) < 0) { + indentation(dump_indent); + error_msg("unable to unpack external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "TARGETFILE \"%s\"", filename); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "TARGETPATH \"%s\"", targname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* dump the external link */ + dump_extlink(group, name, targname); + ctx.indent_level--; + } /* end else */ + } /* end else */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->extlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->extlinkblockend); + if(HDstrlen(h5tools_dump_header_format->extlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->extlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->extlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(targbuf); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->udlinkbegin, name, + h5tools_dump_header_format->udlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "LINKCLASS %d", linfo->type); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->udlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->udlinkblockend); + if(HDstrlen(h5tools_dump_header_format->udlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->udlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->udlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + break; + } /* end switch */ + } /* end else */ + +done: + + h5tools_str_close(&buffer); + + if(obj_path) + HDfree(obj_path); + return ret; +} + +/*------------------------------------------------------------------------- + * Function: attr_iteration + * + * Purpose: Iterate and display attributes within the specified group + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +attr_iteration(hid_t gid, unsigned attr_crt_order_flags) +{ + /* attribute iteration: if there is a request to do H5_INDEX_CRT_ORDER and tracking order is set + in the group for attributes, then, sort by creation order, otherwise by name */ + if(include_attrs) { + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_attr_cb, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_attr_cb, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + } +} + +/*------------------------------------------------------------------------- + * Function: link_iteration + * + * Purpose: Iterate and display links within the specified group + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +link_iteration(hid_t gid, unsigned crt_order_flags) +{ + + /* if there is a request to do H5_INDEX_CRT_ORDER and tracking order is set + in the group, then, sort by creation order, otherwise by name */ + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, dump_all_cb, NULL); +} + +/*------------------------------------------------------------------------- + * Function: dump_named_datatype + * + * Purpose: Dump named datatype + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Pedro Vicente, March 27, 2006 + * added display of attributes + * Pedro Vicente, October 4, 2007, added parameters to H5Aiterate2() to allow for + * other iteration orders + * + *------------------------------------------------------------------------- + */ +void +dump_named_datatype(hid_t tid, const char *name) +{ + H5O_info_t oinfo; + unsigned attr_crt_order_flags; + hid_t tcpl_id = -1; /* datatype creation property list ID */ + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if ((tcpl_id = H5Tget_create_plist(tid)) < 0) { + error_msg("error in getting creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the creation properties for attributes */ + if (H5Pget_attr_creation_order(tcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(tcpl_id) < 0) { + error_msg("error in closing creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datatypebegin, name, + h5tools_dump_header_format->datatypeblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5Oget_info(tid, &oinfo); + + /* Must check for uniqueness of all objects if we've traversed an elink, + * otherwise only check if the reference count > 1. + */ + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(type_table, oinfo.addr); + + if (found_obj == NULL) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (found_obj->displayed) { + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; + } + else + found_obj->displayed = TRUE; + } /* end if */ + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_print_datatype(rawoutstream, &buffer, outputformat, &ctx, tid, FALSE); + + if(H5Tget_class(tid) != H5T_COMPOUND) { + h5tools_str_append(&buffer, ";"); + } + + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* print attributes */ + dump_indent += COL; + + attr_iteration(tid, attr_crt_order_flags); + + dump_indent -= COL; + +done: + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datatypeblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datatypeblockend); + if(HDstrlen(h5tools_dump_header_format->datatypeend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datatypeend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datatypeend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_group + * + * Purpose: Dump everything within the specified group + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + * Call to dump_all_cb -- add parameter to select everything. + * + * Pedro Vicente, October 1, 2007 + * handle several iteration orders for attributes and groups + * + *------------------------------------------------------------------------- + */ +void +dump_group(hid_t gid, const char *name) +{ + H5O_info_t oinfo; + hid_t dset; + hid_t type; + hid_t gcpl_id; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + char type_name[1024]; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->groupbegin, name, + h5tools_dump_header_format->groupblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + if(!HDstrcmp(name, "/") && unamedtype) { + unsigned u; /* Local index variable */ + + /* dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } /* end if */ + + if(display_oid) + h5tools_dump_oid(rawoutstream, outputformat, &ctx, gid); + + h5tools_dump_comment(rawoutstream, outputformat, &ctx, gid); + + H5Oget_info(gid, &oinfo); + + /* Must check for uniqueness of all objects if we've traversed an elink, + * otherwise only check if the reference count > 1. + */ + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(group_table, oinfo.addr); + + if (found_obj == NULL) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + } + else if (found_obj->displayed) { + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + found_obj->displayed = TRUE; + attr_iteration(gid, attr_crt_order_flags); + link_iteration(gid, crt_order_flags); + } + } + else { + attr_iteration(gid, attr_crt_order_flags); + link_iteration(gid, crt_order_flags); + } + + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->groupblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->groupblockend); + if(HDstrlen(h5tools_dump_header_format->groupend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->groupend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->groupend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_dataset + * + * Purpose: Dump the specified data set + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Pedro Vicente, 2004, added dataset creation property list display + * Pedro Vicente, October 4, 2007, added parameters to H5Aiterate2() to allow for + * other iteration orders + * + *------------------------------------------------------------------------- + */ +void +dump_dataset(hid_t did, const char *name, struct subset_t *sset) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hid_t type, space; + unsigned attr_crt_order_flags; + hid_t dcpl_id; /* dataset creation property list ID */ + h5tools_str_t buffer; /* string into which to render */ + hsize_t curr_pos = 0; /* total data element position */ + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if ((dcpl_id = H5Dget_create_plist(did)) < 0) { + error_msg("error in getting creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the creation properties for attributes */ + if (H5Pget_attr_creation_order(dcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_dump_comment(rawoutstream, outputformat, &ctx, did); + + dump_indent += COL; + ctx.indent_level++; + + type = H5Dget_type(did); + h5dump_type_table = type_table; + h5tools_dump_datatype(rawoutstream, outputformat, &ctx, type); + h5dump_type_table = NULL; + + space = H5Dget_space(did); + h5tools_dump_dataspace(rawoutstream, outputformat, &ctx, space); + H5Sclose(space); + + if(display_oid) { + h5tools_dump_oid(rawoutstream, outputformat, &ctx, did); + } + + if(display_dcpl) { + h5dump_type_table = type_table; + h5tools_dump_dcpl(rawoutstream, outputformat, &ctx, dcpl_id, type, did); + h5dump_type_table = NULL; + } + H5Pclose(dcpl_id); + + if(display_data) { + unsigned data_loop = 1; + unsigned u; + + if(display_packed_bits) + data_loop = packed_bits_num; + for(u = 0; u < data_loop; u++) { + if(display_packed_bits) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + packed_data_mask = packed_mask[u]; + packed_data_offset = packed_offset[u]; + packed_data_length = packed_length[u]; + h5tools_print_packed_bits(&buffer, type); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + switch(H5Tget_class(type)) { + case H5T_TIME: + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "DATA{ not yet implemented.}"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + break; + + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_COMPOUND: + case H5T_REFERENCE: + case H5T_ENUM: + case H5T_VLEN: + case H5T_ARRAY: + { + h5tools_dump_data(rawoutstream, outputformat, &ctx, did, TRUE, sset, display_ai, display_char); + } + break; + + case H5T_NO_CLASS: + case H5T_NCLASSES: + default: + HDassert(0); + break; + } /* end switch */ + } /* for(u=0; u<data_loop; u++) */ + } + H5Tclose(type); + + if (!bin_output) { + attr_iteration(did, attr_crt_order_flags); + } + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_data + * + * Purpose: Dump attribute or dataset data + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: pvn, print the matrix indices + * Albert Cheng, 2004/11/18 + * Add --string printing for attributes too. + * + *------------------------------------------------------------------------- + */ +void +dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int display_index) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + int print_dataset = FALSE; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + if(obj_data == DATASET_DATA) + print_dataset = TRUE; + h5tools_dump_data(rawoutstream, outputformat, &ctx, obj_id, print_dataset, sset, display_index, display_char); +} + + +/*------------------------------------------------------------------------- + * Function: dump_fcpl + * + * Purpose: prints file creation property list information + * + * Return: void + * + * Programmer: pvn + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_fcpl(hid_t fid) +{ + hid_t fcpl; /* file creation property list ID */ + hsize_t userblock; /* userblock size retrieved from FCPL */ + size_t off_size; /* size of offsets in the file */ + size_t len_size; /* size of lengths in the file */ + H5F_file_space_type_t fs_strategy; /* file space strategy */ + hsize_t fs_threshold; /* free-space section threshold */ + H5F_info2_t finfo; /* file information */ +#ifdef SHOW_FILE_DRIVER + hid_t fapl; /* file access property list ID */ + hid_t fdriver; /* file driver */ + char dname[32]; /* buffer to store driver name */ +#endif + unsigned sym_lk; /* symbol table B-tree leaf 'K' value */ + unsigned sym_ik; /* symbol table B-tree internal 'K' value */ + unsigned istore_ik; /* indexed storage B-tree internal 'K' value */ + + fcpl=H5Fget_create_plist(fid); + H5Fget_info2(fid, &finfo); + H5Pget_userblock(fcpl,&userblock); + H5Pget_sizes(fcpl,&off_size,&len_size); + H5Pget_sym_k(fcpl,&sym_ik,&sym_lk); + H5Pget_istore_k(fcpl,&istore_ik); + H5Pget_file_space(fcpl, &fs_strategy, &fs_threshold); + H5Pclose(fcpl); +#ifdef SHOW_FILE_DRIVER + fapl=h5_fileaccess(); + fdriver=H5Pget_driver(fapl); + H5Pclose(fapl); +#endif + + /*------------------------------------------------------------------------- + * SUPER_BLOCK + *------------------------------------------------------------------------- + */ + PRINTSTREAM(rawoutstream, "\n%s %s\n",SUPER_BLOCK, BEGIN); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","SUPERBLOCK_VERSION", finfo.super.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","FREELIST_VERSION", finfo.free.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","SYMBOLTABLE_VERSION", 0); /* Retain this for backward compatibility, for now (QAK) */ + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","OBJECTHEADER_VERSION", finfo.sohm.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream,"%s %zu\n","OFFSET_SIZE", off_size); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream,"%s %zu\n","LENGTH_SIZE", len_size); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","BTREE_RANK", sym_ik); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %d\n","BTREE_LEAF", sym_lk); + +#ifdef SHOW_FILE_DRIVER + if(H5FD_CORE==fdriver) + HDstrcpy(dname,"H5FD_CORE"); +#ifdef H5_HAVE_DIRECT + else if(H5FD_DIRECT==fdriver) + HDstrcpy(dname,"H5FD_DIRECT"); +#endif + else if(H5FD_FAMILY==fdriver) + HDstrcpy(dname,"H5FD_FAMILY"); + else if(H5FD_LOG==fdriver) + HDstrcpy(dname,"H5FD_LOG"); + else if(H5FD_MPIO==fdriver) + HDstrcpy(dname,"H5FD_MPIO"); + else if(H5FD_MULTI==fdriver) + HDstrcpy(dname,"H5FD_MULTI"); + else if(H5FD_SEC2==fdriver) + HDstrcpy(dname,"H5FD_SEC2"); + else if(H5FD_STDIO==fdriver) + HDstrcpy(dname,"H5FD_STDIO"); + else + HDstrcpy(dname,"Unknown driver"); + + /* Take out this because the driver used can be different from the + * standard output. */ + /*indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %s\n","FILE_DRIVER", dname);*/ +#endif + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","ISTORE_K", istore_ik); + + indentation(dump_indent + COL); + if(fs_strategy == H5F_FILE_SPACE_ALL_PERSIST) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_ALL_PERSIST"); + } else if(fs_strategy == H5F_FILE_SPACE_ALL) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_ALL"); + } else if(fs_strategy == H5F_FILE_SPACE_AGGR_VFD) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_AGGR_VFD"); + } else if(fs_strategy == H5F_FILE_SPACE_VFD) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_VFD"); + } else + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "Unknown strategy"); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %Hu\n","FREE_SPACE_THRESHOLD", fs_threshold); + + /*------------------------------------------------------------------------- + * USER_BLOCK + *------------------------------------------------------------------------- + */ + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "USER_BLOCK %s\n",BEGIN); + indentation(dump_indent + COL + COL); + PRINTSTREAM(rawoutstream,"%s %Hu\n","USERBLOCK_SIZE", userblock); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s\n",END); + + PRINTSTREAM(rawoutstream, "%s",END); +} + +/*------------------------------------------------------------------------- + * Function: dump_fcontents + * + * Purpose: prints all objects + * + * Return: void + * + * Programmer: pvn + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_fcontents(hid_t fid) +{ + PRINTSTREAM(rawoutstream, "%s %s\n",FILE_CONTENTS, BEGIN); + + /* special case of unamed types in root group */ + if (unamedtype) { + unsigned u; + + for (u = 0; u < type_table->nobjs; u++) { + if (!type_table->objs[u].recorded) + PRINTSTREAM(rawoutstream, " %-10s /#"H5_PRINTF_HADDR_FMT"\n", "datatype", type_table->objs[u].objno); + } + } + + /* print objects in the files */ + h5trav_print(fid); + + PRINTSTREAM(rawoutstream, " %s\n",END); +} + +static herr_t +attr_search(hid_t oid, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *ainfo, void *_op_data) +{ + herr_t ret = SUCCEED; + int j; + char *obj_op_name; + char *obj_name; + trav_attr_udata_t *attr_data = (trav_attr_udata_t*)_op_data; + const char *buf = attr_data->path; + const char *op_name = attr_data->op_name; + + j = (int)HDstrlen(op_name) - 1; + /* find the last / */ + while(j >= 0) { + if(op_name[j] == '/' && (j == 0 || (j > 0 && op_name[j - 1] != '\\'))) + break; + j--; + } + + obj_op_name = h5tools_str_replace(op_name + j + 1, "\\/", "/"); + + if(obj_op_name == NULL) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + if(HDstrcmp(attr_name, obj_op_name)==0) { + size_t u, v, w; + + /* object name */ + u = HDstrlen(buf); + v = HDstrlen(op_name); + w = u + 1 + v + 1 + 2; + obj_name = (char *)HDmalloc(w); + if(obj_name == NULL) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + HDmemset(obj_name, '\0', w); + if(op_name[0] != '/') { + HDstrncat(obj_name, buf, u + 1); + if(buf[u - 1] != '/') + HDstrncat(obj_name, "/", (size_t)2); + } + HDstrncat(obj_name, op_name, v + 1); + + handle_attributes(oid, obj_name, NULL, 0, NULL); + HDfree(obj_name); + } + } + HDfree(obj_op_name); + } + return ret; +} /* end attr_search() */ + +static herr_t +obj_search(const char *path, const H5O_info_t *oi, const char H5_ATTR_UNUSED *already_visited, void *_op_data) +{ + trav_handle_udata_t *handle_data = (trav_handle_udata_t*)_op_data; + const char *op_name = handle_data->op_name; + trav_attr_udata_t attr_data; + + attr_data.path = path; + attr_data.op_name = op_name; + H5Aiterate_by_name(handle_data->fid, path, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_search, (void*)&attr_data, H5P_DEFAULT); + + if(HDstrcmp(path, op_name) == 0) { + switch(oi->type) { + case H5O_TYPE_GROUP: + handle_groups(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_DATASET: + handle_datasets(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_NAMED_DATATYPE: + handle_datatypes(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object type value\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end switch */ + } + + return 0; +} /* end obj_search() */ + +static herr_t +lnk_search(const char *path, const H5L_info_t *li, void *_op_data) +{ + size_t search_len; + size_t k; + char *search_name; + trav_handle_udata_t *handle_data = (trav_handle_udata_t*)_op_data; + const char *op_name = handle_data->op_name; + + search_len = HDstrlen(op_name); + if(search_len > 0 && op_name[0] != '/') + k = 2; + else + k = 1; + search_name = (char *)HDmalloc(search_len + k); + if(search_name == NULL) { + error_msg("creating temporary link\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + if (k == 2) { + HDstrcpy(search_name, "/"); + HDstrncat(search_name, op_name, search_len + 1); + } + else + HDstrncpy(search_name, op_name, search_len + 1); + search_name[search_len + k - 1] = '\0'; + + if(HDstrcmp(path, search_name) == 0) { + switch(li->type) { + case H5L_TYPE_SOFT: + case H5L_TYPE_EXTERNAL: + handle_links(handle_data->fid, op_name, NULL, 0, NULL); + break; + + case H5L_TYPE_HARD: + case H5L_TYPE_MAX: + case H5L_TYPE_ERROR: + default: + error_msg("unknown link type value\n"); + h5tools_setstatus(EXIT_FAILURE); + break; + } /* end switch() */ + } + HDfree(search_name); + } + return 0; +} /* end lnk_search() */ + +/*------------------------------------------------------------------------- + * Function: handle_paths + * + * Purpose: Handle objects from the command. + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +handle_paths(hid_t fid, const char *path_name, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + hid_t gid = -1; + + if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) { + error_msg("unable to open root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + hid_t gcpl_id; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + trav_handle_udata_t handle_udata; /* User data for traversal */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + handle_udata.fid = fid; + handle_udata.op_name = path_name; + if(h5trav_visit(fid, "/", TRUE, TRUE, obj_search, lnk_search, &handle_udata) < 0) { + error_msg("error traversing information\n"); + h5tools_setstatus(EXIT_FAILURE); + } + } +} + +/*------------------------------------------------------------------------- + * Function: handle_attributes + * + * Purpose: Handle the attributes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + * PVN, May 2008 + * add an extra parameter PE, to allow printing/not printing of error messages + * + *------------------------------------------------------------------------- + */ +void +handle_attributes(hid_t fid, const char *attr, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + hid_t oid = -1; + hid_t attr_id = -1; + char *obj_name = NULL; + char *attr_name = NULL; + int j; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + j = (int)HDstrlen(attr) - 1; + obj_name = (char *)HDmalloc((size_t)j + 2); + if(obj_name == NULL) + goto error; + + /* find the last / */ + while(j >= 0) { + if (attr[j] == '/' && (j==0 || (j>0 && attr[j-1]!='\\'))) + break; + j--; + } + + /* object name */ + if(j == -1) + HDstrcpy(obj_name, "/"); + else { + HDstrncpy(obj_name, attr, (size_t)j + 1); + obj_name[j + 1] = '\0'; + } /* end else */ + + dump_indent += COL; + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + attr_name = h5tools_str_replace(attr + j + 1, "\\/", "/"); + + /* handle error case: cannot open the object with the attribute */ + if((oid = H5Oopen(fid, obj_name, H5P_DEFAULT)) < 0) { + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->attributebegin, attr, + h5tools_dump_header_format->attributeblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("unable to open object \"%s\"\n", obj_name); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->attributeblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->attributeblockend); + if(HDstrlen(h5tools_dump_header_format->attributeend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->attributeend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->attributeend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + goto error; + } /* end if */ + + attr_id = H5Aopen(oid, attr_name, H5P_DEFAULT); + oid_output = display_oid; + data_output = display_data; + attr_data_output = display_attr_data; + + h5dump_type_table = type_table; + h5tools_dump_attribute(rawoutstream, outputformat, &ctx, attr_name, attr_id, display_ai, display_char); + h5dump_type_table = NULL; + + if(attr_id < 0) { + goto error; + } + + /* Close object */ + if(H5Oclose(oid) < 0) { + goto error; + } /* end if */ + + HDfree(obj_name); + HDfree(attr_name); + dump_indent -= COL; + return; + +error: + h5tools_setstatus(EXIT_FAILURE); + if(obj_name) + HDfree(obj_name); + + if (attr_name) + HDfree(attr_name); + + H5E_BEGIN_TRY { + H5Oclose(oid); + H5Aclose(attr_id); + } H5E_END_TRY; + dump_indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: handle_datasets + * + * Purpose: Handle the datasets from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * Pedro Vicente, Tuesday, January 15, 2008 + * check for block overlap\ + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_datasets(hid_t fid, const char *dset, void *data, int pe, const char *display_name) +{ + H5O_info_t oinfo; + hid_t dsetid; + hid_t dapl_id = H5P_DEFAULT; /* dataset access property list ID */ + struct subset_t *sset = (struct subset_t *)data; + const char *real_name = display_name ? display_name : dset; + + if(display_data) { + if ((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0) { + error_msg("error in creating default access property list ID\n"); + } + if (display_vds_first) { + if(H5Pset_virtual_view(dapl_id, H5D_VDS_FIRST_MISSING) < 0) + error_msg("error in setting access property list ID, virtual_view\n"); + } + if (vds_gap_size > 0) { + if(H5Pset_virtual_printf_gap(dapl_id, (hsize_t)vds_gap_size) < 0) + error_msg("error in setting access property list ID, virtual_printf_gap\n"); + } + } + if((dsetid = H5Dopen2(fid, dset, dapl_id)) < 0) { + if (pe) + handle_links(fid, dset, data, pe, display_name); + return; + } /* end if */ + + if(sset) { + unsigned int i; + unsigned int ndims; + hid_t sid = H5Dget_space(dsetid); + int ndims_res = H5Sget_simple_extent_ndims(sid); + + H5Sclose(sid); + if(ndims_res < 0) { + error_msg("H5Sget_simple_extent_ndims failed\n"); + h5tools_setstatus(EXIT_FAILURE); + return; + } + ndims = (unsigned)ndims_res; + + if(!sset->start.data || !sset->stride.data || !sset->count.data || !sset->block.data) { + /* they didn't specify a ``stride'' or ``block''. default to 1 in all + * dimensions */ + if(!sset->start.data) { + /* default to (0, 0, ...) for the start coord */ + sset->start.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->start.len = ndims; + } + + if(!sset->stride.data) { + sset->stride.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->stride.len = ndims; + for (i = 0; i < ndims; i++) + sset->stride.data[i] = 1; + } + + if(!sset->count.data) { + sset->count.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->count.len = ndims; + for (i = 0; i < ndims; i++) + sset->count.data[i] = 1; + } + + if(!sset->block.data) { + sset->block.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->block.len = ndims; + for (i = 0; i < ndims; i++) + sset->block.data[i] = 1; + } + } + + /*------------------------------------------------------------------------- + * check for dimension overflow + *------------------------------------------------------------------------- + */ + if(sset->start.len > ndims) { + error_msg("number of start dims (%u) exceed dataset dims (%u)\n", sset->start.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->stride.len > ndims) { + error_msg("number of stride dims (%u) exceed dataset dims (%u)\n", sset->stride.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->count.len > ndims) { + error_msg("number of count dims (%u) exceed dataset dims (%u)\n", sset->count.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->block.len > ndims) { + error_msg("number of block dims (%u) exceed dataset dims (%u)\n", sset->block.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + + /*------------------------------------------------------------------------- + * check for block overlap + *------------------------------------------------------------------------- + */ + for(i = 0; i < ndims; i++) { + if(sset->count.data[i] > 1) { + if(sset->stride.data[i] < sset->block.data[i]) { + error_msg("wrong subset selection; blocks overlap\n"); + h5tools_setstatus(EXIT_FAILURE); + return; + } /* end if */ + } /* end if */ + } /* end for */ + } /* end if */ + + + H5Oget_info(dsetid, &oinfo); + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj) { + if (found_obj->displayed) { + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(dump_indent); + begin_obj(h5tools_dump_header_format->datasetbegin, real_name, h5tools_dump_header_format->datasetblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s \"%s\"\n", HARDLINK, found_obj->objname); + indentation(dump_indent); + end_obj(h5tools_dump_header_format->datasetend, h5tools_dump_header_format->datasetblockend); + } + else { + found_obj->displayed = TRUE; + dump_indent += COL; + dump_dataset(dsetid, real_name, sset); + dump_indent -= COL; + } + } + else + h5tools_setstatus(EXIT_FAILURE); + } + else { + dump_indent += COL; + dump_dataset(dsetid, real_name, sset); + dump_indent -= COL; + } + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + if(H5Dclose(dsetid) < 0) + h5tools_setstatus(EXIT_FAILURE); +} + +/*------------------------------------------------------------------------- + * Function: handle_groups + * + * Purpose: Handle the groups from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: Pedro Vicente, September 26, 2007 + * handle creation order + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_groups(hid_t fid, const char *group, void H5_ATTR_UNUSED *data, int pe, const char *display_name) +{ + hid_t gid; + const char *real_name = display_name ? display_name : group; + + if((gid = H5Gopen2(fid, group, H5P_DEFAULT)) < 0) { + if (pe) { + PRINTVALSTREAM(rawoutstream, "\n"); + begin_obj(h5tools_dump_header_format->groupbegin, real_name, h5tools_dump_header_format->groupblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + error_msg("unable to open group \"%s\"\n", real_name); + end_obj(h5tools_dump_header_format->groupend, h5tools_dump_header_format->groupblockend); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + size_t new_len = HDstrlen(group) + 1; + + if(prefix_len <= new_len) { + prefix_len = new_len; + prefix = (char *)HDrealloc(prefix, prefix_len); + } /* end if */ + + HDstrcpy(prefix, group); + + dump_indent += COL; + dump_group(gid, real_name); + dump_indent -= COL; + + if(H5Gclose(gid) < 0) + h5tools_setstatus(EXIT_FAILURE); + } /* end else */ +} /* end handle_groups() */ + +/*------------------------------------------------------------------------- + * Function: handle_links + * + * Purpose: Handle soft or UD links from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +handle_links(hid_t fid, const char *links, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + H5L_info_t linfo; + + if(H5Lget_info(fid, links, &linfo, H5P_DEFAULT) < 0) { + error_msg("unable to get link info from \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + else if(linfo.type == H5L_TYPE_HARD) { + error_msg("\"%s\" is a hard link\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + else { + char *buf = (char *)HDmalloc(linfo.u.val_size); + PRINTVALSTREAM(rawoutstream, "\n"); + + switch(linfo.type) { + case H5L_TYPE_SOFT: /* Soft link */ + begin_obj(h5tools_dump_header_format->softlinkbegin, links, h5tools_dump_header_format->softlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + if(H5Lget_val(fid, links, buf, linfo.u.val_size, H5P_DEFAULT) >= 0) { + PRINTSTREAM(rawoutstream, "LINKTARGET \"%s\"\n", buf); + } + else { + error_msg("h5dump error: unable to get link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + end_obj(h5tools_dump_header_format->softlinkend, h5tools_dump_header_format->softlinkblockend); + break; + + case H5L_TYPE_EXTERNAL: + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + begin_obj(h5tools_dump_header_format->extlinkbegin, links, h5tools_dump_header_format->extlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + if(H5Lget_val(fid, links, buf, linfo.u.val_size, H5P_DEFAULT) >= 0) { + const char *elink_file; + const char *elink_path; + + if(H5Lunpack_elink_val(buf, linfo.u.val_size, NULL, &elink_file, &elink_path)>=0) { + indentation(COL); + PRINTSTREAM(rawoutstream, "LINKCLASS %d\n", linfo.type); + indentation(COL); + PRINTSTREAM(rawoutstream, "TARGETFILE \"%s\"\n", elink_file); + indentation(COL); + PRINTSTREAM(rawoutstream, "TARGETPATH \"%s\"\n", elink_path); + } + else { + error_msg("h5dump error: unable to unpack external link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + error_msg("h5dump error: unable to get external link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + end_obj(h5tools_dump_header_format->extlinkend, h5tools_dump_header_format->extlinkblockend); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + PRINTSTREAM(rawoutstream, "LINKCLASS %d\n", linfo.type); + end_obj(h5tools_dump_header_format->udlinkend, h5tools_dump_header_format->udlinkblockend); + break; + } /* end switch */ + HDfree(buf); + } /* end else */ +} + +/*------------------------------------------------------------------------- + * Function: handle_datatypes + * + * Purpose: Handle the datatypes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_datatypes(hid_t fid, const char *type, void H5_ATTR_UNUSED * data, int pe, const char *display_name) +{ + hid_t type_id; + const char *real_name = display_name ? display_name : type; + + if((type_id = H5Topen2(fid, type, H5P_DEFAULT)) < 0) { + /* check if type is unamed datatype */ + unsigned idx = 0; + + while(idx < type_table->nobjs ) { + char name[128]; + + if(!type_table->objs[idx].recorded) { + /* unamed datatype */ + sprintf(name, "/#"H5_PRINTF_HADDR_FMT, type_table->objs[idx].objno); + + if(!HDstrcmp(name, real_name)) + break; + } /* end if */ + + idx++; + } /* end while */ + + if(idx == type_table->nobjs) { + if (pe) { + /* unknown type */ + PRINTVALSTREAM(rawoutstream, "\n"); + begin_obj(h5tools_dump_header_format->datatypebegin, real_name, h5tools_dump_header_format->datatypeblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + error_msg("unable to open datatype \"%s\"\n", real_name); + end_obj(h5tools_dump_header_format->datatypeend, h5tools_dump_header_format->datatypeblockend); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + hid_t dsetid = H5Dopen2(fid, type_table->objs[idx].objname, H5P_DEFAULT); + type_id = H5Dget_type(dsetid); + + dump_indent += COL; + dump_named_datatype(type_id, real_name); + dump_indent -= COL; + + H5Tclose(type_id); + H5Dclose(dsetid); + } + } + else { + dump_indent += COL; + dump_named_datatype(type_id, real_name); + dump_indent -= COL; + + if(H5Tclose(type_id) < 0) + h5tools_setstatus(EXIT_FAILURE); + } +} + + +/*------------------------------------------------------------------------- + * Function: dump_extlink + * + * made by: PVN + * + * Purpose: Dump an external link + * Since external links are soft links, they are dumped on a trial error + * basis, attempting to dump as a dataset, as a group and as a named datatype + * Error messages are supressed + * + * Modifications: + * Neil Fortner + * 13 October 2008 + * Function basically rewritten. No longer directly opens the target file, + * now initializes a new set of tables for the external file. No longer + * dumps on a trial and error basis, but errors are still suppressed. + * + *------------------------------------------------------------------------- + */ +static int +dump_extlink(hid_t group, const char *linkname, const char *objname) +{ + hid_t oid; + H5O_info_t oi; + table_t *old_group_table = group_table; + table_t *old_dset_table = dset_table; + table_t *old_type_table = type_table; + hbool_t old_hit_elink; + ssize_t idx; + + /* Open target object */ + if ((oid = H5Oopen(group, linkname, H5P_DEFAULT)) < 0) + goto fail; + + /* Get object info */ + if (H5Oget_info(oid, &oi) < 0) { + H5Oclose(oid); + goto fail; + } + + /* Check if we have visited this file already */ + if ((idx = table_list_visited(oi.fileno)) < 0) { + /* We have not visited this file, build object tables */ + if ((idx = table_list_add(oid, oi.fileno)) < 0) { + H5Oclose(oid); + goto fail; + } + } + + /* Do not recurse through an external link into the original file (idx=0) */ + if (idx) { + /* Update table pointers */ + group_table = table_list.tables[idx].group_table; + dset_table = table_list.tables[idx].dset_table; + type_table = table_list.tables[idx].type_table; + + /* We will now traverse the external link, set this global to indicate this */ + old_hit_elink = hit_elink; + hit_elink = TRUE; + + /* add some indentation to distinguish that these objects are external */ + dump_indent += COL; + + /* Recurse into the external file */ + switch (oi.type) { + case H5O_TYPE_GROUP: + handle_groups(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_DATASET: + handle_datasets(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_NAMED_DATATYPE: + handle_datatypes(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + h5tools_setstatus(EXIT_FAILURE); + } + + dump_indent -= COL; + + /* Reset table pointers */ + group_table = old_group_table; + dset_table = old_dset_table; + type_table = old_type_table; + + /* Reset hit_elink */ + hit_elink = old_hit_elink; + } /* end if */ + + if (H5Idec_ref(oid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + return SUCCEED; + +fail: + return FAIL; +} + diff --git a/tools/src/h5dump/h5dump_ddl.h b/tools/src/h5dump/h5dump_ddl.h new file mode 100644 index 0000000..2b3f61e --- /dev/null +++ b/tools/src/h5dump/h5dump_ddl.h @@ -0,0 +1,52 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef H5DUMP_DDL_H__ +#define H5DUMP_DDL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The dump functions of the dump_function_table */ +/* standard format: no change */ +void dump_group(hid_t, const char *); +void dump_named_datatype(hid_t, const char *); +void dump_dataset(hid_t, const char *, struct subset_t *); +void dump_dataspace(hid_t space); +void dump_datatype(hid_t type); +void dump_data(hid_t, int, struct subset_t *, int); +void dump_fcpl(hid_t fid); +void dump_fcontents(hid_t fid); + +/* callback function used by H5Aiterate2() */ +herr_t dump_attr_cb(hid_t loc_id, const char *attr_name, const H5A_info_t *info, void *_op_data); + +/* other iteration functions */ +void link_iteration(hid_t gid, unsigned crt_order_flags); +void attr_iteration(hid_t gid, unsigned attr_crt_order_flags); + +void handle_paths(hid_t fid, const char *path_name, void *data, int pe, const char *display_name); +void handle_datasets(hid_t fid, const char *dset, void *data, int pe, const char *display_name); +void handle_attributes(hid_t fid, const char *attr, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name); +void handle_groups(hid_t fid, const char *group, void H5_ATTR_UNUSED *data, int pe, const char *display_name); +void handle_links(hid_t fid, const char *links, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name); +void handle_datatypes(hid_t fid, const char *type, void H5_ATTR_UNUSED * data, int pe, const char *display_name); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_DDL_H__ */ diff --git a/tools/src/h5dump/h5dump_defines.h b/tools/src/h5dump/h5dump_defines.h new file mode 100644 index 0000000..2be2dcc --- /dev/null +++ b/tools/src/h5dump/h5dump_defines.h @@ -0,0 +1,56 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_DEFINES_H__ +#define H5DUMP_DEFINES_H__ + +#define H5DUMP_MAX_RANK H5S_MAX_RANK + +#define ATTRIBUTE_DATA 0 +#define DATASET_DATA 1 +#define ENUM_DATA 2 +#define COL 3 + +/* Macros for displaying objects */ +#define begin_obj(obj,name,begin) \ + do { \ + if ((name)) { \ + PRINTSTREAM(rawoutstream, "%s \"%s\" %s", (obj), (name), (begin)); \ + } \ + else { \ + PRINTSTREAM(rawoutstream, "%s %s", (obj), (begin)); \ + } \ + } while(0); + +#define end_obj(obj,end) \ + do { \ + if(HDstrlen(end)) { \ + PRINTSTREAM(rawoutstream, "%s", end); \ + if(HDstrlen(obj)) \ + PRINTVALSTREAM(rawoutstream, " "); \ + } \ + if(HDstrlen(obj)) \ + PRINTSTREAM(rawoutstream, "%s", obj); \ + } while(0); + + +/* 3 private values: can't be set, but can be read. + Note: these are defined in H5Zprivate, they are + duplicated here. + */ +#define H5_SZIP_LSB_OPTION_MASK 8 +#define H5_SZIP_MSB_OPTION_MASK 16 +#define H5_SZIP_RAW_OPTION_MASK 128 + +#endif /* !H5DUMP_DEFINES_H__ */ diff --git a/tools/src/h5dump/h5dump_extern.h b/tools/src/h5dump/h5dump_extern.h new file mode 100644 index 0000000..8fef1b9 --- /dev/null +++ b/tools/src/h5dump/h5dump_extern.h @@ -0,0 +1,114 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_EXTERN_H__ +#define H5DUMP_EXTERN_H__ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_defines.h" + +/** + ** This is the global dispatch table for the dump functions. + **/ +/* the table of dump functions */ +typedef struct dump_functions_t { + void (*dump_group_function) (hid_t, const char *); + void (*dump_named_datatype_function) (hid_t, const char *); + void (*dump_dataset_function) (hid_t, const char *, struct subset_t *); + void (*dump_dataspace_function) (hid_t); + void (*dump_datatype_function) (hid_t); + herr_t (*dump_attribute_function) (hid_t, const char *, const H5A_info_t *, void *); + void (*dump_data_function) (hid_t, int, struct subset_t *, int); +} dump_functions; + +/* List of table structures. There is one table structure for each file */ +typedef struct h5dump_table_list_t { + size_t nalloc; + size_t nused; + struct { + unsigned long fileno; /* File number that these tables refer to */ + hid_t oid; /* ID of an object in this file, held open so fileno is consistent */ + table_t *group_table; /* Table of groups */ + table_t *dset_table; /* Table of datasets */ + table_t *type_table; /* Table of datatypes */ + } *tables; +} h5dump_table_list_t; + +extern h5dump_table_list_t table_list; +extern table_t *group_table, *dset_table, *type_table; +extern unsigned dump_indent; /*how far in to indent the line */ + +extern int unamedtype; /* shared datatype with no name */ +extern hbool_t hit_elink; /* whether we have traversed an external link */ +extern size_t prefix_len; +extern char *prefix; +extern const char *fp_format; + +/* things to display or which are set via command line parameters */ +extern int display_all; +extern int display_oid; +extern int display_data; +extern int display_attr_data; +extern int display_char; /*print 1-byte numbers as ASCII */ +extern int usingdasho; +extern int display_bb; /*superblock */ +extern int display_dcpl; /*dcpl */ +extern int display_fi; /*file index */ +extern int display_ai; /*array index */ +extern int display_escape; /*escape non printable characters */ +extern int display_region; /*print region reference data */ +extern int disable_compact_subset; /* disable compact form of subset notation */ +extern int display_packed_bits; /*print 1-8 byte numbers as packed bits*/ +extern int include_attrs; /* Display attributes */ +extern int display_vds_first; /* vds display to first missing */ +extern int vds_gap_size; /* vds skip missing files */ + +/* sort parameters */ +extern H5_index_t sort_by; /*sort_by [creation_order | name] */ +extern H5_iter_order_t sort_order; /*sort_order [ascending | descending] */ + +#define PACKED_BITS_MAX 8 /* Maximum number of packed-bits to display */ +#define PACKED_BITS_SIZE_MAX 8*sizeof(long long) /* Maximum bits size of integer types of packed-bits */ +/* mask list for packed bits */ +extern unsigned long long packed_mask[PACKED_BITS_MAX]; /* packed bits are restricted to 8*sizeof(llong) bytes */ + +/* packed bits display parameters */ +extern unsigned packed_offset[PACKED_BITS_MAX]; +extern unsigned packed_length[PACKED_BITS_MAX]; + +/* + * The global table is set to either ddl_function_table or + * xml_function_table in the initialization. + */ +extern const dump_functions *dump_function_table; + +#ifdef __cplusplus +extern "C" { +#endif + +void add_prefix(char **prfx, size_t *prfx_len, const char *name); +hid_t h5_fileaccess(void); +ssize_t table_list_add(hid_t oid, unsigned long file_no); +ssize_t table_list_visited(unsigned long file_no); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_EXTERN_H__ */ diff --git a/tools/src/h5dump/h5dump_xml.c b/tools/src/h5dump/h5dump_xml.c new file mode 100644 index 0000000..41f3914 --- /dev/null +++ b/tools/src/h5dump/h5dump_xml.c @@ -0,0 +1,4567 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_dump.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_extern.h" +#include "h5dump_xml.h" + +const char *xmlnsprefix="hdf5:"; + +/* + * Alternative formating for data dumped to XML + * In general, the numbers are the same, but separators + * except spaces are not used. + * + * Some of these are not used, as some kinds of data are + * dumped in completely new subroutines. + * + * Some of this formatting may yet need to change. + * + * This table only affects XML output. + */ +static h5tool_format_t xml_dataformat = { + 0, /*raw */ + + "", /*fmt_raw */ + "%d", /*fmt_int */ + "%u", /*fmt_uint */ + "%hhd", /*fmt_schar */ + "%u", /*fmt_uchar */ + "%d", /*fmt_short */ + "%u", /*fmt_ushort */ + "%ld", /*fmt_long */ + "%lu", /*fmt_ulong */ + NULL, /*fmt_llong */ + NULL, /*fmt_ullong */ + "%g", /*fmt_double */ + "%g", /*fmt_float */ + + 0, /*ascii */ + 0, /*str_locale */ + 0, /*str_repeat */ + + "", /*arr_pre */ + "", /*arr_sep */ + "", /*arr_suf */ + 1, /*arr_linebreak */ + + "", /*cmpd_name */ + "", /*cmpd_sep */ + "", /*cmpd_pre */ + "", /*cmpd_suf */ + "", /*cmpd_end */ + + " ", /*vlen_sep */ + " ", /*vlen_pre */ + "", /*vlen_suf */ + "", /*vlen_end */ + + "%s", /*elmt_fmt */ + "", /*elmt_suf1 */ + " ", /*elmt_suf2 */ + + "", /*idx_n_fmt */ + "", /*idx_sep */ + "", /*idx_fmt */ + + 80, /*line_ncols *//*standard default columns */ + 0, /*line_per_line */ + "", /*line_pre */ + "%s", /*line_1st */ + "%s", /*line_cont */ + "", /*line_suf */ + "", /*line_sep */ + 1, /*line_multi_new */ + " ", /*line_indent */ + + 1, /*skip_first */ + + 1, /*obj_hidefileno */ + " "H5_PRINTF_HADDR_FMT, /*obj_format */ + + 1, /*dset_hidefileno */ + "DATASET %s ", /*dset_format */ + "%s", /*dset_blockformat_pre */ + "%s", /*dset_ptformat_pre */ + "%s", /*dset_ptformat */ + 0, /*array indices */ + 0 /*escape non printable characters */ +}; + + +/* internal functions */ +static int xml_name_to_XID(const char *, char *, int , int ); + +/* internal functions used by XML option */ +static void xml_print_datatype(hid_t, unsigned); +static void xml_print_enum(hid_t); +static int xml_print_refs(hid_t, int); +static int xml_print_strs(hid_t, int); +static char *xml_escape_the_string(const char *, int); +static char *xml_escape_the_name(const char *); + +/*------------------------------------------------------------------------- + * Function: xml_dump_all_cb + * + * Purpose: function callback called by H5Literate, + * displays everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * RMcG, November 2000 + * Added XML support. Also, optionally checks the op_data argument + * + * PVN, May 2008 + * Dump external links + * + *------------------------------------------------------------------------- + */ +static herr_t +xml_dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void H5_ATTR_UNUSED *op_data) +{ + hid_t obj; + herr_t ret = SUCCEED; + char *obj_path = NULL; /* Full path of object */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols==0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + /* Build the object's path name */ + obj_path = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + if(!obj_path) { + ret = FAIL; + goto done; + } + + HDstrcpy(obj_path, prefix); + HDstrcat(obj_path, "/"); + HDstrcat(obj_path, name); + + if(linfo->type == H5L_TYPE_HARD) { + H5O_info_t oinfo; + + /* Stat the object */ + if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) { + error_msg("unable to get object information for \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + goto done; + } /* end if */ + + switch(oinfo.type) { + case H5O_TYPE_GROUP: + if((obj = H5Gopen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump group \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + char *old_prefix; /* Pointer to previous prefix */ + + /* Keep copy of prefix before iterating into group */ + old_prefix = HDstrdup(prefix); + HDassert(old_prefix); + + /* Append group name to prefix */ + add_prefix(&prefix, &prefix_len, name); + + /* Iterate into group */ + dump_function_table->dump_group_function(obj, name); + + /* Restore old prefix name */ + HDstrcpy(prefix, old_prefix); + HDfree(old_prefix); + + /* Close group */ + H5Gclose(obj); + } + break; + + case H5O_TYPE_DATASET: + if((obj = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) { + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj == NULL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + H5Dclose(obj); + goto done; + } + else if(found_obj->displayed) { + /* the XML version */ + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_name = xml_escape_the_name(name); + char *t_objname = xml_escape_the_name(found_obj->objname); + char dsetxid[100]; + char parentxid[100]; + char pointerxid[100]; + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(obj_path, dsetxid, (int)sizeof(dsetxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataset Name=\"%s\" OBJ-XID=\"%s-%d\" " + "H5Path=\"%s\" Parents=\"%s\" " + "H5ParentPaths=\"%s\">", + xmlnsprefix, + t_name, /* Dataset Name */ + dsetxid, get_next_xid(), /* OBJ-XID */ + t_obj_path, /* H5Path */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_name_to_XID(found_obj->objname, pointerxid, (int)sizeof(pointerxid), 1); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDatasetPtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", + xmlnsprefix, + pointerxid,t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataset>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(t_obj_path); + HDfree(t_prefix); + HDfree(t_objname); + + H5Dclose(obj); + goto done; + } + else + found_obj->displayed = TRUE; + } /* end if */ + + dump_function_table->dump_dataset_function(obj, name, NULL); + H5Dclose(obj); + } + else { + error_msg("unable to dump dataset \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + break; + + case H5O_TYPE_NAMED_DATATYPE: + if((obj = H5Topen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump datatype \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + dump_function_table->dump_named_datatype_function(obj, name); + H5Tclose(obj); + } + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + } /* end if */ + else { + char *targbuf; + + switch(linfo->type) { + case H5L_TYPE_SOFT: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + /* print the value of a soft link */ + /* XML */ + char linkxid[100]; + char parentxid[100]; + char targetxid[100]; + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_name = xml_escape_the_name(name); + char *t_targbuf = xml_escape_the_name(targbuf); + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_link_path; + int res; + + t_link_path = (char *)HDmalloc(HDstrlen(prefix) + linfo->u.val_size + 1); + if(targbuf[0] == '/') + HDstrcpy(t_link_path, targbuf); + else { + HDstrcpy(t_link_path, prefix); + HDstrcat(HDstrcat(t_link_path, "/"), targbuf); + } /* end else */ + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + /* Try to create an OBJ-XID for the object pointed to */ + res = xml_name_to_XID(t_link_path, targetxid, (int)sizeof(targetxid), 0); + if (res == 0) { + /* target obj found */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSoftLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetPath=\"%s\" TargetObj=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + t_targbuf, /* TargetPath */ + targetxid, /* TargetObj */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* dangling link -- omit from xml attributes */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSoftLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetPath=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + t_targbuf, /* TargetPath */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_targbuf); + HDfree(t_obj_path); + HDfree(t_link_path); + } + + HDfree(targbuf); + break; + + case H5L_TYPE_EXTERNAL: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + const char *filename; + const char *targname; + + if(H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &targname) < 0) { + error_msg("unable to unpack external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + char linkxid[100]; + char parentxid[100]; + char *t_name = xml_escape_the_name(name); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_filename = xml_escape_the_name(filename); + char *t_targname = xml_escape_the_name(targname); + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sExternalLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetFilename=\"%s\" " + "TargetPath=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + filename, /* TargetFilename */ + targname, /* TargetPath*/ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_filename); + HDfree(t_targname); + HDfree(t_obj_path); + } /* end else */ + } /* end else */ + HDfree(targbuf); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + { + char linkxid[100]; + char parentxid[100]; + char *t_name = xml_escape_the_name(name); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_obj_path = xml_escape_the_name(obj_path); + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sUserDefined LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "LinkClass=\"%d\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + linfo->type, /* LinkClass */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_obj_path); + } + break; + + } /* end switch */ + } /* end else */ + +done: + + h5tools_str_close(&buffer); + + if(obj_path) + HDfree(obj_path); + return ret; +} + +/* + * create a string suitable for and XML NCNAME. Uses the + * object reference to create the string. + * + * 'gen'; 0 - return null if not found + * 1 - generate a fake entry and return fake id. + */ +int +xml_name_to_XID(const char *str , char *outstr, int outlen, int gen) +{ + haddr_t objno; /* Object ID for object at path */ + + if (outlen < 22) return 1; + + objno = ref_path_table_lookup(str); + if (objno == HADDR_UNDEF) { + if (HDstrlen(str) == 0) { + objno = ref_path_table_lookup("/"); + if (objno == HADDR_UNDEF) { + if (gen) { + objno = ref_path_table_gen_fake(str); + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + return 0; + } + else { + return 1; + } + } + } + else { + if (gen) { + objno = ref_path_table_gen_fake(str); + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + return 0; + } + else { + return 1; + } + } + } + + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + + return(0); +} + +static const char *quote = """; +static const char *amp = "&"; +static const char *lt = "<"; +static const char *gt = ">"; +static const char *apos = "'"; + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_name + * + * Purpose: Escape XML reserved chars in a name, so HDF5 strings + * and paths can be correctly read back in XML element. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_name(const char *str) +{ + size_t extra; + size_t len; + size_t i; + const char *cp; + char *ncp; + char *rcp; + size_t ncp_len; + + if (!str) + return NULL; + + cp = str; + len = HDstrlen(str); + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\"') + extra += (HDstrlen(quote) - 1); + else if (*cp == '\'') + extra += (HDstrlen(apos) - 1); + else if (*cp == '<') + extra += (HDstrlen(lt) - 1); + else if (*cp == '>') + extra += (HDstrlen(gt) - 1); + else if (*cp == '&') + extra += (HDstrlen(amp) - 1); + + cp++; + } + + if (extra == 0) + return HDstrdup(str); + + cp = str; + ncp_len = len + extra + 1; + rcp = ncp = (char *)HDmalloc(ncp_len); + + if (!ncp) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + size_t esc_len; + + HDassert(ncp_len); + if (*cp == '\'') { + HDstrncpy(ncp, apos, ncp_len); + esc_len = HDstrlen(apos); + } + else if (*cp == '<') { + HDstrncpy(ncp, lt, ncp_len); + esc_len = HDstrlen(lt); + } + else if (*cp == '>') { + HDstrncpy(ncp, gt, ncp_len); + esc_len = HDstrlen(gt); + } + else if (*cp == '\"') { + HDstrncpy(ncp, quote, ncp_len); + esc_len = HDstrlen(quote); + } + else if (*cp == '&') { + HDstrncpy(ncp, amp, ncp_len); + esc_len = HDstrlen(amp); + } + else { + *ncp = *cp; + esc_len = 1; + } + ncp += esc_len; + ncp_len -= esc_len; + cp++; + } + + *ncp = '\0'; + return rcp; +} + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_string + * + * Purpose: Escape XML reserved chars in a string, so HDF5 strings + * and paths can be correctly read back in XML CDATA. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_string(const char *str, int slen) +{ + size_t extra; + size_t len; + size_t i; + const char *cp; + char *ncp; + char *rcp; + size_t ncp_len; + + if (!str) + return NULL; + + cp = str; + + if (slen < 0) + len = HDstrlen(str); + else + len = (size_t)slen; + + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\\') + extra++; + else if (*cp == '\"') + extra++; + else if (*cp == '\'') + extra += (HDstrlen(apos) - 1); + else if (*cp == '<') + extra += (HDstrlen(lt) - 1); + else if (*cp == '>') + extra += (HDstrlen(gt) - 1); + else if (*cp == '&') + extra += (HDstrlen(amp) - 1); + cp++; + } + + cp = str; + ncp_len = len + extra + 1; + rcp = ncp = (char *) HDcalloc(ncp_len, sizeof(char)); + + if (ncp == NULL) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + size_t esc_len; + + HDassert(ncp_len); + if (*cp == '\\') { + *ncp++ = '\\'; + *ncp = *cp; + esc_len = 1; + } + else if (*cp == '\"') { + *ncp++ = '\\'; + *ncp = *cp; + esc_len = 1; + } + else if (*cp == '\'') { + HDstrncpy(ncp, apos, ncp_len); + esc_len = HDstrlen(apos); + } + else if (*cp == '<') { + HDstrncpy(ncp, lt, ncp_len); + esc_len = HDstrlen(lt); + } + else if (*cp == '>') { + HDstrncpy(ncp, gt, ncp_len); + esc_len = HDstrlen(gt); + } + else if (*cp == '&') { + HDstrncpy(ncp, amp, ncp_len); + esc_len = HDstrlen(amp); + } + else { + *ncp = *cp; + esc_len = 1; + } + ncp += esc_len; + ncp_len -= esc_len; + cp++; + } + + *ncp = '\0'; + return rcp; +} + +/** + ** XML print functions--these replace some functions in the + ** h5tools.c suite. + **/ + +/*------------------------------------------------------------------------- + * Function: xml_print_datatype + * + * Purpose: Print description of a datatype in XML. + * Note: this is called inside a <DataType> element. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_datatype(hid_t type, unsigned in_group) +{ + char *mname; + hid_t mtype; + unsigned nmembers; + unsigned ndims; + unsigned i; + size_t size; + hsize_t dims[H5DUMP_MAX_RANK]; + H5T_str_t str_pad; + H5T_cset_t cset; + hid_t super; + H5T_order_t ord; + H5T_sign_t sgn; + size_t sz; + size_t spos; + size_t epos; + size_t esize; + size_t mpos; + size_t msize; + int nmembs; + htri_t is_vlstr=FALSE; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols==0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if(!in_group && H5Tcommitted(type) > 0) { + H5O_info_t oinfo; + obj_t *found_obj; /* Found object */ + + /* detect a shared datatype, output only once */ + H5Oget_info(type, &oinfo); + found_obj = search_obj(type_table, oinfo.addr); + + if(found_obj) { + /* This should be defined somewhere else */ + /* These 2 cases are handled the same right now, but + probably will have something different eventually */ + char * dtxid = (char *)HDmalloc((size_t)100); + + xml_name_to_XID(found_obj->objname, dtxid, 100, 1); + if (!found_obj->recorded) { + /* 'anonymous' NDT. Use it's object num. + as it's name. */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"/%s\"/>", + xmlnsprefix, dtxid); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* point to the NDT by name */ + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", + xmlnsprefix, dtxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + } + HDfree(dtxid); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unknown committed type. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + /* <hdf5:IntegerType ByteOrder="bo" Sign="torf" Size="bytes"/> */ + ord = H5Tget_order(type); + sgn = H5Tget_sign(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sIntegerType ByteOrder=\"",xmlnsprefix); + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + break; + } /* end switch */ + + h5tools_str_append(&buffer, "\" Sign=\""); + + switch (sgn) { + case H5T_SGN_NONE: + h5tools_str_append(&buffer, "false"); + break; + case H5T_SGN_2: + h5tools_str_append(&buffer, "true"); + break; + case H5T_SGN_ERROR: + case H5T_NSGN: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + break; + } /* end switch */ + + h5tools_str_append(&buffer, "\" Size=\""); + sz = H5Tget_size(type); + h5tools_str_append(&buffer, "%lu", (unsigned long)sz); + h5tools_str_append(&buffer, "\" />"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_FLOAT: + /* <hdf5:FloatType ByteOrder="bo" Size="bytes" + SignBitLocation="bytes" + ExponentBits="eb" ExponentLocation="el" + MantissaBits="mb" MantissaLocation="ml" /> */ + ord = H5Tget_order(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFloatType ByteOrder=\"",xmlnsprefix); + + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + h5tools_str_append(&buffer, "VAX"); + break; + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + } /* end switch */ + + h5tools_str_append(&buffer, "\" Size=\""); + sz = H5Tget_size(type); + h5tools_str_append(&buffer, "%lu", (unsigned long)sz); + H5Tget_fields(type, &spos, &epos, &esize, &mpos, &msize); + h5tools_str_append(&buffer, "\" SignBitLocation=\"%lu\" ", (unsigned long)spos); + h5tools_str_append(&buffer, "ExponentBits=\"%lu\" ExponentLocation=\"%lu\" ", (unsigned long)esize, (unsigned long)epos); + h5tools_str_append(&buffer, "MantissaBits=\"%lu\" MantissaLocation=\"%lu\" />", (unsigned long)msize, (unsigned long)mpos); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_TIME: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sTimeType />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_str_append(&buffer, "<!-- H5T_TIME: not yet implemented -->"); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_STRING: + /* <hdf5:StringType Cset="cs" StrSize="chars" StrPad="pad" /> */ + size = H5Tget_size(type); + str_pad = H5Tget_strpad(type); + cset = H5Tget_cset(type); + is_vlstr = H5Tis_variable_str(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStringType Cset=\"",xmlnsprefix); + + if (cset == H5T_CSET_ASCII) + h5tools_str_append(&buffer, "H5T_CSET_ASCII\" "); + else + h5tools_str_append(&buffer, "unknown_cset\" "); + + if(is_vlstr) + h5tools_str_append(&buffer, "StrSize=\"H5T_VARIABLE\" StrPad=\""); + else + h5tools_str_append(&buffer, "StrSize=\"%d\" StrPad=\"", (int) size); + + if (str_pad == H5T_STR_NULLTERM) + h5tools_str_append(&buffer, "H5T_STR_NULLTERM\"/>"); + else if (str_pad == H5T_STR_NULLPAD) + h5tools_str_append(&buffer, "H5T_STR_NULLPAD\"/>"); + else if (str_pad == H5T_STR_SPACEPAD) + h5tools_str_append(&buffer, "H5T_STR_SPACEPAD\"/>"); + else + h5tools_str_append(&buffer, "H5T_STR_ERROR\"/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_BITFIELD: + /* <hdf5:BitfieldType ByteOrder="bo" Size="bytes"/> */ + ord = H5Tget_order(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sBitfieldType ByteOrder=\"",xmlnsprefix); + + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + } /* end switch */ + + size = H5Tget_size(type); + h5tools_str_append(&buffer, "\" Size=\"%lu\"/>", (unsigned long)size); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_OPAQUE: + /* <hdf5:OpaqueType Tag="tag" Size="bytes" /> */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + mname = H5Tget_tag(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sOpaqueType Tag=\"%s\" ",xmlnsprefix, mname); + H5free_memory(mname); + size = H5Tget_size(type); + h5tools_str_append(&buffer, "Size=\"%lu\"/>", (unsigned long)size); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_COMPOUND: + /* recursively describe the components of a compound datatype */ + + /* type of a dataset */ + nmembers = (unsigned)H5Tget_nmembers(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sCompoundType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* List each member Field of the type */ + /* <hdf5:Field FieldName="name" > */ + /* <hdf5:DataType > */ + ctx.indent_level++; + dump_indent += COL; + for (i = 0; i < nmembers; i++) { + char *t_fname; + + mname = H5Tget_member_name(type, i); + mtype = H5Tget_member_type(type, i); + t_fname = xml_escape_the_name(mname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sField FieldName=\"%s\">",xmlnsprefix, t_fname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5free_memory(mname); + HDfree(t_fname); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(mtype,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sField>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sCompoundType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + /* Only Object references supported at this time */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sReferenceType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sObjectReferenceType />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sReferenceType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_ENUM: + /* <hdf5:EnumType Nelems="ne" > list Name, values of enum */ + nmembs = H5Tget_nmembers(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumType Nelems=\"%d\">",xmlnsprefix, nmembs); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + xml_print_enum(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sVLType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + super = H5Tget_super(type); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + xml_print_datatype(super,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sVLType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + H5Tclose(super); + + break; + + case H5T_ARRAY: + /* Get array base type */ + super = H5Tget_super(type); + + /* Print lead-in */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sArrayType Ndims=\"",xmlnsprefix); + ndims = (unsigned)H5Tget_array_ndims(type); + h5tools_str_append(&buffer, "%u\">", ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Get array information */ + H5Tget_array_dims2(type, dims); + + /* list of dimensions */ + ctx.indent_level++; + for (i = 0; i < ndims; i++) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sArrayDimension DimSize=\"%u\"/>", xmlnsprefix, (int) dims[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + xml_print_datatype(super,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sArrayType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + /* Close array base type */ + H5Tclose(super); + break; + + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- unknown datatype -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_setstatus(EXIT_FAILURE); + break; + } + } /* end else */ + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_datatype + * + * Purpose: Dump description of a datatype in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_datatype(hid_t type) +{ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + dump_indent += COL; + + if(H5Tcommitted(type) > 0) { + H5O_info_t oinfo; + obj_t *found_obj; /* Found object */ + + /* Datatype is a shared or named datatype */ + H5Oget_info(type, &oinfo); + found_obj = search_obj(type_table, oinfo.addr); + + if(found_obj) { + /* Shared datatype, must be entered as an object */ + /* These 2 cases are the same now, but may change */ + char *dtxid = (char *)HDmalloc((size_t)100); + + xml_name_to_XID(found_obj->objname, dtxid, 100, 1); + if (!found_obj->recorded) { + /* anonymous stored datatype: + following the dumper's current + practice: + use it's object ref as its name + */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\"/>", + xmlnsprefix, dtxid); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* pointer to a named datatype already in XML */ + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\" H5Path=\"%s\" />", + xmlnsprefix, dtxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + } + HDfree(dtxid); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unknown committed type. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(type, 0); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_dataspace + * + * Purpose: Dump description of a dataspace in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_dataspace(hid_t space) +{ + hsize_t size[H5DUMP_MAX_RANK]; + hsize_t maxsize[H5DUMP_MAX_RANK]; + int i; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + int ndims = H5Sget_simple_extent_dims(space, size, maxsize); + H5S_class_t space_type = H5Sget_simple_extent_type(space); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataspace>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + switch (space_type) { + case H5S_SCALAR: + /* scalar dataspace (just a tag, no XML attrs. defined */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sScalarDataspace />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5S_SIMPLE: + /* simple dataspace */ + /* <hdf5:SimpleDataspace Ndims="nd"> */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSimpleDataspace Ndims=\"%d\">",xmlnsprefix, ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* print the <hdf5:Dimension> elements */ + ctx.indent_level++; + for (i = 0; i < ndims; i++) { + if (maxsize[i] == H5S_UNLIMITED) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"UNLIMITED\"/>", + xmlnsprefix,size[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else if (maxsize[i] == (hsize_t) 0) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"%" H5_PRINTF_LL_WIDTH "u\"/>", + xmlnsprefix,size[i], size[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"%" H5_PRINTF_LL_WIDTH "u\"/>", + xmlnsprefix, size[i], maxsize[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + } + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sSimpleDataspace>", xmlnsprefix ); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + +#ifdef TMP + /* Commented out: wait until the schema is updated first */ + case H5S_NULL: + /* null dataspace (just a tag, no XML attrs. defined */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNullDataspace />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; +#endif /* TMP */ + + case H5S_NULL: + case H5S_NO_CLASS: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- unknown dataspace -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataspace>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_data + * + * Purpose: Dump description of data in XML. + * Note that this calls the h5dump_xxx calls in + * the h5tools library. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_data(hid_t obj_id, int obj_data, struct subset_t H5_ATTR_UNUSED * sset, int H5_ATTR_UNUSED pindex) +{ + hid_t space = -1; + hid_t type = -1; + hid_t p_type = -1; + hsize_t size[64]; + hsize_t nelmts = 1; + int ndims; + int i; + int status = -1; + void *buf = NULL; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + /* Print all the values. */ + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + string_dataformat.cmpd_sep = " "; + string_dataformat.cmpd_pre = ""; + string_dataformat.cmpd_suf = ""; + string_dataformat.cmpd_end = ""; + string_dataformat.arr_linebreak = 0; + string_dataformat.arr_pre = ""; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + dump_indent += COL; + ctx.indent_level++; + + if (obj_data == DATASET_DATA) { + type = H5Dget_type(obj_id); + if (H5Tget_class(type) == H5T_REFERENCE) + status = xml_print_refs(obj_id, DATASET_DATA); + else if (H5Tget_class(type) == H5T_STRING) + status = xml_print_strs(obj_id, DATASET_DATA); + else { + h5tools_context_t datactx; + HDmemset(&datactx, 0, sizeof(datactx)); + datactx.need_prefix = TRUE; + datactx.indent_level = ctx.indent_level; + datactx.cur_column = ctx.cur_column; + status = h5tools_dump_dset(rawoutstream, outputformat, &datactx, obj_id, NULL); + } + } + else { + /* Attribute data */ + type = H5Aget_type(obj_id); + + if (H5Tget_class(type) == H5T_REFERENCE) { + /* references are done differently than + the standard output: + XML dumps a path to the object + referenced. + */ + status = xml_print_refs(obj_id, ATTRIBUTE_DATA); + H5Tclose(type); + } + else if (H5Tget_class(type) == H5T_STRING) { + status = xml_print_strs(obj_id, ATTRIBUTE_DATA); + } + else { /* all other data */ + /* VL data special information */ + unsigned int vl_data = 0; /* contains VL datatypes */ + + p_type = h5tools_get_native_type(type); + + /* Check if we have VL data in the dataset's datatype */ + if (h5tools_detect_vlen(p_type) == TRUE) + vl_data = TRUE; + + H5Tclose(type); + + space = H5Aget_space(obj_id); + + ndims = H5Sget_simple_extent_dims(space, size, NULL); + + for (i = 0; i < ndims; i++) + nelmts *= size[i]; + + buf = HDmalloc((size_t)(nelmts * MAX(H5Tget_size(type), H5Tget_size(p_type)))); + HDassert(buf); + + if (H5Aread(obj_id, p_type, buf) >= 0) { + h5tools_context_t datactx; + HDmemset(&datactx, 0, sizeof(datactx)); + datactx.need_prefix = TRUE; + datactx.indent_level = ctx.indent_level; + datactx.cur_column = ctx.cur_column; + status = h5tools_dump_mem(rawoutstream, outputformat, &datactx, obj_id, p_type, space, buf); + } + /* Reclaim any VL memory, if necessary */ + if (vl_data) + H5Dvlen_reclaim(p_type, space, H5P_DEFAULT, buf); + + HDfree(buf); + H5Tclose(p_type); + H5Sclose(space); + H5Tclose(type); + } + } + + if (status == FAIL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "Unable to print data."); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + status = 1; + } + ctx.indent_level--; + dump_indent -= COL; + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_attr + * + * Purpose: Dump a description of an HDF5 attribute in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +xml_dump_attr(hid_t attr, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *info, + void H5_ATTR_UNUSED * op_data) +{ + hid_t attr_id = -1; + hid_t type = -1; + hid_t space = -1; + H5S_class_t space_type; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + + char *t_aname = xml_escape_the_name(attr_name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAttribute Name=\"%s\">", xmlnsprefix, t_aname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_aname); + + if ((attr_id = H5Aopen(attr, attr_name, H5P_DEFAULT)) >= 0) { + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + space_type = H5Sget_simple_extent_type(space); + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + ctx.indent_level++; + dump_indent += COL; + + if (display_attr_data && space_type != H5S_NULL) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + + case H5T_TIME: + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time data not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<hdf5:Data>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of compound data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: Region references not supported -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_refs(attr_id, ATTRIBUTE_DATA); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of VL data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + else { + /* The case of an attribute never yet written ?? + * Or dataspace is H5S_NULL. */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr_id); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAttribute>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + return SUCCEED; + } + else { + /* ?? failed */ + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unable to open attribute. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAttribute>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + h5tools_setstatus(EXIT_FAILURE); + return FAIL; + } +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_named_datatype + * + * Purpose: Dump a description of an HDF5 NDT in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_named_datatype(hid_t type, const char *name) +{ + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + char *tmp; + char *dtxid; + char *parentxid; + char *t_tmp; + char *t_prefix; + char *t_name; + + tmp = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + HDstrcat(tmp, "/"); + HDstrcat(tmp, name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + dtxid = (char *)HDmalloc((size_t)100); + parentxid = (char *)HDmalloc((size_t)100); + t_tmp = xml_escape_the_name(tmp); + t_prefix = xml_escape_the_name(prefix); + t_name = xml_escape_the_name(name); + + xml_name_to_XID(tmp, dtxid, 100, 1); + xml_name_to_XID(prefix, parentxid, 100, 1); + if(HDstrncmp(name, "#", (size_t)1) == 0) { + /* Special: this is an 'anonymous' NDT, deleted but + still in use. + We follow the dumper's undocumented practice, and + use its object id as its name. + Exactly the same as normal, but a separate case + in the event we want to do something else in + the future. + */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataType Name=\"%s\" OBJ-XID=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, + name, dtxid, + parentxid, HDstrcmp(prefix,"") ? t_prefix : "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + H5O_info_t oinfo; /* Object info */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataType Name=\"%s\" OBJ-XID=\"%s\" " + "H5Path=\"%s\" Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, + t_name, dtxid, + t_tmp, parentxid, (HDstrcmp(prefix, "") ? t_prefix : "/")); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Check uniqueness of named datatype */ + H5Oget_info(type, &oinfo); + if(oinfo.rc > 1) { + obj_t *found_obj; /* Found object */ + + /* Group with more than one link to it... */ + found_obj = search_obj(type_table, oinfo.addr); + + if (found_obj == NULL) { + indentation(dump_indent); + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if(found_obj->displayed) { + /* We have already printed this named datatype, print it as a + * NamedDatatypePtr + */ + char pointerxid[100]; + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.indent_level++; + + xml_name_to_XID(found_obj->objname, pointerxid, (int)sizeof(pointerxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDatatypePtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", xmlnsprefix, pointerxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sNamedDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + goto done; + } + else + found_obj->displayed = TRUE; + } + } + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(type,1); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sNamedDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + +done: + + h5tools_str_close(&buffer); + + HDfree(dtxid); + HDfree(parentxid); + HDfree(t_tmp); + HDfree(t_prefix); + HDfree(t_name); + HDfree(tmp); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_group + * + * Purpose: Dump a description of an HDF5 Group (and its members) in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * Pedro Vicente, October 9, 2007 + * added parameters to H5A(L)iterate to allow for other iteration orders + * + *------------------------------------------------------------------------- + */ +void +xml_dump_group(hid_t gid, const char *name) +{ + H5O_info_t oinfo; + hid_t gcpl_id; + hid_t dset, type; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + int isRoot = 0; + char type_name[1024]; + char *t_objname = NULL; + char *par_name = NULL; + char *cp = NULL; + char *tmp = NULL; + char *par = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if(HDstrcmp(name, "/") == 0) { + isRoot = 1; + tmp = HDstrdup("/"); + } + else { + tmp = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + par = HDstrdup(tmp); + cp = HDstrrchr(par, '/'); + if(cp) { + if((cp == par) && HDstrlen(par) > 1) + *(cp + 1) = '\0'; + else + *cp = '\0'; + } + } + + H5Oget_info(gid, &oinfo); + + if(oinfo.rc > 1) { + obj_t *found_obj; /* Found object */ + + /* Group with more than one link to it... */ + found_obj = search_obj(group_table, oinfo.addr); + + if (found_obj == NULL) { + indentation(dump_indent); + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + } + else { + char *t_name = xml_escape_the_name(name); + char *grpxid = (char *)HDmalloc((size_t)100); + char *parentxid = (char *)HDmalloc((size_t)100); + + if(found_obj->displayed) { + char *ptrstr = (char *)HDmalloc((size_t)100); + + /* already seen: enter a groupptr */ + if(isRoot) { + /* probably can't happen! */ + xml_name_to_XID("/", grpxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", + xmlnsprefix, grpxid, "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + t_objname = xml_escape_the_name(found_obj->objname); + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s-%d\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix,t_name, grpxid, get_next_xid(), + t_objname, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + HDfree(par_name); + + ctx.indent_level++; + + t_objname = xml_escape_the_name(found_obj->objname);/* point to the NDT by name */ + par_name = xml_escape_the_name(par); + xml_name_to_XID(found_obj->objname, ptrstr, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroupPtr OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + ptrstr, t_objname, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + HDfree(t_objname); + HDfree(par_name); + } + HDfree(ptrstr); + } + else { + + /* first time this group has been seen -- describe it */ + if(isRoot) { + xml_name_to_XID("/", grpxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", + xmlnsprefix, grpxid, "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_tmp = xml_escape_the_name(tmp); + + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" >", + xmlnsprefix,t_name, grpxid, t_tmp, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_tmp); + HDfree(par_name); + } + found_obj->displayed = TRUE; + + /* 1. do all the attributes of the group */ + + ctx.indent_level++; + dump_indent += COL; + + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + if(isRoot && unamedtype) { + unsigned u; + + /* Very special case: dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) { + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the links */ + + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, xml_dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, xml_dump_all_cb, NULL); + + dump_indent -= COL; + ctx.indent_level--; + } + HDfree(t_name); + HDfree(grpxid); + HDfree(parentxid); + } + } + else { + /* only link -- must be first time! */ + char *t_name = xml_escape_the_name(name); + char *grpxid = (char *)HDmalloc((size_t)100); + char *parentxid = (char *)HDmalloc((size_t)100); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + + if(isRoot) { + xml_name_to_XID("/", grpxid, 100, 1); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", xmlnsprefix, grpxid, "/"); + } + else { + char *t_tmp = xml_escape_the_name(tmp); + + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" >", + xmlnsprefix, t_name, grpxid, t_tmp, parentxid, par_name); + HDfree(t_tmp); + HDfree(par_name); + } + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(grpxid); + HDfree(parentxid); + + /* 1. do all the attributes of the group */ + + ctx.indent_level++; + dump_indent += COL; + + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + if(isRoot && unamedtype) { + unsigned u; + + /* Very special case: dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) { + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the links */ + + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, xml_dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, xml_dump_all_cb, NULL); + + dump_indent -= COL; + ctx.indent_level--; + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(isRoot) + h5tools_str_append(&buffer, "</%sRootGroup>", xmlnsprefix); + else + h5tools_str_append(&buffer, "</%sGroup>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + if(par) + HDfree(par); + if(tmp) + HDfree(tmp); +} + +/*------------------------------------------------------------------------- + * Function: xml_print_refs + * + * Purpose: Print a path to the objects referenced by HDF5 Referneces. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_refs(hid_t did, int source) +{ + herr_t e; + hid_t type = -1; + hid_t space = -1; + hssize_t ssiz = -1; + hsize_t i; + size_t tsiz; + hobj_ref_t *refbuf = NULL; + char *buf = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if (source == DATASET_DATA) { + type = H5Dget_type(did); + } + else if (source == ATTRIBUTE_DATA) { + type = H5Aget_type(did); + } + else { + /* return an error */ + return FAIL; + } + if (H5Tget_class(type) != H5T_REFERENCE) { + /* return an error */ + goto error; + } + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + /* region ref not supported yet... */ + /* return an error */ + goto error; + } + if (source == DATASET_DATA) { + space = H5Dget_space(did); + if ((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if ((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = (char *) HDcalloc((size_t)ssiz, tsiz); + if (buf == NULL) + goto error; + e = H5Dread(did, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + /* need to check result here */ + if (e < 0) + goto error; + } + else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + if ((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if ((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = (char *) HDcalloc((size_t)ssiz, tsiz); + if (buf == NULL) + goto error; + e = H5Aread(did, H5T_STD_REF_OBJ, buf); + /* need to check the result here */ + if (e < 0) + goto error; + } + + refbuf = (hobj_ref_t *) buf; + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + for (i = 0; i < (hsize_t)ssiz; i++) { + const char *path = lookup_ref_path(*refbuf); + ctx.indent_level++; + + if (!path) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_path = xml_escape_the_string(path, -1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_path); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_path); + } + ctx.indent_level--; + + refbuf++; + } + + h5tools_str_close(&buffer); + + HDfree(buf); + H5Tclose(type); + H5Sclose(space); + return SUCCEED; + +error: + if(buf) + HDfree(buf); + + H5E_BEGIN_TRY { + H5Tclose(type); + H5Sclose(space); + } H5E_END_TRY; + return FAIL; +} + +/*------------------------------------------------------------------------- + * Function: xml_print_strs + * + * Purpose: Print strings. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_strs(hid_t did, int source) +{ + herr_t e; + hid_t type = -1; + hid_t space = -1; + hssize_t ssiz = -1; + htri_t is_vlstr = FALSE; + size_t tsiz = 0; + hsize_t i; + size_t str_size = 0; + char *bp = NULL; + char *onestring = NULL; + void *buf = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if (source == DATASET_DATA) + type = H5Dget_type(did); + else if (source == ATTRIBUTE_DATA) + type = H5Aget_type(did); + else + /* return an error */ + return FAIL; + if (H5Tget_class(type) != H5T_STRING) + /* return an error */ + goto error; + /* Check if we have VL data in the dataset's datatype */ + is_vlstr = H5Tis_variable_str(type); + + if (source == DATASET_DATA) { + space = H5Dget_space(did); + if((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = HDmalloc((size_t)ssiz * tsiz); + if (buf == NULL) + goto error; + + e = H5Dread(did, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + if (e < 0) + goto error; + } + else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + if((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = HDmalloc((size_t)ssiz * tsiz); + if (buf == NULL) + goto error; + + e = H5Aread(did, type, buf); + if (e < 0) + goto error; + } + + bp = (char*) buf; + if (!is_vlstr) + onestring = (char *) HDcalloc(tsiz, sizeof(char)); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + for (i = 0; i < (hsize_t)ssiz; i++) { + if (is_vlstr) { + onestring = *(char **) bp; + if (onestring) + str_size = HDstrlen(onestring); + } + else { + HDstrncpy(onestring, bp, tsiz); + str_size = tsiz; + } + + if (!onestring) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_onestring = xml_escape_the_string(onestring, (int)str_size); + if (t_onestring) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_onestring); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_onestring); + } + } + bp += tsiz; + } + + h5tools_str_close(&buffer); + + /* Reclaim any VL memory, if necessary */ + if (!is_vlstr) + if (onestring) + HDfree(onestring); + if (buf) { + if (is_vlstr) + H5Dvlen_reclaim(type, space, H5P_DEFAULT, buf); + HDfree(buf); + } + H5Tclose(type); + H5Sclose(space); + return SUCCEED; + +error: + if(buf) + HDfree(buf); + + H5E_BEGIN_TRY { + H5Tclose(type); + H5Sclose(space); + } H5E_END_TRY; + return FAIL; +} + +/*------------------------------------------------------------------------- + * Function: check_filters + * + * Purpose: private function to check for the filters and + * put tags in the XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +check_filters(hid_t dcpl) +{ + int nfilt; + int i; + H5Z_filter_t filter; + char namebuf[120]; + size_t cd_nelmts = 20; + unsigned int cd_values[20]; + unsigned int flags; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + nfilt = H5Pget_nfilters(dcpl); + if (nfilt <= 0) + return; + for (i = 0; i < nfilt; i++) { + filter = H5Pget_filter2(dcpl, (unsigned) i, &flags, (size_t *) &cd_nelmts, cd_values, (size_t)120, namebuf, NULL); + if (filter == H5Z_FILTER_DEFLATE) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDeflate Level=\"", xmlnsprefix); + if (cd_nelmts < 1) { + /* not sure what this means? */ + h5tools_str_append(&buffer, "6"); + } + else { + h5tools_str_append(&buffer, "%d", cd_values[0]); + } + h5tools_str_append(&buffer, "\"/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_FLETCHER32) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFletcher32 />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_SHUFFLE) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sShuffle />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_SZIP) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSZIP ", xmlnsprefix); + if (cd_nelmts < 2) { + /* no pixels ? */ + h5tools_str_append(&buffer, "Pixels_per_block=\"-1\" "); + } + else { + h5tools_str_append(&buffer, "Pixels_per_block=\"%d\" ", cd_values[1]); + } + /* analyse the options mask */ + if (cd_values[0] & H5_SZIP_CHIP_OPTION_MASK) { + h5tools_str_append(&buffer, "Mode =\"Hardware\" "); + } + else if (cd_values[0] & H5_SZIP_ALLOW_K13_OPTION_MASK) { + h5tools_str_append(&buffer, "Mode =\"K13\" "); + } + h5tools_str_append(&buffer, "Coding=\""); + if (cd_values[0] & H5_SZIP_EC_OPTION_MASK) { + h5tools_str_append(&buffer, "Entropy"); + } + else if (cd_values[0] & H5_SZIP_NN_OPTION_MASK) { + h5tools_str_append(&buffer, "NN"); + } + h5tools_str_append(&buffer, "\" "); + + h5tools_str_append(&buffer, "ByteOrder=\""); + if (cd_values[0] & H5_SZIP_LSB_OPTION_MASK) { + h5tools_str_append(&buffer, "LSB"); + } + else if (cd_values[0] & H5_SZIP_MSB_OPTION_MASK) { + h5tools_str_append(&buffer, "MSB"); + } + h5tools_str_append(&buffer, "\" "); + + if (cd_values[0] & H5_SZIP_RAW_OPTION_MASK) { + h5tools_str_append(&buffer, "Header=\"Raw\""); + } + h5tools_str_append(&buffer, "/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else { + /* unknown option */ + } + } + + h5tools_str_close(&buffer); +} + +static void +xml_dump_fill_value(hid_t dcpl, hid_t type) +{ + size_t sz; + size_t i; + hsize_t space; + void *buf; + char *name; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + space = H5Tget_size(type); + buf = HDmalloc((size_t) space); + + H5Pget_fill_value(dcpl, type, buf); + + if (H5Tget_class(type) == H5T_REFERENCE) { + const char * path = lookup_ref_path(*(hobj_ref_t *) buf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!path) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_path = xml_escape_the_string(path, -1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_path); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_path); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else if (H5Tget_class(type) == H5T_STRING) { + /* ????? */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- String fill values not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* all other data */ + switch (H5Tget_class(type)) { + case H5T_INTEGER: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%d\"", *(int *) buf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_FLOAT: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%f\"", (double)*(float *)buf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_BITFIELD: + case H5T_OPAQUE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + sz = H5Tget_size(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\""); + for (i = 0; i < sz; i++) { + h5tools_str_append(&buffer, "%x ", *(unsigned int *) buf); + buf = (char *) buf + sizeof(unsigned int); + } + h5tools_str_append(&buffer, "\""); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_ENUM: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + name = H5Tget_member_name(type, *(unsigned *) buf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if(name) + H5free_memory(name); + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_ARRAY: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Array fill values not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_TIME: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Compound fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- VL fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + case H5T_STRING: + case H5T_REFERENCE: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown fill datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + HDfree(buf); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_dataset + * + * Purpose: Dump a description of an HDF5 dataset in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * Pedro Vicente, October 9, 2007 + * added parameters to H5Aiterate2 to allow for other iteration orders + * + *------------------------------------------------------------------------- + */ +void +xml_dump_dataset(hid_t did, const char *name, struct subset_t H5_ATTR_UNUSED * sset) +{ + hid_t type; + hid_t space; + hid_t dcpl; + H5D_fill_value_t fvstatus; + int maxdims; + hsize_t *chsize; + int ndims; + int i; + H5D_alloc_time_t at; + H5D_fill_time_t ft; + hsize_t tempi; + char *tmp; + char *t_name; + char *t_tmp; + char *t_prefix; + unsigned attr_crt_order_flags; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + char *rstr = (char*) HDmalloc((size_t)100); + char *pstr = (char*) HDmalloc((size_t)100); + + tmp = (char*) HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + HDstrcat(tmp, "/"); + HDstrcat(tmp, name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + t_name = xml_escape_the_name(name); + t_tmp = xml_escape_the_name(tmp); + t_prefix = xml_escape_the_name(prefix); + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + xml_name_to_XID(tmp, rstr, 100, 1); + xml_name_to_XID(prefix, pstr, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataset Name=\"%s\" OBJ-XID=\"%s\" H5Path= \"%s\" Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, t_name, rstr, t_tmp, pstr, + strcmp(prefix, "") ? t_prefix : "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(t_tmp); + HDfree(t_prefix); + HDfree(rstr); + HDfree(pstr); + HDfree(tmp); + + dcpl = H5Dget_create_plist(did); + type = H5Dget_type(did); + space = H5Dget_space(did); + + /* query the creation properties for attributes */ + H5Pget_attr_creation_order(dcpl, &attr_crt_order_flags); + + /* Print information about storage layout */ + if (H5D_CHUNKED == H5Pget_layout(dcpl)) { + maxdims = H5Sget_simple_extent_ndims(space); + HDassert(maxdims >= 0); + chsize = (hsize_t *)HDmalloc((size_t)maxdims * sizeof(hsize_t)); + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sChunkedLayout ", xmlnsprefix); + ndims = H5Pget_chunk(dcpl, maxdims, chsize); + h5tools_str_append(&buffer, "Ndims=\"%d\">", ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + for (i = 0; i < ndims; i++) { + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sChunkDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" />", xmlnsprefix, chsize[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRequiredFilter>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + check_filters(dcpl); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sRequiredFilter>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sChunkedLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + HDfree(chsize); + } + else if (H5D_CONTIGUOUS == H5Pget_layout(dcpl)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sContiguousLayout/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (H5D_COMPACT == H5Pget_layout(dcpl)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sCompactLayout/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + /* and check for external.... ?? */ + + /* fill value */ + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFillValueInfo ", xmlnsprefix); + H5Pget_fill_time(dcpl, &ft); + h5tools_str_append(&buffer, "FillTime=\""); + switch (ft) { + case H5D_FILL_TIME_ALLOC: + h5tools_str_append(&buffer, "FillOnAlloc"); + break; + case H5D_FILL_TIME_NEVER: + h5tools_str_append(&buffer, "FillNever"); + break; + case H5D_FILL_TIME_IFSET: + h5tools_str_append(&buffer, "FillIfSet"); + break; + case H5D_FILL_TIME_ERROR: + HDassert(0); + /* fall through */ + default: + h5tools_str_append(&buffer, "?"); + break; + } /* end switch */ + h5tools_str_append(&buffer, "\" "); + H5Pget_alloc_time(dcpl, &at); + h5tools_str_append(&buffer, "AllocationTime=\""); + switch (at) { + case H5D_ALLOC_TIME_EARLY: + h5tools_str_append(&buffer, "Early"); + break; + case H5D_ALLOC_TIME_INCR: + h5tools_str_append(&buffer, "Incremental"); + break; + case H5D_ALLOC_TIME_LATE: + h5tools_str_append(&buffer, "Late"); + break; + case H5D_ALLOC_TIME_DEFAULT: + case H5D_ALLOC_TIME_ERROR: + HDassert(0); + /* fall through */ + default: + h5tools_str_append(&buffer, "?"); + break; + } /* end switch */ + h5tools_str_append(&buffer, "\""); + h5tools_str_append(&buffer, ">"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFillValue>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5Pfill_value_defined(dcpl, &fvstatus); + if (fvstatus == H5D_FILL_VALUE_UNDEFINED || (fvstatus == H5D_FILL_VALUE_DEFAULT && ft == H5D_FILL_TIME_IFSET)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoFill/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else { + xml_dump_fill_value(dcpl, type); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sFillValue>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sFillValueInfo>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + ctx.indent_level++; + dump_indent += COL; + + if ((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if (H5Aiterate2(did, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if (H5Aiterate2(did, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + ctx.indent_level--; + dump_indent -= COL; + tempi = H5Dget_storage_size(did); + + if (display_data && (tempi > 0)) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_TIME: + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time data not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + break; + + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of compound data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: Region references not supported -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_refs(did, DATASET_DATA); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.indent_level--; + dump_indent -= COL; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of VL data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + else { + /* no data written */ + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + + H5Tclose(type); + H5Sclose(space); + H5Pclose(dcpl); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataset>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_print_enum + * + * Purpose: Print the values of an HDF5 ENUM in XML. + * Very similar to regular DDL output. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_enum(hid_t type) +{ + char **name = NULL; /*member names */ + unsigned char *value = NULL; /*value array */ + unsigned nmembs; /*number of members */ + hid_t super; /*enum base integer type */ + hid_t native = -1; /*native integer datatype */ + size_t dst_size; /*destination value type size */ + unsigned i; /*miscellaneous counters */ + size_t j; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + nmembs = (unsigned)H5Tget_nmembers(type); + super = H5Tget_super(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_datatype(super,0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* + * Determine what datatype to use for the native values. To simplify + * things we entertain three possibilities: + * 1. long long -- the largest native signed integer + * 2. unsigned long long -- the largest native unsigned integer + * 3. raw format + */ + if (H5Tget_size(type) <= sizeof(long long)) { + dst_size = sizeof(long long); + + if (H5T_SGN_NONE == H5Tget_sign(type)) { + native = H5T_NATIVE_ULLONG; + } + else { + native = H5T_NATIVE_LLONG; + } + } + else { + dst_size = H5Tget_size(type); + } + + /* Get the names and raw values of all members */ + name = (char **)HDcalloc((size_t)nmembs, sizeof(char *)); + value = (unsigned char *)HDcalloc((size_t)nmembs, MAX(H5Tget_size(type), dst_size)); + + for (i = 0; i < nmembs; i++) { + name[i] = H5Tget_member_name(type, i); + H5Tget_member_value(type, i, value + i * H5Tget_size(type)); + } + + /* Convert values to native datatype */ + if (native > 0) + H5Tconvert(super, native, (size_t)nmembs, value, NULL, H5P_DEFAULT); + + /* Sort members by increasing value */ + /*not implemented yet */ + + /* Print members */ + ctx.indent_level++; + dump_indent += COL; + for (i = 0; i < nmembs; i++) { + char *t_name = xml_escape_the_name(name[i]); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumElement>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s", t_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_name); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumElement>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumValue>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if (native < 0) { + h5tools_str_append(&buffer, "0x"); + + for (j = 0; j < dst_size; j++) + h5tools_str_append(&buffer, "%02x", value[i * dst_size + j]); + } + else if (H5T_SGN_NONE == H5Tget_sign(native)) { + h5tools_str_append(&buffer,"%" H5_PRINTF_LL_WIDTH "u", *((unsigned long long *) + ((void *) (value + i * dst_size)))); + } + else { + h5tools_str_append(&buffer,"%" H5_PRINTF_LL_WIDTH "d", + *((long long *) ((void *) (value + i * dst_size)))); + } + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumValue>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); + + /* Release resources */ + for (i = 0; i < nmembs; i++) + H5free_memory(name[i]); + + HDfree(name); + HDfree(value); + H5Tclose(super); +} + diff --git a/tools/src/h5dump/h5dump_xml.h b/tools/src/h5dump/h5dump_xml.h new file mode 100644 index 0000000..c1d6c62 --- /dev/null +++ b/tools/src/h5dump/h5dump_xml.h @@ -0,0 +1,39 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_XML_H__ +#define H5DUMP_XML_H__ + +extern const char *xmlnsprefix; + +#ifdef __cplusplus +extern "C" { +#endif + +/* The dump functions of the dump_function_table */ +/* XML format: same interface, alternative output */ + +void xml_dump_group(hid_t, const char *); +void xml_dump_named_datatype(hid_t, const char *); +void xml_dump_dataset(hid_t, const char *, struct subset_t *); +void xml_dump_dataspace(hid_t space); +void xml_dump_datatype(hid_t type); +herr_t xml_dump_attr(hid_t, const char *, const H5A_info_t *, void *); +void xml_dump_data(hid_t, int, struct subset_t *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_XML_H__ */ |