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

#ifndef  __JBXL_TOOLS_HEADER_
#define  __JBXL_TOOLS_HEADER_


/** 
@brief   汎用ツールヘッダ
@file    tools.h
@author  Fumi.Iseki (C)
@date    2005 10/10
*/



#include "common.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <ctype.h>


#ifdef WIN32
	#include <winsock2.h>		// for ntohl, ntohs, htonl, htons
	#ifndef HAVE_TIME_H
		#define  HAVE_TIME_H
	#endif
#else
	#include <unistd.h>	
	#include <sys/sysinfo.h>
#endif


#ifdef HAVE_ARPA_INET_H
	#include <arpa/inet.h>
#endif

#ifdef TIME_WITH_SYS_TIME
	#include <time.h>
	#include <sys/time.h>
#else
	#ifdef HAVE_TIME_H 
		#include <time.h>
	#endif 
	#ifdef HAVE_SYS_TIME_H 
		#include <sys/time.h>
	#endif 
#endif

#ifdef HAVE_SYS_PARAM_H 
	#include <sys/param.h>
#endif

#ifdef HAVE_SYSLOG_H
	#include <syslog.h>
#endif

#ifdef HAVE_WAIT_H 
	#include <wait.h>
#endif
#ifdef HAVE_SYS_WAIT_H 
	#include <sys/wait.h>
#endif

#ifdef HAVE_SYS_ERRNO_H 
	#include <sys/errno.h>
#else
	#include <errno.h>
#endif
#include <signal.h>



/*
マクロ
*/
#define  CHAR_CR	0x0d		///< 改行 
#define  CHAR_LF	0x0a		///< ラインフィード 
#define  CHAR_TAB	0x09		///< タブ 

#define  CODE_US	 0
#define  CODE_EN	 0
#define  CODE_EUC	 1			//  
#define  CODE_SJIS   2			//  
#define  CODE_UTF8   3			//  


#define UNKNOWN_ENDIAN 		0
#ifndef LITTLE_ENDIAN
  #define  LITTLE_ENDIAN  1234
  #define  BIG_ENDIAN 	  4321
  #define  PDP_ENDIAN 	  3412
#endif




typedef union _union_val {
	long long int 			llint;
	unsigned long long int 	ullint;
	long int				lint;
	unsigned long int		ulint;
	int						nint;
	unsigned int			uint;
	short int				sint;
	unsigned short int		usint;
	char					nchar;
	unsigned char			uchar;
	double					dreal;
	float					real;
	sDWord					sdword;
	uDWord					udword;
	sWord					sword;
	uWord					uword;
	sByte					sbyte;
	uByte					ubyte;
} UnionVal;
	

typedef union _union_ptr {
	long long int* 			llintp;
	unsigned long long int* ullintp;
	long int*				lintp;
	unsigned long int*		ulintp;
	int*					nintp;
	unsigned int*			uintp;
	short int*				sintp;
	unsigned short int*		usintp;
	char*					ncharp;
	unsigned char*			ucharp;
	double*					drealp;
	float*					realp;
	sDWord*					sdwordp;
	uDWord*					udwordp;
	sWord*					swordp;
	uWord*					uwordp;
	sByte*					sbytep;
	uByte*					ubytep;
} UnionPtr;
	


// バイト型 リングバッファ
typedef  struct _ringbuffer {
	unsigned char* buf;			///< バッファ
	int   bufsz;				///< バッファ部のサイズ
	int   spoint;				///< バッファデータの開始点
	int   epoint;				///< バッファデータの終点+1 (データの追加点)
	int   npoint;				///< 次のメッセージのスタートポイント
	int   datasz;				///< 保存されているデータの全体の長さ
	int   datano;				///< 格納されているデータの数
	int   state;				///< リングバッファの状態
} ringbuffer;


#define  mstream   ringbuffer	///< バイト型 メッセージストリーム




// 矩形
typedef  struct _rectangle {
	int   x;					///< X 座標
	int   y;					///< Y 座標
	int   xsize;				///< 幅
	int   ysize;				///< 高さ
} rectangle;




//
// 大域変数
//
extern int   DebugMode; 		///< ON の場合 ライブラリ全体がデバックモードであることを示す．デフォルトは OFF．
extern int   UnitTestMode;		///< ユニット単体でのテストを行う場合に使用する．デフォルトは OFF.

extern int   KanjiCode;			///< 処理用漢字コード．CODE_US, CODE_SJIS, CODE_EDUがある．デフォルトは CODE_US．
extern int	 HostEndian;		///< ホストの Endian

extern char  LocalIPNum[4];		///< 127.0.0.1 のバイナリ



#define  LOCAL_IPADDR  "127.0.0.1"



// not C++
#ifndef CPLUSPLUS
  int  isNull(void* p);
  #define freeNull(p)     {if(!isNull(p)) free(p); (p)=NULL;}
