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

/**
	Buffer型サポートプログラム  buffer.c   v.1.3

  	ヘッダ
	  	#include "buffer.h"

 */

#include "buffer.h"



/**
Buffer*  new_Buffer()

	機能：空のBuffer型変数をつくり出す．

	引数：なし．

	戻り値：つくり出した Buffer型変数へのポインタ．
			作成に失敗した場合はNULLが返る．
*/
Buffer*  new_Buffer(void)
{
	Buffer*  buf;

	buf = (Buffer*)malloc(sizeof(Buffer));
	if (buf==NULL) return NULL;

	memset(buf, 0, sizeof(Buffer));
	buf->vldsz = -1;

	return buf;
}





/**
Buffer  init_Buffer()

	機能：初期化したBuffer型変数を返す．

	戻り値：初期化されたBuffer型変数．

	例：
		a = init_Buffer() とした場合，aに元々値が入っていた場合，その値は free
		されないので注意．
*/
Buffer  init_Buffer()
{
	Buffer  buf;

	memset(&buf, 0, sizeof(Buffer));
	buf.vldsz = -1;

	return buf;
}





/**
Buffer  make_Buffer(int sz)

	機能：Buffer型変数のバッファ部をつくり出す．
		  sz は Buffer型変数のバッファの大きさ．
		  バッファ部は 0x00で初期化される．bufsz=sz, vldsz=0 となる．

	引数：sz -- Buffer型変数のバッファの大きさ．

	戻り値：つくり出した Buffer型変数．
			バッファ部の作成に失敗した場合,バッファのサイズ(bufsz)は 0,バッファへのポインタは NULLとなる．
*/
Buffer  make_Buffer(int sz)
{
	Buffer  buf;

	memset(&buf, 0, sizeof(Buffer));
	if (sz<=0) return buf;

	buf.bufsz = sz;
	buf.buf = (unsigned char*)malloc(buf.bufsz+1);

	if (buf.buf==NULL) {
		buf.bufsz = 0;
		buf.vldsz = -1;
	}
	else memset(buf.buf, 0, buf.bufsz+1);

	return buf;
}





/**
Buffer  make_Buffer_bystr(char* str)

	機能：文字列から，Buffer型変数のバッファ部をつくり出す．
		  make_Buffer_bystr("") は Buffer変数の初期化にも使用される．
		  バイナリデータから Buffer変数を作り出すには，set_Buffer()を用いる． 

	引数：sz -- Buffer型変数のバッファに格納する文字列

	戻り値：つくり出した Buffer型変数．バッファ部の作成に失敗した場合,
			バッファのサイズ(bufsz)は 0,バッファへのポインタは NULLとなる．

	#define  make_Buffer_bystr(s)	set_Buffer((void*)(s), -1)
*/






/**
Buffer  make_Buffer_bychar(unsigned char cc)

	機能：文字から，Buffer型変数のバッファ部をつくり出す．
		  make_Buffer_bychar('\0') は Buffer変数の初期化にも使用される．

	引数：sz -- Buffer型変数のバッファに格納する文字列

	戻り値：つくり出した Buffer型変数．バッファ部の作成に失敗した場合,
			バッファのサイズ(bufsz)は 0,バッファへのポインタは NULLとなる．
*/
Buffer  make_Buffer_bychar(unsigned char cc)
{
	Buffer  buf;
	
	buf = make_Buffer(LADDR);
	if (buf.buf==NULL) return buf;

	buf.buf[0] = cc;
	buf.vldsz = 1;
	return buf;
}








/**
void  free_Buffer(Buffer* buf)

	機能：Buffer型変数のバッファ部を開放する．

	引数：buf  -- 開放するバッファを持った Bufferデータへのポインタ．

 */
void  free_Buffer(Buffer* buf)
{
	if (buf!=NULL) {
		freeNull(buf->buf);
		memset(buf, 0, sizeof(Buffer));
		buf->vldsz = -1;
	}
}





/**
void   del_Buffer(Buffer** buf)

	機能：new_Buffer()で作り出した Buffer型変数を削除する．

	引数：buf -- 削除する Bufferデータのポインタへのポインタ．

 */
void   del_Buffer(Buffer** buf)
{
	if (buf!=NULL && *buf!=NULL) {
		freeNull((*buf)->buf);
		free(*buf);
		*buf = NULL;
	}
}





/**
Buffer  set_Buffer(void* buf, int len)

	機能：Buffer型変数のバッファ部を新しく作り, そのバッファに 
		  bufをコピーする．lenはコピーするデータ長．もし lenが 0未満の
		  場合は, bufは文字列として扱われる．
		  buf が文字列の場合は make_Buffer_bystr() も使用可能．

	引数：buf  -- コピーするバッファへのポインタ．
		  len  -- バッファ長(バイト単位)．

	戻り値; 新しく作られた Buffer型データ．
 */
Buffer  set_Buffer(void* buf, int len)
{
	Buffer  str;

	str = init_Buffer();
	if (buf==NULL) return str;

	if (len<0) len = (int)strlen((char*)buf);
	str = make_Buffer((int)((len+1)*BUFFER_FACT));
	if (str.buf==NULL) return str;

	memcpy(str.buf, buf, len);
	str.vldsz = len;
	return  str;
}





/**
Buffer  dup_Buffer(Buffer buf)

	機能：Buffer型変数のコピーをつくる．

	引数：buf -- コピーする変数．

	戻り値; 新しく作られた Buffer型データ．
 */
