

/*!
  @author d金魚
  @since 2004/03/07
	@note
	licence:BSD Licence
*/


#ifndef _dktl_adapters__h_
#define _dktl_adapters__h_



#include <map>
#include <set>
#include <deque>
#include <vector>
#include <list>
#include <dkutil/boost/config.hpp>


#if defined(DKUTIL_SMART_PTR_YANESDK3RD)


#	include <ys3/YTL/smart_ptr.h>
#	define smart_ptr_base yaneuraoGameSDK3rd::YTL::shared_ptr
#	error It will support soon.

#elif defined(DKUTIL_SMART_PTR_IGNIS)

#	error It will support soon.

#else 
#endif
#include <dkutil/boost/shared_ptr.hpp>
#	define smart_ptr_base boost::shared_ptr



namespace dkutil{

//#if defined( DKUTIL_SMART_PTR_BOOST)

///smart , safe ,shared ?? pointer (smart pointer adapter)
template<class T>
class sptr : public smart_ptr_base<T>{
public:
	typedef smart_ptr_base<T> base_type;
	typedef sptr<T> self_type;
	typedef T				element_type;
	typedef T*			pointer_type;
private:
public:
  sptr(){} // never throws
  template<class Y> 
	explicit sptr(Y * p) : base_type(p){
	}
  //template<class Y, class D> shared_ptr(Y * p, D d);

  sptr(self_type const & r) :  // never throws
		base_type(r){

		}
  template<class Y> 
	sptr(smart_ptr_base<Y> const & r) :// never throws
		base_type(r){
	}
#if defined( DKUTIL_SMART_PTR_BOOST)
	template<class Y> explicit sptr(boost::weak_ptr<Y> const & r) : base_type(r){
	}
#	endif
	template<class Y> explicit sptr(std::auto_ptr<Y> & r) : base_type(r){
	}
	inline bool isNull()const{
		return get() == NULL;
	}
	void clear(){
		reset();
	}


};


}//end of namespace




namespace dkutil{



template<class MAP_T>
class map_ex_adapter : public MAP_T{
public:
	typedef MAP_T base_type;
	typedef map_ex_adapter<base_type> self_type;

	/// キーの型 
	typedef typename base_type::key_type key_type;

#if defined(__SGI_STL_PORT)
	///データの型 
	typedef typename base_type::mapped_type mapped_type;
#else
	///データの型 
	typedef typename base_type::referent_type mapped_type;

#endif
	/// キーとデータのペア 
	typedef typename base_type::value_type value_type;
	/// キーを比較するファンクションオブジェクト 
	typedef typename base_type::key_compare key_compare;
	///allocator type
	typedef typename base_type::allocator_type allocator_type;


	//typedef std::pair<bool,void *> GET_DATA;
	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;
	
	///value_typeのkey_typeが非const版
	typedef std::pair<key_type,mapped_type> DATA_TYPE;

	typedef std::pair<iterator,bool> RESULT;
	
public:
	/// compを指定しての初期化。
	map_ex_adapter() : base_type(key_compare(),allocator_type())
	{

	}
	explicit map_ex_adapter(const key_compare& comp, const allocator_type& allocator = allocator_type())
		: base_type(comp,allocator){

	}

	/// [first, last)で初期化。
	template <class InputIterator>
		map_ex_adapter(InputIterator first, InputIterator last,
				const key_compare& comp = key_compare(),
				const allocator_type& allocator = allocator_type()) : base_type(first,last,comp,allocator)
	{
	}

	/// コピーコンストラクタ。
	map_ex_adapter(const base_type& x) : base_type(x){
	}
	map_ex_adapter(const self_type& x) : base_type((base_type&)x){
	}
	~map_ex_adapter(){}
	bool isInserted(const RESULT &r)const{
		return r.second;
	}
	bool rb_insert(const value_type &x){
		RESULT r=base_type::insert(x);
		return isInserted(r);
	}
	///insertのwrapper...
	bool push_back(const value_type &x){
		return rb_insert(x);
	}
	///insertのwrapper...
	bool push(const value_type &x){return push_back(x);}

	/*!
	@param key[in] keyデータを入れる
	@return keyに関連付けられているデータを返す 見つからない時は不定
	@throw key[in]が無効の場合はstd::invalid_argumentを投げる。 
	*/
	///データを見つける
	mapped_type &GetData(const key_type &key){
		iterator it = base_type::find(key);
		if(it==base_type::end()){
			throw std::invalid_argument("keyが無効です。");//だめだめよ！
		}
		return (*it).second;
	}
	const mapped_type &GetData(const key_type &key)const{
		const_iterator it = base_type::find(key);
		if(it==base_type::end()){
			throw std::invalid_argument("keyが無効です。");//だめだめよ！
		}
		return (*it).second;
	}


