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

#ifndef  __JBXL_TINY_LIST_H_
#define  __JBXL_TINY_LIST_H_


/**
Tiny List, Tiny Tree Graph 構造ライブラリヘッダ		tlist.h

*/



#include "buffer.h"



struct  _tList_data;
struct  _tList;



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




/**
tList 構造体
   
	tList_data 	ldat	データ
	tList*	 	next	子ノードへのポインタ
	tList*	 	prev	親ノードへのポインタ
	tList*		altp	他のノードへのポインタ

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

	int 		depth	深さ							for tTree
	int			num		子ノードの数					for tTree
	int			ctrl	制御用							for tTree
	int			state   ノードの状態
 */
struct  _tList {
	struct _tList_data	ldat;
	struct _tList* 	next;
	struct _tList* 	prev;
	struct _tList* 	altp;

	struct _tList* 	back;
	struct _tList* 	esis;
	struct _tList* 	ysis;

	int 			depth;
	int 			num;
	int 			ctrl;
	int				state;
};


typedef  struct _tList_data 	tList_data;
typedef  struct _tList  		tList;
typedef  struct _tList  		tTree;



// Anchor Node
#define	LIST_ANCHOR		"LIST_ANCHOR"


// for strncmp_tList()
#define TLIST_MATCH_COMPLETE	0	
#define TLIST_MATCH_TLISTKEY	-1		
#define TLIST_MATCH_STRINGKEY 	-2		
#define TLIST_MATCH_STRKEY 		-2		



// 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			// 一時的に比較対照から外す場合にノード．作業中に設定．








/**/
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// List Data
//

tList_data  init_tListdata(void);

tList_data  make_tListdata      (int id, int lv, Buffer key, Buffer val, void* ptr, int sz);
tList_data  make_tListdata_bystr(int id, int lv, char*  key, char*  val, void* ptr, int sz);
#define  	make_tListdata_byBuffer(i, l, k, v, d, s)	make_tListdata((i), (l), (k), (v), (d), (s))

#define  	make_tListdata_int(k, v)		make_tListdata_bystr((k), (v), NULL, NULL, NULL, 0)
#define  	make_tListdata_str(k, v)		make_tListdata_bystr(0, 0, (char*)(k), (char*)(v), NULL, 0)
#define  	make_tListdata_Buffer(k, v)		make_tListdata(0, 0, (k), (v), NULL, 0)

tList_data	dup_tListdata (tList_data ldat);
void   		free_tListdata(tList_data* ldat);




////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tiny List Node
//

tList*  new_tList_node(void);
tList  	make_tList_node(tList_data data);

// 追加は new_tList_node() を使用
tList*  add_tList_node_bydata  (tList* pp, tList_data ldat); 
tList*  add_tList_node_bystr   (tList* pp, int id, int lv, char*  key, char*  val, void* ptr, int sz);
tList*  add_tList_node_byBuffer(tList* pp, int id, int lv, Buffer key, Buffer val, void* ptr, int sz); 
#define add_tList_node_int(p, k, v)  			add_tList_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define add_tList_node_str(p, k, v)  			add_tList_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define add_tList_node_null(p)					add_tList_node_bystr((p), 0, 0, NULL, NULL, NULL, 0)
#define add_tList_node_Buffer(p, k, v)			add_tList_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)

#define insert_tList_node(p, t)					insert_tList((p), (t))


// 設定
void	set_tList_node_bydata  (tList* pp, tList_data ldat);
void	set_tList_node_bystr   (tList* pp, int id, int lv, char*  key, char*  val, void* ptr, int sz);
void	set_tList_node_byBuffer(tList* pp, int id, int lv, Buffer key, Buffer val, void* ptr, int sz);
#define set_tList_node_int(p, k, v) 	 		set_tList_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define set_tList_node_str(p, k, v)  			set_tList_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define set_tList_node_Buffer(p, k, v)			set_tList_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)

// 検索して更新．無ければ追加．（追加は new_tList_node()を使用）
tList*	update_tList_node		  (tList* pp, tList* pt);
tList*	update_tList_node_bydata  (tList* pp, char* key, tList_data ldat);
tList*	update_tList_node_bystr   (tList* pp, int id, int lv, char*  key, char*  val, void* ptr, int sz);
tList*	update_tList_node_byBuffer(tList* pp, int id, int lv, Buffer key, Buffer val, void* ptr, int sz);
#define update_tList_node_int(p, k, v)  		update_tList_node_bystr((p), (k), (v), NULL, NULL, NULL, 0)
#define update_tList_node_str(p, k, v)	  		update_tList_node_bystr((p), 0, 0, (char*)(k), (char*)(v), NULL, 0)
#define update_tList_node_Buffer(p, k, v)		update_tList_node_byBuffer((p), 0, 0, (k), (v), NULL, 0)


