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

#ifndef  __JBXL_BUFFER_H_
#define  __JBXL_BUFFER_H_


/** 
@brief   Buffer型サポートヘッダ
@file    buffer.h
@version 1.3
@author  Fumi.Iseki (C)
@date    2012 7/23
@see     Buffer
*/


#include "tools.h"




/** 
<b>Buffer型</b>

Buffer型は文字列操作時の配列破壊を防止する．buffer.c のBuffer型対応関数を使う限り, 
プログラマ(ライブラリ利用者)は配列破壊を考慮する必要は無い．
通常, vldszはプログラマ(ライブラリ利用者)が保証しなければならない．

したがってBuffer型変数を返す関数では常に vldszが設定されているか注意すべきである．
ただし,データが文字列の場合は -1以下にしておいてもよい．
一方 bufszはバッファの長さを現す変数であり，プログラマが書き換えてはいけない．

Buffer型変数はバッファ領域を動的に確保するので,使用が終ったら必ず
del_Buffer(または free_Buffer)でバッファ領域を開放しなければならない．

@attention
buf[bufsz]はシステムが使用するので,プログラマは buf[bufsz]は無いものとして扱うこと．

@see del_Buffer(), free_Buffer()
*/

typedef struct _Buffer {
	int   bufsz; 			//!< 確保してあるバッファの大きさ - 1．
	int   vldsz; 			//!< データの長さ．バイナリデータの場合も使用可能．
	int   state; 			//!< 変数の状態を表す．正常は 0
	unsigned char* buf; 	//!< バッファの先頭へのポインタ．str[bufsz]は必ず 0x00となる．
} Buffer;




// Buffer 変数の領域確保のための領域確保倍率
#define  BUFFER_FACT   (1.5)



Buffer* new_Buffer(void);
Buffer  init_Buffer(void);
Buffer  make_Buffer(int sz);
Buffer  make_Buffer_bychar(unsigned char cc);
Buffer  make_Buffer_randomstr(int sz);
Buffer  set_Buffer(void* buf, int sz);
Buffer  dup_Buffer(Buffer buf);
Buffer  rept_Buffer(unsigned char cc, int n);

void    expand_Buffer(Buffer* buf, int len);

void	del_Buffer(Buffer** buf);
void	free_Buffer(Buffer* buf);
void	clear_Buffer(Buffer* buf);


/** 
Buffer make_Buffer_bystr(const char* str)

文字列から，Buffer型変数のバッファ部をつくり出す．@n
make_Buffer_bystr("") は Buffer変数の初期化にも使用される．
バイナリデータから Buffer変数を作り出すには，set_Buffer()を用いる．@n
バッファ部の作成に失敗した場合, バッファのサイズ(bufsz)は 0, バッファへのポインタは NULLとなる．

@param  str Buffer型変数のバッファに格納する文字列
@return 作り出した Buffer型変数．
@see    set_Buffer()
*/
#define make_Buffer_bystr(str)		set_Buffer((void*)(str), -1)
#define make_Buffer_byrandomstr(sz)	make_Buffer_randomstr(sz)

#define make_Buffer_bybin(str, len)	set_Buffer((void*)(str), (len))
#define make_Buffer_bin(str, len)	set_Buffer((void*)(str), (len))
#define make_Buffer_str(str)		set_Buffer((void*)(str), -1)
#define make_Buffer_char(str)  		make_Buffer_bychar(str)


int		copy_Buffer(Buffer* src, Buffer* dst);
int		cat_Buffer (Buffer* src, Buffer* dst);
int		ins_Buffer (Buffer* src, Buffer* dst);

int		copy_b2Buffer(void* src, Buffer* dst, int sz);
int		cat_b2Buffer (void* src, Buffer* dst, int sz);
int		ins_b2Buffer (void* src, Buffer* dst, int sz);

int		copy_i2Buffer(int src, Buffer* dst);
int		cat_i2Buffer (int src, Buffer* dst);
int		ins_i2Buffer (int src, Buffer* dst);


/** 
int copy_s2Buffer(char* src, Buffer* dst)

char*変数 srcから Buffer型変数dstへ文字列を copyする．@n
もし, dstに srcをコピーするだけのスペースが無い場合は, 新たにバッファ領域を確保してコピーする．

@param  src コピー元へのポインタ．
@param  dst コピー先へのポインタ．
@retval 0     srcまたは dstが NULL
@retval -1    メモリの確保に失敗した．何も実行されなかった．
@retval 1以上 dstのバッファにコピーされた文字数．
*/
#define copy_s2Buffer(src, dst) 	copy_b2Buffer((void*)(src), (dst), (int)strlen((char*)(src)))


/** 
int cat_s2Buffer(char* src, Buffer* dst)

char*変数 srcから Buffer型変数dstへ文字列を catする．@n
もし, dstに srcの文字列を catするだけのスペースが無い場合は新たにバッファ領域を確保して catする．

@param src cat元へのポインタ．
@param dst cat先へのポインタ．
@retval  0    srcまたは dstが NULL
@retval -1    メモリの確保に失敗した．何も実行されなかった．
@retval 1以上 dstのバッファにコピーされた文字数．
*/
#define cat_s2Buffer(src, dst) 	 	cat_b2Buffer( (void*)(src), (dst), (int)strlen((char*)(src)))

