#ifndef HTABLE_INCLUDE_H
#define HTABLE_INCLUDE_H

#ifdef  __cplusplus
extern "C" {
#endif

#include "iterator.h"

/*--------------------------------------------------------------------------*/
typedef struct HTABLE		HTABLE;
typedef struct HTABLE_INFO 	HTABLE_INFO;

/**
 * ϣṹ
 */
struct HTABLE {
	int     size;                   /* length of entries array */
	int     init_size;              /* length of initial entryies array */
	int     used;                   /* number of entries in table */
	HTABLE_INFO **data;             /* entries array, auto-resized */
	int     status;                 /* the operator's status on the htable */

	/* for iterator */

	/* ȡͷ */
	void *(*iter_head)(ITER*, struct HTABLE*);
	/* ȡһ */
	void *(*iter_next)(ITER*, struct HTABLE*);
	/* ȡβ */
	void *(*iter_tail)(ITER*, struct HTABLE*);
	/* ȡһ */
	void *(*iter_prev)(ITER*, struct HTABLE*);
	/* ȡĵǰԱṹ */
	HTABLE_INFO *(*iter_info)(ITER*, struct HTABLE*);
};

/**
 * ϣÿһϣĴ洢Ϣ
 */
struct HTABLE_INFO {
	char *key;
	void *value;			/**< associated value */
	unsigned hash;			/**< store the key's hash value */
	struct HTABLE_INFO *next;	/**< colliding entry */
	struct HTABLE_INFO *prev;	/**< colliding entry */
};

/**
 * ϣ
 * @param size ϣ
 * @return ϣͷָΪ(ʱʾصĴ, Ҫڴ)
 */
HTABLE *htable_create(int size);

/**
 * һιϣϣ״̬
 * @param table ϣָ
 * @return {int} ϣ״̬, μµ HTABLE_STAT_XXX
 */
int htable_errno(HTABLE *table);
#define	HTABLE_STAT_OK          0  /**< ״̬ */
#define	HTABLE_STAT_INVAL       1  /**< Ч */
#define	HTABLE_STAT_DUPLEX_KEY  2  /**< ظ */

/**
 * ùϣĵǰ״̬, error ȡֵ HTABLE_STAT_XXX
 * @param table ϣָ
 * @param error ùϣĴ״̬
 */
void htable_set_errno(HTABLE *table, int error);

/**
 * ϣµ
 * @param table ϣָ
 * @param key , ںڲḴƴ key 
 * @param value ûԼض(Ӳת, Ǵ
 *  ܶջ)
 * @return Ĺϣָ, == NULL: ʾڲڴ, ΪصĴ
 *  עʱùϣڣ򷵻ѾڵĹϣʹӦͨ
 *  htable_last_errno() 鿴Ƿظͬһֵ(HTABLE_STAT_DUPLEX_KEY)
 */
HTABLE_INFO *htable_enter(HTABLE *table, const char *key, void *value);

/**
 *  key Ѱĳһضϣ
 * @param table ϣָ
 * @param key 
 * @return Ϊָ: ʾ鵽˶Ӧ key Ĺϣ
 *         Ϊ: ʾδ鵽Ӧ key Ĺϣ
 */
HTABLE_INFO *htable_locate(HTABLE *table, const char *key);

/**
 *  key Ѱû
 * @param table ϣָ
 * @param key 
 * @return Ϊ: ʾ鵽˶Ӧ key , ûԸûԼ
 *  ͽת; Ϊ: ʾδ鵽Ӧ key 
 */
void *htable_find(HTABLE *table, const char *key);

/**
 *  key ɾĳһϣ
 * @param table ϣָ
 * @param key 
 * @param free_fn úָ벻Ϊղҵ˶Ӧ key , 
 *  ûṩһЩβ, ȻͷŸùϣ
 * @return 0: ɹ;  -1: δҵ key 
 */
int htable_delete(HTABLE *table, const char *key, void (*free_fn) (void *));

/**
 * ֱӸ htable_locate صķǿնӹϣɾö
 * @param table ϣָ
 * @param ht {HTABLE_INFO*} 洢ڹϣеڲṹ
 * @param free_fn úָ벻Ϊղҵ˶Ӧ key , 
 *  ûṩһЩβ, ȻͷŸùϣ
 */
void htable_delete_entry(HTABLE *table, HTABLE_INFO *ht, void (*free_fn) (void *));

/**
 * ͷϣ
 * @param table ϣָ
 * @param free_fn ָ벻ΪԹϣеÿһϣøú
 *  β, Ȼͷ
 */
void htable_free(HTABLE *table, void (*free_fn) (void *));

/**
 * ùϣ, úͷŹϣе, ³ʼ
 * @param table ϣָ
 * @param free_fn ָ벻ΪԹϣеÿһϣøú
 *  β, Ȼͷ
 * @return Ƿóɹ. 0: OK; < 0: error.
 */
int htable_reset(HTABLE *table, void (*free_fn) (void *));

/**
 * Թϣеÿһϣд
 * @param table ϣָ
 * @param walk_fn ÿһϣĺָ, Ϊ
 * @param arg ûԼ͵
 */
void htable_walk(HTABLE *table, void (*walk_fn) (HTABLE_INFO *, void *), void *arg);

/**
 * عϣǰռС
 * @param table ϣָ
 * @return ϣռС
 */
int htable_size(const HTABLE *table);

/**
 * عϣǰԪظ
 * @param table ϣָ
 * @return ϣԪظ
 */
int htable_used(const HTABLE *table);

/**
 * ϣϳһ
 * @param table ϣ
 * @return Ϊ: ָ; Ϊ: ʾùϣûйϣ
 */
HTABLE_INFO **htable_list(const HTABLE *table);

/**
 * ʾϣ key ķֲ״̬
 * @param table ϣָ
 */
void htable_stat(const HTABLE *table);
#define	htable_stat_r	htable_stat

/*--------------------  һЩݵĺ --------------------------------*/

#define	HTABLE_ITER_KEY(iter)	((iter).ptr->key.c_key)
#define	htable_iter_key		HTABLE_ITER_KEY

#define	HTABLE_ITER_VALUE(iter)	((iter).ptr->value)
#define	htable_iter_value	HTABLE_ITER_VALUE

#ifdef  __cplusplus
}
#endif

#endif
