

/*!
@auther d金魚
@since 2003/5/30
*/

#ifndef _dkutil_Defined__
#define _dkutil_Defined__

#include "dkutilDefinedC.h"
#include "dKingyoMacro.h"
#include "dkutilOutput.h"


namespace dkutil{


#if _MSC_VER >= 1000
#	pragma warning(disable:4800)//boolに強制変換できないからって文句言わんどいてくれぃ！
#endif
inline bool isLittleEndian(){
	int x=1;
	return static_cast<bool>((*(char*)&x));
}

inline bool isBigEndian(){
	return (!isLittleEndian());
}
#if _MSC_VER >= 1000
#pragma warning(default:4800)
#endif

//**********************************************************
//抽象クラス
//**********************************************************




template<class V,class K>
class IdKingyoDataWrapper{
public:
	IdKingyoDataWrapper(){}
	virtual ~IdKingyoDataWrapper(){}
	virtual V GetData(K) = 0;
	virtual bool SetData(K,V) = 0;
	virtual bool DeleteDataByKey(K) = 0;
	virtual bool DeleteDataByValue(V) =0;
};


//乱数生成用


template<typename T>
class IdKingyoRandom{
#ifdef _DEBUG
	public:
#else
	protected:
#endif
	unsigned long m_ulSeed;
	T m_Seed;
	T m_Max;
public:
	IdKingyoRandom(){}
	virtual ~IdKingyoRandom(){}
	virtual T Rand() = 0;
	virtual T Random(T) = 0;
	virtual T RandomDomain(T min,T max) = 0;
	virtual T RandomDomainSafety(T min,T max) = 0;
	virtual T GetRandMax() = 0;
	virtual void SetSeed(T) = 0;
	virtual T MesBox(char *str,...) = 0;

};


//よく使うメンバ関数はすでに定義させておく
template<typename T>
class dKingyoRandom_BasicMember : public IdKingyoRandom<T>{
public:
	dKingyoRandom_BasicMember(){}
	virtual ~dKingyoRandom_BasicMember(){}
	virtual T MesBox(char *str,...){
		char s[256];
		SET_VA_LIST(s,256,str);
		return (T) MessageBox(NULL,s,"DEBUG MESSAGE",MB_OK);
	}
	virtual T GetRandMax(){return m_Max;}
	virtual void SetSeed(T set){
		m_Seed = set;
		m_ulSeed=static_cast<ULONG>(m_Seed);
	}
};

extern bool SuperODS(const char *str,...);

namespace private_{

	struct IntegerOrFloating{
	private:
		struct tugReserved{
			tugReserved(){all[0]=0;all[1]=0;}
			struct tugRFlag{
				///フラグ群
				bool mD,mI,mLL,mULL;
				bool Inserted;
			};
			union{
				tugRFlag flag;
				int all[2];
			};
			//２個分
			
		};
		tugReserved mR;
		void flush__(){mR.flag.mD=false;mR.flag.mI=false;mR.flag.mLL=false;mR.flag.mULL=false;}
		void construct_(){flush__();}
	public:
		IntegerOrFloating(){construct_();}
		IntegerOrFloating(int gi){construct_();i=gi;mR.flag.mI=true;}
		IntegerOrFloating(LONGLONG gll){construct_();ll=gll;mR.flag.mLL=true;}
		IntegerOrFloating(ULONGLONG gull){construct_();ull = gull;mR.flag.mULL=true;}
		IntegerOrFloating(float gf){construct_();d=gf;mR.flag.mD=true;}
		IntegerOrFloating(double gd){construct_();d=gd;mR.flag.mD=true;}
		/*IntegerOrFloating(const IntegerOrFloating &get){
			*this = get;
		}*/
		union {
			int i;
			LONGLONG ll;
			ULONGLONG ull;
			double d;
		};
		