	bool GetData(const key_type &key,mapped_type **data){
		iterator it = base_type::find(key);
		if(it==base_type::end()){
			data = NULL;
			return false;
		}
		*data = &((*it).second);
		return true;
	}

	bool GetData(const key_type &key,mapped_type **data)const{
		const_iterator it = base_type::find(key);
		if(it==base_type::end()){
			data = NULL;
			return false;
		}
		*data = const_cast<value_type *>(&((*it).second));
		return true;
	}
	/*!
	@param key[in] keyを入れる。valueと関連付けるために必要
	@param value[in] データを入れる。
	@return true = 成功 false = 失敗(二重登録の可能性有り)
	*/
	///データをキーと一緒に格納する
	bool SetData(const key_type &key,const mapped_type &value){
		RESULT result;
		DATA_TYPE data(key,value);
		result=base_type::insert(data);
		return result.second;
	}
	/*!
	@param key[in] キーを元に、データを探し出してそのデータを抹殺する
	キーがどのデータにも関連付けられていなかったらなにもしないらしい
	@return 成功 = ture  失敗 = false
	*/
	///キーを元にデータを削除
	bool DeleteDataByKey(const key_type &key){
		iterator it = base_type::find(key);
		if(it == base_type::end())
			return false;
		base_type::erase(it);
		return true;
	}
	/*!
	@param value[in] 削除したいデータを入れる
	@return 削除できたらtrue できないなら false
	*/
	/// データを元にデータを削除(キーも抹消されます)
	bool DeleteDataByValue(const mapped_type &value){
		//iterator it=base_type::begin();
		iterator it = begin();
		while(it!=base_type::end()){
			if(value==(*it).second){
				base_type::erase(it);//これでいいんかいな！？だれかhash_mapの関数リファレンスおしえてーな
				return true;
			}
			it++;
		}
		return false;
	}
	///キーを元にiteratorを返す。
	iterator find_by_key(const key_type &key){
		return base_type::find(key);
		}
	///値を元にiteratorを返す。
	iterator find_by_value(const mapped_type &value){
		//terator it=base_type::begin();
		iterator it = begin();
		while(it!=base_type::end()){
			if(value==(*it).second){
				return it;
			}
			it++;
		}
		return base_type::end();
	}
	///@return 見つかったらTRUE
	bool exist_by_key(const key_type &key){
		iterator it = find_by_key(key);
		if(end()==it){
			return false;
		}
		return true;
	}
	///@return 見つかったらTRUE
	bool exist_by_value(const mapped_type &value){
		iterator itfind_by_value(value);
		if(end()==it){
			return false;
		}
		return true;
	}


};

template<class SET_T>
class set_ex_adapter : public SET_T{
public:
	typedef set_ex_adapter<SET_T> self_type;
	typedef SET_T base_type;
	///データの型  
	typedef typename base_type::value_type value_type;
	/// キーを比較するファンクションオブジェクト 
	typedef typename base_type::key_compare key_compare;
	///allocator type
	typedef typename base_type::allocator_type allocator_type;

	typedef value_type DATA_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 std::pair<iterator,bool> RESULT;
	typedef RESULT insert_result;
		
	/// ファンクションオブジェクトの引数。
	explicit set_ex_adapter(const key_compare& comp = key_compare(),
		const allocator_type& allocator__ = allocator_type()) : base_type(comp,allocator__)
		{
	}
	/// [first, last)で初期化。
	template <class InputIterator>
		set_ex_adapter(InputIterator first, InputIterator last,
		const key_compare& comp = key_compare(),
		const allocator_type& allocator__ = allocator_type()) :base_type(first,last,comp,allocator__)
		{
	}
	

	// コピーコンストラクタ
	set_ex_adapter(const base_type& x) : base_type(x)
	{
	}
	set_ex_adapter(const self_type& x) : base_type((base_type&)x)
	{
	}
	~set_ex_adapter(){}

	///挿入されているかどうか？
	bool isInserted(const RESULT &r)const{
		return r.second;
	}
	bool rb_insert(const value_type &x){
		RESULT r=base_type::insert(x);
		return isInserted(r);
	}
	///insertのwrapper...
	bool push_back(const value_type &x){
		return rb_insert(x);
	}
	///insertのwrapper...
	bool push(const value_type &x){return push_back(x);}
};

}//end of dkutil namepsace

#endif //end of include once
