#pragma once


class CID
{
public:
	DWORD	id;
	DWORD	Index() { return id & 0x000fffff; }
			CID( DWORD ID ) { id = ID; }
};



template <class T> class IDContainer
{
	struct Entry
	{
		DWORD	id;
		DWORD	nextIndex;
		T		Data;
	};
	Entry*		m_pData;
	DWORD		m_nSize;
	DWORD		m_nFirstIndex;
	DWORD		m_nLastIndex;
public:
				IDContainer() { m_nSize = 0; m_nFirstIndex = 0; }

	void		Clear() { m_nFirstIndex = m_nLastIndex = 0; for(DWORD i=0; i<m_nSize; i++ ) m_pData[i].id = 0; }

				~IDContainer() { if( m_nSize ) free(m_pData); }
	T*			Allocate( CID id )
				{
					DWORD index = id.Index();
					if( index >= m_nSize )
					{
						DWORD oldSize = m_nSize;
						m_nSize = ( index + 256 ) & 0x000fff00;
						if( m_nFirstIndex == 0 )
						{
							m_pData = (Entry *)malloc( m_nSize * sizeof(Entry) );
						}
						else
						{
							m_pData = (Entry *)realloc( m_pData, m_nSize * sizeof(Entry) );
						}
						for( ; oldSize < m_nSize; oldSize++ )
							m_pData[oldSize].id = 0;
					}
					if( m_nFirstIndex == 0 )
					{
						m_nFirstIndex = m_nLastIndex = index;
					}
					else
					{
						m_pData[m_nLastIndex].nextIndex = index;
						m_nLastIndex = index;
					}
					m_pData[index].id = id.id;
					return &m_pData[index].Data;
				}
	T*			Find( CID id )
				{
					DWORD index = id.Index();
					if( index >= m_nSize )
						return NULL;
					Entry *ptr = m_pData + index;
					if( ptr->id == 0 )
						return NULL;
					return &(ptr->Data);
				}
	bool		Contains( CID id )
				{
					return Find(id) != NULL;
				}

	T*			First()
				{
					if( m_nFirstIndex == 0 )
						return NULL;
					else
						return &m_pData[m_nFirstIndex].Data;
				}
	T*			Last()
				{
					if( m_nFirstIndex == 0 )
						return NULL;
					else
						return &m_pData[m_nLastIndex].Data;
				}
	T*			Next( T* curr )
				{
					if( curr == &m_pData[m_nLastIndex].Data )
						return NULL;
					return &m_pData[ ((DWORD *)curr)[-1] ].Data;
				}
	
};


