
/*
** The "hash" data structure; a hash table
*/

#ifndef _DS_HASH_H_
#define _DS_HASH_H_

#include <odytypes.h>
#include <ds_list.h>

/*
   A hash table is a collection of ds_list_t's.
   They are not thread safe

   Hash tables have many of the same properties that lists do.
   It's probably necessary to understand ds_list_t to understand
   ds_hash_t.  In particular, the ordering function determines whether
   or not the buckets are sorted, and whether the member and duplicate
   tests use pointer-equality or the ordering function for equality.

*/

typedef struct ds_hash_t ds_hash_t;    /* opaque hashtable */

#ifdef __STDC__                       /* hash tables have hash functions */
typedef long (*HFN)(void*);
#else
typedef long (*HFN)();
#endif

/*
   The following operations are allowed on hash tables
*/

/*** Observers ***/

extern bool            ds_hash_valid    (ds_hash_t *t);
extern int             ds_hash_count    (ds_hash_t *t);
extern void           *ds_hash_first    (ds_hash_t *t, 
					 void *e);       
extern void           *ds_hash_last     (ds_hash_t *t, 
					 void *e);       
extern void           *ds_hash_member   (ds_hash_t *t, 
					 void *e); 

/*** Mutators ***/

extern ds_hash_t       *ds_hash_create     (COMPFN c,
					    HFN h,
					    int nbuckets,
					    bool safe_destroy,
					    bool dups_ok);
extern void             ds_hash_destroy    (ds_hash_t *t);
extern void            *ds_hash_insert     (ds_hash_t *t, void *e);
extern void            *ds_hash_append     (ds_hash_t *t, void *e);
extern void            *ds_hash_get_first  (ds_hash_t *t, void *e);
extern void            *ds_hash_get_last   (ds_hash_t *t, void *e);
extern void            *ds_hash_remove     (ds_hash_t *t, void *e);
					 
/*** Iterators ***/

typedef struct ds_hash_iter_t ds_hash_iter_t;  /* opaque */

/* 
   You can create an interator, destroy an iterator, or ask for the
   "next" element in the sequence.  Iterators and hash tables
   communicate with one another: if an iterator's "next" element is
   removed from the iterator's table, the iterator will be advanced
   one element.  Once an iterator has reached the end of the table
   (i.e.  ds_hash_iter_next returns NULL) it is considered closed: new
   items added to the table will not be picked up by the iterator.
   New items added to a table may or may not be picked up by the
   iterator.  Frankly, twiddling the table while the iterator is
   hooked up is kinda silly anyway.
*/

extern ds_hash_iter_t *ds_hash_iter_create  (ds_hash_t *t);
extern void            ds_hash_iter_destroy (ds_hash_iter_t *i);
extern void           *ds_hash_iter_next    (ds_hash_iter_t *i);

#endif /* _DS_HASH_H_ */

