
/*!
@auther d金魚
@since 2003/11/15
*/

#ifndef _dkutilMap__h_
#define _dkutilMap__h_

#include "dKingyoMacro.h"
#include <dkutil/include/dkutilSTLPortPolicy.h>
#include <dkutil/include/dkutilSTLInclude.h>

namespace dkutil{
#ifdef m
#	undef m
#endif

/*!
@note
後々、class map_ex : public MAPTYPE{...};になる予定･･･
MAP_TYPEはG++では反映されない。
*/

template<class K,class V,class MAP_TYPE=std::map<K,V> >
class map_ex{
public:
#ifdef _MSC_VER
	typedef MAP_TYPE CONTAINER_TYPE;
#else
	typedef std::map<K,V> CONTAINER_TYPE;
#endif
	typedef std::pair<K,V> DATA_TYPE;
	typedef std::pair<CONTAINER_TYPE::iterator,bool> RESULT;
	//typedef std::pair<bool,void *> GET_DATA;
	typedef CONTAINER_TYPE::iterator iterator;
	typedef CONTAINER_TYPE::const_iterator const_iterator;
	typedef CONTAINER_TYPE::reverse_iterator reverse_iterator;
	typedef CONTAINER_TYPE::const_reverse_iterator const_reverse_iterator;
protected:

	CONTAINER_TYPE m;//map
	
public:


	iterator begin(){return m.begin();}
	iterator end(){return m.end();}
	const_iterator begin()const{return m.begin();}
	const_iterator end()const{return m.end();}
	//reverse_iterator rbegin(){return m.rbegin();}
	//reverse_iterator rend(){return m.rend();}
	//const_reverse_iterator rbegin()const{return m.rbegin();}
	//const_reverse_iterator rend()const{return m.rend();}
	void clear(){m.clear();}
	void erase(K key){m.erase(key);}
	void erase(iterator it){m.erase(it);}
	iterator find(K key){return m.find(key);}
	const_iterator find(K key)const{return m.find(key);}
	bool empty()const{return m.empty();}
	RESULT insert(DATA_TYPE &d){
		return m.insert(d);
	}
	bool isInserted(RESULT &r){
		return r.second;
	}
	///@return return bool insert;
	bool rb_insert(DATA_TYPE &d){
		return isInserted(insert(d));
	}
	map_ex(){}
	virtual ~map_ex(){}
	/*!
	@param key[in] keyデータを入れる
	@return keyに関連付けられているデータを返す 見つからない時は不定
	@throw key[in]が無効の場合はstd::invalid_argumentを投げる。 
	*/
	///データを見つける
	V &GetData(K &key){
		iterator it = m.find(key);
		if(it==m.end()){
			throw std::invalid_argument("keyが無効です。");//だめだめよ！
		}
		return (*it).second;
	}
	bool GetData(K &key,V **data){
		iterator it = m.find(key);
		if(it==m.end()){
			data = NULL;
			return false;
		}
		*data = &((*it).second);
		return true;
	}
	V &GetData(K &key)const{
		const_iterator it = m.find(key);
		if(it==m.end()){
			throw std::invalid_argument("keyが無効です。");//だめだめよ！
		}
		return (*it).second;
	}
	bool GetData(K &key,V **data)const{
		const_iterator it = m.find(key);
		if(it==m.end()){
			data = NULL;
			return false;
		}
		*data = const_cast<V *>(&((*it).second));
		return true;
	}
	/*!
	@param key[in] keyを入れる。valueと関連付けるために必要
	@param value[in] データを入れる。
	@return true = 成功 false = 失敗(二重登録の可能性有り)
	*/
	///データをキーと一緒に格納する
	bool SetData(K &key,V &value){
		RESULT result;
		DATA_TYPE data(key,value);
		result=m.insert(data);
		return result.second;
	}
	/*!
	@param key[in] キーを元に、データを探し出してそのデータを抹殺する
	キーがどのデータにも関連付けられていなかったらなにもしないらしい
	@return 成功 = ture  失敗 = false
	*/
	///キーを元にデータを削除
	bool DeleteDataByKey(K &key){
		iterator it = m.find(key);
		if(it == m.end())
			return false;
		m.erase(it);
		return true;
	}
	/*!
	@param value[in] 削除したいデータを入れる
	@return 削除できたらtrue できないなら false
	*/
	/// データを元にデータを削除(キーも抹消されます)
	bool DeleteDataByValue(V &value){
		iterator it=m.begin();
		while(it!=m.end()){
			if(value==(*it).second){
				m.erase(it);//これでいいんかいな！？だれかhash_mapの関数リファレンスおしえてーな
				return true;
			}
			it++;
		}
		return false;
	}
	
};

}//end of dkutil namespace


#endif//end of include once