Buffer  dup_Buffer(Buffer buf)
{
	Buffer  str;

	str = make_Buffer(buf.bufsz);
	memcpy(str.buf, buf.buf, buf.bufsz);
	str.vldsz = buf.vldsz;
	str.state = buf.state;
	return  str;
}





/**
Buffer  rept_Buffer(unsigned char cc, int n)

	機能：ccを n回繰り返したBuffer型データを返す．

	引数：cc -- 繰り返す文字．
		  n  -- 繰り返す回数．

	戻り値; 新しく作られた Buffer型データ．
 */
Buffer  rept_Buffer(unsigned char cc, int n)
{
	int  i;
	Buffer  str;
	
	if (n<=0) n = 1;
	str = make_Buffer(n);
	for (i=0; i<n; i++) str.buf[i] = cc;
	str.vldsz = n;
	return  str;
}





/**
void  clear_Buffer(Buffer* str)

	機能：Buffer型変数 のバッファ部を 0クリアする．

	引数：str -- クリアする Buffer型データへのポインタ．

 */
void  clear_Buffer(Buffer* str)
{
	memset(str->buf, 0, str->bufsz+1);
	str->vldsz = 0;
	str->state = 0;
}






/**
int  copy_Buffer(Buffer* src, Buffer* dst)
  
	機能：Buffer型変数 srcから dstへバッファをコピーする．もし, dstに 
		  srcのバッファをコピーするだけのスペースが無い場合は, 新たに
		  バッファ領域を確保してコピーする．

	引数：src -- コピー元へのポインタ．
		  dst -- コピー先へのポインタ．

	戻り値： 0以上  dstのバッファにコピーされた文字数．
				-1  srcまたは dstが NULL 
				-2  メモリの確保に失敗した．何も実行されなかった．


	注(重要): 関数内で使用する場合,参照型以外の引数に対してこの関数を用いては
			  いけない．つまり以下のような使い方は間違い．

			  func(Buffer buf){ 
				  ...............
				  copy_Buffer(&src, &buf);
				  ...............
			  }

		これは下記のように変更する．

			  func(Buffer buf){ 
				  ...............
				  copy_Buffer(&src, &buf);
				  ...............
			  }

		理由：関数内でバッファ部の大きさが変わる可能性があるが，呼び出した側で
			  はそのことを知ることができない．

 */
int  copy_Buffer(Buffer* src, Buffer* dst)
{
	int sz, dz;

	if (src==NULL || dst==NULL) return -1;
	if (src->buf==NULL) return -1;

	sz = src->vldsz;
	if (sz<0)  sz = (int)strlen((const char*)src->buf);
	if (sz==0) return 0;

	if (dst->bufsz < sz) {
		unsigned char* buf;
		//dz  = (int)((src->bufsz+1)*BUFFER_FACT);
		dz  = (int)((sz+1)*BUFFER_FACT);
		buf = (unsigned char*)malloc(dz+1);
		if (buf==NULL) return -2;

	   	free(dst->buf);
		dst->bufsz = dz;
		dst->buf   = buf;
	}

	//memset(dst->buf, 0, dst->bufsz+1);		too late
	memcpy(dst->buf, src->buf, sz);
	dst->buf[sz] = '\0';
	dst->vldsz = sz;
	dst->state = 0;

	return  sz;
}





/**
int  cat_Buffer(Buffer* src, Buffer* dst)
  
	機能：Buffer変数 srcから dstへバッファを catする．もし, dstに srcの
		  バッファを catするだけのスペースが無い場合は新たにバッファ領域
		  を確保して catする．

	引数：src -- cat元へのポインタ．
		  dst -- cat先へのポインタ．

	戻り値： 0以上  dstのバッファにコピーされた文字数．
				-1  srcまたは dstが NULL 
				-2  メモリの確保に失敗した．何も実行されなかった．


	注(重要): 関数内で使用する場合,参照型以外の引数に対してこの関数を用いては
			  いけない．つまり以下のような使い方は間違い．

			  func(Buffer buf){ 
				  ...............
				  cat_Buffer(&src, &buf);
				  ...............
			  }

		これは下記のように変更する．

			  func(Buffer* buf){ 
				  ...............
				  cat_Buffer(&src, buf);
				  ...............
			  }

		理由：関数内でバッファ部の大きさが変わる可能性があるが，呼び出した側で
			  はそのことを知ることができない．

 */
int  cat_Buffer(Buffer* src, Buffer* dst)
{
	int sz, dz;

	if (src==NULL || dst==NULL) return -1;
	if (src->buf==NULL) return -1;

	sz = src->vldsz;
	if (sz<0) sz = (int)strlen((const char*)src->buf);
	if (sz==0) return 0;

	dz = dst->vldsz;
	if (dz<0) {
		if (dst->buf!=NULL) dz = (int)strlen((const char*)dst->buf);
		else				dz = 0;
	}

	if (dst->bufsz < sz+dz) {
		Buffer buf;			 	// dstの待避 
		buf.bufsz = dst->bufsz;
		buf.vldsz = dz;
		buf.buf   = (unsigned char*)malloc(buf.bufsz+1);
		if (buf.buf==NULL) return -2;

 		buf.buf[buf.bufsz] = '\0';
		memcpy(buf.buf, dst->buf, buf.bufsz);
		free_Buffer(dst);

		//dst->bufsz = (int)((buf.bufsz+src->bufsz+1)*BUFFER_FACT);
		dst->bufsz = (int)((buf.bufsz+sz+1)*BUFFER_FACT);
		dst->buf   = (unsigned char*)malloc(dst->bufsz+1);
		if (dst->buf==NULL) {
	   		*dst = buf;
	   		return -2;
		}
		memset(dst->buf, 0, dst->bufsz+1);
		memcpy(dst->buf, buf.buf, buf.vldsz);
		free_Buffer(&buf);
	}

	//memset(dst->buf+dz, 0, dst->bufsz-dz+1);  too late
	memcpy(dst->buf+dz, src->buf, sz);
	dst->buf[dz+sz] = '\0';
	dst->vldsz = sz + dz;
	dst->state = 0;

	return  dst->vldsz;
}





