#include "stdafx.h"
#include "4ObjIDTbl.h"	// This header.

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/*****************************************

	0x X X  X X  X X  X X
       ---  ------ ------
       Tbl   Tbl1   Tbl2

*******************************************/


MC4ObjIDTbl::MC4ObjIDTbl ()
{
	memset(m_pTable, 0, sizeof(MC4ObjIDTbl1*) * TBL1_SIZE);
}

MC4ObjIDTbl::~MC4ObjIDTbl ()
{
	DWORD	dw;
	for (dw = 0; dw < TBL1_SIZE; dw++)
		if (m_pTable[dw] != NULL) delete m_pTable[dw];
}

DWORD MC4ObjIDTbl::Register (void* pObj)
{
	WORD	wCount	= static_cast<WORD>(-1);
	DWORD	dwTarget= static_cast<DWORD>(-1);
	DWORD	dw;

	/*----- _xZkqqHx_iCnMiClIiIoKjCmKiCoI_xHqqkZx_Table1_xZkqqHx_iCpAjClCiCnHiBeBiNmFiCoAjGjOjEhEiCmJiLnPiCkC_xHqqkZx_Table1_xZkqqHx_iCpAjBeJiCnE_xHqqkZx_ -----*/
	for (dw = 0; dw < TBL1_SIZE; dw++)
	{
		if (m_pTable[dw] != NULL && m_pTable[dw]->m_wVacantC != 0)
		{
			if (m_pTable[dw]->m_wVacantC < wCount)
			{
				wCount = m_pTable[dw]->m_wVacantC;
				dwTarget = dw;
			}
		}
	}
	if (dwTarget != static_cast<DWORD>(-1))
		return (TBL2_SIZE * TBL3_SIZE) * dwTarget + m_pTable[dwTarget]->Register(pObj);

	for (dw = 0; dw < TBL1_SIZE; dw++)
	{
		if (m_pTable[dw] == NULL)
		{
			m_pTable[dw] = new MC4ObjIDTbl1;
			return (TBL2_SIZE * TBL3_SIZE) * dw + m_pTable[dw]->Register(pObj);
		}
	}
	return static_cast<DWORD>(-1);
}

void MC4ObjIDTbl::Register (void* pObj, DWORD dwID)
{
	DWORD	dwTbl0 = dwID / (TBL2_SIZE * TBL3_SIZE);
	if (m_pTable[dwTbl0] == NULL) m_pTable[dwTbl0] = new MC4ObjIDTbl1;
	m_pTable[dwTbl0]->Register(pObj, dwID);
}


void MC4ObjIDTbl::Unregister (DWORD dwID)
{
	DWORD	dwTbl0 = dwID / (TBL2_SIZE * TBL3_SIZE);
	if (m_pTable[dwTbl0] == NULL) return;
	m_pTable[dwTbl0]->Unregister(dwID);
	if (m_pTable[dwTbl0]->m_wUsedC == 0)
	{
		delete m_pTable[dwTbl0];
		m_pTable[dwTbl0] = NULL;
	}
}

void MC4ObjIDTbl::ClearAll ()
{
	DWORD	dw;
	for (dw = 0; dw < TBL1_SIZE; dw++)
	{
		if (m_pTable[dw] != NULL)
		{
			m_pTable[dw]->ClearAll();
			delete m_pTable[dw];
		}
	}
	memset(m_pTable, 0, sizeof(MC4ObjIDTbl1*) * TBL1_SIZE);
}


void* MC4ObjIDTbl::IDtoObject (DWORD dwID) const
{
	DWORD	dwTbl0 = dwID / (TBL2_SIZE * TBL3_SIZE);
	DWORD	dwTbl1 = (dwID / TBL3_SIZE) & (TBL2_SIZE - 1);
	DWORD	dwTbl2 = dwID & (TBL3_SIZE - 1);
	if (m_pTable[dwTbl0] == NULL) return NULL;
	if (m_pTable[dwTbl0]->m_pTable[dwTbl1] == NULL) return NULL;
	return m_pTable[dwTbl0]->m_pTable[dwTbl1]->m_pTable[dwTbl2];
}

BOOL MC4ObjIDTbl::IsEmpty () const
{
	DWORD	dw;
	for (dw = 0; dw < TBL1_SIZE; dw++)
		if (m_pTable[dw] != NULL) return FALSE;

	return TRUE;
}

DWORD MC4ObjIDTbl::GetFirstID () const
{
	DWORD dw1, dw2, dw3;
	for (dw1 = 0; dw1 < TBL1_SIZE; dw1++)
	{
		if (m_pTable[dw1] == NULL) continue;
		for (dw2 = 0; dw2 < TBL2_SIZE; dw2++)
		{
			if (m_pTable[dw1]->m_pTable[dw2] == NULL) continue;
			for (dw3 = 0; dw3 < TBL3_SIZE; dw3++)
			{
				if (m_pTable[dw1]->m_pTable[dw2]->m_pTable[dw3] == NULL) continue;
				return (TBL2_SIZE * TBL3_SIZE) * dw1 + TBL3_SIZE * dw2 + dw3;
			}
		}
	}
	return static_cast<DWORD>(-1);
} // MC4ObjIDTbl::GetFirstID.

