mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
304f19d730
Tested on jam, heiwa, and koala.
4406 lines
153 KiB
C
4406 lines
153 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* 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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* Programmer: Robb Matzke <matzke@llnl.gov>
|
|
* Thursday, July 23, 1998
|
|
*
|
|
* Purpose: A library for displaying the values of a dataset in a human
|
|
* readable format.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "h5tools.h"
|
|
#include "h5tools_ref.h"
|
|
#include "h5tools_utils.h"
|
|
#include "H5private.h"
|
|
|
|
#define SANITY_CHECK
|
|
|
|
#define ALIGN(A,Z) ((((A) + (Z) - 1) / (Z)) * (Z))
|
|
|
|
/* global variables */
|
|
hid_t H5tools_ERR_CLS_g = -1;
|
|
hid_t H5E_tools_g = -1;
|
|
hid_t H5E_tools_min_id_g = -1;
|
|
int compound_data;
|
|
FILE *rawdatastream; /* should initialize to stdout but gcc moans about it */
|
|
int bin_output; /* binary output */
|
|
int bin_form; /* binary form */
|
|
int region_output; /* region output */
|
|
int packed_bits_num; /* number of packed bits to display */
|
|
int packed_data_offset; /* offset of packed bits to display */
|
|
unsigned long long packed_data_mask; /* mask in which packed bits to display */
|
|
|
|
static h5tool_format_t h5tools_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 */
|
|
",\n", /*cmpd_sep */
|
|
"{\n", /*cmpd_pre */
|
|
"}", /*cmpd_suf */
|
|
"\n", /*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 */
|
|
1, /*array indices */
|
|
1 /*escape non printable characters */
|
|
};
|
|
|
|
static const h5tools_dump_header_t h5tools_standardformat = {
|
|
"standardformat", /*name */
|
|
"HDF5", /*fileebgin */
|
|
"", /*fileend */
|
|
SUPER_BLOCK, /*bootblockbegin */
|
|
"", /*bootblockend */
|
|
H5_TOOLS_GROUP, /*groupbegin */
|
|
"", /*groupend */
|
|
H5_TOOLS_DATASET, /*datasetbegin */
|
|
"", /*datasetend */
|
|
ATTRIBUTE, /*attributebegin */
|
|
"", /*attributeend */
|
|
H5_TOOLS_DATATYPE, /*datatypebegin */
|
|
"", /*datatypeend */
|
|
DATASPACE, /*dataspacebegin */
|
|
"", /*dataspaceend */
|
|
DATA, /*databegin */
|
|
"", /*dataend */
|
|
SOFTLINK, /*softlinkbegin */
|
|
"", /*softlinkend */
|
|
EXTLINK, /*extlinkbegin */
|
|
"", /*extlinkend */
|
|
UDLINK, /*udlinkbegin */
|
|
"", /*udlinkend */
|
|
SUBSET, /*subsettingbegin */
|
|
"", /*subsettingend */
|
|
START, /*startbegin */
|
|
"", /*startend */
|
|
STRIDE, /*stridebegin */
|
|
"", /*strideend */
|
|
COUNT, /*countbegin */
|
|
"", /*countend */
|
|
BLOCK, /*blockbegin */
|
|
"", /*blockend */
|
|
|
|
"{", /*fileblockbegin */
|
|
"}", /*fileblockend */
|
|
"{", /*bootblockblockbegin */
|
|
"}", /*bootblockblockend */
|
|
"{", /*groupblockbegin */
|
|
"}", /*groupblockend */
|
|
"{", /*datasetblockbegin */
|
|
"}", /*datasetblockend */
|
|
"{", /*attributeblockbegin */
|
|
"}", /*attributeblockend */
|
|
"", /*datatypeblockbegin */
|
|
"", /*datatypeblockend */
|
|
"", /*dataspaceblockbegin */
|
|
"", /*dataspaceblockend */
|
|
"{", /*datablockbegin */
|
|
"}", /*datablockend */
|
|
"{", /*softlinkblockbegin */
|
|
"}", /*softlinkblockend */
|
|
"{", /*extlinkblockbegin */
|
|
"}", /*extlinkblockend */
|
|
"{", /*udlinkblockbegin */
|
|
"}", /*udlinkblockend */
|
|
"{", /*strblockbegin */
|
|
"}", /*strblockend */
|
|
"{", /*enumblockbegin */
|
|
"}", /*enumblockend */
|
|
"{", /*structblockbegin */
|
|
"}", /*structblockend */
|
|
"{", /*vlenblockbegin */
|
|
"}", /*vlenblockend */
|
|
"{", /*subsettingblockbegin */
|
|
"}", /*subsettingblockend */
|
|
"(", /*startblockbegin */
|
|
");", /*startblockend */
|
|
"(", /*strideblockbegin */
|
|
");", /*strideblockend */
|
|
"(", /*countblockbegin */
|
|
");", /*countblockend */
|
|
"(", /*blockblockbegin */
|
|
");", /*blockblockend */
|
|
|
|
"", /*dataspacedescriptionbegin */
|
|
"", /*dataspacedescriptionend */
|
|
"(", /*dataspacedimbegin */
|
|
")", /*dataspacedimend */
|
|
};
|
|
|
|
static const h5tools_dump_header_t * h5tools_dump_header_format;
|
|
|
|
/* local prototypes */
|
|
static int do_bin_output(FILE *stream, hid_t container, hsize_t nelmts, hid_t tid, void *_mem);
|
|
static int render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem);
|
|
static int render_bin_output_region_data_blocks(hid_t region_id, FILE *stream,
|
|
hid_t container, int ndims, hid_t type_id, hssize_t nblocks, hsize_t *ptdata);
|
|
static hbool_t render_bin_output_region_blocks(hid_t region_space, hid_t region_id,
|
|
FILE *stream, hid_t container);
|
|
static hbool_t render_bin_output_region_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, hid_t container);
|
|
static hbool_t h5tools_is_zero(const void *_mem, size_t size);
|
|
|
|
hbool_t h5tools_render_element(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx/*in,out*/,
|
|
h5tools_str_t *buffer/*string into which to render */,
|
|
hsize_t *curr_pos/*total data element position*/,
|
|
size_t ncols, hsize_t local_elmt_counter/*element counter*/,
|
|
hsize_t elmt_counter);
|
|
|
|
hbool_t h5tools_render_region_element(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx/*in,out*/,
|
|
h5tools_str_t *buffer/*string into which to render */,
|
|
hsize_t *curr_pos/*total data element position*/,
|
|
size_t ncols, hsize_t *ptdata,
|
|
hsize_t local_elmt_counter/*element counter*/,
|
|
hsize_t elmt_counter);
|
|
|
|
static int h5tools_print_region_data_blocks(hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info, h5tools_context_t *cur_ctx,
|
|
h5tools_str_t *buffer/*string into which to render */, size_t ncols,
|
|
int ndims, hid_t type_id, hssize_t nblocks, hsize_t *ptdata);
|
|
|
|
hbool_t h5tools_dump_region_data_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx/*in,out*/,
|
|
h5tools_str_t *buffer/*string into which to render */,
|
|
hsize_t *curr_pos/*total data element position*/,
|
|
size_t ncols, hsize_t region_elmt_counter/*element counter*/,
|
|
hsize_t elmt_counter);
|
|
|
|
int h5tools_print_region_data_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info, h5tools_context_t *cur_ctx,
|
|
h5tools_str_t *buffer, size_t ncols,
|
|
int ndims, hid_t type_id, hssize_t npoints, hsize_t *ptdata);
|
|
|
|
hbool_t h5tools_dump_region_data_blocks(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx/*in,out*/,
|
|
h5tools_str_t *buffer/*string into which to render */,
|
|
hsize_t *curr_pos/*total data element position*/,
|
|
size_t ncols, hsize_t region_elmt_counter/*element counter*/,
|
|
hsize_t elmt_counter);
|
|
|
|
/* module-scoped variables */
|
|
static int h5tools_init_g; /* if h5tools lib has been initialized */
|
|
#ifdef H5_HAVE_PARALLEL
|
|
static int h5tools_mpi_init_g; /* if MPI_Init() has been called */
|
|
#endif /* H5_HAVE_PARALLEL */
|
|
|
|
/* Names of VFDs */
|
|
static const char *drivernames[]={
|
|
"sec2",
|
|
"family",
|
|
"split",
|
|
"multi",
|
|
#ifdef H5_HAVE_STREAM
|
|
"stream",
|
|
#endif /* H5_HAVE_STREAM */
|
|
#ifdef H5_HAVE_PARALLEL
|
|
"mpio",
|
|
"mpiposix"
|
|
#endif /* H5_HAVE_PARALLEL */
|
|
};
|
|
|
|
/* This enum should match the entries in the above drivers_list since they
|
|
* are indexes into the drivers_list array. */
|
|
enum {
|
|
SEC2_IDX = 0
|
|
,FAMILY_IDX
|
|
,SPLIT_IDX
|
|
,MULTI_IDX
|
|
#ifdef H5_HAVE_STREAM
|
|
,STREAM_IDX
|
|
#endif /* H5_HAVE_STREAM */
|
|
#ifdef H5_HAVE_PARALLEL
|
|
,MPIO_IDX
|
|
,MPIPOSIX_IDX
|
|
#endif /* H5_HAVE_PARALLEL */
|
|
} driver_idx;
|
|
#define NUM_DRIVERS (sizeof(drivernames) / sizeof(drivernames[0]))
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Initialize the H5 Tools library
|
|
* Description:
|
|
* This should be called before any other h5tools function is called.
|
|
* Effect of any h5tools function called before this has been called is
|
|
* undetermined.
|
|
* Return:
|
|
* None
|
|
* Programmer:
|
|
* Albert Cheng, 2000-10-31
|
|
* Modifications:
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
h5tools_init(void)
|
|
{
|
|
char lib_str[256];
|
|
|
|
if (!h5tools_init_g) {
|
|
/* register the error class */
|
|
HDsnprintf(lib_str, sizeof(lib_str), "%d.%d.%d",H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE);
|
|
|
|
H5TOOLS_INIT_ERROR()
|
|
|
|
if (!rawdatastream)
|
|
rawdatastream = stdout;
|
|
|
|
h5tools_dump_header_format = &h5tools_standardformat;
|
|
|
|
h5tools_init_g++;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Close the H5 Tools library
|
|
* Description:
|
|
* Close or release resources such as files opened by the library. This
|
|
* should be called after all other h5tools functions have been called.
|
|
* Effect of any h5tools function called after this has been called is
|
|
* undetermined.
|
|
* Return:
|
|
* None
|
|
* Programmer:
|
|
* Albert Cheng, 2000-10-31
|
|
* Modifications:
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
h5tools_close(void)
|
|
{
|
|
if (h5tools_init_g) {
|
|
if (rawdatastream && rawdatastream != stdout) {
|
|
if (fclose(rawdatastream))
|
|
perror("closing rawdatastream");
|
|
else
|
|
rawdatastream = NULL;
|
|
}
|
|
|
|
/* Clean up the reference path table, if it's been used */
|
|
term_ref_path_table();
|
|
|
|
H5TOOLS_CLOSE_ERROR()
|
|
|
|
/* Shut down the library */
|
|
H5close();
|
|
|
|
h5tools_init_g = 0;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Private
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Get a FAPL for a driver
|
|
* Description:
|
|
* Get a FAPL for a given VFL driver name.
|
|
* Return:
|
|
* None
|
|
* Programmer:
|
|
* Quincey Koziol, 2004-02-04
|
|
* Modifications:
|
|
* Pedro Vicente Nunes, Thursday, July 27, 2006
|
|
* Added error return conditions for the H5Pset_fapl calls
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hid_t
|
|
h5tools_get_fapl(hid_t fapl, const char *driver, unsigned *drivernum)
|
|
{
|
|
hid_t new_fapl; /* Copy of file access property list passed in, or new property list */
|
|
|
|
/* Make a copy of the FAPL, for the file open call to use, eventually */
|
|
if (fapl == H5P_DEFAULT) {
|
|
if ((new_fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
|
|
goto error;
|
|
} /* end if */
|
|
else {
|
|
if ((new_fapl = H5Pcopy(fapl)) < 0)
|
|
goto error;
|
|
} /* end else */
|
|
|
|
/* Determine which driver the user wants to open the file with. Try
|
|
* that driver. If it can't open it, then fail. */
|
|
if (!strcmp(driver, drivernames[SEC2_IDX])) {
|
|
/* SEC2 driver */
|
|
if (H5Pset_fapl_sec2(new_fapl) < 0)
|
|
goto error;
|
|
|
|
if (drivernum)
|
|
*drivernum = SEC2_IDX;
|
|
}
|
|
else if (!strcmp(driver, drivernames[FAMILY_IDX])) {
|
|
/* FAMILY Driver */
|
|
|
|
/* Set member size to be 0 to indicate the current first member size
|
|
* is the member size.
|
|
*/
|
|
if (H5Pset_fapl_family(new_fapl, (hsize_t) 0, H5P_DEFAULT) < 0)
|
|
goto error;
|
|
|
|
if (drivernum)
|
|
*drivernum = FAMILY_IDX;
|
|
}
|
|
else if (!strcmp(driver, drivernames[SPLIT_IDX])) {
|
|
/* SPLIT Driver */
|
|
if (H5Pset_fapl_split(new_fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT) < 0)
|
|
goto error;
|
|
|
|
if (drivernum)
|
|
*drivernum = SPLIT_IDX;
|
|
}
|
|
else if (!strcmp(driver, drivernames[MULTI_IDX])) {
|
|
/* MULTI Driver */
|
|
if (H5Pset_fapl_multi(new_fapl, NULL, NULL, NULL, NULL, TRUE) < 0)
|
|
goto error;
|
|
|
|
if(drivernum)
|
|
*drivernum = MULTI_IDX;
|
|
#ifdef H5_HAVE_STREAM
|
|
}
|
|
else if(!strcmp(driver, drivernames[STREAM_IDX])) {
|
|
/* STREAM Driver */
|
|
if(H5Pset_fapl_stream(new_fapl, NULL) < 0)
|
|
goto error;
|
|
|
|
if(drivernum)
|
|
*drivernum = STREAM_IDX;
|
|
#endif /* H5_HAVE_STREAM */
|
|
#ifdef H5_HAVE_PARALLEL
|
|
}
|
|
else if(!strcmp(driver, drivernames[MPIO_IDX])) {
|
|
/* MPI-I/O Driver */
|
|
/* check if MPI has been initialized. */
|
|
if(!h5tools_mpi_init_g)
|
|
MPI_Initialized(&h5tools_mpi_init_g);
|
|
if(h5tools_mpi_init_g) {
|
|
if(H5Pset_fapl_mpio(new_fapl, MPI_COMM_WORLD, MPI_INFO_NULL) < 0)
|
|
goto error;
|
|
|
|
if(drivernum)
|
|
*drivernum = MPIO_IDX;
|
|
} /* end if */
|
|
}
|
|
else if (!strcmp(driver, drivernames[MPIPOSIX_IDX])) {
|
|
/* MPI-I/O Driver */
|
|
/* check if MPI has been initialized. */
|
|
if(!h5tools_mpi_init_g)
|
|
MPI_Initialized(&h5tools_mpi_init_g);
|
|
if(h5tools_mpi_init_g) {
|
|
if(H5Pset_fapl_mpiposix(new_fapl, MPI_COMM_WORLD, TRUE) < 0)
|
|
goto error;
|
|
|
|
if(drivernum)
|
|
*drivernum = MPIPOSIX_IDX;
|
|
} /* end if */
|
|
#endif /* H5_HAVE_PARALLEL */
|
|
}
|
|
else {
|
|
goto error;
|
|
}
|
|
|
|
return(new_fapl);
|
|
|
|
error:
|
|
if(new_fapl != H5P_DEFAULT)
|
|
H5Pclose(new_fapl);
|
|
return -1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Open a file with various VFL drivers.
|
|
* Description:
|
|
* Loop through the various types of VFL drivers trying to open FNAME.
|
|
* If the HDF5 library is version 1.2 or less, then we have only the SEC2
|
|
* driver to try out. If the HDF5 library is greater than version 1.2,
|
|
* then we have the FAMILY, SPLIT, and MULTI drivers to play with (and
|
|
* the STREAM driver if H5_HAVE_STREAM is defined, that is).
|
|
*
|
|
* If DRIVER is non-NULL, then it will try to open the file with that
|
|
* driver first. We assume that the user knows what they are doing so, if
|
|
* we fail, then we won't try other file drivers.
|
|
* Return:
|
|
* On success, returns a file id for the opened file. If DRIVERNAME is
|
|
* non-null then the first DRIVERNAME_SIZE-1 characters of the driver
|
|
* name are copied into the DRIVERNAME array and null terminated.
|
|
*
|
|
* Otherwise, the function returns FAIL. If DRIVERNAME is non-null then
|
|
* the first byte is set to the null terminator.
|
|
* Programmer:
|
|
* Lost in the mists of time.
|
|
* Modifications:
|
|
* Robb Matzke, 2000-06-23
|
|
* We only have to initialize driver[] on the first call, thereby
|
|
* preventing memory leaks from repeated calls to H5Pcreate().
|
|
*
|
|
* Robb Matzke, 2000-06-23
|
|
* Added DRIVERNAME_SIZE arg to prevent overflows when writing to
|
|
* DRIVERNAME.
|
|
*
|
|
* Robb Matzke, 2000-06-23
|
|
* Added test to prevent coredump when the file could not be opened by
|
|
* any driver.
|
|
*
|
|
* Robb Matzke, 2000-06-23
|
|
* Changed name from H5ToolsFopen() so it jives better with the names we
|
|
* already have at the top of this source file.
|
|
*
|
|
* Thomas Radke, 2000-09-12
|
|
* Added Stream VFD to the driver[] array.
|
|
*
|
|
* Bill Wendling, 2001-01-10
|
|
* Changed macro behavior so that if we have a version other than 1.2.x
|
|
* (i.e., > 1.2), then we do the drivers check.
|
|
*
|
|
* Bill Wendling, 2001-07-30
|
|
* Added DRIVER parameter so that the user can specify "try this driver"
|
|
* instead of the default behaviour. If it fails to open the file with
|
|
* that driver, this will fail completely (i.e., we won't try the other
|
|
* drivers). We're assuming the user knows what they're doing. How UNIX
|
|
* of us.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hid_t
|
|
h5tools_fopen(const char *fname, unsigned flags, hid_t fapl, const char *driver,
|
|
char *drivername, size_t drivername_size)
|
|
{
|
|
unsigned drivernum;
|
|
hid_t fid = FAIL;
|
|
hid_t my_fapl = H5P_DEFAULT;
|
|
|
|
if (driver && *driver) {
|
|
/* Get the correct FAPL for the given driver */
|
|
if ((my_fapl = h5tools_get_fapl(fapl, driver, &drivernum)) < 0)
|
|
goto done;
|
|
|
|
H5E_BEGIN_TRY {
|
|
fid = H5Fopen(fname, flags, my_fapl);
|
|
} H5E_END_TRY;
|
|
|
|
if (fid == FAIL)
|
|
goto done;
|
|
|
|
}
|
|
else {
|
|
/* Try to open the file using each of the drivers */
|
|
for (drivernum = 0; drivernum < NUM_DRIVERS; drivernum++) {
|
|
/* Get the correct FAPL for the given driver */
|
|
if((my_fapl = h5tools_get_fapl(fapl, drivernames[drivernum], NULL)) < 0)
|
|
goto done;
|
|
|
|
H5E_BEGIN_TRY {
|
|
fid = H5Fopen(fname, flags, my_fapl);
|
|
} H5E_END_TRY;
|
|
|
|
if (fid != FAIL)
|
|
break;
|
|
else {
|
|
/* Close the FAPL */
|
|
H5Pclose(my_fapl);
|
|
my_fapl = H5P_DEFAULT;
|
|
} /* end else */
|
|
}
|
|
}
|
|
|
|
/* Save the driver name */
|
|
if (drivername && drivername_size) {
|
|
if (fid != FAIL) {
|
|
strncpy(drivername, drivernames[drivernum], drivername_size);
|
|
drivername[drivername_size - 1] = '\0';
|
|
}
|
|
else {
|
|
/*no file opened*/
|
|
drivername[0] = '\0';
|
|
}
|
|
}
|
|
|
|
done:
|
|
if(my_fapl != H5P_DEFAULT)
|
|
H5Pclose(my_fapl);
|
|
|
|
return fid;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Count the number of columns in a string.
|
|
* Description:
|
|
* Count the number of columns in a string. This is the number of
|
|
* characters in the string not counting line-control characters.
|
|
* Return:
|
|
* On success, returns the width of the string. Otherwise this function
|
|
* returns 0.
|
|
* Programmer:
|
|
* Robb Matzke, Tuesday, April 27, 1999
|
|
* Modifications:
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static size_t
|
|
h5tools_ncols(const char *s)
|
|
{
|
|
register size_t i;
|
|
|
|
for (i = 0; *s; s++)
|
|
if (*s >= ' ')
|
|
i++;
|
|
|
|
return i;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_detect_vlen
|
|
*
|
|
* Purpose: Recursive check for any variable length data in given type.
|
|
*
|
|
* Return:
|
|
* TRUE : type conatains any variable length data
|
|
* FALSE : type doesn't contain any variable length data
|
|
* Negative value: error occur
|
|
*
|
|
* Programmer: Jonathan Kim March 18, 2011
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
h5tools_detect_vlen(hid_t tid)
|
|
{
|
|
htri_t ret;
|
|
|
|
/* recursive detect any vlen data values in type (compound, array ...) */
|
|
ret = H5Tdetect_class(tid, H5T_VLEN);
|
|
if((ret == TRUE) || (ret < 0))
|
|
goto done;
|
|
|
|
/* recursive detect any vlen string in type (compound, array ...) */
|
|
ret = h5tools_detect_vlen_str(tid);
|
|
if((ret == TRUE) || (ret < 0))
|
|
goto done;
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_detect_vlen_str
|
|
*
|
|
* Purpose: Recursive check for variable length string of a datatype.
|
|
*
|
|
* Return:
|
|
* TRUE : type conatains any variable length string
|
|
* FALSE : type doesn't contain any variable length string
|
|
* Negative value: error occur
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
h5tools_detect_vlen_str(hid_t tid)
|
|
{
|
|
H5T_class_t tclass = -1;
|
|
htri_t ret = FALSE;
|
|
|
|
ret = H5Tis_variable_str(tid);
|
|
if((ret == TRUE) || (ret < 0))
|
|
goto done;
|
|
|
|
tclass = H5Tget_class(tid);
|
|
if(tclass == H5T_ARRAY || tclass == H5T_VLEN) {
|
|
hid_t btid = H5Tget_super(tid);
|
|
|
|
if(btid < 0) {
|
|
ret = (htri_t)btid;
|
|
goto done;
|
|
}
|
|
ret = h5tools_detect_vlen_str(btid);
|
|
if((ret == TRUE) || (ret < 0)) {
|
|
H5Tclose(btid);
|
|
goto done;
|
|
}
|
|
}
|
|
else if(tclass == H5T_COMPOUND) {
|
|
int i = 0;
|
|
int n = H5Tget_nmembers(tid);
|
|
|
|
if(n < 0) {
|
|
n = ret;
|
|
goto done;
|
|
}
|
|
|
|
for(i = 0; i < n; i++) {
|
|
hid_t mtid = H5Tget_member_type(tid, i);
|
|
|
|
ret = h5tools_detect_vlen_str(mtid);
|
|
if((ret == TRUE) || (ret < 0)) {
|
|
H5Tclose(mtid);
|
|
goto done;
|
|
}
|
|
H5Tclose(mtid);
|
|
}
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Emit a simple prefix to STREAM.
|
|
* Description:
|
|
* If /ctx->need_prefix/ is set then terminate the current line (if
|
|
* applicable), calculate the prefix string, and display it at the start
|
|
* of a line.
|
|
* Return:
|
|
* None
|
|
* Programmer:
|
|
* Robb Matzke, Monday, April 26, 1999
|
|
* Modifications:
|
|
* Robb Matzke, 1999-09-29
|
|
* If a new prefix is printed then the current element number is set back
|
|
* to zero.
|
|
* pvn, 2004-07-08
|
|
* Added support for printing array indices:
|
|
* the indentation is printed before the prefix (printed one indentation
|
|
* level before)
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
h5tools_simple_prefix(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, hsize_t elmtno, int secnum)
|
|
{
|
|
h5tools_str_t prefix;
|
|
h5tools_str_t str; /*temporary for indentation */
|
|
size_t templength = 0;
|
|
int i, indentlevel = 0;
|
|
|
|
if (!ctx->need_prefix)
|
|
return;
|
|
|
|
memset(&prefix, 0, sizeof(h5tools_str_t));
|
|
memset(&str, 0, sizeof(h5tools_str_t));
|
|
|
|
/* Terminate previous line, if any */
|
|
if (ctx->cur_column) {
|
|
fputs(OPT(info->line_suf, ""), stream);
|
|
putc('\n', stream);
|
|
fputs(OPT(info->line_sep, ""), stream);
|
|
}
|
|
|
|
/* Calculate new prefix */
|
|
h5tools_str_prefix(&prefix, info, elmtno, ctx->ndims, ctx);
|
|
|
|
/* Write new prefix to output */
|
|
if (ctx->indent_level >= 0) {
|
|
indentlevel = ctx->indent_level;
|
|
}
|
|
else {
|
|
/*
|
|
* This is because sometimes we don't print out all the header
|
|
* info for the data (like the tattr-2.ddl example). If that happens
|
|
* the ctx->indent_level is negative so we need to skip the above and
|
|
* just print out the default indent levels.
|
|
*/
|
|
indentlevel = ctx->default_indent_level;
|
|
}
|
|
|
|
/* when printing array indices, print the indentation before the prefix
|
|
the prefix is printed one indentation level before */
|
|
if (info->pindex) {
|
|
for (i = 0; i < indentlevel - 1; i++) {
|
|
fputs(h5tools_str_fmt(&str, 0, info->line_indent), stream);
|
|
}
|
|
}
|
|
|
|
if (elmtno == 0 && secnum == 0 && info->line_1st)
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_1st), stream);
|
|
else if (secnum && info->line_cont)
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_cont), stream);
|
|
else
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_pre), stream);
|
|
|
|
templength = h5tools_str_len(&prefix);
|
|
|
|
for (i = 0; i < indentlevel; i++) {
|
|
/*we already made the indent for the array indices case */
|
|
if (!info->pindex) {
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_indent), stream);
|
|
templength += h5tools_str_len(&prefix);
|
|
}
|
|
else {
|
|
/*we cannot count the prefix for the array indices case */
|
|
templength += h5tools_str_len(&str);
|
|
}
|
|
}
|
|
|
|
ctx->cur_column = ctx->prev_prefix_len = templength;
|
|
ctx->cur_elmt = 0;
|
|
ctx->need_prefix = 0;
|
|
|
|
/* Free string */
|
|
h5tools_str_close(&prefix);
|
|
h5tools_str_close(&str);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Emit a simple prefix to STREAM.
|
|
* Description:
|
|
* If /ctx->need_prefix/ is set then terminate the current line (if
|
|
* applicable), calculate the prefix string, and display it at the start
|
|
* of a line. Calls region specific function.
|
|
* Return:
|
|
* None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
h5tools_region_simple_prefix(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, hsize_t elmtno, hsize_t *ptdata, int secnum)
|
|
{
|
|
h5tools_str_t prefix;
|
|
h5tools_str_t str; /*temporary for indentation */
|
|
size_t templength = 0;
|
|
int i, indentlevel = 0;
|
|
|
|
if (!ctx->need_prefix)
|
|
return;
|
|
|
|
memset(&prefix, 0, sizeof(h5tools_str_t));
|
|
memset(&str, 0, sizeof(h5tools_str_t));
|
|
|
|
/* Terminate previous line, if any */
|
|
if (ctx->cur_column) {
|
|
fputs(OPT(info->line_suf, ""), stream);
|
|
putc('\n', stream);
|
|
fputs(OPT(info->line_sep, ""), stream);
|
|
}
|
|
|
|
/* Calculate new prefix */
|
|
h5tools_str_region_prefix(&prefix, info, elmtno, ptdata, ctx->ndims, ctx->p_max_idx, ctx);
|
|
|
|
/* Write new prefix to output */
|
|
if (ctx->indent_level >= 0) {
|
|
indentlevel = ctx->indent_level;
|
|
}
|
|
else {
|
|
/*
|
|
* This is because sometimes we don't print out all the header
|
|
* info for the data (like the tattr-2.ddl example). If that happens
|
|
* the ctx->indent_level is negative so we need to skip the above and
|
|
* just print out the default indent levels.
|
|
*/
|
|
indentlevel = ctx->default_indent_level;
|
|
}
|
|
|
|
/* when printing array indices, print the indentation before the prefix
|
|
the prefix is printed one indentation level before */
|
|
if (info->pindex) {
|
|
for (i = 0; i < indentlevel - 1; i++) {
|
|
fputs(h5tools_str_fmt(&str, 0, info->line_indent), stream);
|
|
}
|
|
}
|
|
|
|
if (elmtno == 0 && secnum == 0 && info->line_1st)
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_1st), stream);
|
|
else if (secnum && info->line_cont)
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_cont), stream);
|
|
else
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_pre), stream);
|
|
|
|
templength = h5tools_str_len(&prefix);
|
|
|
|
for (i = 0; i < indentlevel; i++) {
|
|
/*we already made the indent for the array indices case */
|
|
if (!info->pindex) {
|
|
fputs(h5tools_str_fmt(&prefix, 0, info->line_indent), stream);
|
|
templength += h5tools_str_len(&prefix);
|
|
}
|
|
else {
|
|
/*we cannot count the prefix for the array indices case */
|
|
templength += h5tools_str_len(&str);
|
|
}
|
|
}
|
|
|
|
ctx->cur_column = ctx->prev_prefix_len = templength;
|
|
ctx->cur_elmt = 0;
|
|
ctx->need_prefix = 0;
|
|
|
|
/* Free string */
|
|
h5tools_str_close(&prefix);
|
|
h5tools_str_close(&str);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Prints NELMTS data elements to output STREAM.
|
|
* Description:
|
|
* Prints some (NELMTS) data elements to output STREAM. The elements are
|
|
* stored in _MEM as type TYPE and are printed according to the format
|
|
* described in INFO. The CTX struct contains context information shared
|
|
* between calls to this function. The FLAGS is a bit field that
|
|
* indicates whether the data supplied in this call falls at the
|
|
* beginning or end of the total data to be printed (START_OF_DATA and
|
|
* END_OF_DATA).
|
|
* Return:
|
|
* None
|
|
* Programmer:
|
|
* Robb Matzke, Monday, April 26, 1999
|
|
* Modifications:
|
|
* Robb Matzke, 1999-06-04
|
|
* The `container' argument is the optional dataset for reference types.
|
|
*
|
|
* Robb Matzke, 1999-09-29
|
|
* Understands the `per_line' property which indicates that every Nth
|
|
* element should begin a new line.
|
|
*
|
|
* Robb Matzke, LLNL, 2003-06-05
|
|
* Do not dereference the memory for a variable-length string here.
|
|
* Deref in h5tools_str_sprint() instead so recursive types are
|
|
* handled correctly.
|
|
*
|
|
* Pedro Vicente Nunes, The HDF Group, 2005-10-19
|
|
* pass to the prefix in h5tools_simple_prefix the total position
|
|
* instead of the current stripmine position i; this is necessary
|
|
* to print the array indices
|
|
* new field sm_pos in h5tools_context_t, the current stripmine element position
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
h5tools_dump_simple_data(FILE *stream, const h5tool_format_t *info, hid_t container,
|
|
h5tools_context_t *ctx/*in,out*/, unsigned flags,
|
|
hsize_t nelmts, hid_t type, void *_mem)
|
|
{
|
|
unsigned char *mem = (unsigned char*) _mem;
|
|
hsize_t i; /*element counter */
|
|
size_t size; /*size of each datum */
|
|
hid_t region_space;
|
|
hid_t region_id;
|
|
hbool_t dimension_break = TRUE;
|
|
H5S_sel_type region_type;
|
|
size_t ncols = 80; /*available output width */
|
|
h5tools_str_t buffer; /*string into which to render */
|
|
hsize_t curr_pos; /* total data element position */
|
|
hsize_t elmt_counter = 0;/*counts the # elements printed.
|
|
*I (ptl?) needed something that
|
|
*isn't going to get reset when a new
|
|
*line is formed. I'm going to use
|
|
*this var to count elements and
|
|
*break after we see a number equal
|
|
*to the ctx->size_last_dim. */
|
|
|
|
/* binary dump */
|
|
if (bin_output) {
|
|
do_bin_output(rawdatastream, container, nelmts, type, _mem);
|
|
} /* end if */
|
|
else {
|
|
/* setup */
|
|
HDmemset(&buffer, 0, sizeof(h5tools_str_t));
|
|
size = H5Tget_size(type);
|
|
|
|
if (info->line_ncols > 0)
|
|
ncols = info->line_ncols;
|
|
|
|
/* pass to the prefix in h5tools_simple_prefix the total position
|
|
* instead of the current stripmine position i; this is necessary
|
|
* to print the array indices
|
|
*/
|
|
curr_pos = ctx->sm_pos;
|
|
|
|
for (i = 0; i < nelmts; i++, ctx->cur_elmt++, elmt_counter++) {
|
|
void* memref = mem + i * size;
|
|
if (region_output && H5Tequal(type, H5T_STD_REF_DSETREG)) {
|
|
char ref_name[1024];
|
|
|
|
/* region data */
|
|
region_id = H5Rdereference2(container, H5P_DATASET_ACCESS_DEFAULT, H5R_DATASET_REGION, memref);
|
|
if (region_id >= 0) {
|
|
region_space = H5Rget_region(container, H5R_DATASET_REGION, memref);
|
|
if (region_space >= 0) {
|
|
if (h5tools_is_zero(memref, H5Tget_size(type))) {
|
|
h5tools_str_append(&buffer, "NULL");
|
|
}
|
|
else {
|
|
if(H5Rget_name(region_id, H5R_DATASET_REGION, memref, (char*) ref_name, 1024)<0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Rget_name failed");
|
|
|
|
/* Render the region element begin */
|
|
h5tools_str_reset(&buffer);
|
|
|
|
h5tools_str_append(&buffer, info->dset_format, ref_name);
|
|
|
|
dimension_break = h5tools_render_element(stdout, info,
|
|
ctx, &buffer, &curr_pos, ncols, i, elmt_counter);
|
|
|
|
region_type = H5Sget_select_type(region_space);
|
|
if(region_type==H5S_SEL_POINTS)
|
|
/* Print point information */
|
|
dimension_break = h5tools_dump_region_data_points(
|
|
region_space, region_id, stdout, info, ctx,
|
|
&buffer, &curr_pos, ncols, i, elmt_counter);
|
|
else if(region_type==H5S_SEL_HYPERSLABS)
|
|
/* Print block information */
|
|
dimension_break = h5tools_dump_region_data_blocks(
|
|
region_space, region_id, stdout, info, ctx,
|
|
&buffer, &curr_pos, ncols, i, elmt_counter);
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "invalid region type");
|
|
/* Render the region element end */
|
|
|
|
} /* end else to if (h5tools_is_zero(... */
|
|
if(H5Sclose(region_space) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
} /* end if (region_space >= 0) */
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Rget_region failed");
|
|
if(H5Dclose(region_id) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Dclose failed");
|
|
|
|
} /* if (region_id >= 0) */
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Rdereference failed");
|
|
|
|
ctx->need_prefix = TRUE;
|
|
} /* end if (region_output... */
|
|
else {
|
|
/* Render the data element begin*/
|
|
h5tools_str_reset(&buffer);
|
|
h5tools_str_sprint(&buffer, info, container, type, memref, ctx);
|
|
|
|
if (i + 1 < nelmts || (flags & END_OF_DATA) == 0)
|
|
h5tools_str_append(&buffer, "%s", OPT(info->elmt_suf1, ","));
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, &buffer,
|
|
&curr_pos, ncols, i, elmt_counter);
|
|
/* Render the data element end*/
|
|
|
|
}
|
|
if(FALSE==dimension_break)
|
|
elmt_counter = 0;
|
|
} /* end for (i = 0; i < nelmts... */
|
|
|
|
h5tools_str_close(&buffer);
|
|
}/* else bin */
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Render an element to output STREAM.
|
|
* Description:
|
|
* Prints the string buffer to the output STREAM. The string is
|
|
* printed according to the format described in INFO. The CTX struct
|
|
* contains context information shared between calls to this function.
|
|
*
|
|
* Return:
|
|
* False if a dimension end is reached, otherwise true
|
|
*
|
|
* In/Out:
|
|
* h5tools_context_t *ctx
|
|
* h5tools_str_t *buffer
|
|
* hsize_t *curr_pos
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* hsize_t curr_pos is the total data element position
|
|
* size_t ncols
|
|
* hsize_t local_elmt_counter is the local element loop counter
|
|
* hsize_t elmt_count is the data element loop counter
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
h5tools_render_element(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, h5tools_str_t *buffer, hsize_t *curr_pos,
|
|
size_t ncols, hsize_t local_elmt_counter, hsize_t elmt_counter)
|
|
{
|
|
hbool_t dimension_break = TRUE;
|
|
char *s;
|
|
char *section; /*a section of output */
|
|
int secnum; /*section sequence number */
|
|
int multiline; /*datum was multiline */
|
|
|
|
s = h5tools_str_fmt(buffer, 0, "%s");
|
|
|
|
/*
|
|
* If the element would split on multiple lines if printed at our
|
|
* current location...
|
|
*/
|
|
if (info->line_multi_new == 1 &&
|
|
(ctx->cur_column + h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols) {
|
|
if (ctx->prev_multiline) {
|
|
/*
|
|
* ... and the previous element also occupied more than one
|
|
* line, then start this element at the beginning of a line.
|
|
*/
|
|
ctx->need_prefix = TRUE;
|
|
}
|
|
else if ((ctx->prev_prefix_len + h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) <= ncols) {
|
|
/*
|
|
* ...but *could* fit on one line otherwise, then we
|
|
* should end the current line and start this element on its
|
|
* own line.
|
|
*/
|
|
ctx->need_prefix = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We need to break after each row of a dimension---> we should
|
|
* break at the end of the each last dimension well that is the
|
|
* way the dumper did it before
|
|
*/
|
|
if (info->arr_linebreak && ctx->cur_elmt) {
|
|
if (ctx->size_last_dim && (ctx->cur_elmt % ctx->size_last_dim) == 0)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
if (elmt_counter == ctx->size_last_dim) {
|
|
ctx->need_prefix = TRUE;
|
|
dimension_break = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the previous element occupied multiple lines and this element
|
|
* is too long to fit on a line then start this element at the
|
|
* beginning of the line.
|
|
*/
|
|
if (info->line_multi_new == 1 &&
|
|
ctx->prev_multiline &&
|
|
(ctx->cur_column +
|
|
h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/*
|
|
* If too many elements have already been printed then we need to
|
|
* start a new line.
|
|
*/
|
|
if (info->line_per_line > 0 && ctx->cur_elmt >= info->line_per_line)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/*
|
|
* Each OPTIONAL_LINE_BREAK embedded in the rendered string can cause
|
|
* the data to split across multiple lines. We display the sections
|
|
* one-at a time.
|
|
*/
|
|
multiline = 0;
|
|
for (secnum = 0, multiline = 0;
|
|
(section = strtok(secnum ? NULL : s, OPTIONAL_LINE_BREAK));
|
|
secnum++) {
|
|
/*
|
|
* If the current section plus possible suffix and end-of-line
|
|
* information would cause the output to wrap then we need to
|
|
* start a new line.
|
|
*/
|
|
|
|
/*
|
|
* check for displaying prefix for each section
|
|
*/
|
|
if ( (ctx->cur_column + strlen(section) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols)
|
|
ctx->need_prefix = 1;
|
|
|
|
/*
|
|
* Print the prefix or separate the beginning of this element
|
|
* from the previous element.
|
|
*/
|
|
if (ctx->need_prefix) {
|
|
if (secnum)
|
|
multiline++;
|
|
|
|
/* pass to the prefix in h5tools_simple_prefix the total
|
|
* position instead of the current stripmine position i;
|
|
* this is necessary to print the array indices
|
|
*/
|
|
*curr_pos = ctx->sm_pos + local_elmt_counter;
|
|
|
|
h5tools_simple_prefix(stream, info, ctx, *curr_pos, secnum);
|
|
}
|
|
else if ((local_elmt_counter || ctx->continuation) && secnum == 0) {
|
|
fputs(OPT(info->elmt_suf2, " "), stream);
|
|
ctx->cur_column += strlen(OPT(info->elmt_suf2, " "));
|
|
}
|
|
|
|
/* Print the section */
|
|
fputs(section, stream);
|
|
ctx->cur_column += strlen(section);
|
|
}
|
|
|
|
ctx->prev_multiline = multiline;
|
|
return dimension_break;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Render a region element to output STREAM.
|
|
* Description:
|
|
* Prints the string buffer to the output STREAM. The string is
|
|
* printed according to the format described in INFO. The CTX struct
|
|
* contains context information shared between calls to this function.
|
|
*
|
|
* Return:
|
|
* False if a dimension end is reached, otherwise true
|
|
*
|
|
* In/Out:
|
|
* h5tools_context_t *ctx
|
|
* h5tools_str_t *buffer
|
|
* hsize_t *curr_pos
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* hsize_t curr_pos is the total data element position
|
|
* size_t ncols
|
|
* hsize_t *ptdata
|
|
* hsize_t local_elmt_counter is the local element loop counter
|
|
* hsize_t elmt_count is the data element loop counter
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
h5tools_render_region_element(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, h5tools_str_t *buffer, hsize_t *curr_pos,
|
|
size_t ncols, hsize_t *ptdata, hsize_t local_elmt_counter, hsize_t elmt_counter)
|
|
{
|
|
hbool_t dimension_break = TRUE;
|
|
char *s;
|
|
char *section; /*a section of output */
|
|
int secnum; /*section sequence number */
|
|
int multiline; /*datum was multiline */
|
|
|
|
s = h5tools_str_fmt(buffer, 0, "%s");
|
|
|
|
/*
|
|
* If the element would split on multiple lines if printed at our
|
|
* current location...
|
|
*/
|
|
if (info->line_multi_new == 1 &&
|
|
(ctx->cur_column + h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols) {
|
|
if (ctx->prev_multiline) {
|
|
/*
|
|
* ... and the previous element also occupied more than one
|
|
* line, then start this element at the beginning of a line.
|
|
*/
|
|
ctx->need_prefix = TRUE;
|
|
}
|
|
else if ((ctx->prev_prefix_len + h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) <= ncols) {
|
|
/*
|
|
* ...but *could* fit on one line otherwise, then we
|
|
* should end the current line and start this element on its
|
|
* own line.
|
|
*/
|
|
ctx->need_prefix = TRUE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We need to break after each row of a dimension---> we should
|
|
* break at the end of the each last dimension well that is the
|
|
* way the dumper did it before
|
|
*/
|
|
if (info->arr_linebreak && ctx->cur_elmt) {
|
|
if (ctx->size_last_dim && (ctx->cur_elmt % ctx->size_last_dim) == 0)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
if (elmt_counter == ctx->size_last_dim) {
|
|
ctx->need_prefix = TRUE;
|
|
dimension_break = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the previous element occupied multiple lines and this element
|
|
* is too long to fit on a line then start this element at the
|
|
* beginning of the line.
|
|
*/
|
|
if (info->line_multi_new == 1 &&
|
|
ctx->prev_multiline &&
|
|
(ctx->cur_column +
|
|
h5tools_ncols(s) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/*
|
|
* If too many elements have already been printed then we need to
|
|
* start a new line.
|
|
*/
|
|
if (info->line_per_line > 0 && ctx->cur_elmt >= info->line_per_line)
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/*
|
|
* Each OPTIONAL_LINE_BREAK embedded in the rendered string can cause
|
|
* the data to split across multiple lines. We display the sections
|
|
* one-at a time.
|
|
*/
|
|
multiline = 0;
|
|
for (secnum = 0, multiline = 0; (section = strtok(secnum ? NULL : s,
|
|
OPTIONAL_LINE_BREAK)); secnum++) {
|
|
/*
|
|
* If the current section plus possible suffix and end-of-line
|
|
* information would cause the output to wrap then we need to
|
|
* start a new line.
|
|
*/
|
|
|
|
/*
|
|
* Added the info->skip_first because the dumper does not want
|
|
* this check to happen for the first line
|
|
*/
|
|
if ((!info->skip_first || local_elmt_counter) &&
|
|
(ctx->cur_column +
|
|
strlen(section) +
|
|
strlen(OPT(info->elmt_suf2, " ")) +
|
|
strlen(OPT(info->line_suf, ""))) > ncols)
|
|
ctx->need_prefix = 1;
|
|
|
|
/*
|
|
* Print the prefix or separate the beginning of this element
|
|
* from the previous element.
|
|
*/
|
|
if (ctx->need_prefix) {
|
|
if (secnum)
|
|
multiline++;
|
|
|
|
/* pass to the prefix in h5tools_simple_prefix the total
|
|
* position instead of the current stripmine position i;
|
|
* this is necessary to print the array indices
|
|
*/
|
|
*curr_pos = ctx->sm_pos + local_elmt_counter;
|
|
|
|
h5tools_region_simple_prefix(stream, info, ctx, local_elmt_counter, ptdata, secnum);
|
|
}
|
|
else if ((local_elmt_counter || ctx->continuation) && secnum == 0) {
|
|
fputs(OPT(info->elmt_suf2, " "), stream);
|
|
ctx->cur_column += strlen(OPT(info->elmt_suf2, " "));
|
|
}
|
|
|
|
/* Print the section */
|
|
fputs(section, stream);
|
|
ctx->cur_column += strlen(section);
|
|
}
|
|
|
|
ctx->prev_multiline = multiline;
|
|
return dimension_break;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print the data values from a dataset referenced by region blocks.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to print the data in a region reference of type blocks.
|
|
*
|
|
* Return:
|
|
* The function returns FAIL if there was an error, otherwise SUCEED
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* size_t ncols
|
|
* int ndims is the number of dimensions of the region element
|
|
* hssize_t nblocks is the number of blocks in the region
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
h5tools_print_region_data_blocks(hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info, h5tools_context_t *cur_ctx,
|
|
h5tools_str_t *buffer/*string into which to render */, size_t ncols,
|
|
int ndims, hid_t type_id, hssize_t nblocks, hsize_t *ptdata)
|
|
{
|
|
hbool_t dimension_break = TRUE;
|
|
hsize_t *dims1 = NULL;
|
|
hsize_t *start = NULL;
|
|
hsize_t *count = NULL;
|
|
size_t numelem;
|
|
hsize_t total_size[H5S_MAX_RANK];
|
|
hsize_t elmtno; /* elemnt index */
|
|
unsigned int region_flags; /* buffer extent flags */
|
|
hsize_t curr_pos;
|
|
size_t jndx;
|
|
int indx;
|
|
int type_size;
|
|
hid_t mem_space = -1;
|
|
void *region_buf = NULL;
|
|
hsize_t blkndx;
|
|
hid_t sid1 = -1;
|
|
int ret_value = SUCCEED;
|
|
h5tools_context_t ctx;
|
|
|
|
assert(info);
|
|
assert(cur_ctx);
|
|
assert(buffer);
|
|
assert(ptdata);
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
/* Get the dataspace of the dataset */
|
|
if((sid1 = H5Dget_space(region_id)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed");
|
|
|
|
/* Allocate space for the dimension array */
|
|
if((dims1 = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for dims");
|
|
|
|
/* find the dimensions of each data space from the block coordinates */
|
|
numelem = 1;
|
|
for (jndx = 0; jndx < ndims; jndx++) {
|
|
dims1[jndx] = ptdata[jndx + ndims] - ptdata[jndx] + 1;
|
|
numelem = dims1[jndx] * numelem;
|
|
}
|
|
|
|
/* Create dataspace for reading buffer */
|
|
if((mem_space = H5Screate_simple(ndims, dims1, NULL)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Screate_simple failed");
|
|
|
|
if((type_size = H5Tget_size(type_id)) == 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if((region_buf = HDmalloc(type_size * numelem)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate region buffer");
|
|
|
|
/* Select (x , x , ..., x ) x (y , y , ..., y ) hyperslab for reading memory dataset */
|
|
/* 1 2 n 1 2 n */
|
|
if((start = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for start");
|
|
|
|
if((count = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for count");
|
|
|
|
curr_pos = 0;
|
|
ctx.indent_level = cur_ctx->indent_level;
|
|
ctx.cur_column = cur_ctx->cur_column;
|
|
ctx.prev_multiline = cur_ctx->prev_multiline;
|
|
ctx.ndims = ndims;
|
|
for (blkndx = 0; blkndx < nblocks; blkndx++) {
|
|
ctx.need_prefix = TRUE;
|
|
ctx.cur_elmt = 0;
|
|
for (indx = 0; indx < ndims; indx++) {
|
|
start[indx] = ptdata[indx + blkndx * ndims * 2];
|
|
count[indx] = dims1[indx];
|
|
}
|
|
|
|
if(H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sselect_hyperslab failed");
|
|
|
|
if(H5Dread(region_id, type_id, mem_space, sid1, H5P_DEFAULT, region_buf) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Dread failed");
|
|
|
|
ctx.indent_level++;
|
|
if(H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
|
|
/* assume entire data space to be printed */
|
|
for (indx = 0; indx < (size_t) ctx.ndims; indx++)
|
|
ctx.p_min_idx[indx] = start[indx];
|
|
init_acc_pos(&ctx, total_size);
|
|
|
|
/* print the data */
|
|
region_flags = START_OF_DATA;
|
|
if (blkndx == nblocks - 1)
|
|
region_flags |= END_OF_DATA;
|
|
|
|
for (indx = 0; indx < (size_t)ctx.ndims; indx++)
|
|
ctx.p_max_idx[indx] = dims1[indx];
|
|
|
|
curr_pos = 0;
|
|
ctx.sm_pos = blkndx*2*ndims;
|
|
ctx.size_last_dim = dims1[ndims-1];
|
|
|
|
h5tools_region_simple_prefix(stream, info, &ctx, curr_pos, ptdata, 0);
|
|
|
|
elmtno = 0;
|
|
for (jndx = 0; jndx < numelem; jndx++, elmtno++, ctx.cur_elmt++) {
|
|
/* Render the region data element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "%s", jndx ? OPTIONAL_LINE_BREAK "" : "");
|
|
h5tools_str_sprint(buffer, info, region_id, type_id,
|
|
((char*)region_buf + jndx * type_size), &ctx);
|
|
|
|
if (jndx + 1 < numelem || (region_flags & END_OF_DATA) == 0)
|
|
h5tools_str_append(buffer, "%s", OPT(info->elmt_suf1, ","));
|
|
|
|
dimension_break = h5tools_render_region_element(stream, info, &ctx, buffer, &curr_pos,
|
|
ncols, ptdata, jndx, elmtno);
|
|
/* Render the region data element end */
|
|
|
|
if(FALSE == dimension_break)
|
|
elmtno = 0;
|
|
} /* end for (jndx = 0; jndx < numelem; jndx++, region_elmtno++, ctx.cur_elmt++) */
|
|
|
|
ctx.indent_level--;
|
|
} /* end for (blkndx = 0; blkndx < nblocks; blkndx++) */
|
|
|
|
done:
|
|
HDfree(start);
|
|
HDfree(count);
|
|
HDfree(region_buf);
|
|
HDfree(dims1);
|
|
|
|
if(H5Sclose(mem_space) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
if(H5Sclose(sid1) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print some values from a dataset referenced by region blocks.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to dump a region reference using blocks.
|
|
*
|
|
* Return:
|
|
* The function returns False if the last dimension has been reached, otherwise True
|
|
*
|
|
* In/Out:
|
|
* h5tools_context_t *ctx
|
|
* hsize_t *curr_pos
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* hsize_t curr_pos is the total data element position
|
|
* size_t ncols
|
|
* hsize_t region_elmt_counter is the region element loop counter
|
|
* hsize_t elmt_count is the data element loop counter
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
h5tools_dump_region_data_blocks(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx/*in,out*/,
|
|
h5tools_str_t *buffer/*string into which to render */,
|
|
hsize_t *curr_pos/*total data element position*/,
|
|
size_t ncols, hsize_t region_elmt_counter/*element counter*/,
|
|
hsize_t elmt_counter)
|
|
{
|
|
HERR_INIT(hbool_t, TRUE)
|
|
hbool_t dimension_break = TRUE;
|
|
hssize_t nblocks;
|
|
hsize_t alloc_size;
|
|
hsize_t *ptdata = NULL;
|
|
int ndims;
|
|
hid_t dtype;
|
|
hid_t type_id;
|
|
int i;
|
|
|
|
assert(info);
|
|
assert(ctx);
|
|
assert(buffer);
|
|
|
|
if((nblocks = H5Sget_select_hyper_nblocks(region_space)) <= 0)
|
|
H5E_THROW(dimension_break, H5E_tools_min_id_g, "H5Sget_select_hyper_nblocks failed");
|
|
|
|
/* Print block information */
|
|
if((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
|
|
H5E_THROW(dimension_break, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
|
|
|
|
/* Render the region { element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "{");
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region { element end */
|
|
|
|
/* Render the region datatype info and indices element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
ctx->indent_level++;
|
|
ctx->need_prefix = TRUE;
|
|
h5tools_str_append(buffer, "REGION_TYPE BLOCK ");
|
|
|
|
alloc_size = nblocks * ndims * 2 * sizeof(ptdata[0]);
|
|
assert(alloc_size == (hsize_t) ((size_t) alloc_size)); /*check for overflow*/
|
|
if((ptdata = (hsize_t*) malloc((size_t) alloc_size)) == NULL)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "Could not allocate buffer for ptdata");
|
|
|
|
H5_CHECK_OVERFLOW(nblocks, hssize_t, hsize_t);
|
|
if(H5Sget_select_hyper_blocklist(region_space, (hsize_t) 0, (hsize_t) nblocks, ptdata) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Rget_select_hyper_blocklist failed");
|
|
|
|
for (i = 0; i < nblocks; i++) {
|
|
int j;
|
|
|
|
h5tools_str_append(buffer, info->dset_blockformat_pre,
|
|
i ? "," OPTIONAL_LINE_BREAK " " : "", (unsigned long) i);
|
|
|
|
/* Start coordinates and opposite corner */
|
|
for (j = 0; j < ndims; j++)
|
|
h5tools_str_append(buffer, "%s%lu", j ? "," : "(",
|
|
(unsigned long) ptdata[i * 2 * ndims + j]);
|
|
|
|
for (j = 0; j < ndims; j++)
|
|
h5tools_str_append(buffer, "%s%lu", j ? "," : ")-(",
|
|
(unsigned long) ptdata[i * 2 * ndims + j + ndims]);
|
|
|
|
h5tools_str_append(buffer, ")");
|
|
} /* end for (i = 0; i < nblocks; i++) */
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region datatype info and indices element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
if((dtype = H5Dget_type(region_id)) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Dget_type failed");
|
|
if((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Tget_native_type failed");
|
|
|
|
/* Render the datatype element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->datatypebegin,
|
|
h5tools_dump_header_format->datatypeblockbegin);
|
|
|
|
h5tools_print_datatype(buffer, info, ctx, dtype);
|
|
|
|
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);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the datatype element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the dataspace element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
ctx->need_prefix = TRUE;
|
|
h5tools_str_append(buffer, "%s ", h5tools_dump_header_format->dataspacebegin);
|
|
|
|
h5tools_print_dataspace(buffer, region_space);
|
|
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceblockend)) {
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->dataspaceblockend);
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceend))
|
|
h5tools_str_append(buffer, " ");
|
|
}
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceend))
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->dataspaceblockend);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the dataspace element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the databegin element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->databegin,
|
|
h5tools_dump_header_format->datablockbegin);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the databegin element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
h5tools_print_region_data_blocks(region_id, rawdatastream, info, ctx,
|
|
buffer, ncols, ndims, type_id, nblocks, ptdata);
|
|
|
|
done:
|
|
free(ptdata);
|
|
|
|
if(H5Tclose(type_id) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
if(H5Tclose(dtype) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the dataend element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->dataend,
|
|
h5tools_dump_header_format->datablockend);
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos,
|
|
ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the dataend element end */
|
|
|
|
ctx->indent_level--;
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the region } element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "}");
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos,
|
|
ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region } element end */
|
|
|
|
H5_LEAVE(dimension_break)
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print the data values from a dataset referenced by region points.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to print the data in a region reference of type points.
|
|
*
|
|
* Return:
|
|
* The function returns FAIL on error, otherwise SUCCEED
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* size_t ncols
|
|
* int ndims is the number of dimensions of the region element
|
|
* hssize_t npoints is the number of points in the region
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
h5tools_print_region_data_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info, h5tools_context_t *cur_ctx,
|
|
h5tools_str_t *buffer, size_t ncols,
|
|
int ndims, hid_t type_id, hssize_t npoints, hsize_t *ptdata)
|
|
{
|
|
hbool_t dimension_break = TRUE;
|
|
hsize_t *dims1 = NULL;
|
|
hsize_t elmtno; /* elemnt index */
|
|
unsigned int region_flags; /* buffer extent flags */
|
|
hsize_t curr_pos;
|
|
hsize_t total_size[H5S_MAX_RANK];
|
|
int indx;
|
|
size_t jndx;
|
|
int type_size;
|
|
hid_t mem_space = -1;
|
|
void *region_buf = NULL;
|
|
int ret_value = SUCCEED;
|
|
h5tools_context_t ctx;
|
|
|
|
assert(info);
|
|
assert(cur_ctx);
|
|
assert(buffer);
|
|
assert(ptdata);
|
|
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
/* Allocate space for the dimension array */
|
|
if((dims1 = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for dims");
|
|
|
|
dims1[0] = npoints;
|
|
|
|
/* Create dataspace for reading buffer */
|
|
if((mem_space = H5Screate_simple(1, dims1, NULL)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Screate_simple failed");
|
|
|
|
if((type_size = H5Tget_size(type_id)) == 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if((region_buf = HDmalloc(type_size * npoints)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for region");
|
|
|
|
curr_pos = 0;
|
|
ctx.indent_level = cur_ctx->indent_level;
|
|
ctx.cur_column = cur_ctx->cur_column;
|
|
ctx.prev_multiline = cur_ctx->prev_multiline;
|
|
ctx.ndims = ndims;
|
|
|
|
if(H5Dread(region_id, type_id, mem_space, region_space, H5P_DEFAULT, region_buf) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed");
|
|
|
|
elmtno = 0;
|
|
for (jndx = 0; jndx < npoints; jndx++, elmtno++) {
|
|
ctx.need_prefix = TRUE;
|
|
ctx.cur_elmt = 0; /* points are always 0 */
|
|
|
|
ctx.indent_level++;
|
|
if(H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
|
|
/* assume entire data space to be printed */
|
|
for (indx = 0; indx < (size_t) ctx.ndims; indx++)
|
|
ctx.p_min_idx[indx] = 0;
|
|
init_acc_pos(&ctx, total_size);
|
|
|
|
/* print the data */
|
|
region_flags = START_OF_DATA;
|
|
if (jndx == npoints - 1)
|
|
region_flags |= END_OF_DATA;
|
|
|
|
for (indx = 0; indx < (size_t)ctx.ndims; indx++)
|
|
ctx.p_max_idx[indx] = cur_ctx->p_max_idx[indx];
|
|
|
|
ctx.sm_pos = jndx * ndims;
|
|
if (ctx.ndims > 0) {
|
|
ctx.size_last_dim = (int) (ctx.p_max_idx[ctx.ndims - 1]);
|
|
}
|
|
else
|
|
ctx.size_last_dim = 0;
|
|
|
|
curr_pos = 0; /* points requires constant 0 */
|
|
h5tools_region_simple_prefix(stream, info, &ctx, curr_pos, ptdata, 0);
|
|
|
|
/* Render the point element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "%s", jndx ? OPTIONAL_LINE_BREAK "" : "");
|
|
h5tools_str_sprint(buffer, info, region_id, type_id,
|
|
((char*)region_buf + jndx * type_size), &ctx);
|
|
|
|
if (jndx + 1 < npoints || (region_flags & END_OF_DATA) == 0)
|
|
h5tools_str_append(buffer, "%s", OPT(info->elmt_suf1, ","));
|
|
|
|
dimension_break = h5tools_render_region_element(stream, info, &ctx, buffer, &curr_pos,
|
|
ncols, ptdata, (hsize_t)0, elmtno);
|
|
/* Render the point element end */
|
|
if(FALSE == dimension_break)
|
|
elmtno = 0;
|
|
|
|
ctx.indent_level--;
|
|
} /* end for (jndx = 0; jndx < npoints; jndx++, elmtno++) */
|
|
|
|
done:
|
|
HDfree(region_buf);
|
|
HDfree(dims1);
|
|
|
|
if(H5Sclose(mem_space) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print some values from a dataset referenced by region points.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to dump a region reference using points.
|
|
*
|
|
* Return:
|
|
* The function returns False if the last dimension has been reached, otherwise True
|
|
*
|
|
* In/Out:
|
|
* h5tools_context_t *ctx
|
|
* hsize_t *curr_pos
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* hsize_t curr_pos is the total data element position
|
|
* size_t ncols
|
|
* hsize_t region_elmt_counter is the region element loop counter
|
|
* hsize_t elmt_count is the data element loop counter
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
h5tools_dump_region_data_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, const h5tool_format_t *info, h5tools_context_t *ctx,
|
|
h5tools_str_t *buffer, hsize_t *curr_pos, size_t ncols, hsize_t region_elmt_counter,
|
|
hsize_t elmt_counter) {
|
|
HERR_INIT(hbool_t, TRUE)
|
|
hbool_t dimension_break = TRUE;
|
|
hssize_t npoints;
|
|
hsize_t alloc_size;
|
|
hsize_t *ptdata;
|
|
int ndims;
|
|
hssize_t indx;
|
|
hid_t dtype;
|
|
hid_t type_id;
|
|
|
|
assert(info);
|
|
assert(ctx);
|
|
assert(buffer);
|
|
|
|
if((npoints = H5Sget_select_elem_npoints(region_space)) <= 0)
|
|
H5E_THROW(dimension_break, H5E_tools_min_id_g, "H5Sget_select_elem_npoints failed");
|
|
|
|
/* Allocate space for the dimension array */
|
|
if((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
|
|
H5E_THROW(dimension_break, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
|
|
|
|
/* Render the region { element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "{");
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region { element end */
|
|
|
|
/* Render the region datatype info and indices element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
ctx->indent_level++;
|
|
ctx->need_prefix = TRUE;
|
|
h5tools_str_append(buffer, "REGION_TYPE POINT ");
|
|
|
|
alloc_size = npoints * ndims * sizeof(ptdata[0]);
|
|
assert(alloc_size == (hsize_t) ((size_t) alloc_size)); /*check for overflow*/
|
|
if(NULL == (ptdata = (hsize_t *)HDmalloc((size_t) alloc_size)))
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "Could not allocate buffer for ptdata");
|
|
|
|
H5_CHECK_OVERFLOW(npoints, hssize_t, hsize_t);
|
|
if(H5Sget_select_elem_pointlist(region_space, (hsize_t) 0, (hsize_t) npoints, ptdata) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Sget_select_elem_pointlist failed");
|
|
|
|
for (indx = 0; indx < npoints; indx++) {
|
|
int loop_indx;
|
|
|
|
h5tools_str_append(buffer, info->dset_ptformat_pre,
|
|
indx ? "," OPTIONAL_LINE_BREAK " " : "", (unsigned long) indx);
|
|
|
|
for (loop_indx = 0; loop_indx < ndims; loop_indx++)
|
|
h5tools_str_append(buffer, "%s%lu", loop_indx ? "," : "(",
|
|
(unsigned long) (ptdata[indx * ndims + loop_indx]));
|
|
|
|
h5tools_str_append(buffer, ")");
|
|
} /* end for (indx = 0; indx < npoints; indx++) */
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region datatype info and indices element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
if((dtype = H5Dget_type(region_id)) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Dget_type failed");
|
|
|
|
if((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
|
|
HGOTO_ERROR(dimension_break, H5E_tools_min_id_g, "H5Tget_native_type failed");
|
|
|
|
/* Render the datatype element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->datatypebegin,
|
|
h5tools_dump_header_format->datatypeblockbegin);
|
|
|
|
h5tools_print_datatype(buffer, info, ctx, dtype);
|
|
|
|
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);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the datatype element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the dataspace element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
ctx->need_prefix = TRUE;
|
|
h5tools_str_append(buffer, "%s ", h5tools_dump_header_format->dataspacebegin);
|
|
|
|
h5tools_print_dataspace(buffer, region_space);
|
|
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceblockend)) {
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->dataspaceblockend);
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceend))
|
|
h5tools_str_append(buffer, " ");
|
|
}
|
|
if (HDstrlen(h5tools_dump_header_format->dataspaceend))
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->dataspaceblockend);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the dataspace element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the databegin element begin */
|
|
h5tools_str_reset(buffer);
|
|
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->databegin,
|
|
h5tools_dump_header_format->datablockbegin);
|
|
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos, ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the databegin element end */
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
h5tools_print_region_data_points(region_space, region_id,
|
|
rawdatastream, info, ctx, buffer, ncols, ndims, type_id, npoints, ptdata);
|
|
|
|
done:
|
|
free(ptdata);
|
|
|
|
if(H5Tclose(type_id) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
if(H5Tclose(dtype) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the dataend element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "%s %s ",
|
|
h5tools_dump_header_format->dataend,
|
|
h5tools_dump_header_format->datablockend);
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos,
|
|
ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the dataend element end*/
|
|
|
|
ctx->indent_level--;
|
|
ctx->need_prefix = TRUE;
|
|
|
|
/* Render the region } element begin */
|
|
h5tools_str_reset(buffer);
|
|
h5tools_str_append(buffer, "}");
|
|
dimension_break = h5tools_render_element(stream, info, ctx, buffer, curr_pos,
|
|
ncols, region_elmt_counter, elmt_counter);
|
|
/* Render the region } element end */
|
|
|
|
H5_LEAVE(dimension_break)
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: print out the data for a subset of a dataset.
|
|
* Description:
|
|
*
|
|
* Select a hyperslab from the dataset DSET using the parameters
|
|
* specified in SSET. Dump this out to STREAM.
|
|
*
|
|
* Hyperslabs select "count" blocks of size "block", spaced "stride" elements
|
|
* from each other, starting at coordinate "start".
|
|
*
|
|
* Return:
|
|
* On success, return SUCCEED. Otherwise, the function returns FAIL.
|
|
*
|
|
* Algorithm
|
|
*
|
|
* The parameters from SSET are translated into temporary
|
|
* variables so that 1 row is printed at a time (getting the coordinate indices
|
|
* at each row).
|
|
* We define the stride, count and block to be 1 in the row dimension to achieve
|
|
* this and advance until all points are printed.
|
|
*
|
|
* The element position is obtained from the matrix according to:
|
|
* Given an index I(z,y,x) its position from the beginning of an array
|
|
* of sizes A(size_z, size_y,size_x) is given by
|
|
* Position of I(z,y,x) = index_z * size_y * size_x
|
|
* + index_y * size_x
|
|
* + index_x
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
h5tools_print_simple_subset(FILE *stream, const h5tool_format_t *info, h5tools_context_t *ctx,
|
|
hid_t dset, hid_t p_type, struct subset_t *sset,
|
|
hid_t f_space, hsize_t hyperslab_count,
|
|
hsize_t *temp_start,/* start inside offset count loop */
|
|
hsize_t *temp_count,/* count inside offset count loop */
|
|
hsize_t *temp_block,/* block size used in loop */
|
|
hsize_t *temp_stride,/* stride size used in loop */
|
|
hsize_t *total_size,/* total size of dataset */
|
|
unsigned int row_dim/* index of row_counter dimension */)
|
|
{
|
|
HERR_INIT(herr_t, SUCCEED)
|
|
size_t i; /* counters */
|
|
size_t j; /* counters */
|
|
hsize_t zero[1] = {0}; /* vector of zeros */
|
|
unsigned int flags; /* buffer extent flags */
|
|
hsize_t elmtno; /* elemnt index */
|
|
hsize_t low[H5S_MAX_RANK]; /* low bound of hyperslab */
|
|
hsize_t high[H5S_MAX_RANK]; /* higher bound of hyperslab */
|
|
size_t p_type_nbytes; /* size of memory type */
|
|
hsize_t sm_size[H5S_MAX_RANK]; /* stripmine size */
|
|
hsize_t sm_nbytes; /* bytes per stripmine */
|
|
hssize_t ssm_nelmts; /* elements per stripmine*/
|
|
hsize_t sm_nelmts; /* elements per stripmine*/
|
|
unsigned char *sm_buf = NULL; /* buffer for raw data */
|
|
hid_t sm_space = -1; /* stripmine data space */
|
|
hsize_t size_row_block; /* size for blocks along rows */
|
|
hsize_t row_counter = 0;
|
|
|
|
/* VL data special information */
|
|
unsigned int vl_data = 0; /* contains VL datatypes */
|
|
|
|
if ((size_t) ctx->ndims > NELMTS(sm_size))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "ndims and sm_size comparision failed");
|
|
|
|
if (ctx->ndims > 0)
|
|
init_acc_pos(ctx, total_size);
|
|
|
|
size_row_block = sset->block.data[row_dim];
|
|
|
|
/* Check if we have VL data in the dataset's datatype */
|
|
if (h5tools_detect_vlen_str(p_type) == TRUE)
|
|
vl_data = TRUE;
|
|
if (H5Tdetect_class(p_type, H5T_VLEN) == TRUE)
|
|
vl_data = TRUE;
|
|
|
|
/* display loop */
|
|
for (; hyperslab_count > 0; temp_start[row_dim] += temp_stride[row_dim], hyperslab_count--) {
|
|
/* jump rows if size of block exceeded
|
|
cases where block > 1 only and stride > block */
|
|
if (size_row_block > 1
|
|
&& row_counter == size_row_block
|
|
&& sset->stride.data[row_dim] > sset->block.data[row_dim]) {
|
|
|
|
hsize_t increase_rows = sset->stride.data[row_dim] - sset->block.data[row_dim];
|
|
temp_start[row_dim] += increase_rows;
|
|
row_counter = 0;
|
|
}
|
|
|
|
row_counter++;
|
|
|
|
/* calculate the potential number of elements we're going to print */
|
|
if(H5Sselect_hyperslab(f_space, H5S_SELECT_SET, temp_start, temp_stride, temp_count, temp_block) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sselect_hyperslab failed");
|
|
|
|
if((ssm_nelmts = H5Sget_select_npoints(f_space)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_select_npoints failed");
|
|
sm_nelmts = (hsize_t)ssm_nelmts;
|
|
|
|
if (sm_nelmts > 0) {
|
|
/*
|
|
* determine the strip mine size and allocate a buffer. the strip mine is
|
|
* a hyperslab whose size is manageable.
|
|
*/
|
|
if((sm_nbytes = p_type_nbytes = H5Tget_size(p_type)) == 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if (ctx->ndims > 0)
|
|
for (i = ctx->ndims; i > 0; --i) {
|
|
hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes;
|
|
if (size == 0) /* datum size > H5TOOLS_BUFSIZE */
|
|
size = 1;
|
|
sm_size[i - 1] = MIN(total_size[i - 1], size);
|
|
sm_nbytes *= sm_size[i - 1];
|
|
assert(sm_nbytes > 0);
|
|
}
|
|
|
|
assert(sm_nbytes == (hsize_t) ((size_t) sm_nbytes)); /*check for overflow*/
|
|
if(NULL == (sm_buf = (unsigned char *)HDmalloc((size_t) sm_nelmts * p_type_nbytes)))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for strip-mine");
|
|
|
|
if((sm_space = H5Screate_simple(1, &sm_nelmts, NULL)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Screate_simple failed");
|
|
|
|
if(H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &sm_nelmts, NULL) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sselect_hyperslab failed");
|
|
|
|
/* read the data */
|
|
if(H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Dread failed");
|
|
|
|
/* print the data */
|
|
flags = START_OF_DATA;
|
|
|
|
if (hyperslab_count == 1)
|
|
flags |= END_OF_DATA;
|
|
|
|
for (i = 0; i < ctx->ndims; i++)
|
|
ctx->p_max_idx[i] = ctx->p_min_idx[i] + MIN(total_size[i], sm_size[i]);
|
|
|
|
/* print array indices. get the lower bound of the hyperslab and calulate
|
|
the element position at the start of hyperslab */
|
|
if(H5Sget_select_bounds(f_space, low, high) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_select_bounds failed");
|
|
|
|
elmtno = 0;
|
|
for (i = 0; i < (size_t) ctx->ndims - 1; i++) {
|
|
hsize_t offset = 1; /* accumulation of the previous dimensions */
|
|
for (j = i + 1; j < (size_t) ctx->ndims; j++)
|
|
offset *= total_size[j];
|
|
elmtno += low[i] * offset;
|
|
}
|
|
elmtno += low[ctx->ndims - 1];
|
|
|
|
/* initialize the current stripmine position; this is necessary to print the array
|
|
indices */
|
|
ctx->sm_pos = elmtno;
|
|
|
|
h5tools_dump_simple_data(stream, info, dset, ctx, flags, sm_nelmts, p_type, sm_buf);
|
|
|
|
/* Reclaim any VL memory, if necessary */
|
|
if (vl_data)
|
|
H5Dvlen_reclaim(p_type, sm_space, H5P_DEFAULT, sm_buf);
|
|
|
|
if(H5Sclose(sm_space) < 0)
|
|
H5E_THROW(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
if(sm_buf)
|
|
HDfree(sm_buf);
|
|
sm_buf = NULL;
|
|
}
|
|
else
|
|
H5E_THROW(SUCCEED, H5E_tools_min_id_g, "nothing to print");
|
|
/* we need to jump to next line and update the index */
|
|
ctx->need_prefix = 1;
|
|
|
|
ctx->continuation++;
|
|
|
|
} /* hyperslab_count loop */
|
|
|
|
CATCH
|
|
if(sm_buf)
|
|
HDfree(sm_buf);
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: print out the data for a subset of a dataset.
|
|
* Description:
|
|
*
|
|
* Select a hyperslab from the dataset DSET using the parameters
|
|
* specified in SSET. Dump this out to STREAM.
|
|
*
|
|
* Hyperslabs select "count" blocks of size "block", spaced "stride" elements
|
|
* from each other, starting at coordinate "start".
|
|
*
|
|
* Return:
|
|
* On success, return SUCCEED. Otherwise, the function returns FAIL.
|
|
*
|
|
* Algorithm
|
|
*
|
|
* The parameters from SSET are translated into temporary
|
|
* variables so that 1 row is printed at a time (getting the coordinate indices
|
|
* at each row).
|
|
* We define the stride, count and block to be 1 in the row dimension to achieve
|
|
* this and advance until all points are printed.
|
|
*
|
|
* The element position is obtained from the matrix according to:
|
|
* Given an index I(z,y,x) its position from the beginning of an array
|
|
* of sizes A(size_z, size_y,size_x) is given by
|
|
* Position of I(z,y,x) = index_z * size_y * size_x
|
|
* + index_y * size_x
|
|
* + index_x
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
h5tools_display_simple_subset(FILE *stream, const h5tool_format_t *info, h5tools_context_t *ctx,
|
|
hid_t dset, hid_t p_type, struct subset_t *sset,
|
|
hid_t f_space, hsize_t *total_size)
|
|
{
|
|
size_t i; /* counters */
|
|
hsize_t n; /* counters */
|
|
hsize_t count; /* hyperslab count */
|
|
hsize_t outer_count; /* offset count */
|
|
unsigned int row_dim; /* index of row_counter dimension */
|
|
int current_outer_dim; /* dimension for start */
|
|
hsize_t temp_start[H5S_MAX_RANK];/* temporary start inside offset count loop */
|
|
hsize_t max_start[H5S_MAX_RANK]; /* maximum start inside offset count loop */
|
|
hsize_t temp_count[H5S_MAX_RANK];/* temporary count inside offset count loop */
|
|
hsize_t temp_block[H5S_MAX_RANK];/* temporary block size used in loop */
|
|
hsize_t temp_stride[H5S_MAX_RANK];/* temporary stride size used in loop */
|
|
int reset_dim;
|
|
herr_t ret_value = SUCCEED;
|
|
|
|
if (ctx->ndims == 1)
|
|
row_dim = 0;
|
|
else
|
|
row_dim = ctx->ndims - 2;
|
|
|
|
/* get the offset count */
|
|
outer_count = 1;
|
|
if (ctx->ndims > 2)
|
|
for (i = 0; i < (size_t) ctx->ndims - 2; i++) {
|
|
/* consider block size */
|
|
outer_count = outer_count * sset->count.data[i] * sset->block.data[i];
|
|
|
|
}
|
|
|
|
/* initialize temporary start, count and maximum start */
|
|
for (i = 0; i < (size_t) ctx->ndims; i++) {
|
|
temp_start[i] = sset->start.data[i];
|
|
temp_count[i] = sset->count.data[i];
|
|
temp_block[i] = sset->block.data[i];
|
|
temp_stride[i] = sset->stride.data[i];
|
|
max_start[i] = 0;
|
|
}
|
|
|
|
if (ctx->ndims > 2) {
|
|
for (i = 0; i < (size_t) ctx->ndims - 2; i++) {
|
|
max_start[i] = temp_start[i] + sset->count.data[i];
|
|
temp_count[i] = 1;
|
|
|
|
}
|
|
}
|
|
|
|
/* offset loop */
|
|
for (n = 0; n < outer_count; n++) {
|
|
/* number of read iterations in inner loop, read by rows, to match 2D display */
|
|
if (ctx->ndims > 1) {
|
|
|
|
/* count is the number of iterations to display all the rows,
|
|
the block size count times */
|
|
count = sset->count.data[row_dim] * sset->block.data[row_dim];
|
|
|
|
/* always 1 row_counter at a time, that is a block of size 1, 1 time */
|
|
temp_count[row_dim] = 1;
|
|
temp_block[row_dim] = 1;
|
|
|
|
/* advance 1 row_counter at a time */
|
|
if (sset->block.data[row_dim] > 1)
|
|
temp_stride[row_dim] = 1;
|
|
|
|
}
|
|
/* for the 1D case */
|
|
else {
|
|
count = 1;
|
|
}
|
|
|
|
h5tools_print_simple_subset(stream, info, ctx, dset, p_type, sset,
|
|
f_space, count, temp_start, temp_count,
|
|
temp_block, temp_stride, total_size, row_dim);
|
|
|
|
if (ctx->ndims > 2) {
|
|
/* dimension for start */
|
|
current_outer_dim = (ctx->ndims - 2) - 1;
|
|
|
|
/* set start to original from current_outer_dim up */
|
|
for (i = current_outer_dim + 1; i < ctx->ndims; i++) {
|
|
temp_start[i] = sset->start.data[i];
|
|
}
|
|
|
|
/* increment start dimension */
|
|
do {
|
|
reset_dim = 0;
|
|
temp_start[current_outer_dim]++;
|
|
if (temp_start[current_outer_dim] >= max_start[current_outer_dim]) {
|
|
temp_start[current_outer_dim] = sset->start.data[current_outer_dim];
|
|
|
|
/* consider block */
|
|
if (sset->block.data[current_outer_dim] > 1)
|
|
temp_start[current_outer_dim]++;
|
|
|
|
current_outer_dim--;
|
|
reset_dim = 1;
|
|
}
|
|
} while (current_outer_dim >= 0 && reset_dim);
|
|
|
|
} /* ctx.ndims > 1 */
|
|
|
|
} /* outer_count */
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Dump out a subset of a dataset.
|
|
* Description:
|
|
*
|
|
* Select a hyperslab from the dataset DSET using the parameters
|
|
* specified in SSET. Dump this out to STREAM.
|
|
*
|
|
* Hyperslabs select "count" blocks of size "block", spaced "stride" elements
|
|
* from each other, starting at coordinate "start".
|
|
*
|
|
* Return:
|
|
* On success, return SUCCEED. Otherwise, the function returns FAIL.
|
|
*
|
|
* Original programmer:
|
|
* Bill Wendling, Wednesday, March 07, 2001
|
|
*
|
|
* Rewritten with modified algorithm by:
|
|
* Pedro Vicente, Wednesday, January 16, 2008, contributions from Quincey Koziol
|
|
*
|
|
* Algorithm
|
|
*
|
|
* In a inner loop, the parameters from SSET are translated into temporary
|
|
* variables so that 1 row is printed at a time (getting the coordinate indices
|
|
* at each row).
|
|
* We define the stride, count and block to be 1 in the row dimension to achieve
|
|
* this and advance until all points are printed.
|
|
* An outer loop for cases where dimensionality is greater than 2D is made.
|
|
* In each iteration, the 2D block is displayed in the inner loop. The remaining
|
|
* slower dimensions above the first 2 are incremented one at a time in the outer loop
|
|
*
|
|
* The element position is obtained from the matrix according to:
|
|
* Given an index I(z,y,x) its position from the beginning of an array
|
|
* of sizes A(size_z, size_y,size_x) is given by
|
|
* Position of I(z,y,x) = index_z * size_y * size_x
|
|
* + index_y * size_x
|
|
* + index_x
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
h5tools_dump_simple_subset(FILE *stream, const h5tool_format_t *info, hid_t dset,
|
|
hid_t p_type, struct subset_t *sset, int indentlevel)
|
|
{
|
|
HERR_INIT(herr_t, SUCCEED)
|
|
int sndims;
|
|
hid_t f_space = -1; /* file data space */
|
|
size_t i; /* counters */
|
|
hsize_t total_size[H5S_MAX_RANK];/* total size of dataset*/
|
|
h5tools_context_t ctx; /* print context */
|
|
|
|
if((f_space = H5Dget_space(dset)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Dget_space failed");
|
|
|
|
/*
|
|
* check that everything looks okay. the dimensionality must not be too
|
|
* great and the dimensionality of the items selected for printing must
|
|
* match the dimensionality of the dataset.
|
|
*/
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
ctx.indent_level = indentlevel;
|
|
ctx.need_prefix = 1;
|
|
if((sndims = H5Sget_simple_extent_ndims(f_space)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
|
|
ctx.ndims = (unsigned)sndims;
|
|
|
|
/* assume entire data space to be printed */
|
|
if (ctx.ndims > 0)
|
|
for (i = 0; i < (size_t) ctx.ndims; i++)
|
|
ctx.p_min_idx[i] = 0;
|
|
|
|
if(H5Sget_simple_extent_dims(f_space, total_size, NULL) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
ctx.size_last_dim = total_size[ctx.ndims - 1];
|
|
|
|
h5tools_display_simple_subset(stream, info, &ctx, dset, p_type, sset, f_space, total_size);
|
|
|
|
/* Terminate the output */
|
|
if (ctx.cur_column) {
|
|
fputs(OPT(info->line_suf, ""), stdout);
|
|
putc('\n', stdout);
|
|
fputs(OPT(info->line_sep, ""), stdout);
|
|
}
|
|
|
|
CATCH
|
|
if(f_space >= 0 && H5Sclose(f_space) < 0)
|
|
H5E_THROW(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print some values from a dataset with a simple data space.
|
|
* Description:
|
|
* This is a special case of h5tools_dump_dset(). This function only
|
|
* intended for dumping datasets -- it does strip mining and some other
|
|
* things which are unnecessary for smaller objects such as attributes
|
|
* (to print small objects like attributes simply read the attribute and
|
|
* call h5tools_dump_simple_mem()).
|
|
* Return:
|
|
* On success, the function returns SUCCEED. Otherwise, the function
|
|
* returns FAIL.
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
h5tools_dump_simple_dset(FILE *stream, const h5tool_format_t *info,
|
|
hid_t dset, hid_t p_type, int indentlevel)
|
|
{
|
|
hid_t f_space; /* file data space */
|
|
hsize_t elmtno; /* counter */
|
|
size_t i; /* counter */
|
|
int carry; /* counter carry value */
|
|
hsize_t zero[8]; /* vector of zeros */
|
|
unsigned int flags; /* buffer extent flags */
|
|
hsize_t total_size[H5S_MAX_RANK]; /* total size of dataset*/
|
|
|
|
/* Print info */
|
|
h5tools_context_t ctx; /* print context */
|
|
size_t p_type_nbytes; /* size of memory type */
|
|
hsize_t p_nelmts; /* total selected elmts */
|
|
|
|
/* Stripmine info */
|
|
hsize_t sm_size[H5S_MAX_RANK]; /* stripmine size */
|
|
hsize_t sm_nbytes; /* bytes per stripmine */
|
|
hsize_t sm_nelmts; /* elements per stripmine*/
|
|
unsigned char *sm_buf = NULL; /* buffer for raw data */
|
|
hid_t sm_space; /* stripmine data space */
|
|
|
|
/* Hyperslab info */
|
|
hsize_t hs_offset[H5S_MAX_RANK]; /* starting offset */
|
|
hsize_t hs_size[H5S_MAX_RANK]; /* size this pass */
|
|
hsize_t hs_nelmts; /* elements in request */
|
|
|
|
/* VL data special information */
|
|
unsigned int vl_data = 0; /* contains VL datatypes */
|
|
|
|
f_space = H5Dget_space(dset);
|
|
|
|
if (f_space == FAIL)
|
|
return FAIL;
|
|
|
|
/*
|
|
* Check that everything looks okay. The dimensionality must not be too
|
|
* great and the dimensionality of the items selected for printing must
|
|
* match the dimensionality of the dataset.
|
|
*/
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
ctx.ndims = H5Sget_simple_extent_ndims(f_space);
|
|
|
|
if ((size_t)ctx.ndims > NELMTS(sm_size)) {
|
|
H5Sclose(f_space);
|
|
return FAIL;
|
|
}
|
|
|
|
ctx.indent_level = indentlevel;
|
|
ctx.need_prefix = 1;
|
|
|
|
/* Assume entire data space to be printed */
|
|
if (ctx.ndims > 0)
|
|
for (i = 0; i < (size_t)ctx.ndims; i++)
|
|
ctx.p_min_idx[i] = 0;
|
|
|
|
H5Sget_simple_extent_dims(f_space, total_size, NULL);
|
|
|
|
/* calculate the number of elements we're going to print */
|
|
p_nelmts = 1;
|
|
|
|
if (ctx.ndims > 0) {
|
|
for (i = 0; i < ctx.ndims; i++)
|
|
p_nelmts *= total_size[i];
|
|
ctx.size_last_dim = (total_size[ctx.ndims - 1]);
|
|
} /* end if */
|
|
else
|
|
ctx.size_last_dim = 0;
|
|
|
|
if (p_nelmts == 0) {
|
|
/* nothing to print */
|
|
H5Sclose(f_space);
|
|
return SUCCEED;
|
|
}
|
|
|
|
/* Check if we have VL data in the dataset's datatype */
|
|
if (h5tools_detect_vlen_str(p_type) == TRUE)
|
|
vl_data = TRUE;
|
|
if (H5Tdetect_class(p_type, H5T_VLEN) == TRUE)
|
|
vl_data = TRUE;
|
|
|
|
/*
|
|
* Determine the strip mine size and allocate a buffer. The strip mine is
|
|
* a hyperslab whose size is manageable.
|
|
*/
|
|
sm_nbytes = p_type_nbytes = H5Tget_size(p_type);
|
|
|
|
if (ctx.ndims > 0) {
|
|
for (i = ctx.ndims; i > 0; --i) {
|
|
hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes;
|
|
if ( size == 0) /* datum size > H5TOOLS_BUFSIZE */
|
|
size = 1;
|
|
sm_size[i - 1] = MIN(total_size[i - 1], size);
|
|
sm_nbytes *= sm_size[i - 1];
|
|
assert(sm_nbytes > 0);
|
|
}
|
|
}
|
|
|
|
if(!sm_nbytes)
|
|
goto done;
|
|
|
|
assert(sm_nbytes == (hsize_t)((size_t)sm_nbytes)); /*check for overflow*/
|
|
sm_buf = (unsigned char *)HDmalloc((size_t)sm_nbytes);
|
|
|
|
sm_nelmts = sm_nbytes / p_type_nbytes;
|
|
sm_space = H5Screate_simple(1, &sm_nelmts, NULL);
|
|
|
|
if (ctx.ndims > 0)
|
|
init_acc_pos(&ctx, total_size);
|
|
|
|
/* The stripmine loop */
|
|
memset(hs_offset, 0, sizeof hs_offset);
|
|
memset(zero, 0, sizeof zero);
|
|
|
|
for (elmtno = 0; elmtno < p_nelmts; elmtno += hs_nelmts) {
|
|
/* Calculate the hyperslab size */
|
|
if (ctx.ndims > 0) {
|
|
for (i = 0, hs_nelmts = 1; i < ctx.ndims; i++) {
|
|
hs_size[i] = MIN(total_size[i] - hs_offset[i], sm_size[i]);
|
|
ctx.p_max_idx[i] = ctx.p_min_idx[i] + hs_size[i];
|
|
hs_nelmts *= hs_size[i];
|
|
}
|
|
|
|
H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL);
|
|
H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &hs_nelmts, NULL);
|
|
}
|
|
else {
|
|
H5Sselect_all(f_space);
|
|
H5Sselect_all(sm_space);
|
|
hs_nelmts = 1;
|
|
}
|
|
|
|
/* Read the data */
|
|
if (H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf) < 0) {
|
|
H5Sclose(f_space);
|
|
H5Sclose(sm_space);
|
|
free(sm_buf);
|
|
return FAIL;
|
|
}
|
|
|
|
/* Print the data */
|
|
flags = (elmtno == 0) ? START_OF_DATA : 0;
|
|
flags |= ((elmtno + hs_nelmts) >= p_nelmts) ? END_OF_DATA : 0;
|
|
|
|
/* initialize the current stripmine position; this is necessary to print the array
|
|
indices */
|
|
ctx.sm_pos = elmtno;
|
|
|
|
h5tools_dump_simple_data(stream, info, dset, &ctx, flags, hs_nelmts, p_type, sm_buf);
|
|
|
|
/* Reclaim any VL memory, if necessary */
|
|
if (vl_data)
|
|
H5Dvlen_reclaim(p_type, sm_space, H5P_DEFAULT, sm_buf);
|
|
|
|
/* Calculate the next hyperslab offset */
|
|
for (i = ctx.ndims, carry = 1; i > 0 && carry; --i) {
|
|
ctx.p_min_idx[i - 1] = ctx.p_max_idx[i - 1];
|
|
hs_offset[i - 1] += hs_size[i - 1];
|
|
|
|
if (hs_offset[i - 1] == total_size[i - 1])
|
|
hs_offset[i - 1] = 0;
|
|
else
|
|
carry = 0;
|
|
}
|
|
|
|
ctx.continuation++;
|
|
}
|
|
|
|
/* Terminate the output */
|
|
if (ctx.cur_column) {
|
|
fputs(OPT(info->line_suf, ""), stream);
|
|
putc('\n', stream);
|
|
fputs(OPT(info->line_sep, ""), stream);
|
|
}
|
|
|
|
HDfree(sm_buf);
|
|
|
|
done:
|
|
H5Sclose(sm_space);
|
|
H5Sclose(f_space);
|
|
|
|
return SUCCEED;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_dump_simple_mem
|
|
*
|
|
* Purpose: Print some values from memory with a simple data space.
|
|
* This is a special case of h5tools_dump_mem().
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
h5tools_dump_simple_mem(FILE *stream, const h5tool_format_t *info, hid_t obj_id,
|
|
hid_t type, hid_t space, void *mem, int indentlevel)
|
|
{
|
|
int i; /*counters */
|
|
hsize_t nelmts; /*total selected elmts */
|
|
h5tools_context_t ctx; /*printing context */
|
|
|
|
/*
|
|
* Check that everything looks okay. The dimensionality must not be too
|
|
* great and the dimensionality of the items selected for printing must
|
|
* match the dimensionality of the dataset.
|
|
*/
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
ctx.ndims = H5Sget_simple_extent_ndims(space);
|
|
|
|
if ((size_t) ctx.ndims > NELMTS(ctx.p_min_idx))
|
|
return FAIL;
|
|
|
|
ctx.indent_level = indentlevel;
|
|
ctx.need_prefix = 1;
|
|
|
|
/* Assume entire data space to be printed */
|
|
for (i = 0; i < ctx.ndims; i++)
|
|
ctx.p_min_idx[i] = 0;
|
|
|
|
H5Sget_simple_extent_dims(space, ctx.p_max_idx, NULL);
|
|
|
|
for (i = 0, nelmts = 1; ctx.ndims != 0 && i < ctx.ndims; i++)
|
|
nelmts *= ctx.p_max_idx[i] - ctx.p_min_idx[i];
|
|
|
|
if (nelmts == 0)
|
|
return SUCCEED; /*nothing to print*/
|
|
if (ctx.ndims > 0) {
|
|
assert(ctx.p_max_idx[ctx.ndims - 1] == (hsize_t) ((int) ctx.p_max_idx[ctx.ndims - 1]));
|
|
ctx.size_last_dim = (int) (ctx.p_max_idx[ctx.ndims - 1]);
|
|
} /* end if */
|
|
else
|
|
ctx.size_last_dim = 0;
|
|
|
|
if (ctx.ndims > 0)
|
|
init_acc_pos(&ctx, ctx.p_max_idx);
|
|
|
|
/* Print it */
|
|
h5tools_dump_simple_data(stream, info, obj_id, &ctx, START_OF_DATA | END_OF_DATA, nelmts, type, mem);
|
|
|
|
/* Terminate the output */
|
|
if (ctx.cur_column) {
|
|
fputs(OPT(info->line_suf, ""), stream);
|
|
putc('\n', stream);
|
|
fputs(OPT(info->line_sep, ""), stream);
|
|
}
|
|
|
|
return SUCCEED;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_dump_dset
|
|
*
|
|
* Purpose: Print some values from a dataset DSET to the file STREAM
|
|
* after converting all types to P_TYPE (which should be a
|
|
* native type). If P_TYPE is a negative value then it will be
|
|
* computed from the dataset type using only native types.
|
|
*
|
|
* Note: This function is intended only for datasets since it does
|
|
* some things like strip mining which are unnecessary for
|
|
* smaller objects such as attributes. The easiest way to print
|
|
* small objects is to read the object into memory and call
|
|
* h5tools_dump_mem().
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
*
|
|
* Modifications:
|
|
* Robb Matzke, 1999-06-07
|
|
* If info->raw is set then the memory datatype will be the same
|
|
* as the file datatype.
|
|
*
|
|
* Bill Wendling, 2001-02-27
|
|
* Renamed to ``h5tools_dump_dset'' and added the subsetting
|
|
* parameter.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
h5tools_dump_dset(FILE *stream, const h5tool_format_t *info, hid_t dset,
|
|
hid_t _p_type, struct subset_t *sset, int indentlevel)
|
|
{
|
|
hid_t f_space;
|
|
hid_t p_type = _p_type;
|
|
hid_t f_type;
|
|
H5S_class_t space_type;
|
|
int status = FAIL;
|
|
h5tool_format_t info_dflt;
|
|
/* Use default values */
|
|
if (!stream)
|
|
stream = stdout;
|
|
|
|
if (!info) {
|
|
memset(&info_dflt, 0, sizeof info_dflt);
|
|
info = &info_dflt;
|
|
}
|
|
|
|
if (p_type < 0) {
|
|
f_type = H5Dget_type(dset);
|
|
|
|
if (info->raw || bin_form == 1)
|
|
p_type = H5Tcopy(f_type);
|
|
else if (bin_form == 2)
|
|
p_type = h5tools_get_little_endian_type(f_type);
|
|
else if (bin_form == 3)
|
|
p_type = h5tools_get_big_endian_type(f_type);
|
|
else
|
|
p_type = h5tools_get_native_type(f_type);
|
|
|
|
H5Tclose(f_type);
|
|
|
|
if (p_type < 0)
|
|
goto done;
|
|
}
|
|
|
|
/* Check the data space */
|
|
f_space = H5Dget_space(dset);
|
|
|
|
space_type = H5Sget_simple_extent_type(f_space);
|
|
|
|
/* Print the data */
|
|
if (space_type == H5S_SIMPLE || space_type == H5S_SCALAR) {
|
|
if(!sset)
|
|
status = h5tools_dump_simple_dset(rawdatastream, info, dset, p_type, indentlevel);
|
|
else
|
|
status = h5tools_dump_simple_subset(rawdatastream, info, dset, p_type, sset, indentlevel);
|
|
}
|
|
else
|
|
/* space is H5S_NULL */
|
|
status = SUCCEED;
|
|
|
|
/* Close the dataspace */
|
|
H5Sclose(f_space);
|
|
|
|
done:
|
|
if (p_type != _p_type)
|
|
H5Tclose(p_type);
|
|
|
|
return status;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_dump_mem
|
|
*
|
|
* Purpose: Displays the data contained in MEM. MEM must have the
|
|
* specified data TYPE and SPACE. Currently only simple data
|
|
* spaces are allowed and only the `all' selection.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
h5tools_dump_mem(FILE *stream, const h5tool_format_t *info, hid_t obj_id, hid_t type,
|
|
hid_t space, void *mem, int indentlevel)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
h5tool_format_t info_dflt;
|
|
|
|
/* Use default values */
|
|
if (!stream)
|
|
stream = stdout;
|
|
|
|
if (!info) {
|
|
memset(&info_dflt, 0, sizeof(info_dflt));
|
|
info = &info_dflt;
|
|
}
|
|
|
|
/* Check the data space */
|
|
if (H5Sis_simple(space) <= 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sis_simple failed")
|
|
|
|
H5_LEAVE(h5tools_dump_simple_mem(stream, info, obj_id, type, space, mem, indentlevel))
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: print_datatype
|
|
*
|
|
* Purpose: print the datatype.
|
|
*
|
|
* Return: void
|
|
*
|
|
* In/Out: h5tools_str_t *buffer
|
|
* h5tools_context_t *ctx
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
h5tools_print_datatype(h5tools_str_t *buffer, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, hid_t type)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
char *mname;
|
|
hid_t mtype, str_type;
|
|
int snmembers;
|
|
unsigned nmembers;
|
|
int sndims;
|
|
unsigned i;
|
|
size_t size = 0;
|
|
hsize_t dims[H5TOOLS_DUMP_MAX_RANK];
|
|
H5T_str_t str_pad;
|
|
H5T_cset_t cset;
|
|
H5T_order_t order;
|
|
H5T_class_t type_class;
|
|
hid_t super;
|
|
hid_t tmp_type;
|
|
htri_t is_vlstr = FALSE;
|
|
const char *order_s = NULL; /* byte order string */
|
|
H5T_sign_t sign; /* sign scheme value */
|
|
const char *sign_s = NULL; /* sign scheme string */
|
|
|
|
if((type_class = H5Tget_class(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_class failed");
|
|
switch (type_class) {
|
|
case H5T_INTEGER:
|
|
if (H5Tequal(type, H5T_STD_I8BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I8BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I8LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I8LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I16BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I16BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I16LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I16LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I32BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I32BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I32LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I32LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I64BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I64BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_I64LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_I64LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U8BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U8BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U8LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U8LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U16BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U16BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U16LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U16LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U32BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U32BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U32LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U32LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U64BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U64BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_U64LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_U64LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_SCHAR) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_SCHAR");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_UCHAR) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_UCHAR");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_SHORT) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_SHORT");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_USHORT) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_USHORT");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_INT) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_INT");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_UINT) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_UINT");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_LONG) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_LONG");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_ULONG) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_ULONG");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_LLONG) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_LLONG");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_ULLONG) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_ULLONG");
|
|
}
|
|
else {
|
|
|
|
/* byte order */
|
|
if (H5Tget_size(type) > 1) {
|
|
order = H5Tget_order(type);
|
|
if (H5T_ORDER_LE == order) {
|
|
order_s = " little-endian";
|
|
}
|
|
else if (H5T_ORDER_BE == order) {
|
|
order_s = " big-endian";
|
|
}
|
|
else if (H5T_ORDER_VAX == order) {
|
|
order_s = " mixed-endian";
|
|
}
|
|
else {
|
|
order_s = " unknown-byte-order";
|
|
}
|
|
}
|
|
else {
|
|
order_s = "";
|
|
}
|
|
|
|
/* sign */
|
|
if ((sign = H5Tget_sign(type)) >= 0) {
|
|
if (H5T_SGN_NONE == sign) {
|
|
sign_s = " unsigned";
|
|
}
|
|
else if (H5T_SGN_2 == sign) {
|
|
sign_s = "";
|
|
}
|
|
else {
|
|
sign_s = " unknown-sign";
|
|
}
|
|
}
|
|
else {
|
|
sign_s = " unknown-sign";
|
|
}
|
|
|
|
/* print size, order, and sign */
|
|
h5tools_str_append(buffer, "%lu-bit%s%s integer",
|
|
(unsigned long) (8 * H5Tget_size(type)), order_s, sign_s);
|
|
}
|
|
break;
|
|
|
|
case H5T_FLOAT:
|
|
if (H5Tequal(type, H5T_IEEE_F32BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_IEEE_F32BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_IEEE_F32LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_IEEE_F32LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_IEEE_F64BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_IEEE_F64BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_IEEE_F64LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_IEEE_F64LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_VAX_F32) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_VAX_F32");
|
|
}
|
|
else if (H5Tequal(type, H5T_VAX_F64) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_VAX_F64");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_FLOAT) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_FLOAT");
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_DOUBLE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_DOUBLE");
|
|
#if H5_SIZEOF_LONG_DOUBLE !=0
|
|
}
|
|
else if (H5Tequal(type, H5T_NATIVE_LDOUBLE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_NATIVE_LDOUBLE");
|
|
#endif
|
|
}
|
|
else {
|
|
|
|
/* byte order */
|
|
if (H5Tget_size(type) > 1) {
|
|
order = H5Tget_order(type);
|
|
if (H5T_ORDER_LE == order) {
|
|
order_s = " little-endian";
|
|
}
|
|
else if (H5T_ORDER_BE == order) {
|
|
order_s = " big-endian";
|
|
}
|
|
else if (H5T_ORDER_VAX == order) {
|
|
order_s = " mixed-endian";
|
|
}
|
|
else {
|
|
order_s = " unknown-byte-order";
|
|
}
|
|
}
|
|
else {
|
|
order_s = "";
|
|
}
|
|
|
|
/* print size and byte order */
|
|
h5tools_str_append(buffer, "%lu-bit%s floating-point",
|
|
(unsigned long) (8 * H5Tget_size(type)), order_s);
|
|
|
|
}
|
|
break;
|
|
|
|
case H5T_TIME:
|
|
h5tools_str_append(buffer, "H5T_TIME: not yet implemented");
|
|
break;
|
|
|
|
case H5T_STRING:
|
|
/* Make a copy of type in memory in case when TYPE is on disk, the size
|
|
* will be bigger than in memory. This makes it easier to compare
|
|
* types in memory. */
|
|
tmp_type = H5Tcopy(type);
|
|
size = H5Tget_size(tmp_type);
|
|
str_pad = H5Tget_strpad(tmp_type);
|
|
cset = H5Tget_cset(tmp_type);
|
|
is_vlstr = H5Tis_variable_str(tmp_type);
|
|
|
|
h5tools_str_append(buffer, "H5T_STRING %s\n", h5tools_dump_header_format->strblockbegin);
|
|
ctx->indent_level++;
|
|
|
|
if (is_vlstr)
|
|
h5tools_str_append(buffer, "%s H5T_VARIABLE;\n", STRSIZE);
|
|
else
|
|
h5tools_str_append(buffer, "%s %d;\n", STRSIZE, (int) size);
|
|
|
|
h5tools_str_append(buffer, "%s ", STRPAD);
|
|
if (str_pad == H5T_STR_NULLTERM)
|
|
h5tools_str_append(buffer, "H5T_STR_NULLTERM;\n");
|
|
else if (str_pad == H5T_STR_NULLPAD)
|
|
h5tools_str_append(buffer, "H5T_STR_NULLPAD;\n");
|
|
else if (str_pad == H5T_STR_SPACEPAD)
|
|
h5tools_str_append(buffer, "H5T_STR_SPACEPAD;\n");
|
|
else
|
|
h5tools_str_append(buffer, "H5T_STR_ERROR;\n");
|
|
|
|
h5tools_str_append(buffer, "%s ", CSET);
|
|
|
|
if (cset == H5T_CSET_ASCII)
|
|
h5tools_str_append(buffer, "H5T_CSET_ASCII;\n");
|
|
else
|
|
h5tools_str_append(buffer, "unknown_cset;\n");
|
|
|
|
str_type = H5Tcopy(H5T_C_S1);
|
|
if (is_vlstr)
|
|
H5Tset_size(str_type, H5T_VARIABLE);
|
|
else
|
|
H5Tset_size(str_type, size);
|
|
H5Tset_cset(str_type, cset);
|
|
H5Tset_strpad(str_type, str_pad);
|
|
|
|
h5tools_str_append(buffer, "%s ", CTYPE);
|
|
|
|
/* Check C variable-length string first. Are the two types equal? */
|
|
if (H5Tequal(tmp_type, str_type)) {
|
|
h5tools_str_append(buffer, "H5T_C_S1;\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Change the endianness and see if they're equal. */
|
|
order = H5Tget_order(tmp_type);
|
|
if (order == H5T_ORDER_LE)
|
|
H5Tset_order(str_type, H5T_ORDER_LE);
|
|
else if (order == H5T_ORDER_BE)
|
|
H5Tset_order(str_type, H5T_ORDER_BE);
|
|
|
|
if (H5Tequal(tmp_type, str_type)) {
|
|
h5tools_str_append(buffer, "H5T_C_S1;\n");
|
|
goto done;
|
|
}
|
|
|
|
/* If not equal to C variable-length string, check Fortran type. */
|
|
if(H5Tclose(str_type) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
str_type = H5Tcopy(H5T_FORTRAN_S1);
|
|
|
|
H5Tset_cset(str_type, cset);
|
|
H5Tset_size(str_type, size);
|
|
H5Tset_strpad(str_type, str_pad);
|
|
|
|
/* Are the two types equal? */
|
|
if (H5Tequal(tmp_type, str_type)) {
|
|
h5tools_str_append(buffer, "H5T_FORTRAN_S1;\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Change the endianness and see if they're equal. */
|
|
order = H5Tget_order(tmp_type);
|
|
if (order == H5T_ORDER_LE)
|
|
H5Tset_order(str_type, H5T_ORDER_LE);
|
|
else if (order == H5T_ORDER_BE)
|
|
H5Tset_order(str_type, H5T_ORDER_BE);
|
|
|
|
if (H5Tequal(tmp_type, str_type)) {
|
|
h5tools_str_append(buffer, "H5T_FORTRAN_S1;\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Type doesn't match any of above. */
|
|
h5tools_str_append(buffer, "unknown_one_character_type;\n ");
|
|
|
|
done:
|
|
if(H5Tclose(str_type) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
if(H5Tclose(tmp_type) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
ctx->indent_level--;
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->strblockend);
|
|
break;
|
|
|
|
case H5T_BITFIELD:
|
|
if (H5Tequal(type, H5T_STD_B8BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B8BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B8LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B8LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B16BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B16BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B16LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B16LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B32BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B32BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B32LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B32LE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B64BE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B64BE");
|
|
}
|
|
else if (H5Tequal(type, H5T_STD_B64LE) == TRUE) {
|
|
h5tools_str_append(buffer, "H5T_STD_B64LE");
|
|
}
|
|
else {
|
|
h5tools_str_append(buffer, "undefined bitfield");
|
|
}
|
|
break;
|
|
|
|
case H5T_OPAQUE:
|
|
h5tools_str_append(buffer, "\n");
|
|
h5tools_str_append(buffer, "H5T_OPAQUE;\n");
|
|
{
|
|
char *ttag = H5Tget_tag(type);
|
|
h5tools_str_append(buffer, "OPAQUE_TAG \"%s\";\n", ttag);
|
|
if (ttag)
|
|
HDfree(ttag);
|
|
}
|
|
break;
|
|
|
|
case H5T_COMPOUND:
|
|
if((snmembers = H5Tget_nmembers(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed");
|
|
nmembers = (unsigned)snmembers;
|
|
|
|
h5tools_str_append(buffer, "H5T_COMPOUND %s\n", h5tools_dump_header_format->structblockbegin);
|
|
|
|
for (i = 0; i < nmembers; i++) {
|
|
mname = H5Tget_member_name(type, i);
|
|
if((mtype = H5Tget_member_type(type, i))>=0) {
|
|
if (H5Tget_class(mtype) == H5T_COMPOUND)
|
|
ctx->indent_level++;
|
|
|
|
h5tools_print_datatype(buffer, info, ctx, mtype);
|
|
|
|
if (H5Tget_class(mtype) == H5T_COMPOUND)
|
|
ctx->indent_level--;
|
|
|
|
h5tools_str_append(buffer, " \"%s\";\n", mname);
|
|
if(H5Tclose(mtype) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
}
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tget_member_type failed");
|
|
free(mname);
|
|
}
|
|
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->structblockend);
|
|
break;
|
|
|
|
case H5T_REFERENCE:
|
|
h5tools_str_append(buffer, "H5T_REFERENCE");
|
|
if(region_output) {
|
|
if (H5Tequal(type, H5T_STD_REF_DSETREG) == TRUE) {
|
|
h5tools_str_append(buffer, " { H5T_STD_REF_DSETREG }");
|
|
}
|
|
else {
|
|
h5tools_str_append(buffer, " { H5T_STD_REF_OBJECT }");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H5T_ENUM:
|
|
if((super = H5Tget_super(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed");
|
|
|
|
h5tools_str_append(buffer, "H5T_ENUM %s\n", h5tools_dump_header_format->enumblockbegin);
|
|
ctx->indent_level++;
|
|
|
|
h5tools_print_datatype(buffer, info, ctx, super);
|
|
if(H5Tclose(super) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
h5tools_str_append(buffer, ";\n");
|
|
h5tools_print_enum(buffer, type);
|
|
|
|
ctx->indent_level--;
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->enumblockend);
|
|
|
|
break;
|
|
|
|
case H5T_VLEN:
|
|
if((super = H5Tget_super(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed");
|
|
|
|
h5tools_str_append(buffer, "H5T_VLEN %s ", h5tools_dump_header_format->vlenblockbegin);
|
|
|
|
h5tools_print_datatype(buffer, info, ctx, super);
|
|
if(H5Tclose(super) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
h5tools_str_append(buffer, "%s", h5tools_dump_header_format->vlenblockend);
|
|
|
|
break;
|
|
|
|
case H5T_ARRAY:
|
|
h5tools_str_append(buffer, "H5T_ARRAY { ");
|
|
|
|
/* Get array information */
|
|
if((sndims = H5Tget_array_ndims(type)) >= 0) {
|
|
unsigned ndims = (unsigned)sndims;
|
|
|
|
if(H5Tget_array_dims2(type, dims) >= 0) {
|
|
/* Print array dimensions */
|
|
for (i = 0; i < ndims; i++)
|
|
h5tools_str_append(buffer, "[%d]", (int) dims[i]);
|
|
|
|
h5tools_str_append(buffer, " ");
|
|
}
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tget_array_dims2 failed");
|
|
}
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tget_array_ndims failed");
|
|
|
|
/* Get array base type */
|
|
if((super = H5Tget_super(type)) >= 0) {
|
|
/* Print base type */
|
|
h5tools_print_datatype(buffer, info, ctx, super);
|
|
/* Close array base type */
|
|
if(H5Tclose(super) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
}
|
|
else
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tget_super failed");
|
|
|
|
h5tools_str_append(buffer, " }");
|
|
|
|
break;
|
|
|
|
default:
|
|
h5tools_str_append(buffer, "unknown datatype");
|
|
break;
|
|
}
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: print_dataspace
|
|
*
|
|
* Purpose: print the dataspace.
|
|
*
|
|
* Return: void
|
|
*
|
|
* In/Out: h5tools_str_t *buffer
|
|
* h5tools_context_t *ctx
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
h5tools_print_dataspace(h5tools_str_t *buffer, hid_t space)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
hsize_t size[H5TOOLS_DUMP_MAX_RANK];
|
|
hsize_t maxsize[H5TOOLS_DUMP_MAX_RANK];
|
|
int ndims = -1;
|
|
H5S_class_t space_type = -1;
|
|
int i;
|
|
|
|
if((ndims = H5Sget_simple_extent_dims(space, size, maxsize)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
|
|
if((space_type = H5Sget_simple_extent_type(space)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_type failed");
|
|
|
|
switch(space_type) {
|
|
case H5S_SCALAR:
|
|
/* scalar dataspace */
|
|
h5tools_str_append(buffer, "%s %s", h5tools_dump_header_format->dataspacedescriptionbegin, S_SCALAR);
|
|
break;
|
|
|
|
case H5S_SIMPLE:
|
|
/* simple dataspace */
|
|
h5tools_str_append(buffer, "%s %s { %s %" H5_PRINTF_LL_WIDTH "u",
|
|
h5tools_dump_header_format->dataspacedescriptionbegin, S_SIMPLE,
|
|
h5tools_dump_header_format->dataspacedimbegin, size[0]);
|
|
|
|
for(i = 1; i < ndims; i++)
|
|
h5tools_str_append(buffer, ", %" H5_PRINTF_LL_WIDTH "u", size[i]);
|
|
|
|
h5tools_str_append(buffer, " %s / ", h5tools_dump_header_format->dataspacedimend);
|
|
|
|
if(maxsize[0] == H5S_UNLIMITED)
|
|
h5tools_str_append(buffer, "%s %s",
|
|
h5tools_dump_header_format->dataspacedimbegin, "H5S_UNLIMITED");
|
|
else
|
|
h5tools_str_append(buffer, "%s %" H5_PRINTF_LL_WIDTH "u",
|
|
h5tools_dump_header_format->dataspacedimbegin, maxsize[0]);
|
|
|
|
for(i = 1; i < ndims; i++)
|
|
if(maxsize[i] == H5S_UNLIMITED)
|
|
h5tools_str_append(buffer, ", %s", "H5S_UNLIMITED");
|
|
else
|
|
h5tools_str_append(buffer, ", %" H5_PRINTF_LL_WIDTH "u", maxsize[i]);
|
|
|
|
h5tools_str_append(buffer, " %s }", h5tools_dump_header_format->dataspacedimend);
|
|
break;
|
|
|
|
case H5S_NULL:
|
|
/* null dataspace */
|
|
h5tools_str_append(buffer, "%s %s", h5tools_dump_header_format->dataspacedescriptionbegin, S_NULL);
|
|
break;
|
|
|
|
case H5S_NO_CLASS:
|
|
default:
|
|
h5tools_str_append(buffer, "%s unknown dataspace %s\n", BEGIN, END);
|
|
break;
|
|
} /* end switch */
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: print_enum
|
|
*
|
|
* Purpose: prints the enum data
|
|
*
|
|
* Return: void
|
|
*
|
|
* In/Out: h5tools_str_t *buffer
|
|
* h5tools_context_t *ctx
|
|
*
|
|
*-----------------------------------------------------------------------*/
|
|
int
|
|
h5tools_print_enum(h5tools_str_t *buffer, hid_t type)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
char **name = NULL; /*member names */
|
|
unsigned char *value = NULL; /*value array */
|
|
unsigned char *copy = NULL; /*a pointer to value array */
|
|
unsigned nmembs = 0; /*number of members */
|
|
int nchars; /*number of output characters */
|
|
hid_t super = -1; /*enum base integer type */
|
|
hid_t native = -1; /*native integer datatype */
|
|
H5T_sign_t sign_type; /*sign of value type */
|
|
size_t type_size; /*value type size */
|
|
size_t dst_size; /*destination value type size */
|
|
int snmembs;
|
|
unsigned i;
|
|
|
|
if((snmembs = H5Tget_nmembers(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed");
|
|
nmembs = (unsigned)snmembs;
|
|
assert(nmembs > 0);
|
|
|
|
if((super = H5Tget_super(type)) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_super failed");
|
|
|
|
if((type_size = H5Tget_size(type)) <= 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_size(type) failed");
|
|
|
|
/*
|
|
* 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(type_size <= sizeof(long long)) {
|
|
dst_size = sizeof(long long);
|
|
|
|
if((sign_type = H5Tget_sign(type))<0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_sign failed");
|
|
if(H5T_SGN_NONE == sign_type)
|
|
native = H5T_NATIVE_ULLONG;
|
|
else
|
|
native = H5T_NATIVE_LLONG;
|
|
} /* end if */
|
|
else
|
|
dst_size = type_size;
|
|
|
|
/* Get the names and raw values of all members */
|
|
if(NULL == (name = (char **)HDcalloc(nmembs, sizeof(char *))))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for member name");
|
|
if(NULL == (value = (unsigned char *)HDcalloc(nmembs, MAX(type_size, dst_size))))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for member value");
|
|
|
|
for (i = 0; i < nmembs; i++) {
|
|
name[i] = H5Tget_member_name(type, i);
|
|
if(H5Tget_member_value(type, i, value + i * type_size) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_member_value failed");
|
|
}
|
|
|
|
/* Convert values to native datatype */
|
|
if (native > 0)
|
|
if(H5Tconvert(super, native, nmembs, value, NULL, H5P_DEFAULT) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tconvert failed");
|
|
|
|
/*
|
|
* Sort members by increasing value
|
|
* ***not implemented yet***
|
|
*/
|
|
|
|
/* Print members */
|
|
for (i = 0; i < nmembs; i++) {
|
|
h5tools_str_append(buffer, "\"%s\"", name[i]);
|
|
nchars = strlen(name[i]);
|
|
h5tools_str_append(buffer, "%*s ", MAX(0, 16 - nchars), "");
|
|
|
|
if (native < 0) {
|
|
size_t j;
|
|
|
|
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)) {
|
|
/*On SGI Altix(cobalt), wrong values were printed out with "value+i*dst_size"
|
|
*strangely, unless use another pointer "copy".*/
|
|
copy = value + i * dst_size;
|
|
h5tools_str_append(buffer, "%" H5_PRINTF_LL_WIDTH "u", *((unsigned long long *) ((void *) copy)));
|
|
}
|
|
else {
|
|
/*On SGI Altix(cobalt), wrong values were printed out with "value+i*dst_size"
|
|
*strangely, unless use another pointer "copy".*/
|
|
copy = value + i * dst_size;
|
|
h5tools_str_append(buffer, "%" H5_PRINTF_LL_WIDTH "d", *((long long *) ((void *) copy)));
|
|
}
|
|
|
|
h5tools_str_append(buffer, ";\n");
|
|
}
|
|
|
|
CATCH
|
|
if(name) {
|
|
/* Release resources */
|
|
for(i = 0; i < nmembs; i++)
|
|
if(name[i])
|
|
free(name[i]);
|
|
free(name);
|
|
} /* end if */
|
|
|
|
if(value)
|
|
free(value);
|
|
|
|
if(super >= 0 && H5Tclose(super) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "Could not close datatype's super class");
|
|
|
|
if(0 == nmembs)
|
|
h5tools_str_append(buffer, "\n<empty>");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: dump_datatype
|
|
*
|
|
* Purpose: Dump the datatype. Datatype can be HDF5 predefined
|
|
* atomic datatype or committed/transient datatype.
|
|
*
|
|
* Return: void
|
|
*
|
|
* In/Out: h5tools_context_t *ctx
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
h5tools_dump_datatype(FILE *stream, const h5tool_format_t *info,
|
|
h5tools_context_t *ctx, hid_t type)
|
|
{
|
|
size_t ncols = 80; /* available output width */
|
|
h5tools_str_t buffer; /* string into which to render */
|
|
hsize_t curr_pos; /* total data element position */
|
|
hsize_t elmt_counter = 0;/* counts the # elements printed.*/
|
|
|
|
/* setup */
|
|
HDmemset(&buffer, 0, sizeof(h5tools_str_t));
|
|
|
|
if (info->line_ncols > 0)
|
|
ncols = info->line_ncols;
|
|
|
|
/* pass to the prefix in h5tools_simple_prefix the total position
|
|
* instead of the current stripmine position i; this is necessary
|
|
* to print the array indices
|
|
*/
|
|
curr_pos = ctx->sm_pos;
|
|
|
|
h5tools_simple_prefix(stream, info, ctx, curr_pos, 0);
|
|
/* Render the element */
|
|
h5tools_str_reset(&buffer);
|
|
|
|
ctx->indent_level++;
|
|
h5tools_str_append(&buffer, "%s %s ",
|
|
h5tools_dump_header_format->datatypebegin,
|
|
h5tools_dump_header_format->datatypeblockbegin);
|
|
|
|
h5tools_print_datatype(&buffer, info, ctx, type);
|
|
|
|
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_str_append(&buffer, "\n");
|
|
|
|
curr_pos = h5tools_render_element(stream, info, ctx, &buffer, &curr_pos,
|
|
ncols, elmt_counter, 0);
|
|
|
|
ctx->need_prefix = TRUE;
|
|
ctx->indent_level--;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: init_acc_pos
|
|
*
|
|
* Purpose: initialize accumulator and matrix position
|
|
*
|
|
* Return: void
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
init_acc_pos(h5tools_context_t *ctx, hsize_t *dims)
|
|
{
|
|
int i;
|
|
|
|
assert(ctx->ndims);
|
|
|
|
ctx->acc[ctx->ndims - 1] = 1;
|
|
for (i = (ctx->ndims - 2); i >= 0; i--) {
|
|
ctx->acc[i] = ctx->acc[i + 1] * dims[i + 1];
|
|
}
|
|
for (i = 0; i < ctx->ndims; i++)
|
|
ctx->pos[i] = 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: do_bin_output
|
|
*
|
|
* Purpose: Dump memory buffer to a binary file stream
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static
|
|
int do_bin_output(FILE *stream, hid_t container, hsize_t nelmts, hid_t tid, void *_mem)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
unsigned char *mem = (unsigned char*)_mem;
|
|
size_t size; /* datum size */
|
|
hsize_t i; /* element counter */
|
|
|
|
if((size = H5Tget_size(tid)) == 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
for (i = 0; i < nelmts; i++) {
|
|
if (render_bin_output(stream, container, tid, mem + i * size) < 0) {
|
|
printf("\nError in writing binary stream\n");
|
|
return FAIL;
|
|
}
|
|
}
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: render_bin_output
|
|
*
|
|
* Purpose: Write one element of memory buffer to a binary file stream
|
|
*
|
|
* Return: Success: SUCCEED
|
|
* Failure: FAIL
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem)
|
|
{
|
|
HERR_INIT(int, SUCCEED)
|
|
unsigned char *mem = (unsigned char*)_mem;
|
|
size_t size; /* datum size */
|
|
float tempfloat;
|
|
double tempdouble;
|
|
unsigned long long tempullong;
|
|
long long templlong;
|
|
unsigned long tempulong;
|
|
long templong;
|
|
unsigned int tempuint;
|
|
int tempint;
|
|
unsigned short tempushort;
|
|
short tempshort;
|
|
unsigned char tempuchar;
|
|
char tempschar;
|
|
#if H5_SIZEOF_LONG_DOUBLE !=0
|
|
long double templdouble;
|
|
#endif
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
static char fmt_llong[8], fmt_ullong[8];
|
|
if (!fmt_llong[0]) {
|
|
sprintf(fmt_llong, "%%%sd", H5_PRINTF_LL_WIDTH);
|
|
sprintf(fmt_ullong, "%%%su", H5_PRINTF_LL_WIDTH);
|
|
}
|
|
#endif
|
|
|
|
if((size = H5Tget_size(tid)) == 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if (H5Tequal(tid, H5T_NATIVE_FLOAT)) {
|
|
memcpy(&tempfloat, mem, sizeof(float));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%g ", tempfloat);
|
|
#else
|
|
if (1 != fwrite(&tempfloat, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_DOUBLE)) {
|
|
memcpy(&tempdouble, mem, sizeof(double));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%g ", tempdouble);
|
|
#else
|
|
if (1 != fwrite(&tempdouble, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
#if H5_SIZEOF_LONG_DOUBLE !=0
|
|
else if (H5Tequal(tid, H5T_NATIVE_LDOUBLE)) {
|
|
memcpy(&templdouble, mem, sizeof(long double));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%Lf ", templdouble);
|
|
#else
|
|
if (1 != fwrite(&templdouble, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
#endif
|
|
else if (H5T_STRING == H5Tget_class(tid)) {
|
|
unsigned int i;
|
|
H5T_str_t pad;
|
|
char *s;
|
|
|
|
pad = H5Tget_strpad(tid);
|
|
|
|
if (H5Tis_variable_str(tid)) {
|
|
s = *(char**) mem;
|
|
if (s != NULL)
|
|
size = HDstrlen(s);
|
|
}
|
|
else {
|
|
s = (char *) mem;
|
|
if((size = H5Tget_size(tid)) == 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
}
|
|
for (i = 0; i < size && (s[i] || pad != H5T_STR_NULLTERM); i++) {
|
|
memcpy(&tempuchar, &s[i], sizeof(unsigned char));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%d", tempuchar);
|
|
#else
|
|
if (1 != fwrite(&tempuchar, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
} /* i */
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_INT)) {
|
|
memcpy(&tempint, mem, sizeof(int));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%d ", tempint);
|
|
#else
|
|
if (1 != fwrite(&tempint, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_UINT)) {
|
|
memcpy(&tempuint, mem, sizeof(unsigned int));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%u ", tempuint);
|
|
#else
|
|
if (1 != fwrite(&tempuint, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_SCHAR)) {
|
|
memcpy(&tempschar, mem, sizeof(char));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%d ", tempschar);
|
|
#else
|
|
if (1 != fwrite(&tempschar, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_UCHAR)) {
|
|
memcpy(&tempuchar, mem, sizeof(unsigned char));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%u ", tempuchar);
|
|
#else
|
|
if (1 != fwrite(&tempuchar, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_SHORT)) {
|
|
memcpy(&tempshort, mem, sizeof(short));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%d ", tempshort);
|
|
#else
|
|
if (1 != fwrite(&tempshort, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_USHORT)) {
|
|
memcpy(&tempushort, mem, sizeof(unsigned short));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%u ", tempushort);
|
|
#else
|
|
if (1 != fwrite(&tempushort, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_LONG)) {
|
|
memcpy(&templong, mem, sizeof(long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%ld ", templong);
|
|
#else
|
|
if (1 != fwrite(&templong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_ULONG)) {
|
|
memcpy(&tempulong, mem, sizeof(unsigned long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%lu ", tempulong);
|
|
#else
|
|
if (1 != fwrite(&tempulong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_LLONG)) {
|
|
memcpy(&templlong, mem, sizeof(long long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, fmt_llong, templlong);
|
|
#else
|
|
if (1 != fwrite(&templlong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_ULLONG)) {
|
|
memcpy(&tempullong, mem, sizeof(unsigned long long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, fmt_ullong, tempullong);
|
|
#else
|
|
if (1 != fwrite(&tempullong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_HSSIZE)) {
|
|
if (sizeof(hssize_t) == sizeof(int)) {
|
|
memcpy(&tempint, mem, sizeof(int));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%d ", tempint);
|
|
#else
|
|
if (1 != fwrite(&tempint, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (sizeof(hssize_t) == sizeof(long)) {
|
|
memcpy(&templong, mem, sizeof(long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%ld ", templong);
|
|
#else
|
|
if (1 != fwrite(&templong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else {
|
|
memcpy(&templlong, mem, sizeof(long long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, fmt_llong, templlong);
|
|
#else
|
|
if (1 != fwrite(&templlong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
}
|
|
else if (H5Tequal(tid, H5T_NATIVE_HSIZE)) {
|
|
if (sizeof(hsize_t) == sizeof(int)) {
|
|
memcpy(&tempuint, mem, sizeof(unsigned int));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%u ", tempuint);
|
|
#else
|
|
if (1 != fwrite(&tempuint, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else if (sizeof(hsize_t) == sizeof(long)) {
|
|
memcpy(&tempulong, mem, sizeof(unsigned long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%lu ", tempulong);
|
|
#else
|
|
if (1 != fwrite(&tempulong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else {
|
|
memcpy(&tempullong, mem, sizeof(unsigned long long));
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, fmt_ullong, tempullong);
|
|
#else
|
|
if (1 != fwrite(&tempullong, size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
}
|
|
else if (H5Tget_class(tid) == H5T_COMPOUND) {
|
|
unsigned j;
|
|
hid_t memb;
|
|
unsigned nmembs;
|
|
size_t offset;
|
|
|
|
nmembs = H5Tget_nmembers(tid);
|
|
|
|
for (j = 0; j < nmembs; j++) {
|
|
offset = H5Tget_member_offset(tid, j);
|
|
memb = H5Tget_member_type(tid, j);
|
|
|
|
if (render_bin_output(stream, container, memb, mem + offset) < 0)
|
|
return FAIL;
|
|
|
|
H5Tclose(memb);
|
|
}
|
|
}
|
|
else if (H5Tget_class(tid) == H5T_ENUM) {
|
|
unsigned int i;
|
|
if (1 == size) {
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "0x%02x", mem[0]);
|
|
#else
|
|
if (1 != fwrite(&mem[0], size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else {
|
|
for (i = 0; i < size; i++) {
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%s%02x", i?":":"", mem[i]);
|
|
#else
|
|
if (1 != fwrite(&mem[i], sizeof(char), 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
} /*i*/
|
|
}/*else 1 */
|
|
}
|
|
else if (H5Tget_class(tid) == H5T_ARRAY) {
|
|
int k, ndims;
|
|
hsize_t i, dims[H5S_MAX_RANK], temp_nelmts, nelmts;
|
|
hid_t memb;
|
|
|
|
/* get the array's base datatype for each element */
|
|
memb = H5Tget_super(tid);
|
|
size = H5Tget_size(memb);
|
|
ndims = H5Tget_array_ndims(tid);
|
|
H5Tget_array_dims2(tid, dims);
|
|
assert(ndims >= 1 && ndims <= H5S_MAX_RANK);
|
|
|
|
/* calculate the number of array elements */
|
|
for (k = 0, nelmts = 1; k < ndims; k++) {
|
|
temp_nelmts = nelmts;
|
|
temp_nelmts *= dims[k];
|
|
nelmts = (size_t) temp_nelmts;
|
|
}
|
|
|
|
/* dump the array element */
|
|
for (i = 0; i < nelmts; i++) {
|
|
if (render_bin_output(stream, container, memb, mem + i * size) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "render_bin_output failed");
|
|
}
|
|
|
|
H5Tclose(memb);
|
|
}
|
|
else if (H5Tget_class(tid) == H5T_VLEN) {
|
|
unsigned int i;
|
|
hsize_t nelmts;
|
|
hid_t memb;
|
|
|
|
/* get the VL sequences's base datatype for each element */
|
|
memb = H5Tget_super(tid);
|
|
size = H5Tget_size(memb);
|
|
|
|
/* Get the number of sequence elements */
|
|
nelmts = ((hvl_t *) mem)->len;
|
|
|
|
for (i = 0; i < nelmts; i++) {
|
|
/* dump the array element */
|
|
if (render_bin_output(stream, container, memb, ((char *) (((hvl_t *) mem)->p)) + i * size) < 0)
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "render_bin_output failed");
|
|
}
|
|
H5Tclose(memb);
|
|
}
|
|
else if (H5Tequal(tid, H5T_STD_REF_DSETREG)) {
|
|
if (region_output) {
|
|
/* region data */
|
|
hid_t region_id, region_space;
|
|
H5S_sel_type region_type;
|
|
|
|
region_id = H5Rdereference2(container, H5P_DATASET_ACCESS_DEFAULT, H5R_DATASET_REGION, mem);
|
|
if (region_id >= 0) {
|
|
region_space = H5Rget_region(container, H5R_DATASET_REGION, mem);
|
|
if (region_space >= 0) {
|
|
region_type = H5Sget_select_type(region_space);
|
|
if(region_type == H5S_SEL_POINTS)
|
|
render_bin_output_region_points(region_space, region_id, stream, container);
|
|
else
|
|
render_bin_output_region_blocks(region_space, region_id, stream, container);
|
|
H5Sclose(region_space);
|
|
} /* end if (region_space >= 0) */
|
|
H5Dclose(region_id);
|
|
} /* end if (region_id >= 0) */
|
|
} /* end if (region_output... */
|
|
}
|
|
else if (H5Tequal(tid, H5T_STD_REF_OBJ)) {
|
|
}
|
|
else {
|
|
size_t i;
|
|
if (1 == size) {
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "0x%02x", mem[0]);
|
|
#else
|
|
if (1 != fwrite(&mem[0], size, 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
}
|
|
else {
|
|
for (i = 0; i < size; i++) {
|
|
#ifdef DEBUG_H5DUMP_BIN
|
|
fprintf(stream, "%s%02x", i?":":"", mem[i]);
|
|
#else
|
|
if (1 != fwrite(&mem[i], sizeof(char), 1, stream))
|
|
H5E_THROW(FAIL, H5E_tools_min_id_g, "fwrite failed");
|
|
#endif
|
|
} /*i*/
|
|
}/*else 1 */
|
|
}
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print the data values from a dataset referenced by region blocks.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to print the data in a region reference of type blocks.
|
|
*
|
|
* Return:
|
|
* The function returns FAIL if there was an error, otherwise SUCEED
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
render_bin_output_region_data_blocks(hid_t region_id, FILE *stream,
|
|
hid_t container, int ndims, hid_t type_id, hssize_t nblocks, hsize_t *ptdata)
|
|
{
|
|
hsize_t *dims1 = NULL;
|
|
hsize_t *start = NULL;
|
|
hsize_t *count = NULL;
|
|
size_t numelem;
|
|
hsize_t total_size[H5S_MAX_RANK];
|
|
int jndx;
|
|
int type_size;
|
|
hid_t mem_space = -1;
|
|
void *region_buf = NULL;
|
|
int blkndx;
|
|
hid_t sid1 = -1;
|
|
int ret_value = SUCCEED;
|
|
|
|
/* Get the dataspace of the dataset */
|
|
if((sid1 = H5Dget_space(region_id)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed");
|
|
|
|
/* Allocate space for the dimension array */
|
|
if((dims1 = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for dims");
|
|
|
|
/* find the dimensions of each data space from the block coordinates */
|
|
numelem = 1;
|
|
for (jndx = 0; jndx < ndims; jndx++) {
|
|
dims1[jndx] = ptdata[jndx + ndims] - ptdata[jndx] + 1;
|
|
numelem = dims1[jndx] * numelem;
|
|
}
|
|
|
|
/* Create dataspace for reading buffer */
|
|
if((mem_space = H5Screate_simple(ndims, dims1, NULL)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Screate_simple failed");
|
|
|
|
if((type_size = H5Tget_size(type_id)) == 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if((region_buf = HDmalloc(type_size * numelem)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate region buffer");
|
|
|
|
/* Select (x , x , ..., x ) x (y , y , ..., y ) hyperslab for reading memory dataset */
|
|
/* 1 2 n 1 2 n */
|
|
if((start = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for start");
|
|
|
|
if((count = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for count");
|
|
|
|
for (blkndx = 0; blkndx < nblocks; blkndx++) {
|
|
for (jndx = 0; jndx < ndims; jndx++) {
|
|
start[jndx] = ptdata[jndx + blkndx * ndims * 2];
|
|
count[jndx] = dims1[jndx];
|
|
}
|
|
|
|
if(H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sselect_hyperslab failed");
|
|
|
|
if(H5Dread(region_id, type_id, mem_space, sid1, H5P_DEFAULT, region_buf) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Dread failed");
|
|
|
|
if(H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
|
|
for (jndx = 0; jndx < numelem; jndx++) {
|
|
|
|
render_bin_output(stream, container, type_id,
|
|
((char*)region_buf + jndx * type_size));
|
|
/* Render the region data element end */
|
|
} /* end for (jndx = 0; jndx < numelem; jndx++) */
|
|
} /* end for (blkndx = 0; blkndx < nblocks; blkndx++) */
|
|
|
|
done:
|
|
HDfree(start);
|
|
HDfree(count);
|
|
HDfree(region_buf);
|
|
HDfree(dims1);
|
|
|
|
if(H5Sclose(mem_space) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
if(H5Sclose(sid1) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print some values from a dataset referenced by region blocks.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to dump a region reference using blocks.
|
|
*
|
|
* Return:
|
|
* The function returns False if ERROR, otherwise True
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hbool_t
|
|
render_bin_output_region_blocks(hid_t region_space, hid_t region_id,
|
|
FILE *stream, hid_t container)
|
|
{
|
|
HERR_INIT(hbool_t, TRUE)
|
|
hssize_t nblocks;
|
|
hsize_t alloc_size;
|
|
hsize_t *ptdata = NULL;
|
|
int ndims;
|
|
hid_t dtype;
|
|
hid_t type_id;
|
|
|
|
if((nblocks = H5Sget_select_hyper_nblocks(region_space)) <= 0)
|
|
H5E_THROW(FALSE, H5E_tools_min_id_g, "H5Sget_select_hyper_nblocks failed");
|
|
|
|
/* Print block information */
|
|
if((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
|
|
H5E_THROW(FALSE, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
|
|
|
|
alloc_size = nblocks * ndims * 2 * sizeof(ptdata[0]);
|
|
assert(alloc_size == (hsize_t) ((size_t) alloc_size)); /*check for overflow*/
|
|
if((ptdata = (hsize_t*) malloc((size_t) alloc_size)) == NULL)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "Could not allocate buffer for ptdata");
|
|
|
|
H5_CHECK_OVERFLOW(nblocks, hssize_t, hsize_t);
|
|
if(H5Sget_select_hyper_blocklist(region_space, (hsize_t) 0, (hsize_t) nblocks, ptdata) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Rget_select_hyper_blocklist failed");
|
|
|
|
if((dtype = H5Dget_type(region_id)) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Dget_type failed");
|
|
if((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Tget_native_type failed");
|
|
|
|
render_bin_output_region_data_blocks(region_id, stream, container, ndims,
|
|
type_id, nblocks, ptdata);
|
|
|
|
done:
|
|
free(ptdata);
|
|
|
|
if(H5Tclose(type_id) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
if(H5Tclose(dtype) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
H5_LEAVE(TRUE)
|
|
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print the data values from a dataset referenced by region points.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to print the data in a region reference of type points.
|
|
*
|
|
* Return:
|
|
* The function returns FAIL on error, otherwise SUCCEED
|
|
*
|
|
* Parameters Description:
|
|
* h5tools_str_t *buffer is the string into which to render
|
|
* size_t ncols
|
|
* int ndims is the number of dimensions of the region element
|
|
* hssize_t npoints is the number of points in the region
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
render_bin_output_region_data_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, hid_t container,
|
|
int ndims, hid_t type_id, hssize_t npoints, hsize_t *ptdata)
|
|
{
|
|
hsize_t *dims1 = NULL;
|
|
int jndx;
|
|
int type_size;
|
|
hid_t mem_space = -1;
|
|
void *region_buf = NULL;
|
|
int ret_value = SUCCEED;
|
|
|
|
if((type_size = H5Tget_size(type_id)) == 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
|
|
|
|
if((region_buf = HDmalloc(type_size * npoints)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for region");
|
|
|
|
/* Allocate space for the dimension array */
|
|
if((dims1 = (hsize_t *) HDmalloc(sizeof(hsize_t) * ndims)) == NULL)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Could not allocate buffer for dims");
|
|
|
|
dims1[0] = npoints;
|
|
if((mem_space = H5Screate_simple(1, dims1, NULL)) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Screate_simple failed");
|
|
|
|
if(H5Dread(region_id, type_id, mem_space, region_space, H5P_DEFAULT, region_buf) < 0)
|
|
HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed");
|
|
for (jndx = 0; jndx < npoints; jndx++) {
|
|
if(H5Sget_simple_extent_dims(region_space, dims1, NULL) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
|
|
|
|
render_bin_output(stream, container, type_id, ((char*)region_buf + jndx * type_size));
|
|
} /* end for (jndx = 0; jndx < npoints; jndx++) */
|
|
|
|
done:
|
|
HDfree(region_buf);
|
|
HDfree(dims1);
|
|
|
|
if(H5Sclose(mem_space) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Sclose failed");
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Audience: Public
|
|
* Chapter: H5Tools Library
|
|
* Purpose: Print some values from a dataset referenced by region points.
|
|
*
|
|
* Description:
|
|
* This is a special case subfunction to dump a region reference using points.
|
|
*
|
|
* Return:
|
|
* The function returns False if the last dimension has been reached, otherwise True
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hbool_t
|
|
render_bin_output_region_points(hid_t region_space, hid_t region_id,
|
|
FILE *stream, hid_t container)
|
|
{
|
|
HERR_INIT(hbool_t, TRUE)
|
|
hssize_t npoints;
|
|
hsize_t alloc_size;
|
|
hsize_t *ptdata;
|
|
int ndims;
|
|
hid_t dtype;
|
|
hid_t type_id;
|
|
|
|
if((npoints = H5Sget_select_elem_npoints(region_space)) <= 0)
|
|
H5E_THROW(FALSE, H5E_tools_min_id_g, "H5Sget_select_elem_npoints failed");
|
|
|
|
/* Allocate space for the dimension array */
|
|
if((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
|
|
H5E_THROW(FALSE, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
|
|
|
|
alloc_size = npoints * ndims * sizeof(ptdata[0]);
|
|
assert(alloc_size == (hsize_t) ((size_t) alloc_size)); /*check for overflow*/
|
|
if(NULL == (ptdata = (hsize_t *)HDmalloc((size_t) alloc_size)))
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "Could not allocate buffer for ptdata");
|
|
|
|
H5_CHECK_OVERFLOW(npoints, hssize_t, hsize_t);
|
|
if(H5Sget_select_elem_pointlist(region_space, (hsize_t) 0, (hsize_t) npoints, ptdata) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Sget_select_elem_pointlist failed");
|
|
|
|
if((dtype = H5Dget_type(region_id)) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Dget_type failed");
|
|
|
|
if((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
|
|
HGOTO_ERROR(FALSE, H5E_tools_min_id_g, "H5Tget_native_type failed");
|
|
|
|
render_bin_output_region_data_points(region_space, region_id,
|
|
stream, container, ndims, type_id, npoints, ptdata);
|
|
|
|
done:
|
|
free(ptdata);
|
|
|
|
if(H5Tclose(type_id) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
if(H5Tclose(dtype) < 0)
|
|
HERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Tclose failed");
|
|
|
|
H5_LEAVE(ret_value)
|
|
CATCH
|
|
return ret_value;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_is_zero
|
|
*
|
|
* Purpose: Determines if memory is initialized to all zero bytes.
|
|
*
|
|
* Return: TRUE if all bytes are zero; FALSE otherwise
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static
|
|
hbool_t h5tools_is_zero(const void *_mem, size_t size)
|
|
{
|
|
const unsigned char *mem = (const unsigned char *) _mem;
|
|
|
|
while (size-- > 0)
|
|
if (mem[size])
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: h5tools_is_obj_same
|
|
*
|
|
* Purpose: Check if two given object IDs or link names point to the same object.
|
|
*
|
|
* Parameters:
|
|
* hid_t loc_id1: location of the first object
|
|
* char *name1: link name of the first object.
|
|
* Use "." or NULL if loc_id1 is the object to be compared.
|
|
* hid_t loc_id2: location of the second object
|
|
* char *name1: link name of the first object.
|
|
* Use "." or NULL if loc_id2 is the object to be compared.
|
|
*
|
|
* Return: TRUE if it is the same object; FALSE otherwise.
|
|
*
|
|
* Programmer: Peter Cao
|
|
* 4/27/2011
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t h5tools_is_obj_same(hid_t loc_id1, const char *name1,
|
|
hid_t loc_id2, const char *name2)
|
|
{
|
|
H5O_info_t oinfo1, oinfo2;
|
|
hbool_t ret_val = 0;
|
|
|
|
if ( name1 && strcmp(name1, "."))
|
|
H5Oget_info_by_name(loc_id1, name1, &oinfo1, H5P_DEFAULT);
|
|
else
|
|
H5Oget_info(loc_id1, &oinfo1);
|
|
|
|
if ( name2 && strcmp(name2, "."))
|
|
H5Oget_info_by_name(loc_id2, name2, &oinfo2, H5P_DEFAULT);
|
|
else
|
|
H5Oget_info(loc_id2, &oinfo2);
|
|
|
|
if (oinfo1.fileno == oinfo2.fileno && oinfo1.addr==oinfo2.addr)
|
|
ret_val = 1;
|
|
|
|
return ret_val;
|
|
}
|
|
|