From aa87029f12e2b3110cee1d4f0f19bfe270f6fbfe Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 3 Dec 2004 22:36:08 -0500 Subject: [svn-r9615] Purpose: New feature Description: Add callback iteration routine to skip lists. Platforms tested: FreeBSD 4.10 (sleipnir) w/parallel Too minor to require h5committest --- src/H5SL.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ src/H5SLprivate.h | 7 +++++- test/tskiplist.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 130 insertions(+), 6 deletions(-) diff --git a/src/H5SL.c b/src/H5SL.c index 01a413f..fb406db 100644 --- a/src/H5SL.c +++ b/src/H5SL.c @@ -701,6 +701,67 @@ H5SL_item(H5SL_node_t *slist_node) /*-------------------------------------------------------------------------- NAME + H5SL_iterate + PURPOSE + Iterate over all nodes in a skip list + USAGE + herr_t H5SL_iterate(slist, op, op_data) + H5SL_t *slist; IN/OUT: Pointer to skip list to iterate over + H5SL_operator_t op; IN: Callback function for iteration + void *op_data; IN/OUT: Pointer to application data for callback + + RETURNS + Returns a negative value if something is wrong, the return + value of the last operator if it was non-zero, or zero if all + nodes were processed. + DESCRIPTION + Iterate over all the nodes in a skip list, calling an application callback + with the item, key and any operator data. + + The operator callback receives a pointer to the item and key for the list + being iterated over ('mesg'), and the pointer to the operator data passed + in to H5SL_iterate ('op_data'). The return values from an operator are: + A. Zero causes the iterator to continue, returning zero when all + nodes of that type have been processed. + B. Positive causes the iterator to immediately return that positive + value, indicating short-circuit success. + C. Negative causes the iterator to immediately return that value, + indicating failure. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data) +{ + H5SL_node_t *node; /* Pointers to skip list nodes */ + herr_t ret_value=0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_iterate); + + /* Check args */ + assert(slist); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Free skip list nodes */ + node=slist->header->forward[0]; + while(node!=NULL) { + /* Call the iterator callback */ + if((ret_value=(op)(node->item,node->key,op_data))!=0) + break; + + node=node->forward[0]; + } /* end while */ + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_iterate() */ + + +/*-------------------------------------------------------------------------- + NAME H5SL_release PURPOSE Release all nodes from a skip list diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index f2a4e24..633e3e5 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -50,6 +50,10 @@ typedef enum { /**********/ #define H5SL_LEVEL_MAX 32 /* (for now) */ +/* Typedef for iteration operations */ +typedef herr_t (*H5SL_operator_t)(void *item, void *key, + void *operator_data/*in,out*/); + /********************/ /* Private routines */ /********************/ @@ -61,8 +65,9 @@ H5_DLL void *H5SL_search(H5SL_t *slist, void *key); H5_DLL H5SL_node_t *H5SL_first(H5SL_t *slist); H5_DLL H5SL_node_t *H5SL_next(H5SL_node_t *slist_node); H5_DLL void *H5SL_item(H5SL_node_t *slist_node); +H5_DLL herr_t H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data); H5_DLL herr_t H5SL_release(H5SL_t *slist); H5_DLL herr_t H5SL_close(H5SL_t *slist); -#endif /* _H5HPprivate_H */ +#endif /* _H5SLprivate_H */ diff --git a/test/tskiplist.c b/test/tskiplist.c index 4d29d01..e9d7c48 100644 --- a/test/tskiplist.c +++ b/test/tskiplist.c @@ -446,12 +446,12 @@ test_skiplist_remove_many(void) /**************************************************************** ** -** test_skiplist_iterate(): Test H5SL (skip list) code. -** Tests iterating over nodes in skip list. +** test_skiplist_firstnext(): Test H5SL (skip list) code. +** Tests iterating over nodes in skip list with first/next calls. ** ****************************************************************/ static void -test_skiplist_iterate(void) +test_skiplist_firstnext(void) { H5SL_t *slist; /* Skip list created */ H5SL_node_t *node; /* Skip list node */ @@ -495,7 +495,7 @@ test_skiplist_iterate(void) ret=H5SL_close(slist); CHECK(ret, FAIL, "H5SL_close"); -} /* end test_skiplist_iterate() */ +} /* end test_skiplist_firstnext() */ /**************************************************************** ** @@ -576,6 +576,63 @@ test_skiplist_string(void) } /* end test_skiplist_string() */ +static herr_t +test_skiplist_iter(void *item, void UNUSED *key, void *op_data) +{ + size_t *up=(size_t *)op_data; + + VERIFY(*(int *)item,sort_rand_num[*up],"H5SL_iterate"); + (*up)++; + + return(0); +} + +/**************************************************************** +** +** test_skiplist_iterate(): Test H5SL (skip list) code. +** Tests iterating over nodes in skip list with callbacks. +** +****************************************************************/ +static void +test_skiplist_iterate(void) +{ + H5SL_t *slist; /* Skip list created */ + ssize_t num; /* Number of elements in skip list */ + size_t u; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Iterating Over Skip List\n")); + + /* Create a skip list */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Insert many objects into the skip list */ + for(u=0; u