#endif


#define _tochar(a)   (char*)(a)




/**/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 文字（列）操作
char*   get_line(char* buf, int n);								///< 文字型データbufのバッファ内の n行目を取り出す．改行コードは削除される．要free
char*   get_seq_data(char* buf, int* ptr);						///< 文字型データbufのバッファ内の 行データをシーケンシャルに取り出す．
char*   awk (char* str, char cc, int n);						///< ccを区切り記号として, strのバッファ内の n番目の項目を返す．要free
char*   cawk(char* str, char cc, int n);						///< 連続するccを区切り記号として, strのバッファ内の n番目の項目を返す．要free

char*   replace_str(char* buf, int len, const char* frm, const char* tos);	///< 文字列 buf中の frmを tosに書き換えたものを返す．freeしてはいけない．	
char*   cut_str(char* buf, int ls, int le);						///< buf[ls]〜buf[le] を切り出す．要 free
char*   dup_str(char* buf);										///< 文字列を複製する．要 free
#define dup_string(s) dup_str((s))
char*	skip_char(char* mesg, const char* check);				///< check[]中の何れかの文字までポインタをスキップさせる．ただし " ' 内は完全スキップ
char*  	pack_char(char* mesg, char cc);							///< 文字列中及び，先頭のcc(複数)，終わりのcc(複数)，CR, LF を削除．要 free
char*  	pack_head_tail_char(char* mesg, char cc);				///< 文字の先頭のcc(複数)，TAB, CR, LF．終わりのcc(複数)，TAB, CR, LF を削除．要 free
char*  	change_esc(char* mesg);									///< 文字列中の CR, LF を @\r, @\n に変換する．要 free
char*   chomp(char* str);										///< 最初の改行コード以降を無効にする．
char*   double_bs(char* fn);									///< 文字列中の @\ を @\@\に置き換えた文字列を返す．要 free
char*   numbering_name(const char* fmt, int n);					///< フォーマット fmtに従って，nを含む文字列を作り出す．要 free

char*	itostr(int n);											///< int を文字に変換する．free は不要	
char*	ltostr(long int n);										///< long int を文字に変換する．free は不要	
char*	ultostr(unsigned long int n);							///< unsigned long int を文字に変換する．free は不要	
char*	lltostr(long long int n);								///< long long int を文字に変換する．free は不要	
char*	ulltostr(unsigned long long int n);						///< unsigned long long int を文字に変換する．free は不要	
char*	ftostr(float n);										///< float を文字に変換する．free は不要	
char*	dtostr(double n);										///< double を文字に変換する．free は不要	

int     count_lines(const char* buf);							///< 文字列データの行数を数える．行頭が '\0'の場合も1行と数える．
int 	hexstr2i(const char* str);								///< 16進の文字列を整数に変換する．
	
unsigned long long int ntohull(unsigned long long int s);		///< Network形式からHost形式へ，64bit unsigned long long int データの変換 
#define htonull(s)	ntohull((s))								///< Host形式からNetwork形式へ，64bit unsigned long long int データの変換 

void	swap_byte(void* p, int s, int b);						///< sの長さのpのバイト順序をbバイト毎に逆順にする．
short   swaps(unsigned short p);								///< 16bit の上下8bitを入れ替える．
int	 	swapl(unsigned int   p);								///< 32bit pを8bitづつ逆順にする
void	reverse_str(uByte* p, int s);							///< バイト(octet)列を逆順にする．
void	upper_string(char* str);
#define int_swap(p, s) 	{int swap=(p); (p)=(s); (s)=swap;}		///< データを入れ替える



// 比較
int  	bincmp(unsigned char* b1, unsigned char* b2, int n);	///< バイナリデータを n Byte比べる
int	 	strnrvscmp(const char* s1, const char* s2, int n);		///< 文字列 s1と s2を後ろから n文字比較する．
int	 	strncaservscmp(const char* s1, const char* s2, int n);	///< 文字列 s1と s2を後ろから n文字比較する．
char*   strstrcase(const char* buf, const char* nd);			///< 文字列 bufの中に文字列 ndがあるかどうかをチェックする．大文字小文字は区別しない．

int	 	ex_strncmp(const char* s1, const char* s2, int n);		///< 文字列 s1とs2を拡張比較する．
int	 	ex_strncasecmp(const char* s1, const char* s2, int n);	///< 文字列 s1とs2を拡張比較する．
int	 	ex_strnrvscmp(const char* s1, const char* s2, int n);	///< 文字列 s1とs2を後ろから拡張比較する．
int	 	ex_strncaservscmp(const char* s1, const char* s2, int n);	///< 文字列 s1とs2を後ろから拡張比較する．


