

/*!
  @author d金魚
  @since 2003/8/21
	@note
	licence:BSD Licence
*/


#ifndef _dktl_utility__h_
#define _dktl_utility__h_

#include <dkutil/output.hpp>

namespace dkutil{





template<class T,class OBJ>
inline void GeneralPurposeFree(T func,OBJ obj)
{
	if(obj){func(obj);obj=NULL;}
}
template<class T,class OBJ>
inline void GPFree(T func,OBJ obj){
	GeneralPurposeFree(func,obj);
}


template<class T>
inline void GeneralPurposeMessage(T function,char *str,...){
	int c;
	char s[c=1024+512];
	memset(s,'\0',sizeof(s));
	va_list VaList ;
	va_start( VaList , str) ;
	_vsnprintf( s ,c, str , VaList ) ;
	va_end( VaList ) ;
	function(s);
}
///ちょっと邪道
#define GPMessage GeneralPurposeMessage




template<unsigned n>
struct GetKB{
	public:
		enum{value=1024*n,};
		//int GetValue(){return value;}
};

template<unsigned n>
struct GetBit{
	public:
		enum{value=n/8,};
};


template<class CONTAINER,class T,class COMPARE>
void stable_insert(CONTAINER &c,const T &x,COMPARE comp)
{
	c.insert(std::lower_bound(c.begin(), c.end(), x, comp), x);
}

///作りかけ
template<class T,class DEQUE=std::deque<T> ,class COMP=std::less<T> >
class deque_to_set_adapter : public DEQUE{
	COMP mComp;
public:
	typedef DEQUE CONTAINER_TYPE;
	typedef DEQUE::size_type size_type;
	void insert(const T &x){
		stable_insert(static_cast<DEQUE>(*this),x,mComp);
		//DEQUE::push_back(x);
	}
	///これが正しい値を返すかは不明。
	size_type max_size()const
	{
		return UINT_MAX - DEQUE::size();
	}
	

};


///作りかけ
template<class T,class SET=std::set<T> >
class set_to_deque_adapter : public SET{
public:
	typedef std::pair<SET::iterator, bool> INSERT_RESULT;

	void push_back(const T &x){
		INSERT_RESULT r = SET::insert(x);
		DKUTIL_NOT_ASSERT(r.second==false);
	}
};

///オーソドックスなboost:: intrusive_ptrのカウンタポリシー
class intrusive_ptr_count{
private:
	int mCount;
protected:
	void set_ref_count(int c){
		mCount = c;
	}
public:
	intrusive_ptr_count() : mCount(1) {
	}
	intrusive_ptr_count(const intrusive_ptr_count &x){
		(*this) = x;
	}
	intrusive_ptr_count &operator=(const intrusive_ptr_count &x){
		mCount = x.mCount;
		return (*this);
	}

	int add_ref_count()  {
		return ++mCount; 
	}

	int release_count() 
	{
		if( 0 == --mCount )
			delete this;
		return mCount;
	}
	int get_ref_count()const{
		return mCount;
	}
	bool is_release()const{
		return 0 == mCount ;
	}
};


///果たして、virtual 使っただけでポリモーフィックになるのか？
class polymorphic_intrusive_ptr_count : public intrusive_ptr_count{
public:
	typedef intrusive_ptr_count base_type;
	/*explicit polymorphic_intrusive_ptr_count(){
		onConstruct();
	}*/
	polymorphic_intrusive_ptr_count(){
	}
	virtual ~polymorphic_intrusive_ptr_count(){}
	

	virtual void onDelete(){
		delete this;
	}
	virtual void onAdd(int count_up_before){
	}
	/*virtual void onConstruct(){

	}*/

