////////////////////////////////////////////////////////////////////////////
// CWorkMemoryMgr クラスのインタフェース宣言
//
////////////////////////////////////////////////////////////////////////////

#if !defined( WORKMEMORYMGR_H_INCLUDED_ )
#define WORKMEMORYMGR_H_INCLUDED_

// #include "TaEdit_std.h"
#include <map>
#include <string>
#include <wchar.h>
#include <malloc.h>

using namespace std;

class CWorkMemoryMgr
{
	// ローカルのIDを保持する
	class tagLocalID
	{
	public:
		tagLocalID( const wchar_t* pName, const wchar_t *pPluginID ) :
			Name( pName ), PluginID( pPluginID ) {};
	
		tagLocalID( const tagLocalID& r ) :
			Name( r.Name ), PluginID( r.PluginID ){};
	
		tagLocalID(){};
		~tagLocalID(){};
	
		// 比較
		bool operator ==( const tagLocalID& r ) const {
			return Name == r.Name && PluginID == r.PluginID;
		};
		bool operator <( const tagLocalID& r ) const {
			if ( !( Name == r.Name ) ) return Name < r.Name;
			return PluginID < r.PluginID;
		};
	protected:
		wstring Name;
		wstring PluginID;	
	};
	
	
	// 作業用メモリの管理を行う
	template < typename T_ >
	class tagInstanceMgr
	{
	public:
		tagInstanceMgr(){};
		~tagInstanceMgr() {
			Initialize();
		};
	
		// 初期化
		void Initialize() {
			map< T_, void* >::iterator itr = mapMemory.begin();
			for (; itr != mapMemory.end(); itr++ )
				free( itr->second );
			mapMemory.clear();
		};
	
		// 領域の確保
		void *Alloc( const T_ &rKey, unsigned long size ) {
			map< T_, void* >::iterator itr = mapMemory.find( rKey );
			if ( itr != mapMemory.end() ) return NULL;	// 既存のものがある場合はNULLを返す
			void *p = malloc( size );
			if ( NULL == p ) return NULL;
			mapMemory.insert( pair< T_, void* >( rKey, p ) );
			return p; 
		};
	
		// 検索
		void *Find( const T_ &rKey ) {
			map< T_, void* >::iterator itr = mapMemory.find( rKey );
			if ( itr != mapMemory.end() )
				return itr->second;
			else
				return NULL;
		};
	
		// 解放
		void Free( const T_ &rKey ) {
			map< T_, void* >::iterator itr = mapMemory.find( rKey );
			if ( itr != mapMemory.end() ) {
				free( itr->second );
				mapMemory.erase( itr );
			}
		};
	
	protected:
		map< T_, void* > mapMemory;
	};

public:
	CWorkMemoryMgr(){}
	~CWorkMemoryMgr(){
		Initialize();
	};

	void Initialize() {
		im_Local.Initialize();
		im_Global.Initialize();
	};

	void* Alloc( unsigned long size, const wchar_t* pName, const wchar_t *pPluginID ) {
		if ( pPluginID )
			return im_Local.Alloc( tagLocalID( pName, pPluginID ), size );
		else
			return im_Global.Alloc( pName, size );
	};

	void* Find( const wchar_t* pName, const wchar_t *pPluginID ) {
		if ( pPluginID )
			return im_Local.Find( tagLocalID( pName, pPluginID ) );
		else
			return im_Global.Find( pName );
	};

	void Free( const wchar_t* pName, const wchar_t *pPluginID ) {
		if ( pPluginID )
			im_Local.Free( tagLocalID( pName, pPluginID ) );
		else
			im_Global.Free( pName );
	};

protected:
	tagInstanceMgr< tagLocalID > im_Local;	// ローカルの作業用メモリ
	tagInstanceMgr< wstring > im_Global;		// グローバルの作業用メモリ
};
	
#endif // WORKMEMORYMGR_H_INCLUDED_