tList*  del_tList_node (tList* node); 
tList*  dup_tList_node (tList* node);
tList*  move_tList_node(tList* node, tList* pp); 
void  	free_tList_node(tList** node); 




////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tiny List
//

tList*  add_tList_end(tList* pp, tList* pt);
tList*  insert_tList(tList* pp, tList* pt); 
tList*  dup_tList(tList* pp);
void   	print_tList(FILE* fp, tList* pp);
void   	dump_tList(FILE* fp, tList* pp);
int		count_tList(tList* pp);

tList*  del_tList(tList** pp); 
void   	del_all_tList(tList** pp);
int  	del_tList_key(tList** pp, char* key, int no);

tList*  find_tList_top(tList* pp); 
tList*  find_tList_end(tList* pp); 


// 検索  リストへのポインタを返す 
//		len: 1以上:一致させる長さ，0:完全一致，-1:pl->keyの長さに合わせる，-2:keyの長さに合わせる
tList*  strncmp_tList   (tList* pl, char*  key, int len, int no);
tList*  strnrvscmp_tList(tList* pl, char*  key, int len, int no);
tList*  strstr_tList    (tList* pl, char*  key, int len, int no);

tList*  strncasecmp_tList   (tList* pl, char*  key, int len, int no);
tList*  strncaservscmp_tList(tList* pl, char*  key, int len, int no);
tList*  strstrcase_tList    (tList* pl, char*  key, int len, int no);


tList*  strncmp_back_tList   (tList* pl, char*  key, int len, int no);
tList*  strnrvscmp_back_tList(tList* pl, char*  key, int len, int no);
tList*  strstr_back_tList    (tList* pl, char*  key, int len, int no);

tList*  strncasecmp_back_tList   (tList* pl, char*  key, int len, int no);
tList*  strncaservscmp_back_tList(tList* pl, char*  key, int len, int no);
tList*  strstrcase_back_tList    (tList* pl, char*  key, int len, int no);


// リストの削除


// 検索　ldat.val のコピーを返す 
Buffer  search_key_tList(tList* lt, char* key, int no);
Buffer  search_key_value_tList(tList* lt, char* key, char* data, int no);


// Tools
tList*	awk_tList (char* str, char cc);
tList*	cawk_tList(char* str, char cc);
tList*	awk_Buffer_tList (Buffer buf, char cc);
tList*	cawk_Buffer_tList(Buffer buf, char cc);
char*   get_str_join_tList(tList* lp, char* deli);				// 要 free
Buffer  get_Buffer_join_tList(tList* lp, char* deli);


// 値変更
int     set_value_tList(tList* lt, char* key, int no, char* value, int mode);
int     replace_value_tList(tList* lt, char* key, int no, char* srcval, char* value);

int     set_value_tList_node(tList* lt, char* value);
int     replace_value_tList_node(tList* lt, char* srcval, char* value);



// for Configuration File
char* 	get_str_param_tList   (tList* lt, char* key, char* dflt);
int  	get_int_param_tList   (tList* lt, char* key, int dflt);
double  get_double_param_tList(tList* lt, char* key, double dflt);
float   get_float_param_tList (tList* lt, char* key, float dflt);
int     get_bool_param_tList  (tList* lt, char* key, int dflt);

#define get_strparam_tList(l, k, d) 	get_str_param_tList((l), (k), (d))
#define get_intparam_tList(l, k, d) 	get_int_param_tList((l), (k), (d))
#define get_doubleparam_tList(l, k, d) get_double_param_tList((l), (k), (d)) 
#define get_boolparam_tList(l, k, d) 	get_bool_param_tList((l), (k), (d))


////////////////////////////////////////////////////////////////////////////////////////////////////
//
// File I/O with Tiny List
//

tList*  read_tList_fp(FILE* fp, int mode);
tList*  read_tList_file(char* fn, int mode);
tList*  read_index_tList_fp(FILE* fp, char deli);
tList*  read_index_tList_file(char* fn, char deli);

tList*  read_Buffer_tList_fp(FILE* fp);
tList*  read_Buffer_tList_file(char* fn);
int  	save_Buffer_tList_fp(FILE* fp, tList* lt);
int		save_Buffer_tList_file(char* fn, tList* lt);




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

#define	new_tTree_node()						new_tList_node()
#define	make_tTree_node(p)						make_tList_node(p)

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, char*  key, 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*  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	free_tTree_node(p)						free_tList_node(p)
#define dup_tTree_node(p)						dup_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);

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

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);

#define	find_tTree_top(p)					find_tList_top(p)
tTree*	find_tTree_end(tTree* pp);


// 検索/置換
tTree*  strncmp_tTree    (tTree* pp, char*  key, int len, int no);
tTree*  strncasecmp_tTree(tTree* pp, 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, char* key, int len, int no, int* nn);
tTree*  next_strncasecmp_vertical_tTree(tTree* pp, char* key, int len, int no, int* nn);

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



/**/


#endif


