summaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-11-24 16:49:36 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-11-24 16:49:36 (GMT)
commit2f36ea99d4ad1b036d377719e49eaab2dec64444 (patch)
tree63be7c282767004339c49aa0e738e6a62630c280 /tools/lib
parent083357dad3334473507a97e17593a9d68e42d69f (diff)
downloadhdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.zip
hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.gz
hdf5-2f36ea99d4ad1b036d377719e49eaab2dec64444.tar.bz2
[svn-r14284] Description:
Add H5Lvisit_by_name() API routine to library. Eliminated all (five!) other group traversal routines and changed them all to use the new API routine. Cleaned up output of h5ls & h5stat: - Issue error when requesting recursive traversal of a file with the "group info" flag, but no group given - Print info about root group in all(?) appropriate situations - Don't print "verbose" information about root group until the root group is in the list of objects to display (mostly because h5ls & h5stat had a different twist on traversing the groups in a file that the other utilities) Tested on: FreeBSD/32 6.2 (duty) in debug mode FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Mac OS X/32 10.4.10 (amazon) in debug mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/h5tools_ref.c192
-rw-r--r--tools/lib/h5tools_utils.c186
-rw-r--r--tools/lib/h5tools_utils.h2
-rw-r--r--tools/lib/h5trav.c276
-rw-r--r--tools/lib/h5trav.h14
5 files changed, 285 insertions, 385 deletions
diff --git a/tools/lib/h5tools_ref.c b/tools/lib/h5tools_ref.c
index 123065b..de1e2c3 100644
--- a/tools/lib/h5tools_ref.c
+++ b/tools/lib/h5tools_ref.c
@@ -20,6 +20,7 @@
#include "H5SLprivate.h"
#include "h5tools.h"
#include "h5tools_utils.h"
+#include "h5trav.h"
/*
@@ -42,15 +43,12 @@ typedef struct {
} ref_path_node_t;
static H5SL_t *ref_path_table = NULL; /* the "table" (implemented with a skip list) */
-static hid_t thefile;
+static hid_t thefile = (-1);
extern char *progname;
extern int d_status;
static int ref_path_table_put(const char *, haddr_t objno);
-static hbool_t ref_path_table_find(haddr_t objno);
-static herr_t fill_ref_path_table_cb(hid_t group, const char *obj_name,
- const H5L_info_t *linfo, void *op_data);
/*-------------------------------------------------------------------------
* Function: free_ref_path_info
@@ -77,6 +75,61 @@ free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in,
}
/*-------------------------------------------------------------------------
+ * Function: init_ref_path_cb
+ *
+ * Purpose: Called by interator to create references for
+ * all objects and enter them in the table.
+ *
+ * Return: Error status.
+ *
+ * Programmer: REMcG
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+init_ref_path_cb(const char *obj_name, const H5O_info_t *oinfo,
+ const char *already_seen, void UNUSED *_udata)
+{
+ /* Check if the object is already in the path table */
+ if(NULL == already_seen) {
+ /* Insert the object into the path table */
+ ref_path_table_put(obj_name, oinfo->addr);
+ } /* end if */
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: init_ref_path_table
+ *
+ * Purpose: Initalize the reference path table
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+init_ref_path_table(void)
+{
+ /* Sanity check */
+ HDassert(thefile > 0);
+
+ /* Create skip list to store reference path information */
+ if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
+ return (-1);
+
+ /* Iterate over objects in this file */
+ if(h5trav_visit(thefile, "/", TRUE, TRUE, init_ref_path_cb, NULL, NULL) < 0) {
+ error_msg(progname, "unable to construct reference path table\n");
+ d_status = EXIT_FAILURE;
+ } /* end if */
+
+ return(0);
+}
+
+/*-------------------------------------------------------------------------
* Function: term_ref_path_table
*
* Purpose: Terminate the reference path table
@@ -137,39 +190,11 @@ ref_path_table_lookup(const char *thepath)
if(H5Oget_info_by_name(thefile, thepath, &oi, H5P_DEFAULT) < 0)
return HADDR_UNDEF;
- /* All existing objects in the file had better be in the table */
- HDassert(ref_path_table_find(oi.addr));
-
/* Return OID */
return(oi.addr);
}
/*-------------------------------------------------------------------------
- * Function: ref_path_table_find
- *
- * Purpose: Looks up a table entry given a object number.
- * Used during construction of the table.
- *
- * Return: TRUE/FALSE on success, can't fail
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hbool_t
-ref_path_table_find(haddr_t objno)
-{
- HDassert(ref_path_table);
-
- if(H5SL_search(ref_path_table, &objno) == NULL)
- return FALSE;
- else
- return TRUE;
-}
-
-/*-------------------------------------------------------------------------
* Function: ref_path_table_put
*
* Purpose: Enter the 'obj' with 'path' in the table (assumes its not
@@ -200,7 +225,7 @@ ref_path_table_put(const char *path, haddr_t objno)
return(-1);
new_node->objno = objno;
- new_node->path = path;
+ new_node->path = HDstrdup(path);
return(H5SL_insert(ref_path_table, new_node, &(new_node->objno)));
}
@@ -237,17 +262,17 @@ get_fake_xid (void) {
haddr_t
ref_path_table_gen_fake(const char *path)
{
- const char *dup_path;
haddr_t fake_objno;
- if((dup_path = HDstrdup(path)) == NULL)
- return HADDR_UNDEF;
-
/* Generate fake ID for string */
fake_objno = get_fake_xid();
- /* Insert "fake" object into table (takes ownership of path) */
- ref_path_table_put(dup_path, fake_objno);
+ /* Create ref path table, if it hasn't already been created */
+ if(ref_path_table == NULL)
+ init_ref_path_table();
+
+ /* Insert "fake" object into table */
+ ref_path_table_put(path, fake_objno);
return(fake_objno);
}
@@ -271,74 +296,19 @@ lookup_ref_path(haddr_t ref)
ref_path_node_t *node;
/* Be safer for h5ls */
- if(!ref_path_table)
+ if(thefile < 0)
return(NULL);
+ /* Create ref path table, if it hasn't already been created */
+ if(ref_path_table == NULL)
+ init_ref_path_table();
+
node = H5SL_search(ref_path_table, &ref);
return(node ? node->path : NULL);
}
/*-------------------------------------------------------------------------
- * Function: fill_ref_path_table_cb
- *
- * Purpose: Called by interator to create references for
- * all objects and enter them in the table.
- *
- * Return: Error status.
- *
- * Programmer: REMcG
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linfo,
- void *op_data)
-{
- if(linfo->type == H5L_TYPE_HARD) {
- H5O_info_t oinfo;
-
- H5Oget_info_by_name(group, obj_name, &oinfo, H5P_DEFAULT);
-
- /* Check if the object is already in the path table */
- if(!ref_path_table_find(oinfo.addr)) {
- const char *obj_prefix = (const char *)op_data;
- size_t tmp_len;
- char *thepath;
-
- /* Compute length for this object's path */
- tmp_len = HDstrlen(obj_prefix) + HDstrlen(obj_name) + 2;
-
- /* Allocate room for the path for this object */
- if((thepath = (char *)HDmalloc(tmp_len)) == NULL)
- return FAIL;
-
- /* Build the name for this object */
- HDstrcpy(thepath, obj_prefix);
- HDstrcat(thepath, "/");
- HDstrcat(thepath, obj_name);
-
- /* Insert the object into the path table (takes ownership of the path) */
- ref_path_table_put(thepath, oinfo.addr);
-
- if(oinfo.type == H5O_TYPE_GROUP) {
- /* Iterate over objects in this group, using this group's
- * name as their prefix
- */
- if(H5Literate_by_name(group, obj_name, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, thepath, H5P_DEFAULT) < 0) {
- error_msg(progname, "unable to dump group \"%s\"\n", thepath);
- d_status = EXIT_FAILURE;
- } /* end if */
- } /* end if */
- } /* end if */
- } /* end if */
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------
* Function: fill_ref_path_table
*
* Purpose: Called by interator to create references for
@@ -348,37 +318,15 @@ fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linf
*
* Programmer: REMcG
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
fill_ref_path_table(hid_t fid)
{
- H5O_info_t oinfo;
- char *root_path;
-
/* Set file ID for later queries (XXX: this should be fixed) */
thefile = fid;
- /* Create skip list to store reference path information */
- if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
- return (-1);
-
- /* Build the name for root group */
- root_path = HDstrdup("/");
-
- /* Get info for root group */
- H5Oget_info_by_name(fid, root_path, &oinfo, H5P_DEFAULT);
-
- /* Insert the root group into the path table (takes ownership of path) */
- ref_path_table_put(root_path, oinfo.addr);
-
- /* Iterate over objects in this file */
- if(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, (void *)"") < 0) {
- error_msg(progname, "unable to dump root group\n");
- d_status = EXIT_FAILURE;
- } /* end if */
+ /* Defer creating the ref path table until it's needed */
return 0;
}
diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c
index cb38e7a..512a3fb 100644
--- a/tools/lib/h5tools_utils.c
+++ b/tools/lib/h5tools_utils.c
@@ -30,6 +30,7 @@
#include "h5tools_utils.h"
#include "H5private.h"
+#include "h5trav.h"
/* global variables */
int nCols = 80;
@@ -44,10 +45,7 @@ static void init_table(table_t **tbl);
#ifdef H5DUMP_DEBUG
static void dump_table(char* tablename, table_t *table);
#endif /* H5DUMP_DEBUG */
-static void add_obj(table_t *table, haddr_t objno, char *objname, hbool_t recorded);
-static char * build_obj_path_name(const char *prefix, const char *name);
-static herr_t find_objs_cb(hid_t group, const char *name, const H5L_info_t *info,
- void *op_data);
+static void add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t recorded);
/*-------------------------------------------------------------------------
@@ -428,44 +426,15 @@ search_obj(table_t *table, haddr_t objno)
{
unsigned u;
- for (u = 0; u < table->nobjs; u++)
- if (table->objs[u].objno == objno)
- return &(table->objs[u]);
+ for(u = 0; u < table->nobjs; u++)
+ if(table->objs[u].objno == objno)
+ return &(table->objs[u]);
return NULL;
}
/*-------------------------------------------------------------------------
- * Function: build_obj_path_name
- *
- * Purpose: Allocate space & build path name from prefix & name
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static char *
-build_obj_path_name(const char *prefix, const char *name)
-{
- char *path;
-
- path = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2);
- HDstrcpy(path, prefix);
- HDstrcat(path,"/");
- HDstrcat(path,name); /* absolute name of the data set */
-
- return(path);
-} /* end build_obj_path_name() */
-
-
-/*-------------------------------------------------------------------------
* Function: find_objs_cb
*
* Purpose: Callback to find objects, committed types and store them in tables
@@ -481,90 +450,65 @@ build_obj_path_name(const char *prefix, const char *name)
*-------------------------------------------------------------------------
*/
static herr_t
-find_objs_cb(hid_t group, const char *name, const H5L_info_t UNUSED *linfo, void *op_data)
+find_objs_cb(const char *name, const H5O_info_t *oinfo, const char *already_seen,
+ void *op_data)
{
- H5O_info_t oinfo;
find_objs_t *info = (find_objs_t*)op_data;
herr_t ret_value = 0;
- if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0)
- ; /* keep going */
- else {
- switch(oinfo.type) {
- char *tmp;
- size_t tmp_len;
-
- case H5O_TYPE_GROUP:
- if(search_obj(info->group_table, oinfo.addr) == NULL) {
- char *old_prefix;
+ switch(oinfo->type) {
+ case H5O_TYPE_GROUP:
+ if(NULL == already_seen)
+ add_obj(info->group_table, oinfo->addr, name, TRUE);
+ break;
- tmp = build_obj_path_name(info->prefix, name);
- add_obj(info->group_table, oinfo.addr, tmp, TRUE);
+ case H5O_TYPE_DATASET:
+ if(NULL == already_seen) {
+ hid_t dset;
- old_prefix = info->prefix;
- tmp_len = HDstrlen(tmp);
- info->prefix = HDmalloc(tmp_len+1);
- HDstrcpy(info->prefix, tmp);
+ /* Add the dataset to the list of objects */
+ add_obj(info->dset_table, oinfo->addr, name, TRUE);
- if(H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info, H5P_DEFAULT) < 0)
- ret_value = FAIL;
+ /* Check for a dataset that uses a named datatype */
+ if((dset = H5Dopen2(info->fid, name, H5P_DEFAULT)) >= 0) {
+ hid_t type = H5Dget_type(dset);
- info->prefix = old_prefix;
- } /* end if */
- break;
-
- case H5O_TYPE_DATASET:
- if(search_obj(info->dset_table, oinfo.addr) == NULL) {
- hid_t dset;
-
- tmp = build_obj_path_name(info->prefix, name);
- add_obj(info->dset_table, oinfo.addr, tmp, TRUE);
-
- if((dset = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) {
- hid_t type;
+ if(H5Tcommitted(type) > 0) {
+ H5O_info_t type_oinfo;
- type = H5Dget_type(dset);
-
- if(H5Tcommitted(type) > 0) {
- H5Oget_info(type, &oinfo);
- if(search_obj(info->type_table, oinfo.addr) == NULL) {
- char *type_name = HDstrdup(tmp);
-
- add_obj(info->type_table, oinfo.addr, type_name, FALSE);
- } /* end if */
- } /* end if */
-
- H5Tclose(type);
- H5Dclose(dset);
+ H5Oget_info(type, &type_oinfo);
+ if(search_obj(info->type_table, type_oinfo.addr) == NULL)
+ add_obj(info->type_table, type_oinfo.addr, name, FALSE);
} /* end if */
- else
- ret_value = FAIL;
- } /* end if */
- break;
- case H5O_TYPE_NAMED_DATATYPE:
- {
- obj_t *found_obj;
-
- tmp = build_obj_path_name(info->prefix, name);
- if((found_obj = search_obj(info->type_table, oinfo.addr)) == NULL)
- add_obj(info->type_table, oinfo.addr, tmp, TRUE);
- else {
- /* Use latest version of name */
- HDfree(found_obj->objname);
- found_obj->objname = HDstrdup(tmp);
-
- /* Mark named datatype as having valid name */
- found_obj->recorded = TRUE;
- } /* end else */
- break;
- }
-
- default:
- /* Ignore links, etc. */
- break;
+ H5Tclose(type);
+ H5Dclose(dset);
+ } /* end if */
+ else
+ ret_value = FAIL;
+ } /* end if */
+ break;
+
+ case H5O_TYPE_NAMED_DATATYPE:
+ {
+ obj_t *found_obj;
+
+ if((found_obj = search_obj(info->type_table, oinfo->addr)) == NULL)
+ add_obj(info->type_table, oinfo->addr, name, TRUE);
+ else {
+ /* Use latest version of name */
+ HDfree(found_obj->objname);
+ found_obj->objname = HDstrdup(name);
+
+ /* Mark named datatype as having valid name */
+ found_obj->recorded = TRUE;
+ } /* end else */
+ break;
}
- } /* end else */
+
+ default:
+ break;
+ } /* end switch */
return ret_value;
}
@@ -589,31 +533,19 @@ herr_t
init_objs(hid_t fid, find_objs_t *info, table_t **group_table,
table_t **dset_table, table_t **type_table)
{
- H5O_info_t oinfo;
-
/* Initialize the tables */
init_table(group_table);
init_table(dset_table);
init_table(type_table);
/* Init the find_objs_t */
- info->prefix = HDcalloc(1, 1);
+ info->fid = fid;
info->group_table = *group_table;
info->type_table = *type_table;
info->dset_table = *dset_table;
- /* add the root group as an object, it may have hard links to it */
- if(H5Oget_info(fid, &oinfo) < 0)
- return FAIL;
- else {
- /* call with an empty string, it appends '/' group separator */
- char *tmp = build_obj_path_name(info->prefix, "");
-
- add_obj(info->group_table, oinfo.addr, tmp, TRUE);
- } /* end else */
-
/* Find all shared objects */
- return(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info));
+ return(h5trav_visit(fid, "/", TRUE, TRUE, find_objs_cb, NULL, info));
}
@@ -632,22 +564,22 @@ init_objs(hid_t fid, find_objs_t *info, table_t **group_table,
*-------------------------------------------------------------------------
*/
static void
-add_obj(table_t *table, haddr_t objno, char *objname, hbool_t record)
+add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t record)
{
unsigned u;
/* See if we need to make table larger */
- if (table->nobjs == table->size) {
+ if(table->nobjs == table->size) {
table->size *= 2;
- table->objs = HDrealloc(table->objs, table->size * sizeof(obj_t));
- }
+ table->objs = HDrealloc(table->objs, table->size * sizeof(table->objs[0]));
+ } /* end if */
/* Increment number of objects in table */
u = table->nobjs++;
/* Set information about object */
table->objs[u].objno = objno;
- table->objs[u].objname = objname;
+ table->objs[u].objname = HDstrdup(objname);
table->objs[u].recorded = record;
table->objs[u].displayed = 0;
}
diff --git a/tools/lib/h5tools_utils.h b/tools/lib/h5tools_utils.h
index e604e5a..e7b175c 100644
--- a/tools/lib/h5tools_utils.h
+++ b/tools/lib/h5tools_utils.h
@@ -95,7 +95,7 @@ typedef struct table_t {
/*this struct stores the information that is passed to the find_objs function*/
typedef struct find_objs_t {
- char *prefix;
+ hid_t fid;
table_t *group_table;
table_t *type_table;
table_t *dset_table;
diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c
index 97de021..14ced60 100644
--- a/tools/lib/h5trav.c
+++ b/tools/lib/h5trav.c
@@ -24,24 +24,25 @@
typedef struct trav_addr_t {
size_t nalloc;
size_t nused;
- haddr_t *addrs;
+ struct {
+ haddr_t addr;
+ char *path;
+ } *objs;
} trav_addr_t;
typedef struct {
- herr_t (*visit_obj)(const char *path_name, const H5O_info_t *oinfo, hbool_t already_visited, void *udata);
- herr_t (*visit_lnk)(const char *path_name, const H5L_info_t *linfo, void *udata);
+ h5trav_obj_func_t visit_obj; /* Callback for visiting objects */
+ h5trav_lnk_func_t visit_lnk; /* Callback for visiting links */
void *udata; /* User data to pass to callbacks */
} trav_visitor_t;
typedef struct {
trav_addr_t *seen; /* List of addresses seen already */
- const char *curr_path; /* Current path to parent group */
const trav_visitor_t *visitor; /* Information for visiting each link/object */
} trav_ud_traverse_t;
typedef struct {
hid_t fid; /* File ID being traversed */
- trav_table_t *table; /* Table for tracking name of objects with >1 hard link */
} trav_print_udata_t;
/*-------------------------------------------------------------------------
@@ -52,10 +53,8 @@ static void trav_table_add(trav_table_t *table,
const char *objname,
const H5O_info_t *oinfo);
-static size_t trav_table_search(const trav_table_t *table, haddr_t objno);
-
static void trav_table_addlink(trav_table_t *table,
- size_t j /* the object index */,
+ haddr_t objno,
const char *path);
/*-------------------------------------------------------------------------
@@ -78,19 +77,20 @@ static void trav_table_addlink(trav_table_t *table,
*-------------------------------------------------------------------------
*/
static void
-trav_addr_add(trav_addr_t *visited, haddr_t addr)
+trav_addr_add(trav_addr_t *visited, haddr_t addr, const char *path)
{
size_t idx; /* Index of address to use */
/* Allocate space if necessary */
if(visited->nused == visited->nalloc) {
visited->nalloc = MAX(1, visited->nalloc * 2);;
- visited->addrs = (haddr_t *)HDrealloc(visited->addrs, visited->nalloc * sizeof(haddr_t));
+ visited->objs = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0]));
} /* end if */
/* Append it */
idx = visited->nused++;
- visited->addrs[idx] = addr;
+ visited->objs[idx].addr = addr;
+ visited->objs[idx].path = HDstrdup(path);
} /* end trav_addr_add() */
@@ -107,7 +107,7 @@ trav_addr_add(trav_addr_t *visited, haddr_t addr)
*
*-------------------------------------------------------------------------
*/
-static hbool_t
+static const char *
trav_addr_visited(trav_addr_t *visited, haddr_t addr)
{
size_t u; /* Local index variable */
@@ -115,11 +115,11 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr)
/* Look for address */
for(u = 0; u < visited->nused; u++)
/* Check for address already in array */
- if(visited->addrs[u] == addr)
- return(TRUE);
+ if(visited->objs[u].addr == addr)
+ return(visited->objs[u].path);
/* Didn't find address */
- return(FALSE);
+ return(NULL);
} /* end trav_addr_visited() */
@@ -135,68 +135,44 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr)
*-------------------------------------------------------------------------
*/
static herr_t
-traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo,
+traverse_cb(hid_t loc_id, const char *path, const H5L_info_t *linfo,
void *_udata)
{
trav_ud_traverse_t *udata = (trav_ud_traverse_t *)_udata; /* User data */
- hbool_t is_group = FALSE; /* If the object is a group */
- hbool_t already_visited = FALSE; /* Whether the link/object was already visited */
- char *link_path; /* Full path name of a link */
+ char *full_name;
+ const char *already_visited = NULL; /* Whether the link/object was already visited */
- /* Construct the full path name of this link */
- link_path = (char*)HDmalloc(HDstrlen(udata->curr_path) + HDstrlen(link_name) + 2);
- HDassert(link_path);
- HDstrcpy(link_path, udata->curr_path);
- HDstrcat(link_path, "/");
- HDstrcat(link_path, link_name);
+ /* Create the full path name for the link */
+ full_name = HDmalloc(HDstrlen(path) + 2);
+ *full_name = '/';
+ HDstrcpy(full_name + 1, path);
/* Perform the correct action for different types of links */
if(linfo->type == H5L_TYPE_HARD) {
H5O_info_t oinfo;
/* Get information about the object */
- if(H5Oget_info_by_name(loc_id, link_name, &oinfo, H5P_DEFAULT) < 0)
+ if(H5Oget_info_by_name(loc_id, path, &oinfo, H5P_DEFAULT) < 0)
return(H5_ITER_ERROR);
/* If the object has multiple links, add it to the list of addresses
* already visited, if it isn't there already
*/
- if(oinfo.rc > 1) {
- already_visited = trav_addr_visited(udata->seen, oinfo.addr);
- if(!already_visited)
- trav_addr_add(udata->seen, oinfo.addr);
- } /* end if */
-
- /* Check if object is a group, for later */
- is_group = (oinfo.type == H5O_TYPE_GROUP) ? TRUE : FALSE;
+ if(oinfo.rc > 1)
+ if(NULL == (already_visited = trav_addr_visited(udata->seen, oinfo.addr)))
+ trav_addr_add(udata->seen, oinfo.addr, full_name);
/* Make 'visit object' callback */
if(udata->visitor->visit_obj)
- (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata);
+ (*udata->visitor->visit_obj)(full_name, &oinfo, already_visited, udata->visitor->udata);
} /* end if */
else {
/* Make 'visit link' callback */
if(udata->visitor->visit_lnk)
- (*udata->visitor->visit_lnk)(link_path, linfo, udata->visitor->udata);
+ (*udata->visitor->visit_lnk)(full_name, linfo, udata->visitor->udata);
} /* end else */
- /* Check for group that we haven't visited yet & recurse */
- if(is_group && !already_visited) {
- const char *prev_path = udata->curr_path; /* Previous path to link's parent group */
-
- /* Set current path to this object */
- udata->curr_path = link_path;
-
- /* Iterate over all links in group object */
- if(H5Literate_by_name(loc_id, link_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, udata, H5P_DEFAULT) < 0)
- return(H5_ITER_ERROR);
-
- /* Restore path in udata */
- udata->curr_path = prev_path;
- } /* end if */
-
- /* Free path name for current link/object */
- HDfree(link_path);
+ HDfree(full_name);
return(H5_ITER_CONT);
} /* end traverse_cb() */
@@ -217,39 +193,58 @@ traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo,
*-------------------------------------------------------------------------
*/
static int
-traverse(hid_t file_id, const trav_visitor_t *visitor)
+traverse(hid_t file_id, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, const trav_visitor_t *visitor)
{
- H5O_info_t oinfo; /* Object info for root group */
- trav_addr_t seen; /* List of addresses seen */
- trav_ud_traverse_t udata; /* User data for iteration callback */
+ H5O_info_t oinfo; /* Object info for starting group */
- /* Get info for root group */
- if(H5Oget_info(file_id, &oinfo) < 0)
+ /* Get info for starting object */
+ if(H5Oget_info_by_name(file_id, grp_name, &oinfo, H5P_DEFAULT) < 0)
return -1;
- /* Visit the root group of the file */
- (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata);
+ /* Visit the starting object */
+ if(visit_start && visitor->visit_obj)
+ (*visitor->visit_obj)(grp_name, &oinfo, NULL, visitor->udata);
- /* Init addresses seen */
- seen.nused = seen.nalloc = 0;
- seen.addrs = NULL;
+ /* Go visiting, if the object is a group */
+ if(oinfo.type == H5O_TYPE_GROUP) {
+ trav_addr_t seen; /* List of addresses seen */
+ trav_ud_traverse_t udata; /* User data for iteration callback */
- /* Check for multiple links to root group */
- if(oinfo.rc > 1)
- trav_addr_add(&seen, oinfo.addr);
+ /* Init addresses seen */
+ seen.nused = seen.nalloc = 0;
+ seen.objs = NULL;
- /* Set up user data structure */
- udata.seen = &seen;
- udata.curr_path = "";
- udata.visitor = visitor;
+ /* Check for multiple links to top group */
+ if(oinfo.rc > 1)
+ trav_addr_add(&seen, oinfo.addr, grp_name);
- /* Iterate over all links in root group */
- if(H5Literate(file_id, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata) < 0)
- return -1;
+ /* Set up user data structure */
+ udata.seen = &seen;
+ udata.visitor = visitor;
- /* Free visited addresses table */
- if(seen.addrs)
- HDfree(seen.addrs);
+ /* Check for iteration of links vs. visiting all links recursively */
+ if(recurse) {
+ /* Visit all links in group, recursively */
+ if(H5Lvisit_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, traverse_cb, &udata, H5P_DEFAULT) < 0)
+ return -1;
+ } /* end if */
+ else {
+ /* Iterate over links in group */
+ if(H5Literate_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0)
+ return -1;
+ } /* end else */
+
+ /* Free visited addresses table */
+ if(seen.objs) {
+ size_t u; /* Local index variable */
+
+ /* Free paths to objects */
+ for(u = 0; u < seen.nused; u++)
+ HDfree(seen.objs[u].path);
+ HDfree(seen.objs);
+ } /* end if */
+ } /* end if */
return 0;
}
@@ -301,7 +296,7 @@ trav_info_add(trav_info_t *info, const char *path, h5trav_type_t obj_type)
*/
static int
trav_info_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t UNUSED already_visited, void *udata)
+ const char UNUSED *already_visited, void *udata)
{
/* Add the object to the 'info' struct */
/* (object types map directly to "traversal" types) */
@@ -359,7 +354,7 @@ h5trav_getinfo(hid_t file_id, trav_info_t *info)
info_visitor.udata = info;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(file_id, &info_visitor) < 0)
+ if(traverse(file_id, "/", TRUE, TRUE, &info_visitor) < 0)
return -1;
return 0;
@@ -470,24 +465,17 @@ trav_info_free(trav_info_t *info)
*/
static int
trav_table_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t already_visited, void *udata)
+ const char *already_visited, void *udata)
{
trav_table_t *table = (trav_table_t *)udata;
/* Check if we've already seen this object */
- if(!already_visited)
+ if(NULL == already_visited)
/* add object to table */
trav_table_add(table, path, oinfo);
- else {
- size_t found; /* Index of original object seen */
-
- /* Look for object in existing table */
- found = trav_table_search(table, oinfo->addr);
- HDassert(found < table->nobjs);
-
+ else
/* Add alias for object to table */
- trav_table_addlink(table, found, path);
- } /* end else */
+ trav_table_addlink(table, oinfo->addr, path);
return(0);
} /* end trav_table_visit_obj() */
@@ -541,7 +529,7 @@ h5trav_gettable(hid_t fid, trav_table_t *table)
table_visitor.udata = table;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(fid, &table_visitor) < 0)
+ if(traverse(fid, "/", TRUE, TRUE, &table_visitor) < 0)
return -1;
return 0;
}
@@ -670,25 +658,33 @@ trav_table_add(trav_table_t *table,
*/
static void
-trav_table_addlink(trav_table_t *table,
- size_t j /* the object index */,
- const char *path)
+trav_table_addlink(trav_table_t *table, haddr_t objno, const char *path)
{
- size_t new;
+ size_t i; /* Local index variable */
- /* already inserted */
- if(HDstrcmp(table->objs[j].name, path) == 0)
- return;
+ for(i = 0; i < table->nobjs; i++) {
+ if(table->objs[i].objno == objno) {
+ size_t n;
- /* allocate space if necessary */
- if(table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) {
- table->objs[j].sizelinks = MAX(1, table->objs[j].sizelinks * 2);
- table->objs[j].links = (trav_link_t*)HDrealloc(table->objs[j].links, table->objs[j].sizelinks * sizeof(trav_link_t));
- } /* end if */
+ /* already inserted? */
+ if(HDstrcmp(table->objs[i].name, path) == 0)
+ return;
+
+ /* allocate space if necessary */
+ if(table->objs[i].nlinks == (unsigned)table->objs[i].sizelinks) {
+ table->objs[i].sizelinks = MAX(1, table->objs[i].sizelinks * 2);
+ table->objs[i].links = (trav_link_t*)HDrealloc(table->objs[i].links, table->objs[i].sizelinks * sizeof(trav_link_t));
+ } /* end if */
- /* insert it */
- new = table->objs[j].nlinks++;
- table->objs[j].links[new].new_name = (char *)HDstrdup(path);
+ /* insert it */
+ n = table->objs[i].nlinks++;
+ table->objs[i].links[n].new_name = (char *)HDstrdup(path);
+
+ return;
+ } /* end for */
+ } /* end for */
+
+ HDassert(0 && "object not in table?!?");
}
@@ -809,10 +805,8 @@ void trav_table_free( trav_table_t *table )
*/
static int
trav_print_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t already_visited, void *udata)
+ const char *already_visited, void UNUSED *udata)
{
- trav_print_udata_t *print_udata = (trav_print_udata_t *)udata;
-
/* Print the name of the object */
/* (no new-line, so that objects that we've encountered before can print
* the name of the original object)
@@ -836,26 +830,12 @@ trav_print_visit_obj(const char *path, const H5O_info_t *oinfo,
} /* end switch */
/* Check if we've already seen this object */
- if(!already_visited) {
+ if(NULL == already_visited)
/* Finish printing line about object */
printf("\n");
-
- /* Check if we will encounter another hard link to this object */
- if(oinfo->rc > 1) {
- /* Add object to table */
- trav_table_add(print_udata->table, path, oinfo);
- } /* end if */
- } /* end if */
- else {
- size_t found; /* Index of original object seen */
-
- /* Locate object in table */
- found = trav_table_search(print_udata->table, oinfo->addr);
- HDassert(found < print_udata->table->nobjs);
-
- /* Print the link's destination */
- printf(" -> %s\n", print_udata->table->objs[found].name);
- } /* end else */
+ else
+ /* Print the link's original name */
+ printf(" -> %s\n", already_visited);
return(0);
} /* end trav_print_visit_obj() */
@@ -938,16 +918,11 @@ trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata)
int
h5trav_print(hid_t fid)
{
- trav_table_t *table = NULL; /* Table for objects w/multiple hard links */
trav_print_udata_t print_udata; /* User data for traversal */
trav_visitor_t print_visitor; /* Visitor structure for printing objects */
- /* Initialize the table */
- trav_table_init(&table);
-
/* Init user data for printing */
print_udata.fid = fid;
- print_udata.table = table;
/* Init visitor structure */
print_visitor.visit_obj = trav_print_visit_obj;
@@ -955,11 +930,42 @@ h5trav_print(hid_t fid)
print_visitor.udata = &print_udata;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(fid, &print_visitor) < 0)
+ if(traverse(fid, "/", TRUE, TRUE, &print_visitor) < 0)
return -1;
- /* Free table */
- trav_table_free(table);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5trav_visit
+ *
+ * Purpose: Generic traversal routine for visiting objects and links
+ *
+ * Return: 0, -1 on error
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: November 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int
+h5trav_visit(hid_t fid, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk,
+ void *udata)
+{
+ trav_visitor_t visitor; /* Visitor structure for objects */
+
+ /* Init visitor structure */
+ visitor.visit_obj = visit_obj;
+ visitor.visit_lnk = visit_lnk;
+ visitor.udata = udata;
+
+ /* Traverse all objects in the file, visiting each object & link */
+ if(traverse(fid, grp_name, visit_start, recurse, &visitor) < 0)
+ return -1;
return 0;
}
diff --git a/tools/lib/h5trav.h b/tools/lib/h5trav.h
index 05bc3cb..5c07331 100644
--- a/tools/lib/h5trav.h
+++ b/tools/lib/h5trav.h
@@ -18,6 +18,12 @@
#include "hdf5.h"
+/* Typedefs for visiting objects */
+typedef herr_t (*h5trav_obj_func_t)(const char *path_name, const H5O_info_t *oinfo,
+ const char *first_seen, void *udata);
+typedef herr_t (*h5trav_lnk_func_t)(const char *path_name, const H5L_info_t *linfo,
+ void *udata);
+
/*-------------------------------------------------------------------------
* public enum to specify type of an object
* the TYPE can be:
@@ -101,6 +107,14 @@ extern "C" {
#endif
/*-------------------------------------------------------------------------
+ * "h5trav general" public functions
+ *-------------------------------------------------------------------------
+ */
+int h5trav_visit(hid_t file_id, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk,
+ void *udata);
+
+/*-------------------------------------------------------------------------
* "h5trav info" public functions
*-------------------------------------------------------------------------
*/