		bool isDouble()const{return mR.flag.mD;}
		bool isInt()const{return mR.flag.mI;}
		bool isLongLong()const{return mR.flag.mLL;}
		bool isULongLong()const{return mR.flag.mULL;}
		bool empty()const{return isDouble() && isInt() && isLongLong() && isULongLong();}
		void insert(int ig){flush__();i=ig;mR.flag.mI=true;}
		void insert(LONGLONG llg){flush__();ll=llg;mR.flag.mLL=true;}
		void insert(ULONGLONG ullg){flush__();ull=ullg;mR.flag.mULL=true;}
		void insert(double dg){flush__();d=dg;mR.flag.mD=true;}
		bool print()const{

			if(isDouble()){
				dkutil::SuperODS("%f",d);
			}else if(isInt()){
				dkutil::SuperODS("%d",i);
			}else if(isLongLong()){
				dkutil::SuperODS("%d",ll);
			}else if(isULongLong()){
				dkutil::SuperODS("%d",ull);
			}else{
				return false;
			}
			return true;
		}


	};

	template<typename T = IntegerOrFloating>
	struct GeneralPurposeVariable_Base : public T{
	public:
		std::string mstr;
		GeneralPurposeVariable_Base(const char *s){	mstr = s;}
		GeneralPurposeVariable_Base(const std::string &gs){mstr = gs;}
		GeneralPurposeVariable_Base(const int gi) : T(gi){}
		GeneralPurposeVariable_Base(const LONGLONG gll) : T(gll){}
		GeneralPurposeVariable_Base(const ULONGLONG gull) : T(gull){}
		GeneralPurposeVariable_Base(const float gf) : T(gf){}
		GeneralPurposeVariable_Base(const double gd) : T(gd){}
		GeneralPurposeVariable_Base() : T(){}
		/*GeneralPurposeVariable_Base(const GeneralPurposeVariable_Base<T> &get){
			*this = get;
		}*/
		bool isString()const{return !mstr.empty();}
		void insert(const char *s){mstr = s;}
		void insert(std::string s){mstr = s;}
		void insert(int ig){T::insert(ig);}
		void insert(LONGLONG llg){T::insert(llg);}
		void insert(ULONGLONG ullg){T::insert(ullg);}
		void insert(double dg){T::insert(dg);}

		bool empty()const{ return ( T::empty() && mstr.empty() );}
		///文字列を優先的にprintfする
		bool print()const{
			if(isString()){
				dkutil::SuperODS("%s",mstr.c_str());
			}else{
				return T::print();
			}
			return true;
		}
		friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,const char *str){
			if(!one.isString()) return false;
			return (one.mstr == str);
		}
		friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,std::string str){
			if(!one.isString()) return false;
			return (one.mstr == str);
		}
				friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,int two){
			if(!one.isInt()) return false;
			return (one.i == two);
		}
		friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,LONGLONG two){
			if(!one.isLongLong()) return false;
			return (one.ll == two);
		}
		friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,ULONGLONG two){
			if(!one.isULongLong()) return false;
			return (one.ull == two);
		}
		friend bool operator ==(const GeneralPurposeVariable_Base<T> &one,double d){
			if(!one.isDouble()) return false;
			return (one.d == d);
		}
		friend bool operator !=(const GeneralPurposeVariable_Base<T> &one,double d){
			if(!one.isDouble()) return false;
			return (one.d != d);
		}
		
		/*!
		@param your_detail[in] your_detailは
		テンプレートのTに入っているのがデフォルトならば
		IntegerOrFloating::isInt()やIntegerOrFloating::isDouble()を入れてください。
		@return isStringとyour_detailがTRUEならば ture
		@note
		このクラスは文字列と数字を一緒に格納できちゃいます･･･
		（まぁ、仕様ですね。std::stringはunionにぶち込めないので･･･
		まぁ、両方の記憶領域を使いたいなぁ〜って時に使用すると思いますね。
		<PRE>
		使用例：THIS_TYPE =　このクラス
		THIS_TYPE t;
		if(true==t.double_inserted(t.isInt())){
			MB("StringのデータとIntのデータが一緒に入っている。");
		}
		</PRE>
		*/
		bool double_inserted(bool your_detail)const{return isString() && your_detail;}

	};


}//end of private_ namespace


typedef private_::GeneralPurposeVariable_Base<> GeneralPurposeVariable;


}//end of dkutil namespace

#endif //end of include once