Files
hdf5/src/H5ST.c
Quincey Koziol 92fd980ca9 [svn-r18595] Description:
Clean up compiler warnings

Tested on:
    Mac OS X/32 10.6.3 (amazon) w/debug
    (too minor to require h5committest)
2010-04-20 13:26:41 -05:00

794 lines
22 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* TERNARY SEARCH TREE ALGS
This code is described in "Ternary Search Trees" by Jon
Bentley and Robert Sedgewick in the April, 1998, Dr. Dobb's Journal.
*/
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
#include "H5STprivate.h" /* Ternary search trees */
/* Declare a free list to manage the H5ST_node_t struct */
H5FL_DEFINE_STATIC(H5ST_node_t);
/* Declare a free list to manage the H5ST_tree_t struct */
H5FL_DEFINE_STATIC(H5ST_tree_t);
/*--------------------------------------------------------------------------
NAME
H5ST_create
PURPOSE
Create a TST
USAGE
H5ST_ptr_t H5ST_create()
RETURNS
Returns a pointer to the new TST tree on success, NULL on failure.
DESCRIPTION
Create a TST.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
H5ST_tree_t *
H5ST_create(void)
{
H5ST_tree_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5ST_create, NULL)
/* Allocate wrapper for TST */
if(NULL == (ret_value = H5FL_MALLOC(H5ST_tree_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Set the internal fields */
ret_value->root = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_create() */
/*--------------------------------------------------------------------------
NAME
H5ST_close_internal
PURPOSE
Close a TST, deallocating it.
USAGE
herr_t H5ST_close(p)
H5ST_ptr_t p; IN/OUT: Root of TST to free
RETURNS
Returns non-negative on success, negative on failure.
DESCRIPTION
Close a TST, freeing all nodes.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
H5ST_close_internal(H5ST_ptr_t p)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_close_internal)
/* Recursively free TST */
if(p) {
H5ST_close_internal(p->lokid);
if(p->splitchar)
H5ST_close_internal(p->eqkid);
H5ST_close_internal(p->hikid);
p = H5FL_FREE(H5ST_node_t, p);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_close_internal() */
/*--------------------------------------------------------------------------
NAME
H5ST_close
PURPOSE
Close a TST, deallocating it.
USAGE
herr_t H5ST_close(tree)
H5ST_tree_t *tree; IN/OUT: TST tree to free
RETURNS
Returns non-negative on success, negative on failure.
DESCRIPTION
Close a TST, freeing all nodes.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
H5ST_close(H5ST_tree_t *tree)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5ST_close, FAIL)
/* Check arguments */
if(NULL == tree)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid TST")
/* Free the TST itself */
if(H5ST_close_internal(tree->root) < 0)
HGOTO_ERROR(H5E_TST, H5E_CANTFREE, FAIL, "can't free TST")
/* Free root node itself */
tree = H5FL_FREE(H5ST_tree_t, tree);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_close() */
/*--------------------------------------------------------------------------
NAME
H5ST_insert
PURPOSE
Insert a string/object pair into a TST
USAGE
herr_t H5ST_insert(tree,s,obj)
H5ST_tree_t *tree; IN/OUT: TST to insert string into
const char *s; IN: String to use as key for object
void *obj; IN: Pointer to object to insert
RETURNS
Returns non-negative on success, negative on failure.
DESCRIPTION
Insert a key (string)/object pair into a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
H5ST_insert(H5ST_tree_t *tree, const char *s, void *obj)
{
int d; /* Comparison value */
H5ST_ptr_t pp, *p; /* Pointer to current node and pointer to that */
H5ST_ptr_t parent=NULL; /* Pointer to parent node */
H5ST_ptr_t up=NULL; /* Pointer to up node */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5ST_insert,FAIL);
/* Find the correct location to insert object */
p = &tree->root;
while((pp = *p)) {
/* If this node matches the character in the key, then drop down to the lower tree */
if(0 == (d = *s - pp->splitchar)) {
if(*s++ == 0)
HGOTO_ERROR(H5E_TST, H5E_EXISTS, FAIL, "key already in tree")
up=pp;
p = &(pp->eqkid);
} /* end if */
else {
/* Walk through the current tree, searching for the matching character */
parent = pp;
if(d < 0)
p = &(pp->lokid);
else
p = &(pp->hikid);
} /* end else */
} /* end while */
/* Finish walking through the key string, adding nodes until the end */
for (;;) {
if(NULL == (*p = H5FL_MALLOC(H5ST_node_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
pp = *p;
pp->splitchar = *s;
pp->up = up;
pp->parent = parent;
pp->lokid = pp->eqkid = pp->hikid = NULL;
/* If this is the end of the key string, break out */
if(*s++ == 0) {
pp->eqkid = (H5ST_ptr_t)obj;
break;
} /* end if */
/* Continue to next character */
parent = NULL;
up = pp;
p = &(pp->eqkid);
} /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_insert() */
/*--------------------------------------------------------------------------
NAME
H5ST_search
PURPOSE
Determine if a key is in the TST
USAGE
hbool_t H5ST_search(tree,s)
H5ST_tree_t *tree; IN: TST to find string in
const char *s; IN: String to use as key to locate
RETURNS
Success: TRUE if key string in TST, FALSE if not
Failure: negative
DESCRIPTION
Locate a key (string) in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
htri_t
H5ST_search(H5ST_tree_t *tree, const char *s)
{
H5ST_ptr_t p; /* Temporary pointer to TST node */
htri_t ret_value=FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOFUNC(H5ST_search)
p = tree->root;
while (p) {
if (*s < p->splitchar)
p = p->lokid;
else if (*s == p->splitchar) {
if (*s++ == 0)
HGOTO_DONE(TRUE);
p = p->eqkid;
} else
p = p->hikid;
} /* end while */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_search() */
/*--------------------------------------------------------------------------
NAME
H5ST_find_internal
PURPOSE
Find the node matching a particular key string
USAGE
H5ST_ptr_t H5ST_find(p,s)
H5ST_ptr_t p; IN: TST to find string in
const char *s; IN: String to use as key to locate
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Locate a key (string) in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static H5ST_ptr_t
H5ST_find_internal(H5ST_ptr_t p, const char *s)
{
H5ST_ptr_t ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_find_internal)
while (p) {
if (*s < p->splitchar)
p = p->lokid;
else if (*s == p->splitchar) {
if (*s++ == 0)
HGOTO_DONE(p);
p = p->eqkid;
} else
p = p->hikid;
} /* end while */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_find_internal() */
/*--------------------------------------------------------------------------
NAME
H5ST_find
PURPOSE
Find the node matching a particular key string
USAGE
H5ST_ptr_t H5ST_find(tree,s)
H5ST_tree_t *tree; IN: TST to find string in
const char *s; IN: String to use as key to locate
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Locate a key (string) in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
H5ST_ptr_t
H5ST_find(H5ST_tree_t *tree, const char *s)
{
H5ST_ptr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5ST_find, NULL)
if(NULL == (ret_value = H5ST_find_internal(tree->root, s)))
HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_find() */
/*--------------------------------------------------------------------------
NAME
H5ST_locate
PURPOSE
Find an object in a TST
USAGE
void *H5ST_locate(tree,s)
H5ST_tree_t *tree; IN: TST to locate object within
const char *s; IN: String of key for object to locate
RETURNS
Success: Non-NULL, pointer to object stored for key
Failure: Negative
DESCRIPTION
Locate a node in a TST, returning the object from the node.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
void *
H5ST_locate(H5ST_tree_t *tree, const char *s)
{
H5ST_ptr_t node; /* Pointer to node located */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5ST_locate, NULL)
/* Locate the node to remove */
if(NULL == (node = H5ST_find_internal(tree->root, s)))
HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST")
/* Get the pointer to the object to return */
ret_value = node->eqkid;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5ST_locate() */
/*--------------------------------------------------------------------------
NAME
H5ST_findfirst_internal
PURPOSE
Find the first node in a TST
USAGE
H5ST_ptr_t H5ST_findfirst_internal(p)
H5ST_ptr_t p; IN: TST to locate first node within
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Get the first (lexicographically) node in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static H5ST_ptr_t
H5ST_findfirst_internal(H5ST_ptr_t p)
{
H5ST_ptr_t ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_findfirst_internal)
while(p) {
/* Find least node in current tree */
while(p->lokid)
p = p->lokid;
/* Is least node '\0'? */
if(p->splitchar == '\0') {
/* Return it */
HGOTO_DONE(p);
} /* end if */
else {
/* Go down to next level of tree */
p = p->eqkid;
} /* end else */
} /* end while */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_findfirst_internal() */
/*--------------------------------------------------------------------------
NAME
H5ST_findfirst
PURPOSE
Find the first node in a TST
USAGE
H5ST_ptr_t H5ST_findfirst(tree)
H5ST_tree_t *tree; IN: TST to locate first node within
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Get the first (lexicographically) node in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
H5ST_ptr_t
H5ST_findfirst(H5ST_tree_t *tree)
{
H5ST_ptr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5ST_findfirst, NULL)
if(NULL == (ret_value = H5ST_findfirst_internal(tree->root)))
HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"no nodes in TST");
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_findfirst() */
/*--------------------------------------------------------------------------
NAME
H5ST_getnext
PURPOSE
Internal routine to find the next node in a given level of a TST
USAGE
H5ST_ptr_t H5ST_getnext(p)
H5ST_ptr_t *p; IN: Pointer to node to find next node from
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Get the next (lexicographically) node in the current level of a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static H5ST_ptr_t
H5ST_getnext(H5ST_ptr_t p)
{
H5ST_ptr_t ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_getnext)
/* If the node to continue from has higher-valued nodes attached */
if(p->hikid) {
/* Go to first higher-valued node */
p = p->hikid;
/* Find least node from here */
while(p->lokid)
p = p->lokid;
HGOTO_DONE(p);
} /* end if */
else {
H5ST_ptr_t q; /* Temporary TST node pointer */
/* Go up one level in current tree */
q = p->parent;
if(q == NULL)
HGOTO_DONE(NULL);
/* While the previous node was the higher-valued node, keep backing up the tree */
while(q->hikid == p) {
p = q;
q = p->parent;
if(NULL == q)
HGOTO_DONE(NULL);
} /* end while */
HGOTO_DONE(q);
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_getnext() */
/*--------------------------------------------------------------------------
NAME
H5ST_findnext
PURPOSE
Find the next node from a node in a TST
USAGE
H5ST_ptr_t H5ST_findnext(p)
H5ST_ptr_t p; IN: Current node to continue from
RETURNS
Success: Non-NULL
Failure: NULL
DESCRIPTION
Get the next (lexicographically) node in a TST
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
H5ST_ptr_t
H5ST_findnext(H5ST_ptr_t p)
{
H5ST_ptr_t q; /* Temporary pointer to TST node */
H5ST_ptr_t ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOFUNC(H5ST_findnext)
/* Find the next node at the current level, or go back up the tree */
do {
q = H5ST_getnext(p);
if(q) {
HGOTO_DONE(H5ST_findfirst_internal(q->eqkid));
} /* end if */
else
p = p->up;
} while(p);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_findnext() */
/*--------------------------------------------------------------------------
NAME
H5ST_delete_internal
PURPOSE
Delete a node from a TST
USAGE
herr_t H5ST_delete_internal(root,p)
H5ST_ptr_t *root; IN/OUT: Root of TST to delete node from
H5ST_ptr_t p; IN: Node to delete
RETURNS
Success: Non-negative
Failure: Negative
DESCRIPTION
Delete a node from a TST.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
This should be the final node for a string.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
H5ST_delete_internal(H5ST_ptr_t *root, H5ST_ptr_t p)
{
H5ST_ptr_t q, /* Temporary pointer to TST node */
newp; /* Pointer to node which will replace deleted node in tree */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_delete_internal)
/* Find node to replace one being deleted */
if(p->lokid) {
/* If the deleted node has lo & hi kids, attach them together */
if(p->hikid) {
q = p->lokid;
while(q->hikid)
q = q->hikid;
q->hikid = p->hikid;
p->hikid->parent = q;
} /* end if */
newp = p->lokid;
} /* end if */
else if(p->hikid) {
newp = p->hikid;
} /* end if */
else {
newp = NULL;
} /* end else */
/* Deleted node is in middle of tree */
if(p->parent) {
/* Attach new node to correct side of parent */
if(p == p->parent->lokid)
p->parent->lokid = newp;
else
p->parent->hikid = newp;
if(newp)
newp->parent = p->parent;
} /* end if */
else {
if(newp)
newp->parent = p->parent;
if(p->up) {
p->up->eqkid = newp;
/* If we deleted the last node in the TST, delete the upper node also */
if(NULL == newp)
H5ST_delete_internal(root, p->up);
} /* end if */
else /* Deleted last node at top level of tree */
*root = newp;
} /* end else */
p = H5FL_FREE(H5ST_node_t, p);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_delete_internal() */
/*--------------------------------------------------------------------------
NAME
H5ST_delete
PURPOSE
Delete a node from a TST
USAGE
herr_t H5ST_delete(tree,p)
H5ST_tree_t *tree; IN/OUT: TST to delete node from
H5ST_ptr_t p; IN: Node to delete
RETURNS
Success: Non-negative
Failure: Negative
DESCRIPTION
Delete a node from a TST.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
This should be the final node for a string.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
H5ST_delete(H5ST_tree_t *tree, H5ST_ptr_t p)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5ST_delete, FAIL)
if(H5ST_delete_internal(&tree->root, p) < 0)
HGOTO_ERROR(H5E_TST, H5E_CANTDELETE, FAIL, "can't delete node from TST")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_delete() */
/*--------------------------------------------------------------------------
NAME
H5ST_remove
PURPOSE
Remove a node from a TST
USAGE
void *H5ST_remove(tree,s)
H5ST_tree_t *tree; IN/OUT: TST to remove node from
const char *s; IN: String of key for node to remove
RETURNS
Success: Non-NULL, pointer to object stored for key
Failure: Negative
DESCRIPTION
Remove a node from a TST, returning the object from the node.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
void *
H5ST_remove(H5ST_tree_t *tree, const char *s)
{
H5ST_ptr_t node; /* Pointer to node to remove */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5ST_remove, NULL)
/* Locate the node to remove */
if(NULL == (node = H5ST_find_internal(tree->root, s)))
HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST")
/* Get the pointer to the object to return */
ret_value = node->eqkid;
/* Remove the node from the TST */
if(H5ST_delete_internal(&tree->root, node) < 0)
HGOTO_ERROR(H5E_TST, H5E_CANTDELETE, NULL, "can't delete node from TST")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5ST_remove() */
#ifdef H5ST_DEBUG
/*--------------------------------------------------------------------------
NAME
H5ST_dump_internal
PURPOSE
Dump all the nodes of a TST
USAGE
herr_t H5ST_dump(p)
H5ST_ptr_t p; IN: Root of TST to dump
RETURNS
Success: Non-negative
Failure: Negative
DESCRIPTION
Dump information for a TST.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
H5ST_dump_internal(H5ST_ptr_t p)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_dump_internal)
if(p) {
printf("p=%p\n", p);
printf("\tp->up=%p\n", p->up);
printf("\tp->parent=%p\n", p->parent);
printf("\tp->lokid=%p\n", p->lokid);
printf("\tp->hikid=%p\n", p->hikid);
printf("\tp->eqkid=%p\n", p->eqkid);
printf("\tp->splitchar=%c\n", p->splitchar);
H5ST_dump_internal(p->lokid);
if(p->splitchar)
H5ST_dump_internal(p->eqkid);
else
printf("%s\n", (char *)p->eqkid);
H5ST_dump_internal(p->hikid);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_dump_internal() */
/*--------------------------------------------------------------------------
NAME
H5ST_dump
PURPOSE
Dump all the nodes of a TST
USAGE
herr_t H5ST_dump(tree)
H5ST_tree_t *tree; IN: TST to dump
RETURNS
Success: Non-negative
Failure: Negative
DESCRIPTION
Dump information for a TST.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
H5ST_dump(H5ST_tree_t *tree)
{
FUNC_ENTER_NOAPI_NOFUNC(H5ST_dump, NULL)
/* Dump the tree */
H5ST_dump_internal(tree->root);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_dump() */
#endif /* H5ST_DEBUG */