
#ifndef __HTABLE_H_INCLUDED__
#define __HTABLE_H_INCLUDED__

#ifdef  __cplusplus
extern "C" {
#endif

#include "private.h"

#define	HAS_VALUE

/*--------------------------------------------------------------------------*/
/**
 * ϣͶ
 * @param buffer Ҫϣַ
 * @param len s ĳ
 */
typedef unsigned (*HASH_FN)(const void *buffer, size_t len);

/**
 * ϣṹ, Ͷ htable.c Ϊ˱ڲԱ
 */
typedef struct HTABLE	HTABLE;

/**
 * ϣÿһϣĴ洢Ϣ
 */
#ifdef  PACK_STRUCT
#pragma pack(4)
#endif
typedef struct HTABLE_INFO {
	union {
		char   *key;
		const char *c_key;
	} key;				/**< lookup key */
#ifdef	HAS_VALUE
	char   *value;			/**< associated value */
#endif
	struct HTABLE_INFO *next;	/**< colliding entry */
	struct HTABLE_INFO *prev;	/**< colliding entry */
} HTABLE_INFO;
#ifdef  PACK_STRUCT
#pragma pack(0)
#endif

/**
 * ϣ
 * @param size ϣ
 * @param flag  ACL_MDT_IDX е flag ͬ
 * @return ϣͷָΪ(ʱʾصĴ, Ҫڴ)
 */
HTABLE *htable_create(int size, unsigned int flag, int use_slice);

/**
 * ùϣĿƲ
 * @param table ϣ
 * @param name Ʋıγʼֵ, name ԺĿƲ¶
 *  HTABLE_CTL_END: α־
 *  HTABLE_CTL_RWLOCK: Ƿöд
 *  HTABLE_CTL_HASH_FN: ûԶĹϣֵ㺯
 */
void htable_ctl(HTABLE *table, int name, ...);
#define	HTABLE_CTL_END      0  /**< ƽ־ */
#define	HTABLE_CTL_HASH_FN  2  /**< ˽йϣ */

/**
 * һιϣϣ״̬
 * @param table ϣָ
 * @return {int} ϣ״̬, μµ HTABLE_STAT_XXX
 */
int htable_last_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, char *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 
 */
char *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) (char *));

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

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

/**
 * عϣǰռС(ֵӦڹϣԪظ)
 * @param table ϣָ
 * @return ϣռС
 */
int htable_capacity(const HTABLE *table);

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

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

void htable_list_free(HTABLE_INFO ** list);

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

#ifdef  __cplusplus
}
#endif

#endif

