

/*!
@file dkutilStdio.h
@brief		buffer over flowしないよ　関数^^;
@author		d金魚
@since		2003/8/19
@note
ここを見よ！<br>
http://www-6.ibm.com/jp/developerworks/security/000616/j-buffer-defend.html
<br?
で、要約･･･<br>
<PRE>
gets 最も危険 fgets(buf, size, stdin) を使用してください。これは常に大きな問題です! 
strcpy 非常に危険 strncpy を代用してください。 
strcat 非常に危険 strncat を代用してください。 
sprintf 非常に危険 snprintf を代用するか、精度指定子を使用してください。 
scanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
sscanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
fscanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
vfscanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
vsprintf 非常に危険 vsnprintf を代用するか、精度指定子を使用してください。 
vscanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
vsscanf 非常に危険 精度指定子を使用するか、独自の解析を行ってください。 
streadd 非常に危険 宛先のサイズとしてソース・パラメーターの 4 倍のサイズを割り振ってください。 
strecpy 非常に危険 宛先のサイズとしてソース・パラメーターの 4 倍のサイズを割り振ってください。 
strtrns 危険 宛先が少なくともソース・ストリングと同じサイズであることを手作業で確認してください。 
realpath 非常に危険 (インプリメンテーションによっては危険度は低くなります) バッファーを MAXPATHLEN のサイズになるように割り振ってください。また、入力引数が MAXPATHLEN より長くないことを手作業で確認してください。 
syslog 非常に危険 (インプリメンテーションによっては危険度は低くなります) この関数に渡す前に、すべてのストリング入力を適切なサイズに切り捨ててください。 
getopt 非常に危険 (インプリメンテーションによっては危険度は低くなります) この関数に渡す前に、すべてのストリング入力を適切なサイズに切り捨ててください。 
getopt_long 非常に危険 (インプリメンテーションによっては危険度は低くなります) この関数に渡す前に、すべてのストリング入力を適切なサイズに切り捨ててください。 
getpass 非常に危険 (インプリメンテーションによっては危険度は低くなります) この関数に渡す前に、すべてのストリング入力を適切なサイズに切り捨ててください。 
getchar やや危険 この関数をループ内で使用している場合は、バッファー境界をチェックしてください。 
fgetc やや危険 この関数をループ内で使用している場合は、バッファー境界をチェックしてください。 
getc やや危険 この関数をループ内で使用している場合は、バッファー境界をチェックしてください。 
read やや危険 この関数をループ内で使用している場合は、バッファー境界をチェックしてください。 
bcopy 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
fgets 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
memcpy 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
snprintf 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
strccpy 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
strcadd 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
strncpy 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
vsnprintf 危険度は低い バッファー・サイズが思っているとおりの大きさであるかを確認してください。 
</PRE>
ぎゃ〜〜〜！こんなに危ない関数を私たちは使っていたのかい！！<br>

*/

#ifndef _dkutilStdio__
#define _dkutilStdio__

#include "dkutilDefined.h"

namespace dkutil{
	
