/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ #include #if NAMETABLE_CASESENSITIVE==1 #define COMPARENAMES(a, b) (strcmp(a, b)==0) #elif NAMETABLE_CASESENSITIVE==0 #define COMPARENAMES(a, b) (a==b) #else #error "NAMETABLE_CASESENSITIVE not defined" #endif // default constructor CNameTable_TYPE::CNameTable_TYPE(void) { nt_ctCompartments = 0; nt_ctSlotsPerComp = 0; nt_ctSlotsPerCompStep = 0; } // destructor -- frees all memory CNameTable_TYPE::~CNameTable_TYPE(void) { } // remove all slots, and reset the nametable to initial (empty) state void CNameTable_TYPE::Clear(void) { nt_ctCompartments = 0; nt_ctSlotsPerComp = 0; nt_ctSlotsPerCompStep = 0; nt_antsSlots.Clear(); } // internal finding CNameTableSlot_TYPE *CNameTable_TYPE::FindSlot(ULONG ulKey, const CTString &strName) { ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); // find compartment number INDEX iComp = ulKey%nt_ctCompartments; // for each slot in the compartment INDEX iSlot = iComp*nt_ctSlotsPerComp; for(INDEX iSlotInComp=0; iSlotInCompnts_ptElement==NULL) { // skip it continue; } // if it has same key if (pnts->nts_ulKey==ulKey) { // if it is same element if (COMPARENAMES(pnts->nts_ptElement->GetName(), strName)) { // return it return pnts; } } } // not found return NULL; } /* Set allocation parameters. */ void CNameTable_TYPE::SetAllocationParameters( INDEX ctCompartments, INDEX ctSlotsPerComp, INDEX ctSlotsPerCompStep) { ASSERT(nt_ctCompartments==0 && nt_ctSlotsPerComp==0 && nt_ctSlotsPerCompStep==0); ASSERT(ctCompartments>0 && ctSlotsPerComp>0 && ctSlotsPerCompStep>0 ); nt_ctCompartments = ctCompartments; nt_ctSlotsPerComp = ctSlotsPerComp; nt_ctSlotsPerCompStep = ctSlotsPerCompStep; nt_antsSlots.New(nt_ctCompartments*nt_ctSlotsPerComp); } // find an object by name TYPE *CNameTable_TYPE::Find(const CTString &strName) { ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName); if (pnts==NULL) return NULL; return pnts->nts_ptElement; } // expand the name table to next step void CNameTable_TYPE::Expand(void) { ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); // if we are here -> the compartment has overflowed ASSERT(nt_ctSlotsPerCompStep>0); // move the array of slots CStaticArray antsSlotsOld; antsSlotsOld.MoveArray(nt_antsSlots); // allocate new bigger array INDEX ctOldSlotsPerComp = nt_ctSlotsPerComp; nt_ctSlotsPerComp+=nt_ctSlotsPerCompStep; nt_antsSlots.New(nt_ctSlotsPerComp*nt_ctCompartments); // for each compartment for(INDEX iComp =0; iComp0 && nt_ctSlotsPerComp>0); ULONG ulKey = ptNew->GetName().GetHash(); // find compartment number INDEX iComp = ulKey%nt_ctCompartments; // for each slot in the compartment INDEX iSlot = iComp*nt_ctSlotsPerComp; for(INDEX iSlotInComp=0; iSlotInCompnts_ptElement==NULL) { // put it here pnts->nts_ulKey = ulKey; pnts->nts_ptElement = ptNew; return; } // must not already exist //ASSERT(pnts->nts_ptElement->GetName()!=ptNew->GetName()); } // if we are here -> the compartment has overflowed // expand the name table to next step ASSERT(!_bExpanding); _bExpanding = TRUE; Expand(); // add the new element Add(ptNew); _bExpanding = FALSE; } // remove an object void CNameTable_TYPE::Remove(TYPE *ptOld) { ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); // find its slot const CTString &strName = ptOld->GetName(); CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName); if( pnts!=NULL) { // mark slot as unused ASSERT( pnts->nts_ptElement==ptOld); pnts->nts_ptElement = NULL; } } // remove all objects but keep slots void CNameTable_TYPE::Reset(void) { for(INDEX iSlot=0; iSlot