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

#ifndef  __JBXL_TINY_LIST_H_
#define  __JBXL_TINY_LIST_H_


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



#include "buffer.h"



struct  _tList_data;
struct  _tList;



struct  _tList_data {
	int	 	id;					///< ノードID
	int	 	lv;					///< ノード値（整数）
	Buffer  key;				///< ノードのキー
	Buffer  val;				///< ノード値（文字列）
	void*	ptr;				///< 汎用（構造体など）
	int	 	sz;					///< *ptrのサイズ
	struct _tList* 	lst;		///< リストデータへのポインタ
};


/** 
typedef  struct _tList_data 	tList_data;

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



struct  _tList {
	struct _tList_data	ldat;	///< データ

	struct _tList* 		next;	///< 子ノードへのポインタ
	struct _tList* 		prev;	///< 親ノードへのポインタ
	struct _tList* 		altp;	///< 他のノードへのポインタ

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

	int 				depth;	///< 深さ                            for tTree
	int 				num;	///< 子ノードの数                    for tTree
	int 				ctrl;	///< 制御用                          for tTree
	int					state;	///< ノードの状態
};


/** 
typedef  struct _tList 	tList;

@code
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   ノードの状態
@endcode
 */
typedef  struct _tList  tList;



// 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		




/**/
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 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, const char*  key, const 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, const char*  key, const 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, const char*  key, const 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, const char*  key, const 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, const char* key, int no);
#define free_tList(l)   del_tList(l)

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, const char*  key, int len, int no);
tList*  strnrvscmp_tList(tList* pl, const char*  key, int len, int no);
tList*  strstr_tList    (tList* pl, const char*  key, int len, int no);

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


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

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


// リストの削除


// 検索　ldat.val のコピーを返す 
Buffer  search_key_tList(tList* lt, const char* key, int no);
Buffer  search_key_value_tList(tList* lt, const 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, const char* deli);				// 要 free
Buffer  get_Buffer_join_tList(tList* lp, const char* deli);


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

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



// for Configuration File
char* 	get_str_param_tList   (tList* lt, const char* key, const char* dflt);
int  	get_int_param_tList   (tList* lt, const char* key, int dflt);
double  get_double_param_tList(tList* lt, const char* key, double dflt);
float   get_float_param_tList (tList* lt, const char* key, float dflt);
int     get_bool_param_tList  (tList* lt, const 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(const char* fn, int mode);
tList*  read_index_tList_fp(FILE* fp, char deli);
tList*  read_index_tList_file(const char* fn, char deli);

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



/**/


#endif