/**
int  copy_b2Buffer(void* src, Buffer* dst, int sz)
  
	機能：任意のバイナリデータsrcを Buffer型変数dstへ copyする．
		  もし, dstに srcのバッファを copyするだけのスペースが無い場合は
		  新たにバッファ領域を確保して copyする．
		  szが 0未満の場合は, srcは文字列として扱われる．

	引数：src -- copy元の任意データへのポインタ．
		  dst -- copy先のBuffer型変数へのポインタ．
		  sz  -- copyするバイト数．

	戻り値： 0以上  dstのバッファにコピーされた文字数．
				-1  srcまたは dstが NULL 
				-2  メモリの確保に失敗した．何も実行されなかった．


	注(重要): 関数内で使用する場合,参照型以外の引数に対してこの関数を用いては
			  いけない．つまり以下のような使い方は間違い．

			  func(Buffer buf){ 
				  ...............
				  copy_b2Buffer(&src, &buf, n);
				  ...............
			  }

		これは下記のように変更する．

			  func(Buffer* buf){ 
				  ...............
				  copy_b2Buffer(&src, buf, n);
				  ...............
			  }

		理由：関数内でバッファ部の大きさが変わる可能性があるが，func を呼び出した
			  側ではそのことを知ることができない．

 */
int  copy_b2Buffer(void* src, Buffer* dst, int len)
{
	int sz, dz;

	if (src==NULL || dst==NULL) return -1;
	if (len<0) sz = (int)strlen((const char*)src);
	else	   sz = len;
	if (sz<=0) return 0;

	if (dst->bufsz < sz) {
		unsigned char* buf;
		dz  = (int)((sz+1)*BUFFER_FACT);
		buf = (unsigned char*)malloc(dz+1);
		if (buf==NULL) return -2;
	   	free(dst->buf);
		dst->bufsz = dz;
		dst->buf   = buf;
	}

	memcpy(dst->buf, src, sz);
	dst->buf[sz] = '\0';
	dst->vldsz = sz;
	dst->state = 0;

	return  sz;
}





/**
int  cat_b2Buffer(void* src, Buffer* dst, int len)

	機能：任意のバイナリデータsrcを Buffer型変数dstへ catする．
		  もし, dstに srcのバッファを catするだけのスペースが無い場合は
		  新たにバッファ領域を確保して catする．
		  szが 0未満の場合は, srcは文字列として扱われる．

	引数：src -- cat元の任意データへのポインタ．
		  dst -- cat先のBuffer型変数へのポインタ．
		  len -- catするバイト数．

	戻り値： 0以上  dstのバッファにコピーされた文字数．
				-1  srcまたは dstが NULL 
				-2  メモリの確保に失敗した．何も実行されなかった．


	注(重要): 関数内で使用する場合,参照型以外の引数に対してこの関数を用いては
			  いけない．つまり以下のような使い方は間違い．

			  func(Buffer buf){ 
				  ...............
				  cat_b2Buffer(&src, &buf, n);
				  ...............
			  }

		これは下記のように変更する．

			  func(Buffer* buf){ 
				  ...............
				  cat_b2Buffer(&src, buf, n);
				  ...............
			  }

		理由：関数内でバッファ部の大きさが変わる可能性があるが，func を呼び出した
			  側ではそのことを知ることができない．

 */
int  cat_b2Buffer(void* src, Buffer* dst, int len)
{
	int sz, dz;

	if (src==NULL || dst==NULL) return -1;
	if (len<0) sz = (int)strlen((const char*)src);
	else	   sz = len;
	if (sz<=0) return 0;
   
	dz = dst->vldsz;
	if (dz<0) {
		if (dst->buf!=NULL) dz = (int)strlen((const char*)dst->buf);
		else				dz = 0;
	}

	if (dst->bufsz < sz+dz) {
		Buffer buf;			 // dstの待避 
		buf.bufsz = dst->bufsz;
		buf.vldsz = dz;
		buf.buf   = (unsigned char*)malloc(buf.bufsz+1);
		if (buf.buf==NULL) return -2;

 		buf.buf[buf.bufsz] = '\0';
		memcpy(buf.buf, dst->buf, buf.bufsz);
		free_Buffer(dst);

		dst->bufsz = (int)((buf.bufsz+sz+1)*BUFFER_FACT);
		dst->buf   = (unsigned char*)malloc(dst->bufsz+1);
		if (dst->buf==NULL) {
	   		*dst = buf;
	   		return -2;
		}
		memset(dst->buf, 0, dst->bufsz+1);
		memcpy(dst->buf, buf.buf, buf.vldsz);
		free_Buffer(&buf);
	}

	memcpy(dst->buf+dz, src, sz);
	dst->buf[dz+sz] = '\0';
	dst->vldsz = sz + dz;
	dst->state = 0;

	return  dst->vldsz;
}




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

	引数：src -- コピー元へのポインタ．
		  dst -- コピー先へのポインタ．

	戻り値：	 0  srcまたは dstが NULL 
				-1  メモリの確保に失敗した．何も実行されなかった．
			 1以上  dstのバッファにコピーされた文字数．


	#define copy_s2Buffer(s, d)  copy_b2Buffer((void*)(s), (d), (int)strlen((const char*)(s)))
			 