#define ins_s2Buffer(src, dst) 	 	ins_b2Buffer( (void*)(src), (dst), (int)strlen((char*)(src)))


// ツール
void	kanji_convert_Buffer(Buffer* mesg);
Buffer  encode_base64_Buffer(Buffer buf);
Buffer  decode_base64_Buffer(Buffer buf);

Buffer  get_line_Buffer(Buffer buf, int n);  
Buffer  get_seq_data_Buffer(Buffer str, int* ptr);
Buffer  awk_Buffer (Buffer buf, char cc, int n);
Buffer  cawk_Buffer(Buffer buf, char cc, int n);
Buffer	pack_Buffer(Buffer buf, char cc);

int	 	cmp_Buffer(Buffer src, Buffer dst, int n);
void	chomp_Buffer(Buffer* buf);
int		isText_Buffer(Buffer buf);
Buffer	dump_Buffer(Buffer buf);
int		recalc_strlen_Buffer(Buffer* buf);

//#define strlen_Buffer(b) 			strlen((char*)((b).buf))
#define strcmp_Buffer(a, b)			cmp_Buffer((a), (b), 0)
#define strncmp_Buffer(a, b, n)		cmp_Buffer((a), (b), (n))
#define bincmp_Buffer(a, b)			cmp_Buffer((a), (b), 0)
#define binncmp_Buffer(a, b, n)		cmp_Buffer((a), (b), (n))

Buffer  randstr_Buffer(int n);			   //!< 英数字を n個生成
Buffer  randbit_Buffer(int n);			   //!< ビットを n個生成 


// ファイルI/O
int	 	fgets_Buffer(Buffer* str, FILE* fp);	// 拡張fgets
int		read_lines_Buffer(Buffer* str, FILE* fp);

Buffer  read_Buffer_file(const char* fn);
Buffer  read_Buffer_data(FILE* fp, int sz);
int	 	save_Buffer_file(Buffer buf, char* fn);


// 文字削除
Buffer  erase_bBuffer(Buffer buf, char* bin, int len);
#define erase_Buffer(b, f)			erase_bBuffer((b), (char*)((f).buf), (f).vldsz)
#define erase_sBuffer(b, f)			erase_bBuffer((b), (char*)(f), strlen(f))



// 文字列置換
Buffer  replace_sBuffer_bystr(Buffer buf, const char* frm, const char* tos);
int	 	replace_sBuffer_file(char* fn, Buffer frm, Buffer tos);
#define replace_sBuffer_str(b, f, t) 	replace_sBuffer_bystr((b), (f), (t))


/** 
Buffer  replace_sBuffer(Buffer buf, char* frm, char* tos)

buf.buf 中の frm を tos で置き換えたものを返す．@n
frm は buf.buf とメモリ領域が重なってはいけない．文字列型の Buffer にのみ対応．

@param  buf 操作する Buffer変数
@param  frm 変換する文字列
@param  tos 変換後の文字列
@return 変換した文字列を格納した Buffer変数．
@see    replace_sBuffer_bystr()
*/
#define replace_sBuffer(buf, frm, tos)	replace_sBuffer_bystr((buf), (frm), (tos))


/** 
Buffer  replace_Buffer(Buffer buf, Buffer frm, Buffer tos)

buf.buf 中の frm.buf を tos.buf で置き換えたものを返す．@n
frm.buf は buf.buf とメモリ領域が重なってはいけない．文字列型の Buffer にのみ対応．

@param  buf 操作する Buffer変数
@param  frm 変換する文字列を格納したBuffer変数
@param  tos 変換後の文字列を格納したBuffer変数
@return 変換した文字列を格納した Buffer変数．state==-1 の場合は失敗．
@see    replace_sBuffer_bystr()
*/
#define replace_Buffer(buf, frm, tos)	replace_sBuffer_bystr((buf), (char*)((frm).buf), (char*)((tos).buf))


/**
buf.buf自体を書き換える．
後は，replace_sBufferと同じ
*/
void	rewrite_sBuffer_bystr(Buffer* buf, const char* frm, const char* tos);
#define rewrite_sBuffer_str(b, f, t) 	rewrite_sBuffer_bystr((b), (f), (t))
#define rewrite_sBuffer(buf, frm, tos)	rewrite_sBuffer_bystr((buf), (frm), (tos))
#define rewrite_Buffer(buf, frm, tos)	reweite_sBuffer_bystr((buf), (char*)((frm).buf), (char*)((tos).buf))



// ヘッダ(書式)付き特殊ファイルI/O
int	 	save_Buffer_fp(Buffer, FILE*);
Buffer  read_Buffer_fp(FILE*);
int   	save_Buffer2_fp(Buffer  key, Buffer  buf, FILE* fp);
int  	read_Buffer2_fp(Buffer* key, Buffer* buf, FILE* fp);



// Buffer型を利用した 簡易char型リングバッファー
char    get_char_ringbuffer(Buffer* buf);
void    put_char_ringbuffer(Buffer* buf, char cc);

//#define char_ringbuffer(b, n)       (b).buf[((n)%((b).bufsz))]





#endif


