#ifndef __MYU_STANDARD_LIBRARY__mslstr_H__
#define __MYU_STANDARD_LIBRARY__mslstr_H__

////////////////////////////////////////////////////
//
//	include
//

#include "mslcommon.h"
//#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

//	snprintf(),vsnprintf()で使用可能に
#ifndef _MSL_NOTUSE_SNPRINTF_MACRO
	#define snprintf vc_snprintf_conform_c99	//	ISO C99準拠版VCの_snprintf()を使わせる
	#define vsnprintf vc_vsnprintf_conform_c99	//	ISO C99準拠版VCの_vsnprintf()を使わせる
#endif//_MSL_NOTUSE_SNPRINTF_MACRO


////////////////////////////////////////////////////
//
//	関数群
//

namespace msl{

//////////////////////////////////////////////////////////////////////////

//	小文字・大文字に揃える
//	（※日本語には対応していないので注意）
//
//	Memo: 一応string.hにもstrlwr()/strupr()と言うのがある
//	      （ただしstring.hのはfrom/to同一の場合のみ）
char* strtolower( const char* from, char* to );
char* strtoupper( const char* from, char* to );
inline char* strtolower( char* str ){	//	strlwr()で代用可能(string.h)
	return strtolower(str,str); }
inline char* strtoupper( char* str ){	//	strupr()で代用可能(string.h)
	return strtoupper(str,str); }

//////////////////////////////////////////////////////////////////////////

//	数字＋英文字のみで構成されている文字列か
bool isnumengstr( const char* str );
inline bool isalnumstr( const char* str ){ return isnumengstr(str); }

//	英文字のみで構成されている文字列か
bool isengstr( const char* str );
inline bool isalstr( const char* str ){ return isengstr(str); }

//	数字のみで構成されている文字列か
bool isnumstr( const char* str );

//	ASCIIのみで構成されている文字列か
bool isasciistr( const char* str );

//////////////////////////////////////////////////////////////////////////

int vc_snprintf_conform_c99( char *s, size_t n, const char *format, ... );
int vc_vsnprintf_conform_c99( char *s, size_t n, const char *format, va_list ap );
char* del_tail_chars( const char* in_str, char* out_str, const char* del_chars );


//-----------------------------------------------------------------------------
//	16進文字列をunsigned long型に変換する
//
//	パラメータ		: hexstr		- 対象の文字列(in)
//					  result_state	- 結果コードを格納する変数へのポインタ。(out)
//									  正常終了:true  異常終了:false が格納される。
//	復帰値			: unsigned long	- 変換後の値
//	備考/詳細な概要	:
//	＊hexstrとして指定できる文字列の値は"00000000"〜"FFFFFFFF"までの値です。
//	＊先頭の0の数は幾つあっても同じです。（つまり"00000001"と"1"は同意）
//	＊英文字は小文字、大文字、及びその混合も可能です。
//	＊先頭に「0x」が付いていてもいなくても変換可能です。
//	＊空文字、NULLを指定した場合はエラーになります。
//-----------------------------------------------------------------------------
unsigned long hextonum( const char* hexstr, bool *result_state=NULL );


//	数値から文字列
//	注：dest_strのサイズは11バイトである必要がある
//	TODO: itoa()?
inline char* dectostr( int num, char *str ){
	sprintf( str, "%d", num );
	return str;
}
inline char* numtostr(int num, char *str){
	return dectostr(num,str); }
inline char* msl_itoa(int num, char *str){
	return dectostr(num,str); }

//----------------------
inline char* unumtostr( unsigned long num, char *str ){
	sprintf( str, "%u", num );
	return str;
}
inline char* msl_ultoa(unsigned long num, char *str){
	return unumtostr(num,str); }


/*
//	後ろからstrstr
inline char *strstr_tail( char *target_str, const char *find_str )
{
	const char* p = strstr(target_str,find_str);
	if ( p == NULL )
		return NULL;
	else
		return p + strlen(find_str);
}
*/

inline char get_last_char( const char* str ){
	if ( strlen(str) == 0 )
		return '\0';
	return *( str + strlen(str) -1 );
}

char* strccpy( char* to, const char* from, const char c );			//	指定文字までコピー
char* strcncpy( char* to, const char* from, const char c, int n );	//	指定文字または最大文字数までコピー
int strcnt( const char* str, char c );								//	指定文字の出現回数
int strstrcnt( const char* str, const char* search_str );			//	指定文字列の出現回数
char* strchrs( const char* str, const char* chrs );					//	strchrの検索文字複数版
const char *strchr_not( const char *s, int c );
//char *strchr_invert(const char *s, int c);
char* strrpc( char* str, size_t memsize, const char* from, const char* to );


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//	strcmp系

#ifdef WIN32
	#define STRICMP		stricmp
	#define STRNICMP	strnicmp
#else
	#define STRICMP		strcasecmp
	#define STRNICMP	strncasecmp
#endif

//	ASL=Auto StrLen（ASL1は最初の文字列を基準に、ASL2は最後の文字列を基準に）
#define STRNCMP_ASL1(S1,S2)			strncmp(S1,S2,strlen(S1))
#define STRNCMP_ASL2(S1,S2)			strncmp(S1,S2,strlen(S2))
#define STRNICMP_ASL1(S1,S2)		STRNICMP(S1,S2,strlen(S1))
#define STRNICMP_ASL2(S1,S2)		STRNICMP(S1,S2,strlen(S2))

//	何文字一致しているか
int strcmp_len( const char *str, const char *cmpstr );

//	末尾比較
inline int strtailcmp( const char *s1, const char *s2 )
{
	//return SAFE_STRCMP_ASL2( s1 + strlen(s1) - strlen(s2), s2 );
	return strcmp( s1 + strlen(s1) - strlen(s2), s2 );
}
inline int strtailicmp( const char *s1, const char *s2 )
{
	//return SAFE_STRICMP_ASL2( s1 + strlen(s1) - strlen(s2), s2 );
	return strcmp( s1 + strlen(s1) - strlen(s2), s2 );
}
inline int strlcmp( const char *s1, const char *s2 ){ return strtailcmp(s1,s2); }	//	tailの「l」
inline int strtcmp( const char *s1, const char *s2 ){ return strtailcmp(s1,s2); }	//	tailの「t」

inline int strfcmp( const char *str, const char *cmpstr ){	//	← fってなんだ…？
	return strncmp( str, cmpstr, strlen(cmpstr) ); }
/*inline int strlcmp( const char *str, const char *cmpstr ){	//	l=length
	return strncmp( str, cmpstr, strlen(cmpstr) ); }*/


/**************************************************************************/
//
//	Safe系関数 (バッファオーバーラン防止)
//		- バッファを越えようとした場合は、納まり切らなかった文字列を切り捨てます。
//
/**************************************************************************/

inline char* safe_strcpy( char *dest, const char *src, size_t dest_memsize );	//	strcpyのセーフ版
inline char* safe_strcat( char *dest, const char *src, size_t dest_memsize );	//	strcatのセーフ版
inline char* safe_strccpy( char* to, const char* from, const char c, size_t to_memsize );	//	strccpyのセーフ版
inline char* safe_strscpy( char* to, const char* from, const char* endchars, size_t to_memsize );	//	strscpyのセーフ版

//	AS=Auto Sizeof
#define SAFE_STRCPY_AS(DEST,SRC)	safe_strcpy(DEST,SRC,sizeof(DEST))
#define SAFE_STRCAT_AS(DEST,SRC)	safe_strcat(DEST,SRC,sizeof(DEST))
#define SAFE_STRCCPY_AS(DEST,SRC,C)	safe_strccpy(DEST,SRC,C,sizeof(DEST))

//++++++++++++++++++++++++++++++++++++++++
//	Inline substances
//
//	safe_strcpy
char* safe_strcpy( char *dest, const char *src, size_t dest_memsize )
{
	MslZeroMemory( dest, dest_memsize );
	strncpy( dest, src, dest_memsize-1 );
	return dest;
}

//	safe_strcat
char* safe_strcat( char *dest, const char *src, size_t dest_memsize )
{
	int copy_size = dest_memsize-1 - strlen(dest);
	if ( copy_size < 0 )
		copy_size = 0;
	strncat( dest, src, copy_size );
	return dest;
}

//	safe_strccpy
char* safe_strccpy( char* to, const char* from, const char c, size_t to_memsize )
{
	MslZeroMemory( to, to_memsize );
	return strcncpy( to, from, c, to_memsize-1 );
}

//	safe_strscpy
char* safe_strscpy( char* to, const char* from, const char* endchars, size_t to_memsize )
{
	const char* p_end = strchrs( from, endchars );
	int copy_length = p_end - from;
	if ( (size_t)(copy_length+1) > to_memsize )
		copy_length = to_memsize-1;

	MslZeroMemory( to, to_memsize );
	return strncpy( to, from, copy_length );
}


////////////////////////////////////////////////////////

}//namespace msl

#endif//__MYU_STANDARD_LIBRARY__mslstr_H__
