/*	
 *	clipwkst.h
 *
 *	ワークシート(多階層ハッシュテーブル)
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2015-2016 Naoyuki Sawa
 *
 *	* Mon Jul 13 21:22:16 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	* Wed Jul 15 01:12:55 JST 2015 Naoyuki Sawa
 *	- Worksheet_ref_l(),Worksheet_ref_a(),Worksheet_ref_v()を追加しました。
 *	- Worksheet_sum_l(),Worksheet_sum_a(),Worksheet_sum_v()を追加しました。
 *	* Thu Jul 16 22:21:18 JST 2015 Naoyuki Sawa
 *	- Worksheet_sort(),Worksheet_sort_l(),Worksheet_sort_a(),Worksheet_sort_v()を追加しました。
 *	* Sun Jul 19 12:59:05 JST 2015 Naoyuki Sawa
 *	- コメントのみ追記:
 *	  当モジュールの関数は、キーや値に指定できるのは数値のみで、文字列は指定できません。
 *	  キーや値に文字列を指定したい場合は、本日clipstr.cモジュールに追加した、quark_from_string(),quark_to_string()を併用してください。
 *	  <例>
 *	  │Worksheet_set_l(ws,quark_from_string("Value"),quark_from_string("Key"),-1);
 *	  │iVal=Worksheet_get_l(ws,quark_from_string("Key"),-1);
 *	  │if(iVal!=-1){puts(quark_to_string(iVal));}
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Fri Dec 11 21:38:17 JST 2015 Naoyuki Sawa
 *	- Worksheet_incr_l()等が、これまでは戻り値無しでしたが、(1)増加後の値を返すようにしました。
 *	  カウンタとして用いる場合、セルの値を(1)増加して、すぐにその値を参照する事が多いからです。
 *	- 戻り値を無視すれば動作は変わっていないので、既存のアプリケーションへの影響は有りません。
 *	* Sun Jul 17 21:03:07 JST 2016 Naoyuki Sawa
 *	- Worksheet_ref_l(),Worksheet_get_l(),Worksheet_sum_l(),Worksheet_set_l(),Worksheet_unset_l(),Worksheet_incr_l(),Worksheet_first_l(),Worksheet_sort_l(),
 *	  Worksheet_ref_a(),Worksheet_get_a(),Worksheet_sum_a(),Worksheet_set_a(),Worksheet_unset_a(),Worksheet_incr_a(),Worksheet_first_a(),Worksheet_sort_a()をアセンブラ化しました。
 *	  主な目的は、コードサイズの低減です。
 *	  当モジュールコードサイズが、1468バイト⇒1016バイトに減りました。
 *	* Sun Jul 17 22:34:56 JST 2016 Naoyuki Sawa
 *	- USE_WORKSHEET_GTREEシンボルを定義すると、当モジュールがgtree.cモジュールを使用するようにしました。
 *	  USE_WORKSHEET_GTREEシンボルを定義しなければ、これまで通り、ght_hash_table.cモジュールを使用します。
 *	  当面は、USE_WORKSHEET_GTREEシンボルを定義して、gtree.cモジュールを使用するようにして、動作を検証しようと思います。
 *	  万一、動作上の問題が生じたら、ght_hash_table.cモジュールを使用するように戻して下さい。
 *	- gtree.cモジュールを使用するように変更したい理由は、ソート関数(Worksheet_sort()等)が不要になるからです。
 *	  ツリーは常にソートされているので、アプリケーションがイテレーション等の前に、明示的にソートする必要が無くなります。
 *	  USE_WORKSHEET_GTREEが定義されている場合はソート関数はダミー処理となります。
 *	  USE_WORKSHEET_GTREEが定義されている場合はソート関数を無効にしても良いのですが、ソート関数を呼び出している既存のアプリケーションのために残しておく事にしました。
 *	* Mon Jul 18 20:14:53 JST 2016 Naoyuki Sawa
 *	- ワークシート(多階層ハッシュテーブル)の大幅な変更を行いました。
 *	  ・変更前はハッシュテーブルを利用した実装とツリーを利用した実装を選択出来ましたが、変更後はツリーを利用した実装のみとして単純化しました。
 *	  ・ツリーを利用した実装のみとした事に伴い、ソート関数は無意味になったので、ソート関数を完全に廃止しました。
 *	  ・変更前は一度作成されたノードはWorksheet_unset_*()が呼ばれない限り存続し続けましたが、変更後は値が0で子階層も無いノードを自動的に削除して使用メモリを節約するようにしました。
 *	  ・変更前はST_Worksheetは子階層のツリーを常に(空でも)保持していましたが、変更後は子階層のツリーが空ならば未作成のままとして使用メモリを節約するようにしました。
 *	  ・変更前は明示的に0が設定されたノードもイテレートされていましたが、上記の変更に伴い、変更後は値0,かつ,子階層のツリーが空のノードは実体が存在せずイテレートされなくなりました。
 *	  ・ルート階層に対して直接「Worksheet_unset_l(ws,-1)」を呼び出す事は、変更前はエラーでしたが、変更後は可能となりました。ワークシートをクリアする動作となります。
 *	  ・グローバル変数「Worksheet_count」を追加しました。アプリケーション全体で、確保されているST_Worksheetの数を追跡する変数です。(デバッグ用)
 *	- 上述の通り、今回の変更は動作の変更も伴うものです。
 *	  変更前のプログラムは安定して動いた実績があるので、変更前のソースコードを「/clip/keep/18_ワークシート(多階層ハッシュテーブル)変更前保存/」に保存しておきました。	←←←←←←←←2016/07/18以前のソースコードは左記のフォルダを参照して下さい。
 *	* Wed Jul 20 21:23:00 JST 2016 Naoyuki Sawa
 *	- ローカル関数Worksheet_key_compare_func()をアセンブラ化しました。
 *	  小さな関数ですが、ツリーの操作において呼び出される頻度は高いので、多少は高速化の効果が有ると思います。(未計測)
 *	- ヌルポインタを指定してWorksheet_free()を呼び出した場合に、何も解放しないのにWorksheet_countを減らしてしまっていたバグを修正しました。
 */