*/





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

	引数：src -- cat元へのポインタ．
		  dst -- cat先へのポインタ．

	戻り値：	 0  srcまたは dstが NULL 
				-1  メモリの確保に失敗した．何も実行されなかった．
			 1以上  dstのバッファにコピーされた文字数．


	#define cat_s2Buffer(s, d)  cat_b2Buffer((void*)(s), (d), (int)strlen((const char*)(s)))

*/





int  copy_i2Buffer(int src, Buffer* dst)
{
	char num[LEN_INT];

	snprintf(num, LEN_INT-1, "%d", src);
	return copy_b2Buffer((void*)num, dst, (int)strlen(num));
}





int  cat_i2Buffer(int src, Buffer* dst)
{
	char num[22];

	snprintf(num, 21, "%d", src);
	return cat_b2Buffer((void*)num, dst, (int)strlen(num));
}





/**
int  cmp_Buffer(Buffer src, Buffer dst, int n)
  
	機能：バッファ部の比較．
		  Buffer変数 srcと dstのバッファ部分を比較する．n<=0 なら 完全一致,
		  n>0 なら 先頭から nバイト比較する．

	引数：src -- 比較元へのポインタ．
		  dst -- 比較先へのポインタ．
		  n   -- 比較文字数．

	戻り値： 0  srcと dstは一致している．
			 1  srcは dstと一致していない．
			-1  バッファが NULL
			-2  n が vldsz より大きい

	注: 文字列データのみ適用．コーディングがベタベタ．
 */
int  cmp_Buffer(Buffer src, Buffer dst, int n)
{
	int i;

	if (src.buf==NULL || dst.buf==NULL) return -1;
	if (n>src.vldsz   || n>dst.vldsz)   return -2;
	
	if (n<=0) {
		if (src.vldsz!=dst.vldsz) return 1;
		else n = src.vldsz;
	}
	
	for (i=0; i<n; i++) {
		if (src.buf[i]!=dst.buf[i]) return 1;
	}
	return 0;
}





/**
Buffer  encode_base64_Buffer(Buffer buf)

	機能：バイナリデータ buf.bufの buf.vldszバイトを Base64にエンコード
		  する．buf.vldszが -1以下の場合は buf.vldszは buf.bufの最初の 
		  0x00のまでの長さ(strlen()+1)となる．つまり buf.buf は文字列と
		  見なされる．

		  入力バッファ部が 3byte(8bit*3)の場合, 出力バッファ部は 4byte
		  (6bit*4)となる．入力バッファ部が 6bit境界でない場合, 6bit境界
		  まで 0が付加されたと見される． 
		  出力バッファ部が 4byte境界でない場合, 4byte境界まで '='を付加
		  して出力する． また,出力バッファ部での 60byte毎の改行は行わない．
		  一般に n byte 入力された場合, Base64の出力の文字数は (n+2)/3*4 
		  byte となる．

	引数：buf -- Base64にエンコードするデータ．

	戻り値：Base64にエンコードされた文字列(Buffer型)

	例：'A',0x00,0x01 を文字列(sz=1)とみなして符号化すると "QQ==" となる．
		'A',0x00,0x01 の 3byteを符号化(sz=3)すると "QQAB" となる．
*/
Buffer  encode_base64_Buffer(Buffer buf)
{
	unsigned char* bas;
	int	 sz;
	Buffer  ecd;
	 
	memset(&ecd, 0, sizeof(Buffer));

	if (buf.buf==NULL) return ecd;
	if (buf.vldsz<0) sz = (int)strlen((const char*)buf.buf);
	else		 	 sz = buf.vldsz;
	bas = encode_base64(buf.buf, sz);
	if (bas==NULL) return ecd;
	
	ecd = make_Buffer(sz);
	if (ecd.buf==NULL) {
		free(bas);
		return ecd;
	}

	copy_s2Buffer((char*)bas, &ecd);

	free(bas);
	return ecd;
}




/**
Buffer  decode_base64_Buffer(Buffer str)

	機能：strのバッファを Base64からデコードする．
		  変換は str.bufの先頭から順次行われる．A-Za-z0-9+/ 以外は無視
		  する(例えば改行コード)．

		  入力バッファ部が 4byte(6bit*4)の場合, 出力バッファ部は 3byte
		  (8bit*3)となる．入力バッファ部のバイト数が 4の倍数でない場合
		  (不正なデータ), 足りない入力バッファ部には '='が挿入されてい
		  るものとみなす．

	引数：str -- Base64からデコードする文字列．

	戻り値：Base64からデコードされたデータ(Buffer型)

	例："QQ" をデコードすると 'A',0x00 となる．
*/
Buffer  decode_base64_Buffer(Buffer str)
{
	int	sz;
	Buffer dcd;
	unsigned char* bas;

	memset(&dcd, 0, sizeof(Buffer));
	if (str.buf==NULL) return dcd;

	bas = decode_base64(str.buf, &sz);
	if (bas==NULL) return dcd;

	dcd = make_Buffer(sz);
	if (dcd.buf==NULL) {
		free(bas);
		return dcd;
	}

	copy_b2Buffer(bas, &dcd, sz);
	dcd.vldsz = sz;

	free(bas);
	return dcd;
}





