/*
 *	ght_hash_table.h
 *
 *	Generic Hash Table (GHT)
 *
 *	* Sat Jun 06 15:36:36 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	- 「libghthash - Generic Hash Table (GHT)」(http://www.bth.se/people/ska/sim_home/libghthash.html)互換モジュールです。
 *	  関数仕様はlibghthashと同じで、実装は独自です。
 *	  オリジナル版のlibghthashは速度性能を重視して実装されているようですが、当実装は省メモリを優先して単純に実装しました。
 *	- 関数仕様や使用例は、オリジナル版のlibghthashのドキュメントを参照してください。
 *	  オリジナル版のlibghthashを、/clip/tool/libghthash.7z に保存しておきました。
 *	* Sun Jul 12 21:50:47 JST 2015 Naoyuki Sawa
 *	- ght_set_rehash(),ght_rehash()を対応しました。
 *	  速度性能を重視しない方針でこれらの関数には対応していませんでしたが、メモリ効率が改善するために対応する事にしました。
 *	  これまでは、ght_create()の引数に有る程度大きな値を指定する必要が有り、実際の要素数が少ない時に無駄が生じていました。
 *	  今後は、常に'ght_create(0);ght_set_rehash(p_ht,1)'で良く、要素数の増減に応じて自動的にテーブルサイズが調整されます。
 */
#ifndef __GHT_HASH_TABLE_H__
#define __GHT_HASH_TABLE_H__
/****************************************************************************
 *	
 ****************************************************************************/
typedef struct s_hash_entry {
	LIST_ENTRY		le_iterator;
	LIST_ENTRY		le_bucket;
	void*			p_entry_data;			//Entry data.
	int			i_key_size;			//The size in bytes of the key.
	unsigned char		key_data[0/*i_key_size*/];	//Key data.
} ght_hash_entry_t;
/*--------------------------------------------------------------------------*/
typedef struct {
	LIST_ENTRY*		le_next;			//The current entry.		//イテレータは次のノードを指しているので、イテレーションの中で当該ノードをght_remove()しても安全です。使用例はght_finalize()の実装を参照してください。
} ght_iterator_t;
/*--------------------------------------------------------------------------*/
typedef struct {
	struct {
	  unsigned		b_rehash	:1;		//Automatic rehashing status.
	} flag;
	LIST_ENTRY		le_iterator;
	int			i_table_size;			//The number of buckets.
	LIST_ENTRY*		le_bucket/*[i_table_size]*/;
} ght_hash_table_t;
/****************************************************************************
 *	
 ****************************************************************************/
ght_hash_table_t* ght_create(int i_table_size);
int ght_size(ght_hash_table_t* p_ht);
int ght_table_size(ght_hash_table_t* p_ht);
int ght_insert(ght_hash_table_t* p_ht, void* p_entry_data, int i_key_size, const void* p_key_data);
void* ght_replace(ght_hash_table_t* p_ht, void* p_entry_data, int i_key_size, const void* p_key_data);
void* ght_get(ght_hash_table_t* p_ht, int i_key_size, const void* p_key_data);
void* ght_remove(ght_hash_table_t* p_ht, int i_key_size, const void* p_key_data);
void* ght_first(ght_hash_table_t* p_ht, ght_iterator_t* p_iterator, const void** pp_key_data);
void* ght_first_keysize(ght_hash_table_t* p_ht, ght_iterator_t* p_iterator, const void** pp_key_data, int* p_key_size);
void* ght_next(ght_hash_table_t* p_ht, ght_iterator_t* p_iterator, const void** pp_key_data);
void* ght_next_keysize(ght_hash_table_t* p_ht, ght_iterator_t* p_iterator, const void** pp_key_data, int* p_key_size);
void ght_finalize(ght_hash_table_t* p_ht);
void ght_set_rehash(ght_hash_table_t* p_ht, int b_rehash);
void ght_rehash(ght_hash_table_t* p_ht, int i_table_size);
/*--------------------------------------------------------------------------*/
//未対応の関数と、未対応とした理由は、以下の通りです:
//・ght_set_alloc		malloc,free固定で充分だから。
//・ght_set_hash		One-at-a-Time Hash固定で充分だから。
//・ght_set_heuristics		速度性能は重視しないから。
//・ght_set_bounded_buckets	キャッシュとして使う予定は無いから。
//・ght_one_at_a_time_hash	One-at-a-Time Hash固定で充分だから。
//・ght_rotating_hash		One-at-a-Time Hash固定で充分だから。
//・ght_crc_hash		One-at-a-Time Hash固定で充分だから。
//・ght_print			デバッグ機能が必要な程複雑ではない。
#endif//__GHT_HASH_TABLE_H__