// エンディアン  (マクロ isBigEndianは ntohs() を使用したもの）
int 	is_little_endian(void);
int 	is_big_endian(void);
void 	check_endian(void);

double 			double_from_little_endian(void* ptr);
float 			float_from_little_endian(void* ptr);
int  			int_from_little_endian(void* ptr);
unsigned int 	uint_from_little_endian(void* ptr);
short 			short_from_little_endian(void* ptr);
unsigned short 	ushort_from_little_endian(void* ptr);
double 			double_from_big_endian(void* ptr);
float 			float_from_big_endian(void* ptr);
int  			int_from_big_endian(void* ptr);
unsigned int  	uint_from_big_endian(void* ptr);
short 			short_from_big_endian(void* ptr);
unsigned short 	ushort_from_big_endian(void* ptr);


// 時間
char*   get_local_time(char d1, char d2, char d3);				///< 現時刻の文字列を返す．free()してはいけない．


// 入出力
void	print_escape(const char* format, char* mesg);			///< エスケープ文字を含むメッセージの出力（stderr）
void	fdump(FILE* fp, unsigned char* mesg, int n);			///< 16進ダンプを吐き出す
void	print_16x(FILE* fp, unsigned char* mesg, int n);		///< 16進ダンプを吐き出す（１行）


// 漢字コード
void	kanji_convert(unsigned char* mesg);						///< 大域変数 KnjiCodeに従って漢字コードを変換する．
void	kanji_convert_euc2sjis(unsigned char* mesg);			///< EUCをSJISに変換する．
void	kanji_convert_sjis2euc(unsigned char* mesg);			///< SJISをEUCに変換する．
void	euc2sjis(unsigned char *c1, unsigned char *c2);			///< EUC  -> SJIS
void	sjis2euc(unsigned char *c1, unsigned char *c2);			///< SJIS -> EUC


// ファイル
int		file_from_to(const char* s, const char* d, const char* mode);	///< modeに従って,ファイル sを dにコピーする．
int		fp_from_to(FILE* s, FILE* d, long int sz);				///< ファイル sを dにコピーする．
char*   get_file_name(const char* str);							///< フルパスからファイル名へのポインタを取り出す．free してはいけない．
char*	get_file_extension(const char* str);					///< フルパスからファイル名の拡張子へのポインタを取り出す．free してはいけない．
unsigned long file_size(const char* fn);						///< ファイルの大きさを返す．
int	 	file_exist(const char* fn);								///< ファイルの存在を検査する．
FILE* 	file_chmod_open(const char* fn, const char* fm, mode_t mode);
char*   temp_filename(const char*, int);

unsigned char* 	read_file (const char* fname, unsigned long int* size);
long int  		write_file(const char* fname, unsigned char* buf, unsigned long int size);



// 乱数
void	init_rand(void);										///< /dev/urandom からデータで乱数の系列を初期化する
char*   randstr(int n);											///< ランダムに A-Za-z0-9 までの文字を n文字生成する．
unsigned char* randbit(int n);									///< ランダムに n bitのバイナリを生成する．
#define random_str(n)   temp_filename(NULL, (n))				///< ランダムな文字列を生成．要 free


// Base64
unsigned char*  encode_base64(unsigned char* str, int  sz);				// 要 free
unsigned char*  decode_base64(unsigned char* str, int* sz);				// 要 free
unsigned char*  encode_urlenc(unsigned char* str, int  sz);				// 要 free
unsigned char*  decode_urlenc(unsigned char* str, int* sz);				// 要 free
unsigned char*  encode_quoted_printable(unsigned char* str, int  sz);	// 要 free
unsigned char*  decode_quoted_printable(unsigned char* str, int* sz);	// 要 free
unsigned char*  encode_hex(unsigned char cc);							// 要 free
unsigned char	decode_hex(unsigned char c1, unsigned char c2);			// 内容の書き換え


// バイト型リングバッファー
ringbuffer* 	new_ringbuffer(void);
ringbuffer  	init_ringbuffer(void);
ringbuffer  	make_ringbuffer(int sz);
void  			del_ringbuffer  (ringbuffer** pp);
void  			free_ringbuffer (ringbuffer* pp);
void  			clear_ringbuffer(ringbuffer* pp);
int   			put_ringbuffer(ringbuffer* rb, unsigned char* pp, int sz);
unsigned char* 	get_ringbuffer(ringbuffer* rb, int sz);


// メッセージストリーム
int   			put_mstream(mstream* sb, unsigned char* pp);
unsigned char* 	get_mstream(mstream* sb);
unsigned char* 	fgets_mstream(unsigned char* mesg, mstream* sb);

#define  init_mstream()		init_ringbuffer()
#define  new_mstream()		new_ringbuffer()
#define  make_mstream(s)  	make_ringbuffer((s))
#define  free_mstream(s)  	free_ringbuffer((s))
#define  del_mstream(s)   	del_ringbuffer((s))
#define  clear_mstream(s) 	clear_ringbuffer((s))