/**
Buffer  get_line_Buffer(Buffer str, int n)

	機能：複数行の文字列バッファから任意の行を取り出す．
		  strのバッファ内の n行目を取り出す．改行コードは削除される．
		  n は 1から数える．取り出した行を Buffer型変数のバッファに格納（コピー）
		  して返す．

	引数：str -- 操作対象の文字列(含む改行)．
		  n   -- 行の指定．

	戻り値：指定された n行目の文字列(Buffer型)．改行は含まない．
*/
Buffer  get_line_Buffer(Buffer str, int n)
{
	int i, j, pos, cnt;
	unsigned char* buf;
	Buffer ret;

	ret = init_Buffer();
	buf = str.buf;
	for(i=0,j=0; j<n-1; j++) {
		while (buf[i]!=LF && buf[i]!=CR && buf[i]!='\0') i++;
		while (buf[i]==LF || buf[i]==CR) i++;
	}
	if (buf[i]=='\0') return  ret;

	pos = i;
	while (buf[i]!=LF && buf[i]!=CR && buf[i]!='\0') i++;
	cnt = i - pos;

	if (cnt!=0) {  
	ret = make_Buffer(cnt);
	if (ret.buf==NULL) return str;
		for(i=0; i<cnt; i++) ret.buf[i] = buf[pos+i];
	}
	ret.vldsz = (int)strlen((const char*)ret.buf);

	return  ret;
}





/**
Buffer  awk_Buffer(Buffer str, char cc, int n)

	機能：Buffer文字列に対する awk．
		  ccを区切り記号として, strのバッファ内の n番目の項目を返す．
		  n は 1から数える．

	引数：str -- 操作対象文字列．
		  cc  -- 区切り文字．
		  n   -- 項目の指定．

	戻り値：指定された n番目の項目の文字列(Buffer型)．

*/
Buffer  awk_Buffer(Buffer str, char cc, int n)
{
	int i, j, pos, cnt;
	unsigned char* buf = str.buf;
	Buffer item = init_Buffer();

	if (buf==NULL) return item;
	if (n<=0) n = 1;

	for(i=0,j=0; j<n-1; j++) {
		while (buf[i]!='\0' && buf[i]!=cc) i++;
		if (buf[i]==cc) i++;
	}
	if (buf[i]=='\0') return item;

	pos = i;
	while (buf[i]!='\0' && buf[i]!=cc) i++;
	cnt = i - pos;

	item = make_Buffer(cnt);
	if (item.buf==NULL) return item;
	for (i=0; i<cnt; i++) item.buf[i] = buf[pos+i];
	item.vldsz = (int)strlen((const char*)item.buf);

	return item;
}





/**
Buffer  cawk_Buffer(Buffer str, char cc, int n)

	機能：Buffer文字列に対する(変形の)awk．
		  ccを区切り記号として, strのバッファ内の n番目の項目を返す．
		  n は 1から数える．連続する cc(区切り)は一つの区切りとみなす．

	引数：str -- 操作対象文字列．
		  cc  -- 区切り文字．
		  n   -- 項目の指定．

	戻り値：指定された n番目の項目の文字列(Buffer型)．
*/
Buffer  cawk_Buffer(Buffer str, char cc, int n)
{
	int i, j, pos, cnt;
	unsigned char* buf = str.buf;
	Buffer item = init_Buffer();

	if (buf==NULL) return item;
	if (n<=0) n = 1;

	i = 0;
	for(j=0; j<n-1; j++) {
		while (buf[i]!='\0' && buf[i]!=cc) i++;
		while (buf[i]!='\0' && buf[i]==cc) i++;
	}
	if (buf[i]=='\0') return item;

	pos = i;
	while (buf[i]!='\0' && buf[i]!=cc) i++;
	cnt = i - pos;

	item = make_Buffer(cnt);
	if (item.buf==NULL) return item;
	for (i=0; i<cnt; i++) item.buf[i] = buf[pos+i];
	item.vldsz = (int)strlen((const char*)item.buf);

	return item;
}




/**
void kanji_convert_Buffer(Buffer* str)

	機能：大域変数 KanjiCode(tools.h) に従って漢字コードを変換する．

	引数：str -- 変換する文字列を持つBuffer型データ．内容が書き換えられる．

	注：現在は KanjiCodeが SJISの場合のみ EUCを SJISに変換する．
 */
void kanji_convert_Buffer(Buffer* str)
{
	int i; 
	unsigned char *c1, *c2;

	if (KanjiCode==SJIS) {
		i = 0;
		while(str->buf[i]!='\0'){
			c1 = &(str->buf[i]);
			c2 = c1 + 1;
			if(*c1>=0xa1 && *c1<=0xfe){
				euc2sjis(c1, c2);	
				i = i + 2;
			} 
			else  i++;
		}
	}			  
	/*
	else if (KanjiCode==EUC) {
		i = 0;
		while(str->buf[i]!='\0'){
			c1 = (unsigned char) str->buf[i];
			c2 = (unsigned char) str->buf[i+1];
			if((c1>=0x81 && c1<=0x9f) || (c1>=0xe0 && c1<=0xff)) {
				sjis2euc(c1, c2);	
				i = i + 2;
			} 
			else  i++;
		}
	} 
	*/			 
}




