/* vi: set tabstop=4 paste nocindent noautoindent: */

#ifndef  __JBXL_TINY_TREE_H_
#define  __JBXL_TINY_TREE_H_


/** 
@brief   Tiny Tree Graph 構造ライブラリヘッダ
@file    tTree.h
@version
@author  Fumi.Iseki (C)
@date    2008 2/1
@see     tList (_tList), tTree
*/



#include "buffer.h"
#include "tlist.h"




/** 
typedef  tList  	tTree;

@code
tTree 構造体
	tList_data 	ldat		データ

	tList*	 	next		子ノードへのポインタ
	tList*	 	prev		親ノードへのポインタ
	tList*		altp		他のノードへのポインタ

	tList*		back		子（末っ子）ノードへのポインタ
	tList*		esis		前の姉妹ノードへのポインタ
	tList*		ysis		次の姉妹ノードへのポインタ

	int 		depth		深さ                    
	int			num			子ノードの数 
	int			ctrl		制御用         
	int			state   	ノードの状態



tList_data 構造体
	int	 		id;			ノードID
	int	 		lv;			ノード値（整数）
	Buffer  	key;		ノードのキー
	Buffer  	val;		ノード値（文字列）
	void*		ptr;		汎用．構造体などへのポインタ．（ptr->X を freeできないので，リストのようなポインタを設定してはいけない）
	int	 		sz;			*ptr のサイズ
	struct _tList* 	lst;	リストデータへのポインタ
@endcode
 */
typedef  tList  		tTree;






/// ldat.ctrl リスト制御用
#define	TREE_NOCTRL_NODE 				0			///< 何の制御（制限）も受けていないノード．デフォルト．
#define	TREE_NOCMP_NODE 				100			///< 比較対照から外すノード．通常は無条件で一致させる．
#define	TREE_NOCMP_COPY_NODE 			101			///< 比較対照から外し，最後にコピー処理を行うノード．通常は無条件で一致させる．
#define	TREE_COPY_NODE					102			///< 後でコピー処理を行うノード．copy_tTree_byctrl()など．
#define	TREE_ALREADY_FOUND_NODE			110			///< 検索などにおいて既に見つけたノード．見つけたことを確定したノード．
#define	TREE_ALREADY_FOUND_NODE_TEMP 	111			///< 一時的に比較対照から外す場合にノード．作業中に設定．






////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tiny Tree Graph Node
//

tTree*  new_tTree_node(void);
tTree   make_tTree_node(tList_data data);


tTree* 	add_tTree_node		   (tTree* pp, tTree* pt);
tTree* 	add_tTree_node_bydata  (tTree* pp, tList_data ldat);
tTree*  add_tTree_node_bystr   (tTree* pp, int id, int lv, const char*  key, const char*  val, void* ptr, int sz);
tTree* 	add_tTree_node_byBuffer(tTree* pp, int id, int lv, Buffer key, Buffer val, void* ptr, int sz); 

#define add_tTree_node_int(p, k, v)			add_tTree_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define add_tTree_node_str(p, k, v)        	add_tTree_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define add_tTree_node_Buffer(p, k, v)     	add_tTree_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)

tTree* 	insert_tTree_node		  (tTree* pp, tTree* pt);
tTree*  insert_tTree_node_bydata  (tTree* pp, tList_data ldat);
tTree*  insert_tTree_node_bystr   (tTree* pp, int id, int lv, const char*  key, const char*  val, void* ptr, int sz);
tTree* 	insert_tTree_node_byBuffer(tTree* pp, int id, int lv, Buffer key, Buffer val, void* ptr, int sz); 

#define insert_tTree_node_int(p, k, v)		insert_tTree_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define insert_tTree_node_str(p, k, v)      insert_tTree_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define insert_tTree_node_Buffer(p, k, v)   insert_tTree_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)


tTree*  del_tTree_node(tTree** node); 
tTree*  move_tTree_node(tTree* node, tTree* pp); 
int  	replace_all_tTree_node(tTree* pp, char* key, char* src, char* dst, int len);

#define set_tTree_node_bydata(p, k)						set_tList_node_bydata((p), (k))
#define set_tTree_node_bystr(p, i, l, k, v, d, s) 		set_tList_node_bystr((p), (i), (l), (k), (v), (d), (s))
#define set_tTree_node_byBuffer(p, i, l, k, v, d, s) 	set_tList_node_byBuffer((p), (i), (l), (k), (v), (d), (s))

#define set_tTree_node_int(p, k, d) 	 	set_tList_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define set_tTree_node_str(p, k, d)  		set_tList_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define set_tTree_node_Buffer(p, k, d)		set_tList_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)

#define dup_tTree_node(p)					dup_tList_node(p)

/** 
void  free_tTree_node(tList** p)
ノードのバッファ部(データ)の開放．
@param  p  -- 開放するノードへのポインタ．
*/
#define	free_tTree_node(p)						free_tList_node(p)




////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tiny Tree Graph
//

tTree*  del_tTree(tTree** pp); 
void   	del_all_tTree(tTree** pp);
tTree*	del_children_tTree(tTree** pp);
tTree*	del_sisters_children_tTree(tTree** pp);
#define free_tTree(t)  del_tTree((t))

void   	adjust_tTree_depth(tTree* pp);
void   	print_tTree(FILE* fp, tTree* pp, const char* sp);

tTree* 	add_tTree(tTree* pp, tTree* pt);
tTree* 	div_tTree(tTree* pp);
tTree*	dup_merge_tTree(tTree* pp, tTree* tp);
void  	merge_tTree(tTree* pp, tTree* pt);
void  	exchange_tTree(tTree* tl, tTree* tt);
int		count_tTree(tTree* pp);

/**
tList*  find_tTree_top(tList* p)
ツリーのトップ（ルート）を見つける
@param p 検索するツリーの一部へのポインタ
*/
#define	find_tTree_top(p)	find_tList_top((p))

tTree*	find_tTree_end(tTree* pp);


// 検索/置換
tTree*  strncmp_tTree    (tTree* pp, const char*  key, int len, int no);
tTree*  strncasecmp_tTree(tTree* pp, const char*  key, int len, int no);

tTree*  cmp_sisters_tTree (tTree* tp, tTree* tr);
int  	check_match_tTree (tTree* tp, tTree* tr);
int 	find_match_tTree  (tTree* pp, tTree* pt);
int 	replace_tTree_node(tTree* pp, tTree* pt);
void 	copy_tTree_byctrl (tTree* pt);

tList*	find_match_tTree_endlist(tTree* pp, tTree* pt);
tList*	find_match_tTree_endlist_rcsv(tTree* pp, tTree* pt, tTree* te);
void   	clear_tTree_ctrl(tTree* pp);

Buffer	get_value_tTree  (tTree* pp, tTree* pt);
#define	set_value_tTree(p, t)	replace_tTree_node((p), (t))


// 補助的関数
tTree*  next_strncmp_vertical_tTree    (tTree* pp, const char* key, int len, int no, int* nn);
tTree*  next_strncasecmp_vertical_tTree(tTree* pp, const char* key, int len, int no, int* nn);

tTree*  next_strncmp_horizon_tTree    (tTree* pp, const char* key, int len, int no, int* nn);
tTree*  next_strncasecmp_horizon_tTree(tTree* pp, const char* key, int len, int no, int* nn);



/**/


#endif