#ifndef __CLIP_WKST_H__
#define __CLIP_WKST_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/****************************************************************************
 *	グローバル変数
 ****************************************************************************/
#ifdef  _DEBUG
extern int Worksheet_count;	//確保されているST_Worksheetの数を追跡する。	デバッグ用
#endif//_DEBUG
/****************************************************************************
 *	構造体
 ****************************************************************************/
//集計表の単一階層
typedef struct _ST_Worksheet {
	int			iVal;		//この階層のセルの値
	GTree*			tKey;		//子階層のツリー		子階層のツリーが空(未作成)ならばNULLとする。
} ST_Worksheet;
/*--------------------------------------------------------------------------*/
//集計表のイテレータ
typedef struct _ST_Worksheet_Iterator {
	GTree*			tree;		//走査中のツリー		走査対象のツリーが無かった場合はNULLとする。
	GTreeIteratorNP		it;		//ツリーのイテレータ		tree==NULLの場合はイテレータを初期化しない。
} ST_Worksheet_Iterator;
/****************************************************************************
 *	グローバル関数
 ****************************************************************************/
//作成/開放
ST_Worksheet* Worksheet_new();
void Worksheet_free(ST_Worksheet* ws/*NULL可*/);
/*--------------------------------------------------------------------------*/
//参照
ST_Worksheet* Worksheet_ref_l(ST_Worksheet* ws/*NULL可*/, ... /*,(-1)*/);
ST_Worksheet* Worksheet_ref_a(ST_Worksheet* ws/*NULL可*/, va_list ap);
ST_Worksheet* Worksheet_ref_v(ST_Worksheet* ws/*NULL可*/, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//取得
int Worksheet_get_l(ST_Worksheet* ws/*NULL可*/, ... /*,(-1)*/);
int Worksheet_get_a(ST_Worksheet* ws/*NULL可*/, va_list ap);
int Worksheet_get_v(ST_Worksheet* ws/*NULL可*/, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//合計
int Worksheet_sum_l(ST_Worksheet* ws/*NULL可*/, ... /*,(-1)*/);
int Worksheet_sum_a(ST_Worksheet* ws/*NULL可*/, va_list ap);
int Worksheet_sum_v(ST_Worksheet* ws/*NULL可*/, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//設定
void Worksheet_set_l(ST_Worksheet* ws, int iVal, ... /*,(-1)*/);
void Worksheet_set_a(ST_Worksheet* ws, int iVal, va_list ap);
void Worksheet_set_v(ST_Worksheet* ws, int iVal, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//削除
void Worksheet_unset_l(ST_Worksheet* ws/*NULL可*/, ... /*,(-1)*/);
void Worksheet_unset_a(ST_Worksheet* ws/*NULL可*/, va_list ap);
void Worksheet_unset_v(ST_Worksheet* ws/*NULL可*/, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//計数
int Worksheet_incr_l(ST_Worksheet* ws, ... /*,(-1)*/);
int Worksheet_incr_a(ST_Worksheet* ws, va_list ap);
int Worksheet_incr_v(ST_Worksheet* ws, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//走査開始
int Worksheet_first_l(ST_Worksheet* ws/*NULL可*/, ST_Worksheet_Iterator* it, ... /*,(-1)*/);
int Worksheet_first_a(ST_Worksheet* ws/*NULL可*/, ST_Worksheet_Iterator* it, va_list ap);
int Worksheet_first_v(ST_Worksheet* ws/*NULL可*/, ST_Worksheet_Iterator* it, const int* aKey/*={key,key,...,key,-1}*/);
/*--------------------------------------------------------------------------*/
//走査継続
int Worksheet_next(ST_Worksheet_Iterator* it);
/*--------------------------------------------------------------------------*/
//ダンプ
void Worksheet_dump(ST_Worksheet* ws/*NULL可*/);
/*--------------------------------------------------------------------------*/
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_WKST_H__