	/*!
	@param dest[out] コピー先
	@param size1[in] destのサイズ
	@param src[in] コピー元
	@param size2[in] srcのサイズ
	@return size1 < size2 だったらedk_FAILEDを返す。
	*/
	///memcpyの安全版？
	inline int dkmemcpy(void *dest,size_t size1,const void *src,size_t size2){
		if(size1 < size2) return edk_FAILED;
		::memcpy(dest,src,size2);
		return edk_SUCCEEDED;
	}
	inline int dksprintf(char *buff,size_t bufsize,char *format,...){
		SET_VA_LIST(buff,bufsize,format);		
		return edk_SUCCEEDED;
	}
	/*!
	@note
	<b>strncpyの危険性</b><br>
	string2 の最初の count 文字数を string1 にコピーしてから string1 を返します。
	count がstring2 の長さ以下の場合は、
	<font color=red>コピーした文字列に自動的に NULL 文字 (\0) を付けません。</font><br>
	<br>
	なので、srclenのサイズがsize1より大きい場合はedk_FAILEDを返します。
	@param dest[out] コピー先
	@param size1[in] destのサイズ
	@oaram src[in] コピー元
	@param srclen[in] srcからコピーする文字数
	*/
	inline int dkstrcpy(char *dest,size_t size1,const char *src,size_t srclen){
		if(size1 < srclen) return edk_FAILED;
		::strncpy(dest,src,srclen);
		//if(dest[srclen] != '\0') return edk_FAILED;
		dest[srclen] = '\0';
		return edk_SUCCEEDED;
	}
	///dkstrcpyと違い、バッファに入るだけコピーする。@note amap = as much as possible.
	inline int dkstrcpy_amap(char *dest,size_t size1,const char *src,size_t srclen){
		if(size1 < srclen){//ここは<=か！？
			::strncpy(dest,src,size1);
			dest[size1 - 1] = '\0';
			return edk_Not_Satisfactory;
		}else{
			::strncpy(dest,src,srclen);
			dest[srclen] = '\0';
			return edk_SUCCEEDED;
		}
	}
	inline int dkstrcpy_amap2(char *dest,size_t size1,const char *src){
		return dkstrcpy_amap(dest,size1,src,strlen(src));
	}
	/*!
	@param dest[out] コピー先
	@param destsize[in] destのサイズ(byte)
	@param destlen[in] destに入っている文字列の長さ *1
	@param src[in] コピー元
	@param srclen[in] コピー元に入っている文字列の長さ *1
	@note
	<b>*1:</b> NULL文字を含まない。<br>
	<b>strncatの危険性？</b><br>
	内部実装がどうなっているかは分からないが、
	いちおうdestのサイズをチェックしておいた方が安全だと思う。<br>
	*/
	inline int dkstrcat(char *dest,size_t destsize,size_t destlen,
		const char *src,size_t srclen)
	{
		//destlen + srclen + NULL文字
		if(destsize < destlen + srclen + 1)	return edk_FAILED;
		::strncat(dest,src,srclen);
		return edk_SUCCEEDED;
	}
	///dkstrcat()のHelper 関数
	inline int dkstrcat2(char *dest,size_t destsize,const char *src){
		return dkstrcat(dest,destsize,strlen(dest),src,strlen(src));
	}
	///dkstrcat()の出来るだけコピーする版 
	inline int dkstrcat_amap(char *dest,size_t destsize,size_t destlen,
		const char *src,size_t srclen)
	{
		//destlen + srclen + NULL文字
		int result = edk_SUCCEEDED;
		size_t lsize = destlen + srclen + 1;
		if(destsize < lsize)
		{//オーバーしてたら･･･
			srclen = lsize - destsize - 1;
			result = edk_Not_Satisfactory;
		}
		::strncat(dest,src,srclen);
		//dest[destlen + srclen - 1] = '\0';
		return result;
	}
	///dkstrcat3のHelper
	inline int dkstrcat_amap2(char *dest,size_t destsize,const char *src){
		return dkstrcat_amap(dest,destsize,strlen(dest),src,strlen(src));
	}

	/*!
	@param buf1[in] 比較バッファその１
	@param buf1PermitSize[in] buf1のサイズ
	@param buf2[in] 比較バッファその２
	@param count[in] 何バイト比較するかどうかのサイズ
	*/	
	inline int dkmemcmp( const void *buf1,size_t buf1PermitSize, const void *buf2, size_t count )
	{
		if(buf1PermitSize < count)return edk_FAILED;
		if(0 !=::memcmp(buf1,buf2,count))return edk_FAILED;
		return edk_SUCCEEDED;
	}
		





#if 0

	class datatable{
		enum{
			enuDigitNum=10,
			enuDigit16Num=6,
			enuCTOI_CHECK=48,
			enuCTOI16_LOWER=97,
			enuCTOI16_WUPPER=65,
		};
		static char digit[enuDigitNum];
		static char digit16[enuDigit16Num];
		datatable(){
			{for(int i=0;i<enuDigitNum;i++){
				digit[i]=i;
			}}
			{for(int i=0;i<enuDigit16Num;i++){
				digit16[i]=10+i;
			}}
		}
		int ctoi(char c){
#		ifdef _DEBUG
			char *str="へんな引数を入れるな！";
			if(c < enuCTOI_CHECK){
				throw std::invalid_argument(str);
			}else if(c > enuCTOI_CHECK + 10){
				throw std::invalid_argument(str);
			}
#		endif
			return digit[c-48];
		}
		int ctoi16(char c){
			if(isAlpha(c)){
				if(islower(c)){
					return digit16[c - enuCTOI16_LOWER];
				}else
				{
#		ifdef _DEBUG
					if(iswupper(c)){
						return digit16[c - enuCTOI16_WUPPER];
					}else{
						throw std::invalid_argument("引数が間違ってます");
					}
#		else
					return digit16[c - enuCTOI16_WUPPER];
#		endif
				}
			}else{
				return ctoi(c);
			}
		}
	};
	datatable &GetDataTable(){
		static datatable tbl;
		return tbl;
	}
#	endif

		
			


#if 0
	inline int textcmp(char *
#endif
}//end of dkutil namespace

#endif //end of include once