From 46f683cf14957d39550e826e374e1f3f5a64958c Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Thu, 5 Nov 1998 15:28:34 -0500 Subject: [svn-r876] Changes since 19981102 ---------------------- ./bin/snapshot Made same fix as for the release script yesterday. ./src/H5D.c ./src/H5Dprivate.h ./src/H5G.c ./src/H5Gprivate.h ./src/H5Gpublic.h ./src/H5O.c ./src/H5Oprivate.h ./src/H5RA.c ./src/H5RAprivate.h ./src/H5T.c ./src/H5Tprivate.h Improved object type checking. Instead of determining the object type by trying to open each of the possible types, we keep a table of associations between object type number (like H5G_GROUP, H5G_DATASET, H5D_TYPE, and H5D_RAGGED) and an `isa' function that returns true if the object header has the right messages to make the object a particular type. This mechanism also allows specialization of object types by permitting an object to satisfy more than one `isa' function. Added `isa' functions for groups, datasets, ragged arrays, and committed data types. ./src/H5config.h.in Added HAVE_STAT_ST_BLOCKS. I thought this had already been added, but apparently not. ./tools/h5ls.c Removed system include files since they're already included by H5private.h and since I wasn't including them portably anyway. By default, 1-byte integer types are printed as integer values instead of ASCII characters. However, the `-s' or `--string' command-line switch causes the data to be interpretted as ASCII. String data types are always printed as character data. Ragged arrays are now identified as ragged arrays and h5ls doesn't descend into the group automatically. This uses the new object type specialization stuff. ./tools/h5tools.c ./tools/h5tools.h Added the ability to print 1-byte integer types as either ASCII or numeric data instead of always ASCII. The default is to print as numeric data. --- bin/snapshot | 2 +- configure.in | 2 +- src/H5D.c | 61 +++++++++++++-- src/H5Dprivate.h | 1 + src/H5G.c | 220 +++++++++++++++++++++++++++++++++++++++++++++--------- src/H5Gprivate.h | 15 ++++ src/H5Gpublic.h | 18 ++++- src/H5O.c | 49 ++++++++++++ src/H5Oprivate.h | 1 + src/H5RA.c | 61 +++++++++++++++ src/H5RAprivate.h | 1 + src/H5T.c | 35 +++++++++ src/H5Tprivate.h | 1 + src/H5config.h.in | 5 +- tools/h5ls.c | 66 ++++++++++++---- tools/h5tools.c | 15 +++- tools/h5tools.h | 8 ++ 17 files changed, 498 insertions(+), 63 deletions(-) diff --git a/bin/snapshot b/bin/snapshot index d87dd3a..ef49c29 100755 --- a/bin/snapshot +++ b/bin/snapshot @@ -42,7 +42,7 @@ snapshot=yes if [ -d ${COMPARE}/previous ]; then if (diff -c ${COMPARE}/previous/MANIFEST ${COMPARE}/current/MANIFEST); then snapshot=no - for src in `grep '^\.' ${COMPARE}/current/MANIFEST|expand|cut -f1`; do + for src in `grep '^\.' ${COMPARE}/current/MANIFEST|expand|cut -f1 -d' '`; do if (diff -I H5_VERS_RELEASE -I " released on " \ ${COMPARE}/previous/$src ${COMPARE}/current/$src); then else diff --git a/configure.in b/configure.in index c26a3c3..0999e01 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl Process this file with autoconf to produce configure. -*-indented-text-*- +dnl Process this file with autoconf to produce configure. dnl dnl Copyright (C) 1997 National Center for Supercomputing Applications. dnl All rights reserved. diff --git a/src/H5D.c b/src/H5D.c index 62e6b74..65dca31 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -1101,7 +1101,57 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, FUNC_LEAVE(ret_value); } + /*------------------------------------------------------------------------- + * Function: H5D_isa + * + * Purpose: Determines if an object has the requisite messages for being + * a dataset. + * + * Return: Success: TRUE if the required dataset messages are + * present; FALSE otherwise. + * + * Failure: FAIL if the existence of certain messages + * cannot be determined. + * + * Programmer: Robb Matzke + * Monday, November 2, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5D_isa(H5G_entry_t *ent) +{ + htri_t exists; + + FUNC_ENTER(H5D_isa, FAIL); + assert(ent); + + /* Data type */ + if ((exists=H5O_exists(ent, H5O_DTYPE, 0))<0) { + HRETURN_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read object header"); + } else if (!exists) { + HRETURN(FALSE); + } + + /* Layout */ + if ((exists=H5O_exists(ent, H5O_LAYOUT, 0))<0) { + HRETURN_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read object header"); + } else if (!exists) { + HRETURN(FALSE); + } + + + + FUNC_LEAVE(TRUE); +} + +/* + *------------------------------------------------------------------------- * Function: H5D_open * * Purpose: Finds a dataset named NAME in file F and builds a descriptor @@ -1130,7 +1180,7 @@ H5D_open(H5G_entry_t *loc, const char *name) { H5D_t *dataset = NULL; /*the dataset which was found */ H5D_t *ret_value = NULL; /*return value */ - H5G_entry_t ent; /* Dataset symbol table entry */ + H5G_entry_t ent; /*dataset symbol table entry */ FUNC_ENTER(H5D_open, NULL); @@ -1173,10 +1223,10 @@ done: H5D_t * H5D_open_oid(H5G_entry_t *ent) { - H5D_t *dataset = NULL; /* New dataset struct */ - H5D_t *ret_value = NULL; /*return value */ + H5D_t *dataset = NULL; /*new dataset struct */ + H5D_t *ret_value = NULL; /*return value */ + H5S_t *space = NULL; /*data space */ intn i; - H5S_t *space = NULL; FUNC_ENTER(H5D_open_oid, NULL); @@ -1290,8 +1340,7 @@ H5D_open_oid(H5G_entry_t *ent) ret_value = dataset; done: - if (space) - H5S_close (space); + if (space) H5S_close (space); if (ret_value==NULL && dataset) { if (H5F_addr_defined(&(dataset->ent.header))) { H5O_close(&(dataset->ent)); diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index bdf66f7..3a30731 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -71,6 +71,7 @@ H5D_t *H5D_create (H5G_entry_t *loc, const char *name, const H5T_t *type, const H5S_t *space, const H5D_create_t *create_parms); H5D_t *H5D_open (H5G_entry_t *loc, const char *name); herr_t H5D_close (H5D_t *dataset); +htri_t H5D_isa(H5G_entry_t *ent); herr_t H5D_read (H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, const H5D_xfer_t *xfer_parms, void *buf/*out*/); diff --git a/src/H5G.c b/src/H5G.c index bf15f3d..992de26 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -95,6 +95,9 @@ static hbool_t interface_initialize_g = FALSE; #define INTERFACE_INIT H5G_init_interface static herr_t H5G_init_interface(void); static void H5G_term_interface(void); +static H5G_typeinfo_t *H5G_type_g = NULL; /*object typing info */ +static size_t H5G_ntypes_g = 0; /*entries in type table */ +static size_t H5G_atypes_g = 0; /*entries allocated */ /*------------------------------------------------------------------------- @@ -523,8 +526,9 @@ H5Gget_objinfo(hid_t loc_id, const char *name, hbool_t follow_link, * most SIZE characters (counting the null terminator) are * copied to the BUF result buffer. * - * Return: Non-negative on success (the link value is in BUF.) /Negative on - * failure + * Return: Success: Non-negative with the link value in BUF. + * + * Failure: Negative * * Programmer: Robb Matzke * Monday, April 13, 1998 @@ -684,6 +688,17 @@ H5G_init_interface(void) HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to initialize interface"); } + + /* + * Initialize the type info table. Begin with the most general types and + * end with the most specific. For instance, any object that has a data + * type message is a data type but only some of them are datasets. + */ + H5G_register_type(H5G_TYPE, H5T_isa, "data type"); + H5G_register_type(H5G_GROUP, H5G_isa, "group"); + H5G_register_type(H5G_DATASET, H5D_isa, "dataset"); + H5G_register_type(H5G_RAGGED, H5RA_isa, "ragged array"); + FUNC_LEAVE(SUCCEED); } @@ -710,6 +725,85 @@ H5G_term_interface(void) /*------------------------------------------------------------------------- + * Function: H5G_register_type + * + * Purpose: Register a new object type so H5G_get_type() can detect it. + * One should always register a general type before a more + * specific type. For instance, any object that has a data type + * message is a data type, but only some of those objects are + * datasets. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, November 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_register_type(intn type, htri_t(*isa)(H5G_entry_t*), const char *_desc) +{ + char *desc = NULL; + size_t i; + herr_t ret_value = FAIL; + + FUNC_ENTER(H5G_register_type, FAIL); + assert(type>=0); + assert(isa); + assert(_desc); + + /* Copy the description */ + if (NULL==(desc=H5MM_strdup(_desc))) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed for object type description"); + } + + /* + * If the type is already registered then just update its entry without + * moving it to the end + */ + for (i=0; i=H5G_atypes_g) { + size_t n = MAX(32, 2*H5G_atypes_g); + H5G_typeinfo_t *x = H5MM_realloc(H5G_type_g, + n*sizeof(H5G_typeinfo_t)); + if (!x) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed for objec type table"); + } + H5G_atypes_g = n; + H5G_type_g = x; + } + + /* Add a new entry */ + H5G_type_g[H5G_ntypes_g].type = type; + H5G_type_g[H5G_ntypes_g].isa = isa; + H5G_type_g[H5G_ntypes_g].desc = desc; /*already copied*/ + H5G_ntypes_g++; + + ret_value = SUCCEED; + + done: + if (ret_value<0) H5MM_xfree(desc); + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5G_component * * Purpose: Returns the pointer to the first component of the @@ -842,14 +936,14 @@ H5G_basename(const char *name, size_t *size_p) * * Errors: * - * Return: Success: Non-negative if name can be fully resolved. See - * above for values of REST, GRP_ENT, and + * Return: Success: Non-negative if name can be fully resolved. + * See above for values of REST, GRP_ENT, and * OBJ_ENT. NLINKS has been decremented for * each symbolic link that was followed. * - * Failure: Negative if the name could not be fully resolved. - * See above for values of REST, GRP_ENT, and - * OBJ_ENT. + * Failure: Negative if the name could not be fully + * resolved. See above for values of REST, + * GRP_ENT, and OBJ_ENT. * * Programmer: Robb Matzke * matzke@llnl.gov @@ -1191,6 +1285,42 @@ H5G_create(H5G_entry_t *loc, const char *name, size_t size_hint) grp->nref = 1; FUNC_LEAVE(grp); } + + +/*------------------------------------------------------------------------- + * Function: H5G_isa + * + * Purpose: Determines if an object has the requisite messages for being + * a group. + * + * Return: Success: TRUE if the required group messages are + * present; FALSE otherwise. + * + * Failure: FAIL if the existence of certain messages + * cannot be determined. + * + * Programmer: Robb Matzke + * Monday, November 2, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5G_isa(H5G_entry_t *ent) +{ + htri_t exists; + + FUNC_ENTER(H5G_isa, FAIL); + assert(ent); + + if ((exists=H5O_exists(ent, H5O_STAB, 0))<0) { + HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, + "unable to read object header"); + } + FUNC_LEAVE(exists); +} + /*------------------------------------------------------------------------- * Function: H5G_open @@ -1431,8 +1561,8 @@ H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent) * * Errors: * - * Return: Success: Non-negative, see above for values of GRP_ENT and - * OBJ_ENT. + * Return: Success: Non-negative, see above for values of GRP_ENT + * and OBJ_ENT. * * Failure: Negative * @@ -1761,12 +1891,54 @@ H5G_link (H5G_entry_t *loc, H5G_link_t type, const char *cur_name, /*------------------------------------------------------------------------- + * Function: H5G_get_type + * + * Purpose: Returns the type of object pointed to by `ent'. + * + * Return: Success: An object type defined in H5Gpublic.h + * + * Failure: H5G_UNKNOWN + * + * Programmer: Robb Matzke + * Wednesday, November 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5G_get_type(H5G_entry_t *ent) +{ + htri_t isa; + size_t i; + + FUNC_ENTER(H5G_get_type, H5G_UNKNOWN); + + for (i=H5G_ntypes_g; i>0; --i) { + if ((isa=(H5G_type_g[i-1].isa)(ent))<0) { + HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, + "unable to determine object type"); + } else if (isa) { + HRETURN(H5G_type_g[i-1].type); + } + } + + if (0==i) { + HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, + "unable to determine object type"); + } + FUNC_LEAVE(H5G_UNKNOWN); +} + + +/*------------------------------------------------------------------------- * Function: H5G_get_objinfo * * Purpose: Returns information about an object. * - * Return: Success: Non-negative with info about the object returned - * through STATBUF if it isn't the null pointer. + * Return: Success: Non-negative with info about the object + * returned through STATBUF if it isn't the null + * pointer. * * Failure: Negative * @@ -1784,9 +1956,6 @@ H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, H5O_stab_t stab_mesg; H5G_entry_t grp_ent, obj_ent; const char *s = NULL; - H5D_t *temp_dset = NULL; - H5G_t *temp_grp = NULL; - H5T_t *temp_type = NULL; FUNC_ENTER (H5G_get_objinfo, FAIL); @@ -1833,24 +2002,7 @@ H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, H5E_clear(); statbuf->mtime = 0; } - - /* - * Determining the type of an object is a rather expensive - * operation compared to the other stuff here. It's also not - * very flexible. - */ - if (NULL!=(temp_dset=H5D_open (loc, name))) { - statbuf->type = H5G_DATASET; - H5D_close (temp_dset); - } else if (NULL!=(temp_grp=H5G_open (loc, name))) { - statbuf->type = H5G_GROUP; - H5G_close (temp_grp); - } else if (NULL!=(temp_type=H5T_open(loc, name))) { - statbuf->type = H5G_TYPE; - H5T_close(temp_type); - } else { - statbuf->type = H5G_UNKNOWN; - } + statbuf->type = H5G_get_type(&obj_ent); H5E_clear(); /*clear errors resulting from checking type*/ } } @@ -1864,8 +2016,8 @@ H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, * * Purpose: Returns the value of a symbolic link. * - * Return: Success: Non-negative, with at most SIZE bytes of the link - * value copied into the BUF buffer. If the + * Return: Success: Non-negative, with at most SIZE bytes of the + * link value copied into the BUF buffer. If the * link value is larger than SIZE characters * counting the null terminator then the BUF * result will not be null terminated. diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 1cf448f..ac430c1 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -96,9 +96,22 @@ typedef struct H5G_entry_t { typedef struct H5G_t H5G_t; /* + * This table contains a list of object types, descriptions, and the + * functions that determine if some object is a particular type. The table + * is allocated dynamically. + */ +typedef struct H5G_typeinfo_t { + intn type; /*one of the public H5G_* types */ + htri_t (*isa)(H5G_entry_t*); /*function to determine type */ + char *desc; /*description of object type */ +} H5G_typeinfo_t; + +/* * Library prototypes... These are the ones that other packages routinely * call. */ +herr_t H5G_register_type(intn type, htri_t(*isa)(H5G_entry_t*), + const char *desc); H5G_entry_t *H5G_loc (hid_t loc_id); herr_t H5G_mkroot (H5F_t *f, H5G_entry_t *root_entry); H5G_entry_t *H5G_entof (H5G_t *grp); @@ -108,8 +121,10 @@ H5G_t *H5G_open (H5G_entry_t *loc, const char *name); H5G_t *H5G_reopen (H5G_t *grp); herr_t H5G_close (H5G_t *grp); H5G_t *H5G_rootof(H5F_t *f); +htri_t H5G_isa(H5G_entry_t *ent); herr_t H5G_link (H5G_entry_t *loc, H5G_link_t type, const char *cur_name, const char *new_name, uintn namei_flags); +intn H5G_get_type(H5G_entry_t *ent); herr_t H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, H5G_stat_t *statbuf/*out*/); herr_t H5G_linkval (H5G_entry_t *loc, const char *name, size_t size, diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index cc3cc7d..32fc1d4 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -34,13 +34,27 @@ typedef enum H5G_link_t { H5G_LINK_SOFT = 1 } H5G_link_t; -/* An object has a certain type */ +/* + * An object has a certain type. The first few numbers are reserved for use + * internally by HDF5. Users may add their own types with higher values. The + * values are never stored in the file -- they only exist while an + * application is running. An object may satisfy the `isa' function for more + * than one type. + */ #define H5G_UNKNOWN (-1) /* Unknown object type */ #define H5G_LINK 0 /* Object is a symbolic link */ #define H5G_GROUP 1 /* Object is a group */ #define H5G_DATASET 2 /* Object is a dataset */ #define H5G_TYPE 3 /* Object is a named data type */ -#define H5G_NTYPES 4 /* THIS MUST BE LAST */ +#define H5G_RAGGED 4 /* Object is a ragged array */ +#define H5G_RESERVED_5 5 /* Reserved for future use */ +#define H5G_RESERVED_6 6 /* Reserved for future use */ +#define H5G_RESERVED_7 7 /* Reserved for future use */ + +#define H5G_NTYPES 256 /* Max possible number of types */ +#define H5G_NLIBTYPES 8 /* Number of internal types */ +#define H5G_NUSERTYPES (H5G_NTYPES-H5G_NLIBTYPES) +#define H5G_USERTYPE(X) (8+(X)) /* User defined types */ /* Information about an object */ typedef struct H5G_stat_t { diff --git a/src/H5O.c b/src/H5O.c index 8d7ee63..d1e1d07 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -878,6 +878,55 @@ H5O_count (H5G_entry_t *ent, const H5O_class_t *type) /*------------------------------------------------------------------------- + * Function: H5O_exists + * + * Purpose: Determines if a particular message exists in an object + * header without trying to decode the message. + * + * Return: Success: FALSE if the message does not exist; TRUE if + * th message exists. + * + * Failure: FAIL if the existence of the message could + * not be determined due to some error such as + * not being able to read the object header. + * + * Programmer: Robb Matzke + * Monday, November 2, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5O_exists(H5G_entry_t *ent, const H5O_class_t *type, intn sequence) +{ + H5O_t *oh=NULL; + intn i; + + FUNC_ENTER(H5O_exists, FAIL); + assert(ent); + assert(ent->file); + assert(type); + assert(sequence>=0); + + /* Load the object header */ + if (NULL==(oh=H5AC_find(ent->file, H5AC_OHDR, &(ent->header), + NULL, NULL))) { + HRETURN_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, + "unable to load object header"); + } + + /* Scan through the messages looking for the right one */ + for (i=0; inmesgs; i++) { + if (type->id!=oh->mesg[i].type->id) continue; + if (--sequence<0) break; + } + + FUNC_LEAVE(sequence<0); +} + + +/*------------------------------------------------------------------------- * Function: H5O_read * * Purpose: Reads a message from an object header and returns a pointer diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 7dff3c9..16fbded 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -273,6 +273,7 @@ herr_t H5O_open (H5G_entry_t *ent); herr_t H5O_close (H5G_entry_t *ent); intn H5O_link (H5G_entry_t *ent, intn adjust); intn H5O_count (H5G_entry_t *ent, const H5O_class_t *type); +htri_t H5O_exists(H5G_entry_t *ent, const H5O_class_t *type, intn sequence); void *H5O_read (H5G_entry_t *ent, const H5O_class_t *type, intn sequence, void *mesg); intn H5O_modify (H5G_entry_t *ent, const H5O_class_t *type, intn overwrite, diff --git a/src/H5RA.c b/src/H5RA.c index c0ed491..11d02e9 100644 --- a/src/H5RA.c +++ b/src/H5RA.c @@ -398,6 +398,67 @@ H5RAopen(hid_t loc_id, const char *name) /*------------------------------------------------------------------------- + * Function: H5RA_isa + * + * Purpose: Determines if an object is a ragged array. + * + * Return: Success: TRUE if the object is a ragged array; FALSE + * otherwise. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, November 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5RA_isa(H5G_entry_t *ent) +{ + htri_t exists; + H5G_entry_t d_ent; + + FUNC_ENTER(H5RA_isa, FAIL); + + /* Open the container group */ + if ((exists=H5G_isa(ent))<0) { + HRETURN_ERROR(H5E_RAGGED, H5E_CANTINIT, FAIL, + "unable to read object header"); + } else if (!exists) { + HRETURN(FALSE); + } + + /* Is `raw' a dataset? */ + if (H5G_find(ent, "raw", NULL, &d_ent)<0 || + (exists=H5D_isa(&d_ent))<0) { + HRETURN_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); + } else if (!exists) { + HRETURN(FALSE); + } + + /* Is `over' a dataset? */ + if (H5G_find(ent, "over", NULL, &d_ent)<0 || + (exists=H5D_isa(&d_ent))<0) { + HRETURN_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); + } else if (!exists) { + HRETURN(FALSE); + } + + /* Is `meta' a dataset? */ + if (H5G_find(ent, "meta", NULL, &d_ent)<0 || + (exists=H5D_isa(&d_ent))<0) { + HRETURN_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); + } else if (!exists) { + HRETURN(FALSE); + } + + FUNC_LEAVE(TRUE); +} + + +/*------------------------------------------------------------------------- * Function: H5RA_open * * Purpose: Open a ragged array. The name of the array is the same as diff --git a/src/H5RAprivate.h b/src/H5RAprivate.h index 19e11d7..89e83db 100644 --- a/src/H5RAprivate.h +++ b/src/H5RAprivate.h @@ -19,6 +19,7 @@ herr_t H5RA_close(H5RA_t *ra); H5RA_t *H5RA_create(H5G_entry_t *loc, const char *name, H5T_t *type, const H5D_create_t *dcpl); H5RA_t *H5RA_open(H5G_entry_t *loc, const char *name); +htri_t H5RA_isa(H5G_entry_t *ent); herr_t H5RA_write(H5RA_t *ra, hssize_t start_row, hsize_t nrows, H5T_t *type, hsize_t size[], void *buf[]); herr_t H5RA_read(H5RA_t *ra, hssize_t start_row, hsize_t nrows, H5T_t *type, diff --git a/src/H5T.c b/src/H5T.c index 916bc87..517e6a3 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -3466,6 +3466,41 @@ H5T_create(H5T_class_t type, size_t size) /*------------------------------------------------------------------------- + * Function: H5T_isa + * + * Purpose: Determines if an object has the requisite messages for being + * a data type. + * + * Return: Success: TRUE if the required data type messages are + * present; FALSE otherwise. + * + * Failure: FAIL if the existence of certain messages + * cannot be determined. + * + * Programmer: Robb Matzke + * Monday, November 2, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5T_isa(H5G_entry_t *ent) +{ + htri_t exists; + + FUNC_ENTER(H5T_isa, FAIL); + assert(ent); + + if ((exists=H5O_exists(ent, H5O_DTYPE, 0))<0) { + HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to read object header"); + } + FUNC_LEAVE(exists); +} + + +/*------------------------------------------------------------------------- * Function: H5T_open * * Purpose: Open a named data type. diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 25d4f6d..3b602a1 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -44,6 +44,7 @@ typedef enum H5T_copy_t { /* Private functions */ herr_t H5T_init (void); herr_t H5T_init_interface (void); +htri_t H5T_isa(H5G_entry_t *ent); H5T_t *H5T_open (H5G_entry_t *loc, const char *name); H5T_t *H5T_create (H5T_class_t type, size_t size); H5T_t *H5T_copy (const H5T_t *old_dt, H5T_copy_t method); diff --git a/src/H5config.h.in b/src/H5config.h.in index 755ec7e..a08c7e2 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -44,7 +44,7 @@ /* Define if it's safe to use `long long' for hsize_t and hssize_t */ #undef HAVE_LARGE_HSIZET -/* The width parameter for printf formats for type `long long', us. `ll' */ +/* Width for printf() for type `long long' or `__int64', us. `ll' */ #undef PRINTF_LL_WIDTH /* Define if `tm_gmtoff' is a member of `struct tm' */ @@ -56,6 +56,9 @@ /* Define if `struct timezone' is defined */ #undef HAVE_STRUCT_TIMEZONE +/* Define if `struct stat' has the `st_blocks' field */ +#undef HAVE_STAT_ST_BLOCKS + /* The number of bytes in a __int64. */ #undef SIZEOF___INT64 diff --git a/tools/h5ls.c b/tools/h5ls.c index 39124b8..3d7b845 100644 --- a/tools/h5ls.c +++ b/tools/h5ls.c @@ -5,14 +5,15 @@ * Programmer: Robb Matzke * Monday, March 23, 1998 */ -#include -#include -#include -#include -#include -#include + +/* + * We include the private header file so we can get to the uniform + * programming environment it declares. + */ #include +#include + #ifndef HAVE_ATTRIBUTE # undef __attribute__ # define __attribute__(X) /*void*/ @@ -25,6 +26,7 @@ static int verbose_g = 0; static int dump_g = 0; static int width_g = 80; +static int string_g = FALSE; /* Information about how to display each type of object */ static struct dispatch_t { @@ -68,6 +70,7 @@ usage: %s [OPTIONS] FILE [OBJECTS...]\n\ OPTIONS\n\ -h, -?, --help Print a usage message and exit\n\ -d, --dump Print the values of datasets\n\ + -s, --string Print 1-byte integer datasets as ASCII\n\ -wN, --width=N Set the number of columns of output\n\ -v, --verbose Generate more verbose output\n\ -V, --version Print version number and exit\n\ @@ -112,9 +115,11 @@ dump_dataset_values(hid_t dset) /* * If the dataset is a 1-byte integer type then format it as an ASCI - * character string instead of integers. + * character string instead of integers if the `-s' or `--string' + * command-line option was given. */ - if (1==size && H5T_INTEGER==H5Tget_class(f_type)) { + if (string_g && 1==size && H5T_INTEGER==H5Tget_class(f_type)) { + info.ascii = TRUE; info.elmt_suf1 = ""; info.elmt_suf2 = ""; info.idx_fmt = " (%s) \""; @@ -286,6 +291,34 @@ dataset_list2(hid_t dset) /*------------------------------------------------------------------------- + * Function: ragged_list2 + * + * Purpose: List information about a ragged array which should appear + * after information which is general to all objects. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +ragged_list2(hid_t __unused__ ra) +{ + if (dump_g) { + puts(" Data: Not implemented yet (see values of member"); + puts(" datasets `raw', `over', and `meta')"); + } + return -1; +} + + +/*------------------------------------------------------------------------- * Function: link_open * * Purpose: This gets called to open a symbolic link. Since symbolic @@ -399,7 +432,6 @@ list (hid_t group, const char *name, void __unused__ *cd) return 0; } - /*------------------------------------------------------------------------- * Function: main @@ -426,6 +458,7 @@ main (int argc, char *argv[]) const char *s; char *rest; int argno; + H5G_stat_t sb; DISPATCH(H5G_DATASET, "Dataset", H5Dopen, H5Dclose, dataset_list1, dataset_list2); @@ -435,6 +468,8 @@ main (int argc, char *argv[]) NULL, NULL); DISPATCH(H5G_LINK, "-> ", link_open, NULL, NULL, NULL); + DISPATCH(H5G_RAGGED, "Ragged Array", H5Gopen, H5Gclose, + NULL, ragged_list2); /* Name of this program without the path */ if ((progname=strrchr (argv[0], '/'))) progname++; @@ -451,6 +486,8 @@ main (int argc, char *argv[]) exit(0); } else if (!strcmp(argv[argno], "--dump")) { dump_g++; + } else if (!strcmp(argv[argno], "--string")) { + string_g = TRUE; } else if (!strncmp(argv[argno], "--width=", 8)) { width_g = strtol(argv[argno]+8, &rest, 0); if (width_g<=0 || *rest) { @@ -488,6 +525,9 @@ main (int argc, char *argv[]) case 'd': /* --dump */ dump_g++; break; + case 's': + string_g = TRUE; + break; case 'v': /* --verbose */ verbose_g++; break; @@ -531,17 +571,15 @@ main (int argc, char *argv[]) H5Giterate(file, "/", NULL, list, NULL); } else { for (/*void*/; argno=0) { + if (H5Gget_objinfo(file, argv[argno], TRUE, &sb)>=0 && + H5G_GROUP==sb.type) { H5Giterate(file, argv[argno], NULL, list, NULL); } else if ((root=H5Gopen(file, "/"))<0) { exit(1); } else { list(root, argv[argno], NULL); + if (H5Gclose(root)<0) exit(1); } - if (H5Gclose(root)<0) exit(1); } } diff --git a/tools/h5tools.c b/tools/h5tools.c index d3c9615..83915b3 100644 --- a/tools/h5tools.c +++ b/tools/h5tools.c @@ -22,7 +22,7 @@ * size of that temporary buffer in bytes. For efficiency's sake, choose the * largest value suitable for your machine (for testing use a small value). */ -#if 0 +#if 1 #define H5DUMP_BUFSIZE (1024*1024) #else #define H5DUMP_BUFSIZE (1024) @@ -126,8 +126,9 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp) } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) { sprintf(temp, "%g", *((float*)vp)); - } else if (H5Tequal(type, H5T_NATIVE_CHAR) || - H5Tequal(type, H5T_NATIVE_UCHAR)) { + } else if (info->ascii && + (H5Tequal(type, H5T_NATIVE_CHAR) || + H5Tequal(type, H5T_NATIVE_UCHAR))) { switch (*((char*)vp)) { case '"': strcpy(temp, "\\\""); @@ -223,7 +224,13 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp) } } if (quote) sprintf(temp+strlen(temp), "%c", quote); - + + } else if (H5Tequal(type, H5T_NATIVE_CHAR)) { + sprintf(temp, "%d", *((signed char*)vp)); + + } else if (H5Tequal(type, H5T_NATIVE_UCHAR)) { + sprintf(temp, "%u", *((unsigned char*)vp)); + } else if (H5Tequal(type, H5T_NATIVE_SHORT)) { sprintf(temp, "%d", *((short*)vp)); diff --git a/tools/h5tools.h b/tools/h5tools.h index 374bb71..54017aa 100644 --- a/tools/h5tools.h +++ b/tools/h5tools.h @@ -58,6 +58,13 @@ typedef struct h5dump_t { /* * Fields associated with the individual elements. * + * ascii: If set then print 1-byte integer values as an ASCII + * character (no quotes). If the character is one of the + * standard C escapes then print the escaped version. If + * the character is unprintable then print a 3-digit octal + * escape. If `ascii' is zero then then 1-byte integers are + * printed as numeric values. The default is zero. + * * fmt: A printf(3c) format to use to print the value string * after it has been rendered. The default is "%s". * @@ -69,6 +76,7 @@ typedef struct h5dump_t { * are followed on the same line by another element. The * default is a single space. */ + int ascii; const char *elmt_fmt; const char *elmt_suf1; const char *elmt_suf2; -- cgit v0.12