DWORD MC4ObjIDTbl::GetNextID (DWORD dwID) const
{
	// _xZkqqHx_iCnMiClIiBeB_xHqqkZx_ID_xZkqqHx_iCmJiCfAiCpAiJmBiCkGiCoJiBeCjDkPiClG_xHqqkZx_ID_xZkqqHx_iCmMiDgFiBfLiDhFiDiLiCmJiDeBiDeOiDfKiDfIiClHiCoJiCmMiCpAjGgIiCkOiInHiBeC_xHqqkZx_
	dwID++;
	// ID_xZkqqHx_iCkJiCoHiBeBiCfCjCgJiKeLiCmMiDgFiBfLiDhFiDiLiCmMiImKjChFiCpAiMhGiOfKiBeC_xHqqkZx_
	DWORD dw1 = dwID / (TBL2_SIZE * TBL3_SIZE);
	DWORD dw2 = (dwID / TBL3_SIZE) & (TBL2_SIZE - 1);
	DWORD dw3 = dwID & (TBL3_SIZE - 1);

	for (; dw1 < TBL1_SIZE; dw1++, dw2 = 0, dw3 = 0)
	{
		if (m_pTable[dw1] == NULL) continue;
		for (; dw2 < TBL2_SIZE; dw2++, dw3 = 0)
		{
			if (m_pTable[dw1]->m_pTable[dw2] == NULL) continue;
			for (; dw3 < TBL3_SIZE; dw3++)
			{
				if (m_pTable[dw1]->m_pTable[dw2]->m_pTable[dw3] == NULL) continue;
				return (TBL2_SIZE * TBL3_SIZE) * dw1 + TBL3_SIZE * dw2 + dw3;
			}
		}
	}
	return static_cast<DWORD>(-1);
} // MC4ObjIDTbl::GetNextID.

MC4ObjIDTbl1::MC4ObjIDTbl1 ()
{
	m_wVacantC	= TBL2_SIZE;
	m_wUsedC	= 0;
	memset(m_pTable, 0, sizeof(MC4ObjIDTbl2*) * TBL2_SIZE);
}

MC4ObjIDTbl1::~MC4ObjIDTbl1 ()
{
	DWORD	dw;
	for (dw = 0; dw < TBL2_SIZE; dw++)
		if (m_pTable[dw] != NULL) delete m_pTable[dw];
}


DWORD MC4ObjIDTbl1::Register (void* pObj)
{
	WORD	wCount	= static_cast<WORD>(-1);
	DWORD	dwTarget= static_cast<DWORD>(-1);
	DWORD	dw;
	/*----- _xZkqqHx_iCnMiClIiIoKjCmKiCoI_xHqqkZx_Table2_xZkqqHx_iCpAjClCiCnHiBeBiNmFiCoAjGjOjEhEiCmJiLnPiCkC_xHqqkZx_Table2_xZkqqHx_iCpAjBeJiCnE_xHqqkZx_ -----*/
	for (dw = 0; dw < TBL2_SIZE; dw++)
	{
		if (m_pTable[dw] != NULL && m_pTable[dw]->m_wCount != 0)
		{
			if (m_pTable[dw]->m_wCount < wCount)
			{
				wCount = m_pTable[dw]->m_wCount;
				dwTarget = dw;
			}
		}
	}
	if (dwTarget != static_cast<DWORD>(-1))	// _xZkqqHx_iLpDiCkLiCkKiCkAiCoJiPoKiNiHiBeC_xHqqkZx_
	{
		if (wCount == 1) m_wVacantC--;	// _xZkqqHx_iClBiCmM_xHqqkZx_Table2_xZkqqHx_iCmNiCoAiCkEjGjOjEhEiCmJiCmIiCoJiCkJiCoHiBeC_xHqqkZx_
		return dwTarget * TBL3_SIZE + m_pTable[dwTarget]->Register(pObj);
	}
	/*----- _xZkqqHx_jAfGiLeLiCmJ_xHqqkZx_Table2_xZkqqHx_iCpAiNoMiCoJ_xHqqkZx_ -----*/
	for (dw = 0; dw < TBL2_SIZE; dw++)
	{
		if (m_pTable[dw] == NULL)
		{
			m_wUsedC++;		// _xZkqqHx_iOgHjHhAjCiGiCmM_xHqqkZx_Table2_xZkqqHx_iCkKiCfAiCmCjBjNiCkGiCoJiCkJiCoHiBeC_xHqqkZx_
			m_pTable[dw] = new MC4ObjIDTbl2;
			return dw * TBL3_SIZE + m_pTable[dw]->Register(pObj);
		}
	}
	// _xZkqqHx_iClBiClBiCmJjHiIiCoJiCmMiCmNjHeMiCoIjDlOiCmIiCkC_xHqqkZx_. m_wVacantC_xZkqqHx_iCmFiDgAiDeGiDgCiDeOiClDiCoKiCmEiCkCiCoJiClNiCnPiBeC_xHqqkZx_
	ASSERT(FALSE);
	return static_cast<DWORD>(-1);
}