	int add_ref_count(){
		onAdd(get_ref_count());
		return base_type::add_ref_count();
	}
	int release_count(){
		set_ref_count( get_ref_count() - 1);
		if( 0 == get_ref_count() ){
			onDelete();
		}
		return get_ref_count();
	}


};

template<class T>
class mediator{
private:
	T *mptr;
public:
	mediator(T *ptr=NULL) : mptr(ptr){}
	virtual ~mediator(){}
	void set_outer(T *ptr){	mptr = ptr;}
	T *get_outer(){return mptr;}
	T &get_outer_ref(){return *get_outer();}
};

/*!
私はアホ也。車輪の再発明也。
auto_ptrについての質問に答えてくださった、cppll_noviceのTietew 氏に感謝。
*/
///ちょこっと便利なauto_ptr
template<class T>
class relief_auto_ptr {
public:
	typedef T DATA_TYPE;
	typedef T element_type;
	typedef relief_auto_ptr<T> self_type;
protected:
	DATA_TYPE *mPtr;
	void check()const{
		DKUTIL_NOT_ASSERT(get()==NULL);
		//assert(!(get()==NULL));//上記は左記のような意味です。
	}
	
public:
	
	explicit relief_auto_ptr(T* p) {
		mPtr = p;
	}
	relief_auto_ptr(){
		mPtr = NULL;
	}
	~relief_auto_ptr(){
		Delete();
	}
	
	relief_auto_ptr( self_type &self){
		mPtr = NULL;//これが必要ですね。
		*this = self;
	}

	void reset(DATA_TYPE *p){
		if(p != mPtr){
			if(mPtr){//怖がりなんです＾＾；
				delete mPtr;
			}
		}
		mPtr = p;
	}
	void Delete(){
		T *ptr = release();
		if(ptr){//私、怖がりなの＾＾；
			delete ptr;
			//ptr = NULL;
		}
	}

	bool isNull()const{return (get()==NULL);}

	DATA_TYPE *get(){return mPtr;}
	const DATA_TYPE *get()const{return mPtr;}
	
	///@return deleteしないでpointerを返す。
	DATA_TYPE *release(){
		DATA_TYPE* p = get(); 
    mPtr = 0; 
    return p;
	}


	const DATA_TYPE* operator->() const { 
    check();
    return get(); 
  }
  const DATA_TYPE& operator*() const  { 
		check();
		return *get();
	}
	DATA_TYPE* operator->()  { 
    check();
    return get(); 
  }
  DATA_TYPE& operator*()   { 
		check();
		return *get();
	}
	self_type& operator=(self_type& get_power)  {
    reset(get_power.release());
    return *this;
  }

};
/**
メモリ節約ベクター
*/
template<class T,class A=std::allocator<T> >
class saving_vector : public std::vector<T,A>{
public:
	typedef typename std::vector<T,A> base_type;
	typedef typename saving_vector<T,A> self_type;
	typedef typename base_type::iterator iterator;
	typedef typename base_type::const_iterator const_iterator;
	typedef typename base_type::reverse_iterator reverse_iterator;
	typedef typename base_type::const_reverse_iterator const_reverse_iterator;
	typedef typename base_type::size_type size_type;

	saving_vector(size_type size){
		base_type::reserve(size);
	}
	~saving_vector(){}

	///メモリは節約する。これで節約できるといいが･･･
	void resize(size_type new_size, T& x = T()){
		saving();
		base_type::resize(new_size,x);
	}

	///resize()同
	void reserve(size_type n){
		base_type v((base_type)*this);
		base_type::clear();
		base_type::reserve(n);
		*this = v;
	}
	void saving(){
		base_type v((base_type)*this);
		base_type::clear();
		*this = v;
	}


};
/*
template<class T,class PTR_TYPE=relief_auto_ptr<T> >
class aho_ptr : public PTR_TYPE{
public:
	typedef aho_ptr self_type;
	typedef PTR_TYPE base_type;
	typedef T DATA_TYPE;
protected:
	void reset(const DATA_TYPE *p)const{
		if(p != mPtr){
			if(mPtr){//怖がりなんです＾＾；
				delete mPtr;
			}
		}
		mPtr = p;
	}
	///@return deleteしないでpointerを返す。
	const DATA_TYPE *release()const{
		const DATA_TYPE* p = get(); 
    mPtr = 0; 
    return p;
	}
public:

	explicit aho_ptr(T* p) : PTR_TYPE(p){}

	
	aho_ptr( const self_type &self){
		mPtr = NULL;//これが必要ですね。
		*this = self;
	}

	self_type& operator=(const self_type& get_power)  {
		reset(get_power.release());
    return *this;
  }


};
*/


#if 0
/*!
@param ET キャッチカウントの対象の例外タイプ
@param FUNCTION__ boost::function(いやyaneSDK3rdのfunction_callbackだな。等のものをぶち込む
*/

template<class ET,class FUNCTION__>
class try_catch_loop{
public:
	typedef ET exception_type;