/**
Buffer  randstr_Buffer(int n)

	機能：ランダムに A-Za-z0-9+/ までの文字を n文字生成する．

	引数：n -- 出力する文字数．

	戻り値：ランダムに生成された n文字の文字列(Buffer型)．
*/
Buffer  randstr_Buffer(int n)
{
	char   base[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	Buffer pass;
	int	i, sz;

	pass = make_Buffer(n);
	if (pass.buf==NULL) return pass;

	sz = (int)strlen(base);
	for (i=0; i<n; i++) pass.buf[i] = base[rand()%sz];
	pass.vldsz = n;

	return pass;
}





/**
Buffer  randbit_Buffer(int n) 

	機能：ランダムに n bitのバイナリを生成する．

	引数：n -- 出力する bit数．

	戻り値：ランダムに生成された n bitのデータ(Buffer型)．
 */
Buffer  randbit_Buffer(int n) 
{
	int   i, sz;
	Buffer str;
	
	sz = (n+7)/8;
	str = make_Buffer(sz);
	if (str.buf==NULL) return str;
	str.vldsz = sz;

	for (i=0; i<n; i++) setBit(str.buf, i, rand()%2);
	return str;	 
}





/**
Buffer  dump_Buffer(Buffer buf)

	機能：Buffer型変数のデバッグ用 16進を Buffer型変数に出力する
		  buf.bufの buf.vldszバイトを16進表示する． 
		  buf.vldsz<0 の場合は 文字列とみなす．

	引数：buf -- 変換する Buffer型データ．
*/
#define  DUMP_BUFFER_LINE_SIZE	 85  	// 16*5("%02x "+"%c ") + 5("   "+"\r\n");
#define  DUMP_BUFFER_DELI_START	 48 	// 16*3("%02x ") 
#define  DUMP_BUFFER_CHAR_START	 51  	// 16*3("%02x ") + 3("   ") 

Buffer  dump_Buffer(Buffer buf)
{
	int    sz;
	char   wrkbuf[10];
	Buffer str = init_Buffer();

	if (buf.buf==NULL) return str;
	if (buf.vldsz<0) sz = (int)strlen((const char*)buf.buf) + 1;
	else			 sz = buf.vldsz;

	int lineno = (sz + 15)/16;
	str = make_Buffer(lineno*DUMP_BUFFER_LINE_SIZE+1);

	int l;
	for (l=0; l<lineno; l++) {
		int sp = l*DUMP_BUFFER_LINE_SIZE;
		int i  = 0;
		while (i<16) {
			sprintf(wrkbuf, "%02x ", buf.buf[l*16+i]);
			memcpy(str.buf+sp+i*3, wrkbuf, 3);

			if (buf.buf[l*16+i]>=0x20 && buf.buf[l*16+i]<=0x7e) {
				sprintf(wrkbuf, "%c ", buf.buf[l*16+i]);
				memcpy(str.buf+sp+DUMP_BUFFER_CHAR_START+i*2, wrkbuf, 2);
			}
			else {
				memcpy(str.buf+sp+DUMP_BUFFER_CHAR_START+i*2, ". ", 2);
			}

			if (l*16+i>=sz) {
				memcpy(str.buf+sp+i*3, "   ", 3);
				memcpy(str.buf+sp+DUMP_BUFFER_CHAR_START+i*2, "  ", 2);
			}

			i++;
		}
		memcpy(str.buf+sp+DUMP_BUFFER_DELI_START, "   ", 3);
		str.buf[sp+DUMP_BUFFER_LINE_SIZE-2] = '\r';
		str.buf[sp+DUMP_BUFFER_LINE_SIZE-1] = '\n';
	}
	
	str.vldsz = lineno*DUMP_BUFFER_LINE_SIZE;
	return str;
}





/**
int  recalc_strlen_Buffer(Buffer* buf)

	機能：Buffer型変数のデータ部を文字列と見なして，その長さを返す．
		　また，vldsz も再計算される．
*/
int  recalc_strlen_Buffer(Buffer* buf)
{
	int len = (int)strlen((char*)buf->buf);
	buf->vldsz = len;
	return len;
}





/**
void  chomp_Buffer(Buffer* str)

	機能：最初の改行コード以降を無視する．

	引数：str -- 改行を無効にする文字列(Buffer型)．
 */
void  chomp_Buffer(Buffer* str)
{
	int i, len;
	
	if (str->buf==NULL) return;

	len = (int)strlen((const char*)str->buf);
	for (i=0; i<len; i++) {
		if (str->buf[i]==LF || str->buf[i]==CR) {
			str->buf[i] = '\0';
			str->vldsz = (int)strlen((const char*)str->buf);
			return;
		}
	}
}





int  isText_Buffer(Buffer buf)
{
	if (buf.vldsz==(int)strlen((const char*)buf.buf)) return TRUE;
	return FALSE;
}






////////////////////////////////////////////////////////////////////////////////////
//
// File I/O
// 

/**
int  fgets_Buffer(Buffer* str, FILE* fp)

	機能：拡張fgets．文字列の読み込みに使用する．改行コードは削除する．
	 	  strのバッファは予め十分な大きさを確保しておかなければならない． 

	引数：str -- 文字列を読みこむための Buffer型データバッファ．
		  fp  -- 文字列を読みこむファイルへのポインタ．

	戻り値：読み込んだ文字列の長さ（改行コードを含む）．
*/
int  fgets_Buffer(Buffer* str, FILE* fp)
{
	int   n, m;

	memset(str->buf, 0, str->bufsz);
	fgets((char*)str->buf, str->bufsz, fp);
	m = (int)strlen((const char*)str->buf);

	n = 0;
	while(str->buf[n]!=LF && str->buf[n]!=CR && str->buf[n]!='\0') n++;
	str->buf[n] = '\0';
	str->vldsz  = n;

//	if (KanjiCode!=US) kanji_convert_Buffer(str);

	return m;
}






/**
int  read_lines_Buffer(Buffer* str, FILE* fp)

	機能：複数文字列行の読み込み．文字列の読み込みに使用する．
	 	  strのバッファは予め十分な大きさを確保しておかなければならない． 

	引数：str -- 文字列を読みこむための Buffer型データバッファ．
		  fp  -- 文字列を読みこむファイルへのポインタ．

	戻り値：読み込んだ全データの長さ．
*/
int  read_lines_Buffer(Buffer* str, FILE* fp)
{
	Buffer buf;

	buf = make_Buffer(str->bufsz);
	if (buf.buf==NULL) return -1;

	fgets((char*)buf.buf, buf.bufsz, fp);
	buf.vldsz = (int)strlen((const char*)buf.buf);
	copy_Buffer(&buf, str);
	clear_Buffer(&buf);

	while (!feof(fp)) {
		fgets((char*)buf.buf, buf.bufsz, fp);
		buf.vldsz = (int)strlen((const char*)buf.buf);
		cat_Buffer(&buf, str);
		clear_Buffer(&buf);
	}

	free_Buffer(&buf);
	return str->vldsz;
}






/**
Buffer  read_Buffer_file(char* fn)

	機能：ファイル fn の内容を Buffer型変数に読み込み返す．

*/
Buffer  read_Buffer_file(char* fn)
{
	int     sz;
	Buffer  buf;
	FILE*   fp;

	buf = init_Buffer();

	sz = file_size(fn);
	if (sz<=0) return buf;

	fp = fopen(fn, "rb");
	if (fp==NULL) return buf;

	buf = read_Buffer_data(fp, sz);
	fclose(fp);
	
	return buf;
}




/**
Buffer  read_Buffer_data(FILE* fp, int sz)

	機能：ファイルポインタ fp から szバイトをBuffer型変数に読み込み，返す．

*/
Buffer  read_Buffer_data(FILE* fp, int sz)
{
	int     cc;
	Buffer  buf;

	buf = init_Buffer();
	if (sz<0) return buf;

	buf = make_Buffer(sz);
	if (buf.buf==NULL) return buf;
	buf.vldsz = sz;

	cc = (int)fread(buf.buf, buf.vldsz, 1, fp);
	if (cc!=1) {
		free_Buffer(&buf);
		return buf;
	}
	
	return buf;
}





/**
int   save_Buffer_file(Buffer buf, char* fn)

	機能：ファイル fn へ Buffer型変数の buf部を書き込む．

	引数：buf -- 書き込む Buffer型変数．
		  fn  -- ファイル名

	戻り値：TRUE　書き込み成功．
		　　FALSE 書き込みに失敗．ファイルの内容は保証されない．
*/
int   save_Buffer_file(Buffer buf, char* fn)
{
	int   cc;
	FILE* fp;

	fp = fopen(fn, "wb");
	if (fp==NULL) return FALSE;

	cc = (int)fwrite(buf.buf, buf.vldsz, 1, fp);
	if (cc!=1) return FALSE;
	fclose(fp);
	
	return TRUE;
}






////////////////////////////////////////////////////////////////////////////////////
//
//  文字列操作
// 


/**
Buffer  erase_bBuffer(Buffer buf, char* bin, int len);

	機能：buf.buf 中にある bin のデータ（各1Byte，順不同）を削除する．

	引数：buf -- 操作する Buffer変数
		  bin -- 削除するデータを格納したメモリへのポインタ
		  len -- binデータの長さ

	戻り値：変換した文字列を格納した Buffer変数．要free

*/
Buffer  erase_bBuffer(Buffer buf, char* bin, int len)
{
	int	 i, j, n;
	char cc;

	Buffer res = dup_Buffer(buf);
	Buffer wrk = make_Buffer(buf.vldsz+1);

	for (i=0; i<len; i++) {
		cc = bin[i];
		n  = 0;
		for (j=0; j<res.vldsz; j++) {
			if (cc!=res.buf[j]) wrk.buf[n++] = res.buf[j];
		}
		wrk.vldsz = n;

		copy_Buffer(&wrk, &res);
		clear_Buffer(&wrk);
	}
				
	free_Buffer(&wrk);

	return res;
}





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

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

	引数：buf -- 操作する Buffer変数
		  frm -- 変換する文字列を格納したBuffer変数
		  tos -- 変換後の文字列を格納したBuffer変数

	戻り値：変換した文字列を格納した Buffer変数．要free

	#define replace_Buffer(b, f, t)    replace_sBuffer_bystr((b), (char*)((f).buf), (char*)((t).buf))
*/




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

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

	引数：buf -- 操作する Buffer変数
		  frm -- 変換する文字列
		  tos -- 変換後の文字列

	戻り値：変換した文字列を格納した Buffer変数．要free

	#define replace_sBuffer(b, f, t)    replace_sBuffer_bystr((b), (f), (t))
*/





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

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

	引数：buf -- 操作する Buffer変数
		  frm -- 変換する文字列
		  tos -- 変換後の文字列

	戻り値：変換した文字列を格納した Buffer変数．要free
*/
Buffer  replace_sBuffer_bystr(Buffer buf, char* frm, char* tos)
{
	int	i, j, flen, tlen;
	Buffer res;

	res = init_Buffer();
	if (buf.buf==NULL || frm==NULL || tos==NULL) return res;

	flen = (int)strlen(frm);
	tlen = (int)strlen(tos);
	if (buf.vldsz<0) buf.vldsz = (int)strlen((const char*)buf.buf);

	res = make_Buffer((int)((buf.vldsz+tlen-flen+1)*BUFFER_FACT));

	i = j = 0;
	while (i<buf.vldsz && j<res.bufsz) {
		if (!strncmp((const char*)(buf.buf+i), frm, flen)){
			res.vldsz = (int)strlen((const char*)res.buf);
			cat_s2Buffer(tos, &res);
			i += flen;
			j += tlen;
		}
		else {
			res.buf[j++] = buf.buf[i++];
		}
	}

	res.vldsz = (int)strlen((const char*)res.buf);
	return res;
}





/**
int  replace_sBuffer_file(char* fn, Buffer frm, Buffer tos)

	機能：テキストファイル中の frm の文字列を tos に書き換える

	引数：fn  -- 操作するファイル名
		  frm -- 変換する文字列
		  tos -- 変換後の文字列

	戻り値：TRUE　書き込み成功．
		　　FALSE 書き込みに失敗．ファイルの内容は保証されない．
*/
int  replace_sBuffer_file(char* fn, Buffer frm, Buffer tos)
{
	int  ret;
	Buffer buf, res;

	buf = read_Buffer_file(fn);
	if (buf.buf==NULL) return FALSE;

	res = replace_Buffer(buf, frm, tos);
	free_Buffer(&buf);
	if (res.buf==NULL) return FALSE;

	ret = save_Buffer_file(res, fn);
	free_Buffer(&buf);

	return ret;
}








////////////////////////////////////////////////////////////////////////////////////
//
//  ヘッダ（書式）付特殊ファイルI/O
// 
/**
int   save_Buffer2_fp(Buffer key, Buffer buf, FILE* fp)

	機能：ファイル fp へ 2つのBuffer型変数 keyと bufを書き込む．
	      データ検索用ファイルを作成するときに使用する．

	引数：key -- 書き込むキー部のBuffer型変数．
		  buf -- 書き込むデータ部のBuffer型変数．
		  fp  -- ファイルディスクリプタ

	戻り値：TRUE　書き込み成功．
		　　FALSE 書き込みに失敗．ファイルの内容は保証されない．
*/
int   save_Buffer2_fp(Buffer key, Buffer buf, FILE* fp)
{
	int   cc;
	
	cc = save_Buffer_fp(key, fp);
	if (!cc) return FALSE;

	cc = save_Buffer_fp(buf, fp);
	if (!cc) return FALSE;
	
	return TRUE;
}





/**
int   save_Buffer_fp(Buffer buf, FILE* fp)

	機能：ファイル fp へ Buffer型変数の buf部を書き込む．buf部に先立ち，
	　　　buf部の大きさが int で書き込まれる．

	引数：buf -- 書き込む Buffer型変数．
		  fp  -- ファイルディスクリプタ

	戻り値：TRUE　書き込み成功．
		　　FALSE 書き込みに失敗．ファイルの内容は保証されない．
*/
int   save_Buffer_fp(Buffer buf, FILE* fp)
{
	int   cc, sz;

	sz = htonl(buf.vldsz);
	cc = (int)fwrite(&sz, sizeof(sz), 1, fp);
	if (cc!=1) return FALSE;

	cc = (int)fwrite(buf.buf, buf.vldsz, 1, fp);
	if (cc!=1) return FALSE;
	
	return TRUE;
}





/**
Buffer  read_Buffer_fp(FILE* fp)

	機能：ファイル fp から Buffer型変数の buf部を読み込む．
		  ただしファイルの先頭にファイルサイズを示す4Byteの値が必要

	引数：fp  -- ファイルディスクリプタ
	
	戻り値：読み込んだ buf部を持つ Buffer型変数．

*/
Buffer  read_Buffer_fp(FILE* fp)
{
	int     cc, sz;
	Buffer  buf;

	buf = init_Buffer();
	cc = (int)fread(&sz, sizeof(sz), 1, fp);
	if (cc!=1) return buf;
	sz = ntohl(sz);

	buf = make_Buffer(sz);
	if (buf.buf==NULL) return buf;
	buf.vldsz = sz;
	cc = (int)fread(buf.buf, buf.vldsz, 1, fp);
	if (cc!=1) {
		free_Buffer(&buf);
		return buf;
	}
	
	return buf;
}





/**
int  read_Buffer2_fp(Buffer* key, Buffer* buf, FILE* fp)

	機能：ファイル fp から 2つのBuffer型変数の keyと bufを読み込む．
	      データ検索用ファイルからの読み込み時に使用する．

	引数：key -- 読み込むキー部のBuffer型変数へのポインタ．
		  buf -- 読み込むデータ部のBuffer型変数へのポインタ．
		  fp  -- ファイルディスクリプタ
	
	戻り値：TRUE　読み込み成功．
		　　FALSE 読み込みに失敗．

*/
int  read_Buffer2_fp(Buffer* key, Buffer* buf, FILE* fp)
{
	if (key==NULL || buf==NULL) return FALSE;

	*key = init_Buffer();
	*buf = init_Buffer();
	
	*key = read_Buffer_fp(fp);
	if (key->buf==NULL) return FALSE;

	*buf = read_Buffer_fp(fp);
	if (buf->buf==NULL) {
		free_Buffer(key);
		return FALSE;
	}

	return TRUE;
}




/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// etc. etc.
//

/**
char*  dup_string(char* src)

    機能：文字列をコピーする．

*/
char*  dup_string(char* src)
{
	if (src==NULL) return NULL;

	Buffer buf = make_Buffer_bystr(src);
	return (char*)buf.buf;
}

