
#ifndef DKUTIL_STRING_UTIL_HPP
#define DKUTIL_STRING_UTIL_HPP


//#include <dkutil/scoped_array_ex.hpp>
#include <deque>


#include <dkutil/boost/parm_string.hpp>
#include <dkutil/macro.hpp>
#include <dkutil/config.hpp>
#include <dkutil/scoped_buffer.hpp>
#include <dkutil/parser/general_purpose_data.hpp>
#include <dkutil/math/utility.hpp>

#include <dkutil_c/dkcString.h>

#include <dkutil/dktl/traits.hpp>

#include <dkutil/parser/char_util.hpp>
#include <dkutil/parser/string_printf.hpp>
#include <dkutil/parser/sjis_util.hpp>
#include <dkutil/parser/to_string.hpp>

namespace dkutil{

template<typename CHAR_T>
inline size_t double_null_strlen(const CHAR_T *p){
	size_t i=0;
	typedef policy::non_const_traits<CHAR_T>::value_type CTT;
	CTT temp = 1;
	while(1){
		if('\0'==temp && '\0'==p[i]){
			return i;
		}
		temp = p[i];
		i++;	
	}
}

#if 0
	/*
template<size_t s>
class char_array{
protected:
	char str[s];
	enum{
		enuSize=s;
	};
public:
	
	char_array(){::memset(str,0,sizeof(str));}
	virtual ~char_array(){}
	char *get(){return str;}
	void set(char *p,size_t s){
		if(
		::memcpy(str,p,s);
		}
*/
	
	
template<class T>
class dkbasic_string{
public:
	typedef size_t size_type;
protected:
	T *m_str;
	size_type m_size;
public:
	dkbasic_string(){
		m_str=NULL;
		m_size = 0;
	}
	virtual ~dkbasic_string(){}
	T *get_str(){return m_str;}
	void set_str(T *str){
		size_type size = _tcslen(str);
		if(size >= m_size){
			DK_THROW(std::overflow_error("set_str overflow"));
			return;
		}
		::memcpy(m_str,str,size);
	}
	void allocate_str(size_type size){
		if(!m_str){
			m_str = malloc(size);



class dkstring : {
protected:
	
	char *get_str(){return c_str();

		
#endif


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


#ifdef DKUTIL_BORLAND_COMPILER
inline const char *strtail( const char *stringg )
{
	return strchr( (const char *)stringg, '\0' );
}//strtail
#else

/// 文字列末尾の文字 '\0' の位置を返す
inline char *strtail( const char *stringg )
{
	return ::strchr( (const char *)stringg, '\0' );
}//strtail
#endif

///atoiのunsigned版
/*inline UINT atoui(const char *s){
	return atoll(s);//面倒なので64ビットで･･･(ｵｨ
}*/

/*!
MSVC6では関数テンプレートはバグってくれる＾＾；なのでFUNCTOR仕様･･･
*/
template<typename RESULT_,size_t MAXLEN_>
struct atointeger{
		
	inline RESULT_ operator()(const char *a){
		const char *b = a;
		RESULT_ ret;
		size_t maxlen = MAXLEN_;
		ret = 0;
		if(a==NULL || a=='\0') return 0;
		
		for (size_t i=0;;a++,i++)
		{
			if(false==dkutil::isDigit((*a)) && (*a) != '\0'){
				throw std::invalid_argument("文字列が混じっていたぞ！");
			}
			if(maxlen < i){
				throw std::overflow_error("オーバーフローしちまったぞ！よって戻り値はアホ値だ！");
			}
			switch (*a)
			{
			case '\0':
				return ret;

			case '0': case '1': case '2': case '3':
			case '4': case '5': case '6': case '7':
			case '8': case '9':
				ret *= 10;
				ret += (*a) - '0';
				break;
			}
		}
		return 0;
	}
};



inline UINT atoui(const char *a){
	atointeger<UINT,UINT_MAX_STR_LEN> functor_;
	return functor_(a);
}


///MSVC：_atoi64のWrapper OTHER：dkutilの付属品
inline LONGLONG atoi64(const char *a){
#	ifdef _MSC_VER
	return ::_atoi64(a);
#	else
	atointeger<LONGLONG,LONGLONG_MAX_STR_LEN> functor_;
	return functor_(a);
#	endif
}

///atoi64()のWrapper
inline LONGLONG atoll(const char *s){
	return atoi64(s);
}

inline ULONGLONG atoull(const char *a){
	atointeger<ULONGLONG,ULONGLONG_MAX_STR_LEN> functor_;
	return functor_(a);
}




/*!
@param dest[out] コピー先
@param size1[in] destのサイズ
@oaram src[in] コピー元
@param srclen[in] srcからコピーする文字数
*/
///src内の文字列をdestにすべて小文字にして格納する
inline int toTolower(char *dest,size_t size1,const char *src,size_t srclen){
	if(size1 <= srclen){
		for(size_t i=0;i<size1;i++){
			dest[i] = tolower(src[i]);
		}
		//::strncpy(dest,src,size1);
		dest[size1 - 1] = '\0';
		return edk_Not_Satisfactory;
	}else{
		for(size_t i=0;i<srclen;i++){
			dest[i] = tolower(src[i]);
		}
		dest[srclen] = '\0';
		return edk_SUCCEEDED;
	}
}


/*
template<class FUNC>
struct isStringBase{
	inline bool operator()(const char *str,FUNC func)
	{
		size_t len = strlen(str);
		for(size_t i=0;i<len;i++){
			if(!func(str[i])) return false;
		}
		return true;
	}
};
*/


///邪道･･･
#define IS_STRING_BASE__(str,func)\
{\
	size_t len = strlen(str);\
	for(size_t i=0;i<len;i++){\
		if(!func(str[i])) return false;\
	}\
	return true;\
}
inline bool isStringDigit(const char *str){
	IS_STRING_BASE__(str,isDigit);
}

inline bool isStringAlpha(const char *str){
	IS_STRING_BASE__(str,isAlpha);
}

///@return sに入れたものが16進の数字だったらTRUE
inline bool isStringHex(const char *s){
	size_t size=strlen(s);
	size_t begin = 0;
	if(size <= 1){ return isDigit(*s);}

	if('0' == s[0] && 'x' == s[1]){
		begin = 2;
	}
	for(size_t i=begin;i<size;i++){
		if(!isHex(s[i])) return false;
	}
	return true;
}

/*!
もし、文字列が変数にされるなら何になるか
@note
-の時はsigned
+の時はunsignedになりますかなぁ？
*/

class StringToVariable{
	bool isPutInBy__(size_t len,size_t mymax,size_t mymin)const
	{
		if(mymin < len) return false;//比較的、MINの方が'-'分一文字多いので
		if(mymax < len)
		{//表現できない変数を省く
			return false;
		}
		return true;
	}
	
	bool check_double(){
		double max = DBL_MAX;
		double min = DBL_MIN;
		//max len = 316 min len = 8 
		char buf[1024]="";

		_snprintf(buf,sizeof(buf) - 1,"%f",max);
		if(316 != strlen(buf)){return false;}

		_snprintf(buf,sizeof(buf) - 1,"%f",min);
		if(8 != strlen(buf)){return false;}
		
		return true;
	}
public:
	StringToVariable(){
		DKUTIL_NOT_ASSERT(sizeof(int)!=4);
		DKUTIL_NOT_ASSERT(sizeof(long)!=4);
		DKUTIL_NOT_ASSERT(sizeof(LONGLONG)!=8);
		DKUTIL_NOT_ASSERT(sizeof(double)!=8);
		//DKUTIL_NOT_ASSERT(check_double()==false);
	}
	virtual ~StringToVariable(){}
	///@return s[0]が'-'だったらtrue
	bool isSigned(const char *s)const{
		DKUTIL_NOT_ASSERT(s==NULL);
		return (s[0] == '-');
	}
	///@return isSignedの反対
	bool isUnsigned(const char *s)const{
		return !isSigned(s);
	}
	//bool isPutInByDouble(const char *s)const{
	
	///INT型変数に入るかどうか？
	bool isPutInByInt(const char *s)const{
		size_t len = strlen(s);
		return isPutInByInt(len);
	}
	bool isPutInByInt(size_t len)const{
		return isPutInBy__(len,INT_MAX_STR_LEN,INT_MIN_STR_LEN);
	}
	///UINT型変数に入るかどうか？
	bool isPutInByUInt(const char *s)const{
		size_t len = strlen(s);
		return isPutInByUInt(len);
	}
	bool isPutInByUInt(size_t len)const{
		return isPutInBy__(len,UINT_MAX_STR_LEN,
			UINT_MAX_STR_LEN//別に同じでしょ^^；
		);
	}
	///LONGLONG型の変数が入るかどうか。
	bool isPutInByLongLong(const char *s)const{
		size_t len = strlen(s);
		return isPutInByLongLong(len);
	}
	bool isPutInByLongLong(size_t len)const{
		return isPutInBy__(len,LONGLONG_MAX_STR_LEN,LONGLONG_MIN_STR_LEN);
	}
	///ULONGLONG型の変数に入るかどうか。
	bool isPutInByULongLong(const char *s)const{
		size_t len = strlen(s);
		return isPutInByULongLong(len);
	}
	bool isPutInByULongLong(size_t len)const{
		return isPutInBy__(len,ULONGLONG_MAX_STR_LEN,ULONGLONG_MAX_STR_LEN);
	}
	///double型の変数に入るかどうか。
	bool isPutInByDouble(const char *s)const{
		size_t len = strlen(s);
		return isPutInByDouble(len);
	}
	bool isPutInByDouble(size_t len)const{
		return isPutInBy__(len,DBL_MAX_STR_LEN,DBL_MAX_STR_LEN);
	}
	///@return signedでintegerな変数のどれかを返す。
	int SignedIntegerType(size_t len)const{
		
		if(isPutInByInt(len)){return edkInt;}
		if(isPutInByLongLong(len)){return edkLongLong;}
		return edkVariableUnknown;
	}
	///@return unsignedでintegerな変数のどれかを返す。
	int UnsignedIntegerType(size_t len)const{
		if(isPutInByUInt(len)){return edkUInt;}
		if(isPutInByULongLong(len)){return edkULongLong;}
		return edkVariableUnknown;
	}
	



	/*!
	@param s[in] 数字の文字列
	@param len[in] sの文字数
	@param bForceSigned[in] trueだと、unsignedでintegerなものを返すときでもsignedなものを返すようになる。
	@return 
	edkVariableTypeの要素を返す。
	表現し切れなかったらedkVariableUnknownを返す。
	@note
	-はsignedとして返すようになっている。<br>
	+はunsignedとして返すようになっている。<br>
	bForceSignedをTRUEにすると、+でもsignedを返すようになる。<br>
	<s>しかし、ULONGLONGで表現できるが、LONGLONGで表現できない場合はedkVariableUnknownを返す。</s>
	この場合、ULONGLONGで表現できるならば、戻り値はedkULongLongになりました。
	*/
	///もし、文字列が変数になるとしたら、どの変数に入れられるか。
	inline int if_string_is_made_into_a_variable(const char *s,size_t len,bool bForceSigned=false)
	{
		bool isMinus = false;//マイナスを表現していたら。
		bool isDouble = false;//浮動小数点だったら
		bool isString = false;//文字列だったら、
		bool is0x_f = false;//もし、0xで16進数をあらわしていたら
		



		//チェック
		
		{
			//マイナスチェック
			for(size_t i=0;i<len;i++)
			{
				if(isSpace(s[i])==true)continue;
				else{
					if(s[i]=='-'){isMinus=true;}
					break;
				}
			}
		}

		{
		
			//文字列か、doubleか　どうかチェック
			for(size_t i=0;i<len;i++)
			{
				if(isSpace(s[i])) continue;
				if(s[i] == '.')
				{//2004/10/29 処理順を変更
					//if(false==isString) continue;
					isDouble = true;
					break;
				}
				if(isDigit(s[i])==false){
					

					if(i >= 1 && is0x(&s[i-1],len - (i + 1))){
						is0x_f = true;
						continue;
					}
					isString = true;
					break;
				}

			}
		}


		int result = edkString;
		const int result_unknown = edkVariableUnknown;//分からなかったら強制的に文字列だと認識させてやろう^^；
		if(isString){
			return edkString;
		}
		//overflow check
		if(isDouble)
		{//float
			
			if(false==isPutInByDouble(len))
			{
				return result_unknown;
			}
			return edkDouble;
			
			//end of code;
		}
		else
		{//integer
			if(isMinus){//signed
				if(false==isPutInByLongLong(len)){
					return result_unknown;
				}
				result =  SignedIntegerType(len);
				if(edkVariableUnknown == result){
					return  result_unknown;
				}
				return result;
				//end of code
			}else{//unsigned

				if(bForceSigned)
				{//強制的にsignedのものを返す。
					result = SignedIntegerType(len);
					if(edkVariableUnknown != result){
						return result;//end of code
					}
					//begin unsigned pattern
				}
				if(false==isPutInByULongLong(len)){
					return result_unknown;
				}
				
				result = UnsignedIntegerType(len);
				if(edkVariableUnknown == result){
					return result_unknown;
				}
				return result;
				//end of code
			}

		}
		
		return result_unknown;
		//not return
	}
	/*!
	@param v[out] GeneralPurposeVariable型の変数(オブジェクト)に解析されたStringが格納される。
	@param s[in] 解析したいString（文字列）
	@param len[in] sの文字数
	@param bForceSigned[in] 強制的にSignedと認識させる。（sが整数型の場合)
	@return trueだと成功
	*/
	bool StringToGeneralPurposeVariable(GeneralPurposeVariable *v,const char *s,
		size_t len,bool bForceSigned=false)
	{
		GeneralPurposeVariable::UNION_TYPE uni;
		radix_convert conv;
		GeneralPurposeVariable &da = (*v);
		bool result = true; 

		int ty=if_string_is_made_into_a_variable(s,len,bForceSigned);
		
	

		switch(ty){
		case edkString:
			da.insert(s);
			break;
		case edkInt:
			if(is0x(s,len)){
				da.insert(conv.a16toi(s));
			}else{
				da.insert(::atoi(s));
			}
			break;
		case edkUInt:
			if(is0x(s,len)){
				da.insert(conv.a16toui(s));
			}else{
				da.insert(atoui(s));
			}
			break;
		case edkLongLong:
			if(is0x(s,len)){
				da.insert(conv.a16toll(s));
			}else{
				da.insert(atoll(s));
			}
			break;
		case edkULongLong:
			if(is0x(s,len)){
				da.insert(conv.a16toull(s));
			}else{
				da.insert(atoull(s));
			}
			break;
		case edkDouble:
			uni.d = atof(s);
			da.insert(uni.d);
			break;
		default:
			result = false;
			break;
		}
		return result;
	}
	/*
	int GetStringToIntLengthType(const char *s,bool bFOrceSigned=false){
		size_t len = strlen(s);
		int ty=if_string_is_made_into_a_variable(s,len,bForceSigned);
	*/


};



/*!
@throw std::invalid_argumentを返す。もち、文字列が数字じゃない時にね^^;
@return srcの中身の数字がstrの中身の数字より大きければtrueを返す ( == の時はfalse)
*/
extern bool isBigStrNum(char *src,char *str);


namespace private_{

///数字の文字列の長さによってどの変数に直るかを返してくれる。
///@return enuSTRLENGTH_INT_DU とかを返す。
struct GetStringToIntLengthTypeBase{
	typedef size_t size_type;
private:
	size_type strint;
	size_type struint;
	size_type strlonglong;
	size_type strulonglong;
public:
	GetStringToIntLengthTypeBase(){
		strint = strlen(INT_MAX_STR);
		struint = strlen(UINT_MAX_STR);
		strlonglong = strlen(LONGLONG_MAX_STR);
		strulonglong = strlen(ULONGLONG_MAX_STR);
	}
	//virtual ~GetStringToIntLengthTypeBase(){}
	

	int operator ()(const char *s)
	{

		size_type size= strlen(s);
		//マイナスかどうかフラグ
		bool isMinus = false;

		if(*s == '-'){
			isMinus = true;
		}

		{//アホ値検索（BM法使うか！？（いや使えねぇ･･･)
			//bool isSTR_ = false;
			for(size_type i=0;i<size;i++)
			{
				if(!isDigit(s[i]))
				{//ヴぁかもん
					if(s[i] == '.')
					{//こいつぁ〜　どヴる（double)しかねぇ！
						return enuSTRLENGTH_DOUBLE;
					}
					return -1;
				}
			}
		}

		//bool finished = false;//まだ処理が終わってないよフラ具（おいしそうな具だなぁ(爆))
		int result = 0;
		if(strulonglong < size)
		{//いやいや無理だよ^^;
			return -1;
		}
		//VC依存なのかな〜？
		//size_type num = ::atoi(s);
		LONGLONG num;
		ULONGLONG unum;
		if(isMinus){
			num = ::_atoi64(s);
		}else{
			unum = atoull(s);
		}
	#		define GOTOEND() if(result){ goto end;}
		
		//intで大丈夫か？
		int rere = length_check(isMinus,size,strint,unum,num,enuSTRLENGTH_INT_DU,-2,-2);
		if(rere!=-2){
			result = enuSTRLENGTH_INT_DU;
		}
		/*
		if(strint >= size){
			if(isMinus){
				if(!(num >= INT_MAX)){
					result = enuSTRLENGTH_INT_DU;
				}
			}else
		}*/
		GOTOEND();

		//uintで大丈夫か？
		rere = length_check(isMinus,size,struint,unum,num,enuSTRLENGTH_INT_DU,enuSTRLENGTH_UINT_DU,-2);
		if(rere != -2){
			result = rere;
		}
		/*
		if(struint >= size){
			if(!(num >= UINT_MAX)){
				result = enuSTRLENGTH_UINT_DU;
			}
		}
		*/
		GOTOEND();

		//longlongで大丈夫か？
		/*if(strlonglong >= size){
			if(!(num >= LONGLONG_MAX)){
				result = enuSTRLENGTH_INT_DU;
			}
		}*/
		rere = length_check(isMinus,size,strlonglong,unum,num,enuSTRLENGTH_LONGLONG_DU,enuSTRLENGTH_LONGLONG_DU,-2);
		if(rere != -2){
			result = rere;
		}
		GOTOEND();

		//ulonglong でだいぞーぶか？
		if(strulonglong >= size){
			if(!(num >= ULONGLONG_MAX)){
				result = enuSTRLENGTH_INT_DU;
			}
		}
	#	undef GOTOEND
	end:
		return result;

	}

	/*!
	@param isMinus[in] 文字列がマイナスだったらtrue
	@param size[in] その文字列のサイズ
	@param maxlength[in] sizeと比較するサイズ(これが限界値
	@param unum[in] unsigned typeの時の値
	@param num[in] isMinus == trueの時の値
	@param ResultIsMinus isMinus==TRUEの時の戻り値
	@param ResultNoMinus isMinus==falesの時の戻り値
	@param ResultOfError 何にも値しなかったときの戻り値
	*/
	int length_check(bool isMinus,size_t size,size_t maxlength,
		ULONGLONG unum,LONGLONG num,int ResultIsMinus,int ResultNoMinus,int ResultOfError)
	{
		//intで大丈夫か？
		if(strint >= size){
			if(isMinus){
				if(!(num >= INT_MAX)){
					return ResultIsMinus;
				}
			}else{
				if(!(num >= INT_MAX)){
					return ResultNoMinus;
				}
			}
		}
		return ResultOfError;
	}
		
};




}//end of private_ namespace


inline int GetStringToIntLengthType(const char *s){
	static private_::GetStringToIntLengthTypeBase f;
	return f(s);
}





#if 0

struct string_convert{

inline std::pair<bool,int> to_unicode(wchar_t *dest,size_t dsize,const char *src){
	//size_t length = strlen(str);
	typedef std::pair<bool,int> mp;
	int strnum = 
		::MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, src, -1, NULL,0);
	
	if((size_t)strnum >= dsize){//NULL文字分？
		return mp(false,strnum);//取得出来ていない。
	}

	strnum = 
		::MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, src, -1, dest,dsize);
	if(0==strnum){
#	ifdef DEBUG
		OutputWin32LastError();
#	else
#	endif
		return mp(false,strnum);
	}

	return mp(true,strnum);
}

inline std::wstring to_unicode(const char *str){
	size_t length = strlen(str) + 1;
	//int strnum;
	int i;
	scoped_array_ex<wchar_t> buff;

	
	std::pair<bool,int> r;
	for(i = 0;i<5;i++)
	{
		buff.reset(length);

		r = to_unicode((wchar_t *)buff.get(),buff.size(),str);
		if(r.first==false)
		{
			if(r.second==0){
				throw std::runtime_error(GetWin32LastErrorString());
			}else{
				length = (size_t)r.second;
				continue;
			}
		}else{
			break;
		}
	}
	if(r.first==false){
		throw std::runtime_error("to_unicode 上手く変換できない");
	}
	//wchar_t *tp = (wchar_t *)buff.get();
	//size_t tlen = wcslen(tp);
	//tp[tlen]=0x0000;
	//std::wstring tstr;
	//tstr += ((wchar_t *)buff.get());
	return std::wstring((wchar_t *)buff.get());
	//return tstr;
}

inline size_t to_sjis_strlen(const wchar_t *src){
	size_t count = 0;
	for(size_t i=0;;i++)
	{
		if(src[i] >= 0x100)
		{//2byte文字
			count += 2;
		}else if(src[i] == 0){
			count ++;//念のため
			break;
		}else{
			count++;
		}
	}
	return count;
}

#if 0
inline std::pair<bool,int> to_sjis(char *dest,size_t dsize,const wchar_t *src)
{
	size_t len = wcslen(src);
	typedef std::pair<bool,int> mp;
	//まずは文字数を受け取る。
	/*int strnum = ::WideCharToMultiByte(
		CP_ACP,         // コードページ
		//WC_NO_BEST_FIT_CHARS,         // 処理速度とマッピング方法を決定するフラグ
		WC_SEPCHARS,
		src, // ワイド文字列のアドレス
		len,       // ワイド文字列の文字数
		NULL,  // 新しい文字列を受け取るバッファのアドレス
		0,      // 新しい文字列を受け取るバッファのサイズ
		NULL,  // マップできない文字の既定値のアドレス
		NULL   // 既定の文字を使ったときにセットするフラグのアドレス
	);

	
	if((size_t)strnum > dsize){
		return mp(false,strnum);
	}
		*/
	int strnum = (int)to_sjis_strlen(src);
	if((size_t)strnum > dsize){
		return mp(false,strnum);
	}
	//文字をゲット
	strnum = ::WideCharToMultiByte(
		CP_ACP,         // コードページ
		//WC_NO_BEST_FIT_CHARS,         // 処理速度とマッピング方法を決定するフラグ
		WC_COMPOSITECHECK | WC_SEPCHARS,
		src, // ワイド文字列のアドレス
		len,       // ワイド文字列の文字数
		dest,  // 新しい文字列を受け取るバッファのアドレス
		dsize,      // 新しい文字列を受け取るバッファのサイズ
		NULL,  // マップできない文字の既定値のアドレス
		NULL   // 既定の文字を使ったときにセットするフラグのアドレス
	);
	if(0==strnum){
#	ifdef DEBUG
		OutputWin32LastError();
		//VISUAL_LASTERROR();
#	else
#	endif
		return mp(false,strnum);
	}
	return mp(true,strnum);
}

#endif
inline std::pair<bool,int> to_sjis(char *dest,size_t dsize,const wchar_t *src)
{
	typedef std::pair<bool,int> mp;
	/*size_t length = ::wcstombs(NULL, src, 0);
	if(length >= dsize){
		return mp(false,(int)length);
	}
	::wcstombs(dest,src,dsize);

	*/
	size_t wlen = wcslen(src);
	size_t length = ::WideCharToMultiByte(0, 0,src,wlen,
		NULL, 0, NULL, NULL);
	if(length >= dsize){
		return mp(false,(int)length);
	}
	::WideCharToMultiByte(0, 0, src, wlen, dest,
		dsize, NULL, NULL);

	dest[wlen]='\0';

	return mp(true,(int)length);
}


inline std::string to_sjis(const wchar_t *unicode_str){
	//size_t length = wcslen( unicode_str ) + 1;
	
	size_t length = to_sjis_strlen(unicode_str);
	int i;

	scoped_array_ex<char> buff;
	std::pair<bool,int> r;
	for(i = 0;i<5;i++)
	{
		buff.reset(length);

		r = to_sjis((char *)buff.get(),buff.size(),unicode_str);
		if(r.first==false)
		{
			if(r.second==0){
				throw std::runtime_error(GetWin32LastErrorString());
			}else{
				length = (size_t)r.second;
				continue;
			}
		}else{
			break;
		}
	}
	if(r.first==false){
		throw std::runtime_error("to_unicode 上手く変換できない");
	}
	return std::string((char *)buff.get());
}
inline std::string to_sjis(const std::wstring &str){
	return to_sjis(str.c_str());
}
inline std::wstring to_unicode(const std::string &str){
	return to_unicode(str.c_str());
}

/*
inline std::wstring to_unicode(const std::string &src){
	
	std::wstring dest;
	for(std::string::const_iterator it = src.begin();
		it != src.end();it++)
	{
		BYTE b = (BYTE)(*it);
		if((0x80 <= b) && (b <= 0x9f) && 
			(0xe0 <= b) && (b <= 0xff))
		{
			it++;
			if(it==src.end()) break;
			dest += (wchar_t)((((wchar_t)b)<<8) + (*it));
		}else{
			dest += (wchar_t)b;
		}
	}
	return dest;
}

inline std::string to_sjis(const std::wstring &src){
	std::string dest;
	for(std::wstring::const_iterator it=src.begin();
		it != src.end();
		it++)
	{
		wchar_t t = *it;
		if(t >= 0x100)
		{//2byte文字
			dest += (t >> 8);
			dest += (t & 0xff);
		}else{
			dest += (char)(BYTE)t;
		}
	}
	return dest;
}
*/
};//end of string_convert;

#endif //end of if 0


#if 0
///@todo バグをなくす（笑）仕様を変える。
template<class STRING_T >
class BMStringSearch{
public:

	typedef STRING_T::size_type size_type;
	typedef STRING_T STRING_TYPE;
	struct DATA_TYPE{
		DATA_TYPE(size_type _point) : point(_point){}
		size_type point;
	};
	typedef std::deque<DATA_TYPE> CONTAINER_TYPE;
	typedef CONTAINER_TYPE::iterator iterator;
	typedef CONTAINER_TYPE::const_iterator const_iterator;
private:
	STRING_T mS;
	STRING_T mSearch;

	CONTAINER_TYPE mC;
	
	size_type mSkipTable[UCHAR_MAX + 1];
	size_t mPatSize;
public:
	BMStringSearch(){
		NULL_CHAR_ARRAY(mSkipTable);
		mPatSize = 0;
		mC.clear();
	}
	virtual ~BMStringSearch(){}
	///@return 見つかった所を返す。失敗なら-1
	static int find_logic(const char *text,const char *pattern)
	{
		int i, j, k, len;
		int skip[UCHAR_MAX + 1];
		unsigned char c, tail;

		len = strlen((char *)pattern);  /* 文字列の長さ */
		if (len == 0) return -1;        /* エラー: 長さ0 */
		tail = pattern[len - 1];        /* 最後の文字 */
		if (len == 1) {                 /* 長さ1なら簡単! */
			for (i = 0; text[i] != '\0'; i++)
				if (text[i] == tail) return i;
		} else {                        // 長さ2以上なら表を作って… 
			for (i = 0; i <= UCHAR_MAX; i++) skip[i] = len;
			for (i = 0; i < len - 1; i++)
				skip[pattern[i]] = len - 1 - i;
			/* i = len - 1; */          // いよいよ照合 
			while ((c = text[i]) != '\0') {
	/*     // デモンストレーション用 
				printf("テ: %s\n", text);
				printf("照: %*s\n", i + 1, pattern);
	*/
				if (c == tail) {
					j = len - 1;  k = i;
					while (pattern[--j] == text[--k])
						if (j == 0) return k;  //見つかった 
				}
				i += skip[c];
			}
		}
		return -1;  // 見つからなかった 
	}
	bool empty()const{
		return mC.empty();
	}
	const_iterator begin(){	return mC.begin();}
	const_iterator end(){return mC.end();}
	
	void find_base(){
		//内部のデックをクリア
		mC.clear();
		DKUTIL_NOT_ASSERT("まだこの関数は使えないよ！！");
		size_type pat_size = mPatSize;
		char c, tail;
		tail = mSearch[pat_size];        /* 最後の文字 */
		if (mSearch.size() == 1) {// 長さ1ならテーブルを作るのは無駄
			STRING_TYPE::iterator it=mS.begin();
			for(size_type i=0;
				it != mS.end();
				it++,i++)
			{
				if(mS[i] == tail){
					mC.push_back(DATA_TYPE(i));
				}
			}
			return;
			//end of code
		} else {// 長さ2以上
			//照合
			size_type len=mSearch.size(), j=0 , k=0 ,SSize = mS.size();
			STRING_TYPE::iterator it = mS.begin();
			size_type RealLen = pat_size;//len - 1;
			it += RealLen;
			size_type count=0;
			while(it != mS.end())
			{
				//bool skip_flag=false;
				if((*it) == tail){

					j = RealLen; k =  RealLen;
					while (mSearch[--j] == mS[--k]){
						if (j == 0){//みっけた！
							mC.push_back(DATA_TYPE(count));
							/*if(count + RealLen > SSize - RealLen)
							{//すまん、この条件間違っているかもシレン。
								return;
							}else{
								//skip_flag=true;
								it += mSkipTable[(*it)];
								count += mSkipTable[(*it)];
							}
							break;*/
						}
					}
				}/*else{
					char cc=(*it);
					it += mSkipTable[(*it)];
					count += mSkipTable[(*it)];
				}*/
				if(count + RealLen >= SSize - RealLen)
				{//すまん、この条件間違っているかもシレン。
					return;
				}else{
					//skip_flag=true;
					char cc = (*it);
					it += mSkipTable[(*it)];
					count += mSkipTable[(*it)];
				}
				/*if(skip_flag){
					char cc = (*it);
					it += mSkipTable[cc];
				}*/
			}
		}
		//return -1;  /* 見つからなかった */
	}
	void reset(const char *src){
		mS = src;
	}
	void ready(const char *str){
		size_t pat_size = strlen(str);
		size_t num = DKUTIL_ARRAY_NUMOF(mSkipTable);
		{for (size_t i = 0; i < num; i++) mSkipTable[i] = pat_size;}
		//::memset(mSkipTable,(int)pat_size,sizeof(mSkipTable));
		mSearch = str;
		if(pat_size==1) return;
		{for(size_t i = 0; i < pat_size - 1; i++){
       mSkipTable[str[i]] = pat_size - 1 - i;
		}}
		mPatSize = (--pat_size);

	}

	void find()
	{
		if(mS.empty() || mSearch.empty()){
			throw std::runtime_error("BMStringSearch:find error / dest or src string empty.");
		}
		find_base();
	
	}
	

	void find(const char *src,const char *str){
		reset(src);
		ready(str);
		find();
	}
};
#endif


//もっと見やすく出来ないかな〜〜（メッちゃきたねぇソースだし！
inline bool isBigStrNum(char *src,char *str)
{
	
	//アホらしい　エラーチェック。
	//こいつのチェックで処理の半分以上はかかっているような気が･･･
	//GetStringToIntLengthType cls;
	//if(!isStringDigit(src)) return false;
	//if(!isStringDigit(str)) return false;
	
	//int srclen_ = strlen(src);
	//int strlen_ = strlen(str);

	double srcnumd = 0;
	LONGLONG srcnum = 0;
	double strnumd = 0;
	LONGLONG strnum = 0;

	int r;
	//**********************************************************
	//srcのチェック
	r = GetStringToIntLengthType(src);

	if(r == 0)
	{//アホ値は　しけー
		goto THROW_END;
	}


	if(r==enuSTRLENGTH_DOUBLE){
		srcnumd = ::atof(src);
	}else{
		//スマソ･･･　_atoi64だめだったらatoiにでも･･･
		LONGLONG srcnum = ::_atoi64(src);
	}
	//**********************************************************
	//strのチェック

	r = GetStringToIntLengthType(str);
	if(r == 0){
		goto THROW_END;
	}

	if(r == enuSTRLENGTH_DOUBLE){
		strnumd = ::atof(str);
	}else{ 
		strnum = ::_atoi64(str);
	}

	if(srcnum != 0 && strnum != 0)
	{//LONGLONGで比較
		if(srcnum > strnum){
			return true;
		}else{
			return false;
		}

	}else if(srcnumd != 0 && strnumd != 0)
	{//DOUBLEで比較
		if(srcnumd > strnumd){
			return true;
		}else{
			return false;
		}
	}else
	{//DOUBLEを強制キャストして　LONGLONGで比較
		LONGLONG cm1;
		LONGLONG cm2;
		if(srcnum != 0){
			cm1 = srcnum;
		}else{
			cm1 =(LONGLONG) srcnumd;
		}

		if(strnum != 0){
			cm2 = strnum;
		}else{
			cm2 = (LONGLONG)strnumd;
		}
		if(cm1 > cm2){
			return true;
		}else{
			return false;
		}

		goto THROW_END;
	}
THROW_END:
	throw std::invalid_argument("数字以外の文字列入れてるかも！");
	return false;
}

template<typename T,size_t BUFFER_SIZE__ = 64>
struct to_hex_string_functor{
	typedef typename T value_type;
	inline std::string operator()(value_type &x){
		char buff[BUFFER_SIZE__];
		_snprintf(buff,sizeof(buff),"%0x",(value_type)x);
		return std::string(buff);
	}
};
		
inline std::string toHexString(const uint8 *p,size_t size,bool with_sep=false)
{
	char buff[20]="";
	std::string rs;
	for(size_t i=0;i<size;i++){
		//_itoa( , buff, 16 );
		_snprintf(buff,sizeof(buff),"%02x",(uint8)p[i]);
		rs += buff;
		if(with_sep){
			rs += ",";
		}
	}
	return rs;
}


inline bool to_string_or_data_hex(std::string &dest,const uint8 *src,size_t size)
{
	bool is1 = true;
	size_t i;
	for(i=0;i<size;i++)
	{
		if(isVisible(src[i])){
			dest += (char)src[i];
		}
		else if('\0'==src[i] && i== size - 1)
		{
			return true;
		}/*else if('\0'==src[i]){
			dest = toHexString(src,size,false);
			return true;
		}*/
		else
		{
			if(is1){
				if(IsSJIS1(src[i])){
					is1 = false;
					dest += (char)src[i];
				}else{
					dest = toHexString(src,size,false);
					return true;
				}
			}else{
				if(IsSJIS2(src[i])){
					is1 = true;
					dest += (char)src[i];
				}else{
					dest = toHexString(src,size,false);
					return true;
				}
			}
		}
	}//eof
	return true;
}

}//end of dkutil namespace




#endif//end of include once
