
#ifndef _dkutilString__
#define _dkutilString__


#include "dkutilDefined.h"
//まだまだテスト中なので･･･　使わんといてください。
//完全VC依存だな･･･

namespace dkutil{
#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





#if defined(jms1) || defined(jms2)
#	error please undef jms1 and jms2
#endif

#define jms1(c) (((((unsigned char)(c))>=0x81)&&(((unsigned char)(c))<=0x9F))||((((unsigned char)(c))>=0xE0)&&(((unsigned char)(c))<=0xFC)))
#define jms2(c) ((((unsigned char)(c))!=0x7F)&&(((unsigned char)(c))>=0x40)&&(((unsigned char)(c))<=0xFC))


/*!
 文字列 str の str[nPos] について、<br>
 @return
   ０ …… １バイト文字<br>
   １ …… ２バイト文字の一部（第１バイト）<br>
   ２ …… ２バイト文字の一部（第２バイト）<br>
<br>

シフトＪＩＳ文字列の判定をします。
*/ 
inline int isShiftJIS( const char *str, int nPos )
{
	int i;
	int state; // { 0, 1, 2 } = { １バイト文字, ２バイト文字の第１バイト, ２バイト文字の第２バイト }

	state = 0;
	for( i = 0; str[i] != '\0'; i++ )
	{
		if      ( ( state == 0 ) && ( jms1( str[i] ) ) ) state = 1; // 0 -> 1
		else if ( ( state == 1 ) && ( jms2( str[i] ) ) ) state = 2; // 1 -> 2
		else if ( ( state == 2 ) && ( jms1( str[i] ) ) ) state = 1; // 2 -> 1
		else                                             state = 0; // 2 -> 0, その他

		// str[nPos] での状態を返す。
		if ( i == nPos ) return state;
	}
	return 0;
}//isShiftJIS

#undef jms1
#undef jms2

///dkutil_beta2との互換性を保つため･･･
inline int isJMS(const char *str,int nPos){
	return isShiftJIS(str,nPos);
}



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


///lpが空白文字かどうかを調べる。@return 空白らしきものだったらtrue
inline bool isSpace(char lp){
	if(!(lp=='\0' || lp==0x0a || lp==0x0d || lp==' ' || lp=='\t')){
		return false;
	}
	return true;
}

///@return 可視できるASCII文字だったらTRUE
inline bool isVisible(char v){
	if((0x21 > v && 0x7E < v)){
		return false;
	}
	return true;
}


inline bool isDigit(int c){
	if(::isdigit(c)){return true;}
	return false;
}
inline bool isAlpha(int c){
	if(::isalpha(c)){return true;}
	return false;
}
///@return cに入れた値が16進文字のだったらTRUE（ASCII
inline bool isHex(int c){
	if(isDigit(c)){	return true;}

	if(('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')){
		return true;
	}
	return false;
}
	
	

inline ULONGLONG atoull(const char *a){
	const char *b = a;
	ULONGLONG ret;
	size_t maxlen = strlen(ULONGLONG_MAX_STR);
	ret = 0;
	
	for (size_t i=0;;a++,i++)
	{
		if(!isDigit((*a))){
			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;
}
/*!
@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;
	}
}

#ifdef UNICODE
#	error "多分、UNICODEだとradix_convertはエラーするでしょう。"
#endif
class radix_convert{
public://MessageBox

#define RADIX_CONVERT_LOCAL(R){\
		const char enuCTOI_CHECK=48;\
		const char enuCTOI16_LOWER=97;\
		const char enuCTOI16_WUPPER=65;\
		const char *begin = s;\
		R ret;\
		ret = 0;\
		s = s+2;\
		register int i=strlen(s) - 1;\
		while(*s){\
			R tmp;\
			if('0'<=(*s) && '9' >= (*s))\
			{\
				tmp = static_cast<R>(pow(16,i));\
				ret += ((*s) - enuCTOI_CHECK) * tmp;\
			}else{\
				tmp = static_cast<R>(pow(16,i));\
				if(iswupper(*s))\
				{\
					ret += ((*s) - enuCTOI16_WUPPER + 10) * tmp;\
				}else{\
					ret += ((*s) - enuCTOI16_LOWER + 10) * tmp;\
				}\
			}\
			s++;\
			i--;\
		}\
		return ret;\
	}
	inline ULONGLONG a16toull(const char *s){
		RADIX_CONVERT_LOCAL(ULONGLONG)
	}
	inline UINT a16toui(const char *s){
		RADIX_CONVERT_LOCAL(UINT)
	}
	inline INT a16toi(const char *s){
		RADIX_CONVERT_LOCAL(INT)
	}
	inline LONGLONG a16toll(const char *s){
		RADIX_CONVERT_LOCAL(LONGLONG)
	}
};


template<class FUNC>
inline bool isStringBase(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;
}

inline bool isStringDigit(const char *str){
	return isStringBase(str,isDigit);
}

inline bool isStringAlpha(const char *str){
	return isStringBase(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;
}
	




/*!
@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);
		
};




}//end of private_ namespace

extern int GetStringToIntLengthType(const char *s);
}//end of dkutil namespace


#ifndef _MSC_VER
inline LONGLONG _atoi64(const char *a){
	const char *b = a;
	LONGLONG ret;
	size_t maxlen = strlen(LONGLONG_MAX_STR);
	ret = 0;
	
	for (size_t i=0;;a++,i++)
	{
		if(!dkutil::isDigit((*a))){
			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;
}
#endif


#endif//end of include once
