/*
 *	gdataset.h
 *
 *	Keyed Data Lists, Datasets
 *
 *	* Tue May 31 22:28:49 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	- GLibのKeyed Data List(https://developer.gnome.org/glib/stable/glib-Keyed-Data-Lists.html),及び,Datasets(https://developer.gnome.org/glib/stable/glib-Datasets.html)を参考にしました。
 *	  関数仕様はオリジナル版と同じですが、実装は独自で、省メモリよりも単純な実装を優先しました。
 *	- オリジナル版は単純な配列を用いて省メモリを優先して実装されていますが、当実装ではght_hash_tableを利用して単純な実装を優先しました。
 *	  オリジナル版はGObject(GLibの基底クラス)で使用するために省メモリを最優先としているようですが、当ライブラリではユーティリティとして使う予定なので省メモリはさほど重要ではないからです。
 *	* Wed Jun 01 21:34:08 JST 2016 Naoyuki Sawa
 *	- gdataset.cの一番下に、データセットの使用例を追記しました。
 *	  データリストの使用例は書いていません。
 *	  実際にデータリストを直接使用する事はほとんど無く、データセットを介して利用する事しか無いと思うので、データリストの使用例は不要だと思います。
 *	  データリストの使用例が必要な場合は、データセットの実装からデータリストを利用している部分を参照して下さい。
 */