void MC4ObjIDTbl1::Register (void* pObj, DWORD dwID)
{
	DWORD	dwTbl1 = (dwID / TBL3_SIZE) & (TBL2_SIZE - 1);
	if (m_pTable[dwTbl1] == NULL)
	{
		m_wUsedC++;		// _xZkqqHx_iOgHjHhAjCiGiCmM_xHqqkZx_Table2_xZkqqHx_iCkKiCfAiCmCjBjNiCkGiCoJiCkJiCoHiBeC_xHqqkZx_
		m_pTable[dwTbl1] = new MC4ObjIDTbl2;
	} else if (m_pTable[dwTbl1]->m_wCount == 1)
	{
		m_wVacantC--;	// _xZkqqHx_iClBiCmM_xHqqkZx_Table2_xZkqqHx_iCmNjGjOjEhEiCmJiCmIiCoJiCkJiCoHiBeC_xHqqkZx_
	}
	m_pTable[dwTbl1]->Register(pObj, dwID);
}


void MC4ObjIDTbl1::Unregister (DWORD dwID)
{
	DWORD	dwTbl1 = (dwID / TBL3_SIZE) & (TBL2_SIZE - 1);
	if (m_pTable[dwTbl1] == NULL) return;
	if (m_pTable[dwTbl1]->m_wCount == 0) m_wVacantC++;	// _xZkqqHx_iClBiCmM_xHqqkZx_Table2_xZkqqHx_iCmJiLpDiCkLiCkKiCmFiCkLiCoJiCkJiCoHiBeC_xHqqkZx_
	m_pTable[dwTbl1]->Unregister(dwID);
	if (m_pTable[dwTbl1]->m_wCount == TBL3_SIZE)	// _xZkqqHx_iClBiCmM_xHqqkZx_Table2_xZkqqHx_iCmNjGlDiOgHjHhAiBeC_xHqqkZx_
	{
		m_wUsedC--;
		delete m_pTable[dwTbl1];
		m_pTable[dwTbl1] = NULL;
	}
}

void MC4ObjIDTbl1::ClearAll ()
{
	DWORD	dw;
	for (dw = 0; dw < TBL2_SIZE; dw++)
	{
		if (m_pTable[dw] != NULL)
		{
			m_pTable[dw]->ClearAll();
			delete m_pTable[dw];
		}
	}
	m_wVacantC	= TBL2_SIZE;
	m_wUsedC	= 0;
	memset(m_pTable, 0, sizeof(MC4ObjIDTbl2*) * TBL2_SIZE);
}

MC4ObjIDTbl2::MC4ObjIDTbl2 ()
{
	m_wCount = TBL3_SIZE;
	memset(m_pTable, 0, sizeof(void*) * TBL3_SIZE);
}

MC4ObjIDTbl2::~MC4ObjIDTbl2 ()
{
	// m_pTable_xZkqqHx_iCmMjCiGjAgHiCmN_xHqqkZx_void*_xZkqqHx_iCmIiCmMiCmFiNoNiPjMiClFiCmEiCmNiCmIiCoHiCmIiCkC_xHqqkZx_.
}

DWORD MC4ObjIDTbl2::Register (void* pObj)
{
	DWORD dw;
	for (dw = 0; dw < TBL3_SIZE; dw++)
	{
		if (m_pTable[dw] == NULL)
		{
			m_wCount--;
			m_pTable[dw] = pObj;
			return dw;
		}
	}
	// _xZkqqHx_iClBiClBiCmJjHiIiCoJiCmMiCmNjHeMiCoIjDlOiCmIiCkC_xHqqkZx_. m_wCount_xZkqqHx_iCmFiDgAiDeGiDgCiDeOiClDiCoKiCmEiCkCiCoJiClNiCnPiBeC_xHqqkZx_
	ASSERT(FALSE);
	return static_cast<DWORD>(-1);
}

void MC4ObjIDTbl2::Register (void* pObj, DWORD dwID)
{
	DWORD	dwTbl2 = dwID & (TBL3_SIZE - 1);
	ASSERT(m_pTable[dwTbl2] == NULL);
	m_wCount--;
	m_pTable[dwTbl2] = pObj;
}

void MC4ObjIDTbl2::Unregister (DWORD dwID)
{
	DWORD	dwTbl2 = dwID & (TBL3_SIZE - 1);
	ASSERT(m_pTable[dwTbl2] != NULL);
	m_wCount++;
	m_pTable[dwTbl2] = NULL;
}

void MC4ObjIDTbl2::ClearAll ()
{
	m_wCount = TBL3_SIZE;
	memset(m_pTable, 0, sizeof(void*) * TBL3_SIZE);
}
