summaryrefslogtreecommitdiffstats
path: root/src/H5G.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5G.c')
-rw-r--r--src/H5G.c721
1 files changed, 373 insertions, 348 deletions
diff --git a/src/H5G.c b/src/H5G.c
index 1b7a700..f5162e0 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -4,21 +4,62 @@
*
*-------------------------------------------------------------------------
*
- * Created: H5G.c
- * Jul 18 1997
- * Robb Matzke <matzke@llnl.gov>
+ * Created: H5G.c
+ * Jul 18 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Symbol table functions. The functions that begin with
+ * `H5G_stab_' don't understand the naming system; they operate
+ * on a single symbol table at a time.
+ *
+ * The functions that begin with `H5G_node_' operate on the leaf
+ * nodes of a symbol table B-tree. They should be defined in
+ * the H5Gnode.c file.
+ *
+ * The remaining functions know how to traverse the group
+ * directed graph.
+ *
+ * Names: Object names are a slash-separated list of components. If
+ * the name begins with a slash then it's absolute, otherwise
+ * it's relative ("/foo/bar" is absolute while "foo/bar" is
+ * relative). Multiple consecutive slashes are treated as
+ * single slashes and trailing slashes are ignored. The special
+ * case `/' is the root group. Every file has a root group.
+ *
+ * API functions that look up names take a location ID and a
+ * name. The location ID can be a file ID or a group ID and the
+ * name can be relative or absolute.
+ *
+ * +--------------+----------- +--------------------------------+
+ * | Location ID | Name | Meaning |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "/foo/bar" | Find `foo' within `bar' within |
+ * | | | the root group of the specified|
+ * | | | file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "foo/bar" | Find `foo' within `bar' within |
+ * | | | the current working group of |
+ * | | | the specified file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "/" | The root group of the specified|
+ * | | | file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "." | The current working group of |
+ * | | | the specified file. |
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "/foo/bar" | Find `foo' within `bar' within |
+ * | | | the root group of the file |
+ * | | | containing the specified group.|
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "foo/bar" | File `foo' within `bar' within |
+ * | | | the specified group. |
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "/" | The root group of the file |
+ * | | | containing the specified group.|
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "." | The specified group. |
+ * +--------------+------------+--------------------------------+
*
- * Purpose: Symbol table functions. The functions that
- * begin with `H5G_stab_' don't understand the
- * naming system; they operate on a single
- * symbol table at a time.
- *
- * The functions that begin with `H5G_node_' operate
- * on the leaf nodes of a symbol table B-tree. They
- * should be defined in the H5Gnode.c file.
- *
- * The remaining functions know how to traverse the
- * group directed graph
*
* Modifications:
*
@@ -30,7 +71,7 @@
*
*-------------------------------------------------------------------------
*/
-#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
+#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
/* Packages needed by this file... */
#include <H5private.h>
@@ -47,19 +88,17 @@
#define PABLO_MASK H5G_mask
/* Interface initialization */
-static hbool_t interface_initialize_g = FALSE;
+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 herr_t H5G_init_interface(void);
+static void H5G_term_interface(void);
-static H5G_entry_t *H5G_getcwg(H5F_t *f);
/*-------------------------------------------------------------------------
* Function: H5Gcreate
*
- * Purpose: Creates a new group in FILE and gives it the specified
- * NAME. Unless NAME begins with `/' it is relative to the
- * current working group. The group is opened for write access
+ * Purpose: Creates a new group relative to LOC_ID and gives it the
+ * specified NAME. The group is opened for write access
* and it's object ID is returned.
*
* The optional SIZE_HINT specifies how much file space to
@@ -85,24 +124,24 @@ static H5G_entry_t *H5G_getcwg(H5F_t *f);
*-------------------------------------------------------------------------
*/
hid_t
-H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
+H5Gcreate(hid_t loc_id, const char *name, size_t size_hint)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *loc = NULL;
+ H5G_t *grp = NULL;
hid_t ret_value = FAIL;
FUNC_ENTER(H5Gcreate, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given");
}
+
/* Create the group */
- if (NULL == (grp = H5G_create(f, name, size_hint))) {
+ if (NULL == (grp = H5G_create(loc, name, size_hint))) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group");
}
if ((ret_value = H5I_register(H5_GROUP, grp)) < 0) {
@@ -112,6 +151,7 @@ H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gopen
@@ -133,24 +173,24 @@ H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
*-------------------------------------------------------------------------
*/
hid_t
-H5Gopen(hid_t file_id, const char *name)
+H5Gopen(hid_t loc_id, const char *name)
{
- hid_t ret_value = FAIL;
- H5F_t *f = NULL;
- H5G_t *grp = NULL;
+ hid_t ret_value = FAIL;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gopen, FAIL);
/* Check args */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
+
/* Open the group */
- if (NULL == (grp = H5G_open(f, name))) {
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group");
}
/* Register an atom for the group */
@@ -161,6 +201,7 @@ H5Gopen(hid_t file_id, const char *name)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gclose
@@ -198,6 +239,7 @@ H5Gclose(hid_t grp_id)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gset
@@ -211,6 +253,8 @@ H5Gclose(hid_t grp_id)
* handles, then each handle's current working group can be
* set independently of the other file handles for that file.
*
+ * The initial current working group is the root group.
+ *
* See also: H5Gpush(), H5Gpop()
*
* Errors:
@@ -227,35 +271,37 @@ H5Gclose(hid_t grp_id)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gset(hid_t file_id, const char *name)
+H5Gset(hid_t loc_id, const char *name)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gset, FAIL);
/* Check/fix arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
- if (NULL == (grp = H5G_open(f, name))) {
+
+ /* Set the current working group */
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_ARGS, H5E_NOTFOUND, FAIL, "no such group");
}
- /* Set the current working group */
- if (H5G_set(f, grp) < 0) {
+ if (H5G_set(grp) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
"unable to change current working group");
}
+
/* Close the handle */
- if (H5G_close(grp) < 0) {
+ if (H5G_close(grp)<0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close group");
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gpush
@@ -285,26 +331,26 @@ H5Gset(hid_t file_id, const char *name)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gpush(hid_t file_id, const char *name)
+H5Gpush(hid_t loc_id, const char *name)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gpush, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
- if (NULL == (grp = H5G_open(f, name))) {
+
+ /* Push group onto stack */
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_ARGS, H5E_NOTFOUND, FAIL, "no such group");
}
- /* Push group onto stack */
- if (H5G_push(f, grp) < 0) {
+ if (H5G_push(grp) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
"can't change current working group");
}
@@ -314,6 +360,7 @@ H5Gpush(hid_t file_id, const char *name)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gpop
@@ -327,6 +374,9 @@ H5Gpush(hid_t file_id, const char *name)
* handles, then each handle's current working group can be
* set independently of the other file handles for that file.
*
+ * If LOC_ID is a group ID then it's used only to determine the
+ * file from which to pop.
+ *
* See also: H5Gset(), H5Gpush()
*
* Errors:
@@ -345,21 +395,20 @@ H5Gpush(hid_t file_id, const char *name)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gpop(hid_t file_id)
+H5Gpop(hid_t loc_id)
{
- H5F_t *f = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gpop, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
+
/* pop */
- if (H5G_pop(f) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "stack is empty");
+ if (H5G_pop(H5G_fileof (loc))<0) {
+ HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "stack is empty");
}
FUNC_LEAVE(SUCCEED);
}
@@ -368,8 +417,8 @@ H5Gpop(hid_t file_id)
/*-------------------------------------------------------------------------
* Function: H5Giterate
*
- * Purpose: Iterates over the entries of a group. The FILE_ID and NAME
- * identify the group over which to iterate and INDEX indicates
+ * Purpose: Iterates over the entries of a group. The LOC_ID and NAME
+ * identify the group over which to iterate and IDX indicates
* where to start iterating (zero means at the beginning). The
* OPERATOR is called for each member and the iteration
* continues until the operator returns non-zero or all members
@@ -393,25 +442,24 @@ H5Gpop(hid_t file_id)
*-------------------------------------------------------------------------
*/
herr_t
-H5Giterate (hid_t file_id, const char *name, int *index,
+H5Giterate (hid_t loc_id, const char *name, int *idx,
H5G_iterate_t op, void *op_data)
{
- H5F_t *f = NULL;
- int _index = 0;
+ int _idx = 0;
H5G_bt_ud2_t udata;
herr_t ret_value = FAIL;
+ H5G_t *loc = NULL;
FUNC_ENTER (H5Giterate, FAIL);
/* Check args */
- if (H5_FILE!=H5I_group (file_id) ||
- NULL==(f=H5I_object (file_id))) {
- HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
}
- if (!index) index = &_index;
+ if (!idx) idx = &_idx;
if (!op) {
HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified");
}
@@ -420,7 +468,7 @@ H5Giterate (hid_t file_id, const char *name, int *index,
* Open the group on which to operate. We also create a group ID which
* we can pass to the application-defined operator.
*/
- if (NULL==(udata.group = H5G_open (f, name))) {
+ if (NULL==(udata.group = H5G_open (loc, name))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to open group");
}
if ((udata.group_id=H5I_register (H5_GROUP, udata.group))<0) {
@@ -430,12 +478,12 @@ H5Giterate (hid_t file_id, const char *name, int *index,
}
/* Build udata to pass through H5B_iterate() to H5G_node_iterate() */
- udata.skip = *index;
+ udata.skip = *idx;
udata.op = op;
udata.op_data = op_data;
/* Iterate over the group members */
- if ((ret_value = H5B_iterate (f, H5B_SNODE,
+ if ((ret_value = H5B_iterate (H5G_fileof(udata.group), H5B_SNODE,
&(udata.group->ent.cache.stab.btree_addr),
&udata))<0) {
HERROR (H5E_SYM, H5E_CANTINIT, "iteration operator failed");
@@ -482,6 +530,7 @@ H5G_init_interface(void)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_term_interface
@@ -502,6 +551,7 @@ H5G_term_interface(void)
{
H5I_destroy_group(H5_GROUP);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_component
@@ -525,17 +575,16 @@ H5G_term_interface(void)
*
*-------------------------------------------------------------------------
*/
-static const char *
+static const char *
H5G_component(const char *name, size_t *size_p)
{
assert(name);
- while ('/' == *name)
- name++;
- if (size_p)
- *size_p = HDstrcspn(name, "/");
+ while ('/' == *name) name++;
+ if (size_p) *size_p = HDstrcspn(name, "/");
return name;
}
+
/*-------------------------------------------------------------------------
* Function: H5G_namei
@@ -566,22 +615,14 @@ H5G_component(const char *name, size_t *size_p)
* GRP_ENT has an undefined object header address, and GRP_ENT
* is the symbol table entry for `bar' in `/foo'.
*
- * If a file contains more than one object, then `/' is the name
- * of the root object which is a group. Otherwise, a file can
- * consist of a single object, not necessarily a group, whose
- * name is `/foo' where `foo' is the value of the name messsage
- * in the object header. A file can also contain no objects in
- * which case the function returns so REST points to the
- * beginning of NAME and OBJ_ENT and GRP_ENT contain undefined
- * header addresses.
- *
- * Components of a name are separated from one another by one or
- * more slashes (/). Slashes at the end of a name are ignored.
- * If the name begins with a slash then the search begins at the
- * root object, otherwise it begins at the group CWG, otherwise
- * it begins at the current working group of file F. The
- * component `.' is a no-op, but `..' is not understood by this
- * function (unless it appears as an entry in the symbol table).
+ * Every file has a root group whose name is `/'. Components of
+ * a name are separated from one another by one or more slashes
+ * (/). Slashes at the end of a name are ignored. If the name
+ * begins with a slash then the search begins at the root group
+ * of the file containing LOC_ENT. Otherwise it begins at
+ * LOC_ENT. The component `.' is a no-op, but `..' is not
+ * understood by this function (unless it appears as an entry in
+ * the symbol table).
*
* Errors:
*
@@ -602,15 +643,13 @@ H5G_component(const char *name, size_t *size_p)
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
- const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/,
- H5G_entry_t *obj_ent/*out*/)
+H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
+ H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/)
{
H5G_entry_t _grp_ent; /*entry for current group */
H5G_entry_t _obj_ent; /*entry found */
size_t nchars; /*component name length */
char comp[1024]; /*component name buffer */
- hbool_t aside = FALSE; /*did we look at a name message?*/
/* clear output args before FUNC_ENTER() in case it fails */
if (rest) *rest = name;
@@ -623,36 +662,43 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
FUNC_ENTER(H5G_namei, FAIL);
- /* check args */
- assert(f);
- assert(name && *name);
-
- /* If the file contains no objects then return failure */
- if (!f->shared->root_ent) {
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no root group");
- }
- /* starting point */
- if ('/' == *name) {
- *obj_ent = *(f->shared->root_ent);
- } else if (cwg) {
- *obj_ent = *cwg;
- } else if ((cwg = H5G_getcwg(f))) {
- *obj_ent = *cwg;
+ /*
+ * Where does the searching start? For absolute names it starts at the
+ * root of the file; for relative names it starts at CWG.
+ */
+ if (!name || !*name) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no name given");
+ } else if (!loc_ent) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
+ "no current working group");
+ } else if ('/' == *name) {
+ *obj_ent = loc_ent->file->shared->root_grp->ent;
} else {
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group");
+ *obj_ent = *loc_ent;
}
- assert(H5F_addr_defined(&(obj_ent->header)));
/* traverse the name */
while ((name = H5G_component(name, &nchars)) && *name) {
- if (rest)
- *rest = name;
+ if (rest) *rest = name;
+
+ /*
+ * Copy the component name into a null-terminated buffer so
+ * we can pass it down to the other symbol table functions.
+ */
+ if (nchars+1 > sizeof(comp)) {
+ HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, FAIL,
+ "component is too long");
+ }
+ HDmemcpy(comp, name, nchars);
+ comp[nchars] = '\0';
/*
* The special name `.' is a no-op.
*/
- if ('.' == name[0] && !name[1])
+ if ('.' == comp[0] && !comp[1]) {
+ name += nchars;
continue;
+ }
/*
* Advance to the next component of the name.
@@ -661,68 +707,35 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
HDmemset(obj_ent, 0, sizeof(H5G_entry_t));
H5F_addr_undef(&(obj_ent->header));
- /*
- * Copy the component name into a null-terminated buffer so
- * we can pass it down to the other symbol table functions.
- */
- if (nchars + 1 > sizeof(comp)) {
- HRETURN_ERROR(H5E_SYM, H5E_COMPLEN, FAIL, "component is too long");
- }
- HDmemcpy(comp, name, nchars);
- comp[nchars] = '\0';
-
- if (H5G_stab_find(grp_ent, comp, obj_ent /*out */ ) < 0) {
+ if (H5G_stab_find(grp_ent, comp, obj_ent/*out*/)<0) {
/*
* Component was not found in the current symbol table, possibly
- * because GRP_ENT isn't a symbol table. If it is the root symbol
- * then see if it has the appropriate name field. The ASIDE
- * variable prevents us from saying `/foo/foo' where the root object
- * has the name `foo'.
+ * because GRP_ENT isn't a symbol table.
*/
- H5O_name_t mesg =
- {0};
- if (!aside &&
- H5F_addr_eq(&(grp_ent->header),
- &(f->shared->root_ent->header)) &&
- H5O_read(grp_ent, H5O_NAME, 0, &mesg) &&
- !HDstrcmp(mesg.s, comp)) {
- H5O_reset(H5O_NAME, &mesg);
- *obj_ent = *grp_ent;
- HDmemset(grp_ent, 0, sizeof(H5G_entry_t));
- H5F_addr_undef(&(grp_ent->header));
- aside = TRUE;
- } else {
- H5O_reset(H5O_NAME, &mesg);
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
- }
+ HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
}
/* next component */
name += nchars;
}
- if (rest)
- *rest = name; /*final null */
+ if (rest) *rest = name; /*final null */
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_mkroot
*
- * Purpose: Creates the root group if it doesn't exist; otherwise
- * nothing happens. If the root symbol table entry previously
- * pointed to something other than a group, then that object
- * is made a member of the root group and is given a name
- * corresponding to the object's name message (the name message
- * is removed). If the root object doesn't have a name message
- * then the name `Root Object' is used.
+ * Purpose: Creates a root group in an empty file and opens it. If a
+ * root group is already open then this function immediately
+ * returnes. If ENT is non-null then it's the symbol table
+ * entry for an existing group which will be opened as the root
+ * group. Otherwise a new root group is created and then
+ * opened.
*
- * Errors:
- *
* Return: Success: SUCCEED
*
- * Failure: FAIL. This function returns -2 if the
- * failure is because a root group already
- * exists.
+ * Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -732,88 +745,68 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5G_mkroot(H5F_t *f, size_t size_hint)
+herr_t
+H5G_mkroot (H5F_t *f, H5G_entry_t *ent)
{
- herr_t ret_value = FAIL; /*return value */
- H5O_name_t name =
- {NULL}; /*object name */
- H5O_stab_t stab; /*symbol table message */
- H5G_entry_t new_root; /*new root object */
- const char *obj_name = NULL; /*name of old root object */
+ H5G_entry_t new_root; /*new root object */
+ H5O_stab_t stab; /*symbol table message */
FUNC_ENTER(H5G_mkroot, FAIL);
/* check args */
assert(f);
+ if (f->shared->root_grp) return SUCCEED;
/*
- * If we already have a root object, then get it's name.
+ * If there is no root object then create one. The root group always has
+ * a hard link count of one since it's pointed to by the boot block.
*/
- if (f->shared->root_ent) {
- if (H5O_read(f->shared->root_ent, H5O_STAB, 0, &stab)) {
- HGOTO_ERROR(H5E_SYM, H5E_EXISTS, -2, "root group already exists");
- } else if (NULL == H5O_read(f->shared->root_ent, H5O_NAME, 0, &name)) {
- obj_name = "Root Object";
- } else {
- obj_name = name.s; /*don't reset message until the end! */
+ if (!ent) {
+ ent = &new_root;
+ if (H5G_stab_create (f, 16, ent/*out*/)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
+ "unable to create root group");
}
- }
- /*
- * Create the new root group. Set the link count to 1.
- */
- if (H5G_stab_create(f, size_hint, &new_root /*out */ ) < 0) {
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cant create root");
- }
- if (1 != H5O_link(&new_root, 1)) {
- HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL,
- "internal error (wrong link count)");
- }
- /*
- * If there was a previous root object then insert it into the new root
- * symbol table with the specified name. Then make the root object the
- * new symbol table.
- */
- if (f->shared->root_ent) {
- assert(1 == H5O_link(f->shared->root_ent, 0));
-
- if (H5G_stab_insert(&new_root, obj_name, f->shared->root_ent) < 0) {
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "can't reinsert old root object");
+ if (1 != H5O_link (ent, 1)) {
+ HRETURN_ERROR (H5E_SYM, H5E_LINK, FAIL,
+ "internal error (wrong link count)");
}
+ } else {
/*
- * Remove all `name' messages from the old root object. The only time
- * a name message should ever appear is to give the root object a name,
- * but the old root object is no longer the root object.
+ * Open the root object as a group.
*/
- H5O_remove(f->shared->root_ent, H5O_NAME, H5O_ALL);
- H5E_clear(); /*who really cares? */
-
- *(f->shared->root_ent) = new_root;
-
- } else {
- f->shared->root_ent = H5G_ent_calloc(&new_root);
+ if (H5O_open (ent)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, FAIL,
+ "unable to open root group");
+ }
+ if (NULL==H5O_read (ent, H5O_STAB, 0, &stab)) {
+ H5O_close (ent);
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
+ "root object is not a group");
+ }
+ H5O_reset (H5O_STAB, &stab);
}
- H5O_close(&new_root);
- ret_value = SUCCEED;
+ /*
+ * Create the group pointer. Also decrement the open object count so we
+ * don't count the root group as an open object. The root group will
+ * never be closed.
+ */
+ f->shared->root_grp = H5MM_xcalloc (1, sizeof(H5G_t));
+ f->shared->root_grp->ent = *ent;
+ f->shared->root_grp->nref = 1;
+ assert (1==f->nopen);
+ f->nopen = 0;
- done:
- H5O_reset(H5O_NAME, &name);
- FUNC_LEAVE(ret_value);
+ FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_create
*
* Purpose: Creates a new empty group with the specified name. The name
- * is either an absolute name or is relative to the current
- * working group.
- *
- * A root group is created implicitly by this function
- * when necessary. Calling this function with the name "/"
- * (or any equivalent name) will result in an H5E_EXISTS
- * failure.
+ * is either an absolute name or is relative to LOC.
*
* Errors:
*
@@ -832,32 +825,22 @@ H5G_mkroot(H5F_t *f, size_t size_hint)
*-------------------------------------------------------------------------
*/
H5G_t *
-H5G_create(H5F_t *f, const char *name, size_t size_hint)
+H5G_create(H5G_t *loc, const char *name, size_t size_hint)
{
const char *rest = NULL; /*the base name */
H5G_entry_t grp_ent; /*group containing new group */
char _comp[1024]; /*name component */
size_t nchars; /*number of characters in compon*/
- herr_t status; /*function return status */
H5G_t *grp = NULL; /*new group */
FUNC_ENTER(H5G_create, NULL);
/* check args */
- assert(f);
+ assert(loc);
assert(name && *name);
- /*
- * Try to create the root group. Ignore the error if this function
- * fails because the root group already exists.
- */
- if ((status=H5G_mkroot(f, H5G_SIZE_HINT))<0 && -2!=status) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create root group");
- }
- H5E_clear();
-
/* lookup name */
- if (0 == H5G_namei(f, NULL, name, &rest, &grp_ent, NULL)) {
+ if (0 == H5G_namei(H5G_entof(loc), name, &rest, &grp_ent, NULL)) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, NULL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
@@ -881,7 +864,7 @@ H5G_create(H5F_t *f, const char *name, size_t size_hint)
/* create an open group */
grp = H5MM_xcalloc(1, sizeof(H5G_t));
- if (H5G_stab_create(f, size_hint, &(grp->ent)/*out*/) < 0) {
+ if (H5G_stab_create(grp_ent.file, size_hint, &(grp->ent)/*out*/) < 0) {
grp = H5MM_xfree(grp);
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create grp");
}
@@ -914,7 +897,7 @@ H5G_create(H5F_t *f, const char *name, size_t size_hint)
*-------------------------------------------------------------------------
*/
H5G_t *
-H5G_open(H5F_t *f, const char *name)
+H5G_open(H5G_t *loc, const char *name)
{
H5G_t *grp = NULL;
H5G_t *ret_value = NULL;
@@ -923,15 +906,15 @@ H5G_open(H5F_t *f, const char *name)
FUNC_ENTER(H5G_open, NULL);
/* Check args */
- assert(f);
+ assert(loc);
assert(name && *name);
/* Open the object, making sure it's a group */
grp = H5MM_xcalloc(1, sizeof(H5G_t));
- if (H5G_find(f, name, NULL, &(grp->ent)) < 0) {
+ if (H5G_find(loc, name, NULL, &(grp->ent)/*out*/) < 0) {
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "group not found");
}
- if (H5O_open(f, &(grp->ent)) < 0) {
+ if (H5O_open(&(grp->ent)) < 0) {
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group");
}
if (NULL==H5O_read (&(grp->ent), H5O_STAB, 0, &mesg)) {
@@ -947,6 +930,7 @@ H5G_open(H5F_t *f, const char *name)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_reopen
@@ -964,7 +948,7 @@ H5G_open(H5F_t *f, const char *name)
*
*-------------------------------------------------------------------------
*/
-H5G_t *
+H5G_t *
H5G_reopen(H5G_t *grp)
{
FUNC_ENTER(H5G_reopen, NULL);
@@ -976,6 +960,7 @@ H5G_reopen(H5G_t *grp)
FUNC_LEAVE(grp);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_close
@@ -1003,6 +988,7 @@ H5G_close(H5G_t *grp)
assert(grp->nref > 0);
if (1 == grp->nref) {
+ assert (grp!=H5G_fileof(grp)->shared->root_grp);
if (H5O_close(&(grp->ent)) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close");
}
@@ -1011,6 +997,7 @@ H5G_close(H5G_t *grp)
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_set
@@ -1041,13 +1028,15 @@ H5G_close(H5G_t *grp)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_set(H5F_t *f, H5G_t *grp)
+H5G_set (H5G_t *grp)
{
+ H5F_t *f;
+
FUNC_ENTER(H5G_set, FAIL);
/* check args */
- assert(f);
assert(grp);
+ f = H5G_fileof (grp);
/*
* If there is no stack then create one, otherwise close the current
@@ -1056,25 +1045,23 @@ H5G_set(H5F_t *f, H5G_t *grp)
if (!f->cwg_stack) {
f->cwg_stack = H5MM_xcalloc(1, sizeof(H5G_cwgstk_t));
} else if (H5G_close(f->cwg_stack->grp) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CWG, FAIL, "couldn't close previous c.w.g.");
+ HRETURN_ERROR(H5E_SYM, H5E_CWG, FAIL,
+ "couldn't close previous current working group");
}
- f->cwg_stack->grp = H5G_reopen(grp);
+ f->cwg_stack->grp = H5G_reopen (grp);
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_getcwg
*
- * Purpose: Returns a ptr to the symbol table entry for the current
- * working group. If there is no current working group then a
- * pointer to the root symbol is returned. If there is no root
- * symbol then the null pointer is returned.
- *
- * Return: Success: Ptr to the current working group or root
- * object. The pointer is valid only until the
- * root object changes or the current working
- * group changes.
+ * Purpose: Returns the current working group.
+ *
+ * Return: Success: The current working group. This group should
+ * not* be closed with H5G_close() when the
+ * caller is done with it.
*
* Failure: NULL
*
@@ -1085,25 +1072,25 @@ H5G_set(H5F_t *f, H5G_t *grp)
*
*-------------------------------------------------------------------------
*/
-static H5G_entry_t *
+H5G_t *
H5G_getcwg(H5F_t *f)
{
- H5G_entry_t *ret_value = NULL;
+ H5G_t *ret_value = NULL;
FUNC_ENTER(H5G_getcwg, NULL);
/* check args */
assert(f);
- /* return a pointer directly into the stack */
- if (f->cwg_stack && f->cwg_stack->grp) {
- ret_value = &(f->cwg_stack->grp->ent);
+ if (f->cwg_stack) {
+ ret_value = f->cwg_stack->grp;
} else {
- ret_value = f->shared->root_ent;
+ ret_value = f->shared->root_grp;
}
-
+
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_push
@@ -1112,8 +1099,6 @@ H5G_getcwg(H5F_t *f)
* is reopened and held open until it is removed from the stack.
*
* Errors:
- * SYM CWG Can't open group.
- * SYM CWG Not a group.
*
* Return: Success: SUCCEED
*
@@ -1127,14 +1112,13 @@ H5G_getcwg(H5F_t *f)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_push(H5F_t *f, H5G_t *grp)
+H5G_push (H5G_t *grp)
{
- H5G_cwgstk_t *stack = NULL;
+ H5G_cwgstk_t *stack = NULL;
FUNC_ENTER(H5G_push, FAIL);
/* check args */
- assert(f);
assert(grp);
/*
@@ -1142,20 +1126,21 @@ H5G_push(H5F_t *f, H5G_t *grp)
*/
stack = H5MM_xcalloc(1, sizeof(H5G_cwgstk_t));
stack->grp = H5G_reopen(grp);
- stack->next = f->cwg_stack;
- f->cwg_stack = stack;
+ stack->next = H5G_fileof(grp)->cwg_stack;
+ H5G_fileof(grp)->cwg_stack = stack;
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_pop
*
- * Purpose: Pops the top current working group off the stack.
+ * Purpose: Pops the top current working group off the stack. If the
+ * stack becomes empty then the current working group is
+ * implicitly the root group.
*
* Errors:
- * SYM CWG Can't close current working group.
- * SYM CWG Stack is empty.
*
* Return: Success: SUCCEED
*
@@ -1169,7 +1154,7 @@ H5G_push(H5F_t *f, H5G_t *grp)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_pop(H5F_t *f)
+H5G_pop (H5F_t *f)
{
H5G_cwgstk_t *stack = NULL;
@@ -1192,12 +1177,12 @@ H5G_pop(H5F_t *f)
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_insert
*
- * Purpose: Inserts a symbol table entry into the group graph. The file
- * that is used is contained in the ENT argument.
+ * Purpose: Inserts a symbol table entry into the group graph.
*
* Errors:
*
@@ -1213,46 +1198,29 @@ H5G_pop(H5F_t *f)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_insert(const char *name, H5G_entry_t *ent)
+H5G_insert(H5G_t *loc, const char *name, H5G_entry_t *ent)
{
const char *rest = NULL; /*part of name not existing yet */
H5G_entry_t grp; /*entry for group to contain obj */
size_t nchars; /*number of characters in name */
char _comp[1024]; /*name component */
- hbool_t update_grp;
- herr_t status;
FUNC_ENTER(H5G_insert, FAIL);
/* Check args. */
- assert(name && *name);
- assert(ent);
+ assert (loc);
+ assert (name && *name);
+ assert (ent);
/*
* Look up the name -- it shouldn't exist yet.
*/
- if (H5G_namei(ent->file, NULL, name, &rest, &grp, NULL) >= 0) {
+ if (H5G_namei(H5G_entof(loc), name, &rest, &grp, NULL) >= 0) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
rest = H5G_component(rest, &nchars);
- if (!rest || !*rest) {
- /*
- * The caller is attempting to insert a root object that either
- * doesn't have a name or we shouldn't interfere with the name
- * it already has as a message.
- */
- if (ent->file->shared->root_ent) {
- HRETURN_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "root exists");
- }
- if (1 != H5O_link(ent, 1)) {
- HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "bad link count");
- }
- ent->name_off = 0;
- ent->file->shared->root_ent = H5G_ent_calloc(ent);
- HRETURN(SUCCEED);
- }
/*
* There should be one component left. Make sure it's null
* terminated.
@@ -1269,40 +1237,9 @@ H5G_insert(const char *name, H5G_entry_t *ent)
rest = _comp;
}
}
- if (!ent->file->shared->root_ent) {
- /*
- * This will be the only object in the file. Insert it as the root
- * object and add a name messaage to the object header (or modify
- * the first one we find).
- */
- H5O_name_t name_mesg;
- name_mesg.s = rest;
- if (H5O_modify(ent, H5O_NAME, 0, 0, &name_mesg) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "cannot add/change name message");
- }
- if (1 != H5O_link(ent, 1)) {
- HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "bad link count");
- }
- ent->file->shared->root_ent = H5G_ent_calloc(ent);
- HRETURN(SUCCEED);
- }
- /*
- * Make sure the root group exists. Ignore the failure if it's
- * because the group already exists.
- */
- update_grp = (hbool_t)H5F_addr_eq(&(grp.header),
- &(ent->file->shared->root_ent->header));
- if ((status = H5G_mkroot(ent->file, H5G_SIZE_HINT)) < 0 && -2 != status) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create root group");
- }
- H5E_clear();
- if (update_grp==TRUE)
- grp = *(ent->file->shared->root_ent);
/*
- * This is the normal case. The object is just being inserted as a normal
- * entry into a symbol table.
+ * The object into a symbol table.
*/
if (H5O_link(ent, 1) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "link inc failure");
@@ -1312,23 +1249,19 @@ H5G_insert(const char *name, H5G_entry_t *ent)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_find
*
- * Purpose: Finds an object with the specified NAME in file F. If
- * the name is relative then it is interpretted relative
- * to the current working group. On successful return,
- * GRP_ENT (if non-null) will be initialized with the symbol
- * table information for the group in which the object
- * appears (it will have an undefined object header address if
- * the object is the root object) and OBJ_ENT will be
+ * Purpose: Finds an object with the specified NAME at location LOC. On
+ * successful return, GRP_ENT (if non-null) will be initialized
+ * with the symbol table information for the group in which the
+ * object appears (it will have an undefined object header
+ * address if the object is the root object) and OBJ_ENT will be
* initialized with the symbol table entry for the object
* (OBJ_ENT is optional when the caller is interested only in
- * the existence of the object).
- *
- * This function will fail if the root object is requested and
- * there is none.
+ * the existence of the object).
*
* Errors:
*
@@ -1346,17 +1279,109 @@ H5G_insert(const char *name, H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_find(H5F_t *f, const char *name,
- H5G_entry_t *grp_ent /*out */ , H5G_entry_t *obj_ent /*out */ )
+H5G_find(H5G_t *loc, const char *name,
+ H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/)
{
FUNC_ENTER(H5G_find, FAIL);
/* check args */
- assert(f);
- assert(name && *name);
+ assert (loc);
+ assert (name && *name);
- if (H5G_namei(f, NULL, name, NULL, grp_ent, obj_ent) < 0) {
+ if (H5G_namei(H5G_entof(loc), name, NULL, grp_ent, obj_ent) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
}
FUNC_LEAVE(SUCCEED);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_entof
+ *
+ * Purpose: Returns a pointer to the entry for a group.
+ *
+ * Return: Success: Ptr to group entry
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_entof (H5G_t *grp)
+{
+ return grp ? &(grp->ent) : NULL;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_fileof
+ *
+ * Purpose: Returns the file to which the specified group belongs.
+ *
+ * Return: Success: File pointer.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_t *
+H5G_fileof (H5G_t *grp)
+{
+ assert (grp);
+ return grp->ent.file;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_loc
+ *
+ * Purpose: Given a location ID return a group. The group should not be
+ * closed.
+ *
+ * Return: Success: Group pointer.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_t *
+H5G_loc (hid_t loc_id)
+{
+ H5F_t *f;
+ H5G_t *ret_value = NULL;
+
+ FUNC_ENTER (H5G_loc, NULL);
+
+ if (H5_FILE==H5I_group (loc_id)) {
+ if (NULL==(f=H5I_object (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid file ID");
+ }
+ if (NULL==(ret_value=H5G_getcwg (f))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL,
+ "unable to get current working directory");
+ }
+ } else if (H5_GROUP==H5I_group (loc_id)) {
+ if (NULL==(ret_value=H5I_object (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid group ID");
+ }
+ } else {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, NULL, "not a location");
+ }
+
+ FUNC_LEAVE (ret_value);
+}