// UUID
unsigned char*  uuid2guid(unsigned char* p);			///< 要free
unsigned char*  guid2uuid(unsigned char* p);			///< 要free


#ifndef WIN32
// プロセス
unsigned long int get_used_memory(void);
unsigned long int get_free_memory(void);

void  	set_sigterm_child(void (*handler)(int));
void  	sigterm_child(int signal);

void  	ignore_sigterm_child(void);

void	set_sigsegv_handler(void (*handler)(int));
void	trap_segmentation_falt(int signal);

#define  set_sigseg_handler(h)    set_sigsegv_handler((h))

#endif


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// for Windows

#ifdef WIN32

//void  bzero(char* p, unsigned int n);
//void  bcopy(char* f, char* t, unsigned int n);

#endif   // WIN32



/**/

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// マクロ関数
//

#define copy_file(src, dst)  file_from_to((src), (dst), "wb")	///< srcから dsへファイルをコピーする．
#define cat_file(src, dst)   file_from_to((src), (dst), "ab")	///< srcから dstへファイルを catする．

#define  isBigEndian	(is_big_endian())
#define  isLittleEndian (is_little_endian())

#define  ntoh_st(p, s) {if(!isBigEndian) swap_byte((void*)(p),sizeof(*(p)),(s));}	///< network形式から host形式へ．構造体pに対して sバイトづつ変換．
#define  hton_st(p, s) {if(!isBigEndian) swap_byte((void*)(p),sizeof(*(p)),(s));}	///< host形式から network形式へ．構造体pに対して sバイトづつ変換．
#define  ntoh_ar(p, s) {if(!isBigEndian) swap_byte((void*)(p),(s),sizeof(*(p)));}	///< network形式から host形式へ．長さsバイトの配列pに対して変換
#define  hton_ar(p, s) {if(!isBigEndian) swap_byte((void*)(p),(s),sizeof(*(p)));}	///< host形式から network形式へ．長さsバイトの配列pに対して変換．

#define  ntoh_data(p, s, c) {if(!isBigEndian) swap_byte((void*)(p),(s),(c));} 		///< network形式からhost形式へ.  cバイトづつ変換する．
#define  hton_data(p, s, c) {if(!isBigEndian) swap_byte((void*)(p),(s),(c));} 		///< host形式から network形式へ. cバイトづつ変換する．



/////////////////////////////////////////////////////////////////////////////////////
// for Debug


#ifdef _DEBUG
	#ifndef EBUG
		#define EBUG
	#endif
#endif



// ログファイル

#ifdef WIN32
	#define  JBXL_LOG_FILE   "C:\\jbxl.log"
#else
	#define  JBXL_LOG_FILE   "/var/log/jbxl.log"
#endif


extern  FILE*  FP_LogFile;


void	open_logfile (void);
void	close_logfile(void);
void	print_logfile(const char*, ...);




// エラーメッセージ関数

void	 print_message(const char*, ...);					///< バッファリングなしのメッセージ出力（stderr）
void	fprint_message(FILE*, const char*, ...);			///< バッファリングなしのメッセージ出力

#define   print_mesg  print_message
#define  fprint_mesg fprint_message




#ifdef EBUG
    /** DEBUG_MESG(char* fmt, ...)
    デバッグ情報を stderr に出力する．@n
    -DEBUG オプションつきでコンパイルされた時に出力される．@n
    静的に制御する場合に使用．つまり作成時のデバッグで使用する場合に使用し，製品版では削除することが可能．
    */
	#define DEBUG_MESG  print_message

    /** DEBUG_ESCP(char* fmt, ...)
    エスケープシーケンスの文字を可視化して stderr に出力する．@n
    -DEBUG オプションつきでコンパイルされた時に出力される．@n
    静的に制御する場合に使用．つまり作成時のデバッグで使用する場合に使用し，製品版では削除することが可能．
    */
	#define DEBUG_ESCP  print_escape

    /** DEBUG_LOG(char* fmt, ...)
     デバッグ情報を JBXL_LOG_FILE に出力する．改行付き．@n
    -DEBUG オプションつきでコンパイルされた時に出力される．@n
    静的に制御する場合に使用．つまり作成時のデバッグで使用する場合に使用し，製品版では削除することが可能．
    */
	#define DEBUG_LOG   print_logfile


	#ifndef _DEBUG
		#define _DEBUG
	#endif
#else
	#define DEBUG_MESG(f, ...)  {}
	#define DEBUG_ESCP(f, ...)  {}
	#define DEBUG_LOG(f, ...)   {}
#endif


#define  DEBUG_MODE  if(DebugMode==ON)


#endif