	try_catch_loop(size_t count,T

};
#endif

///ポインタのまとめ役
template<class T,class Container=std::deque<T *> >
class PointerAlignment : public Container{
public:
	typedef T element_type;
	typedef T *pointer_type;
	typedef Container base_type;
	typedef base_type::iterator iterator;
	typedef base_type::const_iterator const_iterator;
	typedef base_type::reverse_iterator reverse_iterator;
	typedef base_type::const_reverse_iterator const_reverse_iterator;
	typedef PointerAlignment self_type;
public:
	PointerAlignment(){}
	virtual ~PointerAlignment(){
		clear();
	}
	///ポインタを挿入する。
	void Insert(const pointer_type &x){
		//base_type::insert(end(),x);
		base_type::push_back(x);
	}
	///挿入したポインタをdelete
	void Delete(iterator it){
		delete Release(it);
	}
	///挿入したポインタをリリース
	pointer_type Release(iterator it){
		pointer_type r = (*it);
		base_type::erase(it);
		return r;
	}
	void clear(){
		//std::for_each(begin(),end(),self_type::Delete);
		iterator it = begin();
		for(;it != end();it++){
			Delete(it);
		}
	}

	/*!
	yaneSDK3rdのYTL/list_chain.hより引用
	いや、この機構を最初に見た時感銘を受けました。

	template <class R>
	void	for_each(R (T::*fn)()){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(); it++; }
	}
	template <class R,class Arg1>
	void	for_each(R (T::*fn)(Arg1),const Arg1& a1){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1); it++; }
	}
	template <class R,class Arg1,class Arg2>
	void	for_each(R (T::*fn)(Arg1,Arg2),const Arg1& a1,const Arg2& a2){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1,a2); it++; }
	}
	template <class R,class Arg1,class Arg2,class Arg3>
	void	for_each(R (T::*fn)(Arg1,Arg2,Arg3),const Arg1& a1
		,const Arg2& a2,const Arg3& a3){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1,a2,a3); it++; }
	}
	template <class R,class Arg1,class Arg2,class Arg3,class Arg4>
	void	for_each(R (T::*fn)(Arg1,Arg2,Arg3,Arg4),const Arg1& a1
		,const Arg2& a2,const Arg3& a3,const Arg4& a4){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1,a2,a3,a4); it++; }
	}
	template <class R,class Arg1,class Arg2,class Arg3,class Arg4,
		class Arg5>
	void	for_each(R (T::*fn)(Arg1,Arg2,Arg3,Arg4,Arg5),const Arg1& a1,
		const Arg2& a2,const Arg3& a3,const Arg4& a4,const Arg5& a5){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1,a2,a3,a4,a5); it++; }
	}
	template <class R,class Arg1,class Arg2,class Arg3,class Arg4,
		class Arg5,class Arg6>
	void	for_each(R (T::*fn)(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6),const Arg1& a1,
		const Arg2& a2,const Arg3& a3,const Arg4& a4,const Arg5& a5,
		const Arg6& a6){
		iterator it = begin();
		while (it!=end()){ ((**it).*fn)(a1,a2,a3,a4,a5,a6); it++; }
	}	*/
};


}//end of dkutil namepsace

#endif //end of include once