#ifndef __G_DATASET_H__
#define __G_DATASET_H__
#ifdef	__cplusplus
extern "C" {
#endif//__cplusplus
/*****************************************************************************
 *	Keyed Data Lists - lists of data elements which are accessible by a string or GQuark identifier
 *****************************************************************************/
typedef struct _GData GData;		//The GData struct is an opaque data structure to represent a Keyed Data List. It should only be accessed via the following functions.
#define G_DATALIST_FLAGS_MASK 3		//A bitmask that restricts the possible flags passed to g_datalist_set_flags(). Passing a flags value where flags & ~G_DATALIST_FLAGS_MASK != 0 is an error.
/*--------------------------------------------------------------------------*/
void g_datalist_init(GData** datalist);
#define g_datalist_id_set_data(dl,q,d)		g_datalist_id_set_data_full((dl),(q),(d),NULL)
void g_datalist_id_set_data_full(GData** datalist, /*GQuark*/int key_id, void* data, void (*destroy_func)(void* data));
void* g_datalist_id_get_data(GData** datalist, /*GQuark*/int key_id);
#define g_datalist_id_remove_data(dl,q)		g_datalist_id_set_data((dl),(q),NULL)
void* g_datalist_id_remove_no_notify(GData** datalist, /*GQuark*/int key_id);
void* g_datalist_id_dup_data(GData** datalist, /*GQuark*/int key_id, void* (*dup_func)(void* data, void* user_data), void* user_data);
int g_datalist_id_replace_data(GData** datalist, /*GQuark*/int key_id, void* oldval, void* newval, void (*destroy)(void* data), void (**old_destroy)(void* data));
#define g_datalist_set_data(dl,k,d)		g_datalist_set_data_full((dl),(k),(d),NULL)
#define g_datalist_set_data_full(dl,k,d,f)	g_datalist_id_set_data_full((dl),quark_from_string(k),(d),(f))
#define g_datalist_get_data(dl,k)		g_datalist_id_get_data(dl,quark_from_string(k))			//オリジナル版では文字列引数版の内これだけ何故か関数として実装されていたが、他との対称性のためにこれもマクロで実装するのが良いと思うので、当実装ではマクロとする事にした。
#define g_datalist_remove_data(dl,k)		g_datalist_id_set_data((dl),quark_from_string(k),NULL)		//オリジナル版ではg_quark_try_string()を使用していたが、当実装ではquark_from_string()を使用する事にした。g_quark_try_string()がNULLを返すようなケースでは、そのクォークはまだ存在しない,即ち,その文字列に対応するデータも未登録であるはずだから、どちらにしても結果はNULLになるはずである。両者の違いは無駄なクォークの登録が発生するかどうかだけであり、実用上は多少の無駄なクォークの登録が発生しても支障無いだろう。
#define g_datalist_remove_no_notify(dl,k)	g_datalist_id_remove_no_notify((dl),quark_from_string(k))	//オリジナル版ではg_quark_try_string()を使用していたが、当実装ではquark_from_string()を使用する事にした。g_quark_try_string()がNULLを返すようなケースでは、そのクォークはまだ存在しない,即ち,その文字列に対応するデータも未登録であるはずだから、どちらにしても結果はNULLになるはずである。両者の違いは無駄なクォークの登録が発生するかどうかだけであり、実用上は多少の無駄なクォークの登録が発生しても支障無いだろう。
void g_datalist_foreach(GData** datalist, void (*func)(/*GQuark*/int key_id, void* data, void* user_data), void* user_data);
void g_datalist_clear(GData** datalist);
void g_datalist_set_flags(GData** datalist, int flags);
void g_datalist_unset_flags(GData** datalist, int flags);
int g_datalist_get_flags(GData** datalist);
/*****************************************************************************
 *	Datasets - associate groups of data elements with particular memory locations
 *****************************************************************************/
#define g_dataset_id_set_data(l,k,d)		g_dataset_id_set_data_full((l),(k),(d),NULL)
void g_dataset_id_set_data_full(const void* dataset_location, /*GQuark*/int key_id, void* data, void (*destroy_func)(void* data));
void* g_dataset_id_get_data(const void* dataset_location, /*GQuark*/int key_id);
#define g_dataset_id_remove_data(l,k)		g_dataset_id_set_data((l),(k),NULL)
void* g_dataset_id_remove_no_notify(const void* dataset_location, /*GQuark*/int key_id);
#define g_dataset_set_data(l,k,d)		g_dataset_set_data_full((l),(k),(d),NULL)
#define g_dataset_set_data_full(l,k,d,f)	g_dataset_id_set_data_full((l),quark_from_string(k),(d),(f))
#define g_dataset_get_data(l,k)			g_dataset_id_get_data((l),quark_from_string(k))			//オリジナル版ではg_quark_try_string()を使用していたが、当実装ではquark_from_string()を使用する事にした。g_quark_try_string()がNULLを返すようなケースでは、そのクォークはまだ存在しない,即ち,その文字列に対応するデータも未登録であるはずだから、どちらにしても結果はNULLになるはずである。両者の違いは無駄なクォークの登録が発生するかどうかだけであり、実用上は多少の無駄なクォークの登録が発生しても支障無いだろう。
#define g_dataset_remove_data(l,k)		g_dataset_id_set_data((l),quark_from_string(k),NULL)		//オリジナル版ではg_quark_try_string()を使用していたが、当実装ではquark_from_string()を使用する事にした。g_quark_try_string()がNULLを返すようなケースでは、そのクォークはまだ存在しない,即ち,その文字列に対応するデータも未登録であるはずだから、どちらにしても結果はNULLになるはずである。両者の違いは無駄なクォークの登録が発生するかどうかだけであり、実用上は多少の無駄なクォークの登録が発生しても支障無いだろう。
#define g_dataset_remove_no_notify(l,k)		g_dataset_id_remove_no_notify((l),quark_from_string(k))		//オリジナル版ではg_quark_try_string()を使用していたが、当実装ではquark_from_string()を使用する事にした。g_quark_try_string()がNULLを返すようなケースでは、そのクォークはまだ存在しない,即ち,その文字列に対応するデータも未登録であるはずだから、どちらにしても結果はNULLになるはずである。両者の違いは無駄なクォークの登録が発生するかどうかだけであり、実用上は多少の無駄なクォークの登録が発生しても支障無いだろう。
void g_dataset_foreach(const void* dataset_location, void (*func)(/*GQuark*/int key_id, void* data, void* user_data), void* user_data);
void g_dataset_destroy(const void* dataset_location);
#ifdef	__cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__G_DATASET_H__
