NameTable.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include <Engine/Templates/StaticArray.cpp>
  13. #if NAMETABLE_CASESENSITIVE==1
  14. #define COMPARENAMES(a, b) (strcmp(a, b)==0)
  15. #elif NAMETABLE_CASESENSITIVE==0
  16. #define COMPARENAMES(a, b) (a==b)
  17. #else
  18. #error "NAMETABLE_CASESENSITIVE not defined"
  19. #endif
  20. // default constructor
  21. CNameTable_TYPE::CNameTable_TYPE(void)
  22. {
  23. nt_ctCompartments = 0;
  24. nt_ctSlotsPerComp = 0;
  25. nt_ctSlotsPerCompStep = 0;
  26. }
  27. // destructor -- frees all memory
  28. CNameTable_TYPE::~CNameTable_TYPE(void)
  29. {
  30. }
  31. // remove all slots, and reset the nametable to initial (empty) state
  32. void CNameTable_TYPE::Clear(void)
  33. {
  34. nt_ctCompartments = 0;
  35. nt_ctSlotsPerComp = 0;
  36. nt_ctSlotsPerCompStep = 0;
  37. nt_antsSlots.Clear();
  38. }
  39. // internal finding
  40. CNameTableSlot_TYPE *CNameTable_TYPE::FindSlot(ULONG ulKey, const CTString &strName)
  41. {
  42. ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0);
  43. // find compartment number
  44. INDEX iComp = ulKey%nt_ctCompartments;
  45. // for each slot in the compartment
  46. INDEX iSlot = iComp*nt_ctSlotsPerComp;
  47. for(INDEX iSlotInComp=0; iSlotInComp<nt_ctSlotsPerComp; iSlotInComp++, iSlot++) {
  48. CNameTableSlot_TYPE *pnts = &nt_antsSlots[iSlot];
  49. // if empty
  50. if (pnts->nts_ptElement==NULL) {
  51. // skip it
  52. continue;
  53. }
  54. // if it has same key
  55. if (pnts->nts_ulKey==ulKey) {
  56. // if it is same element
  57. if (COMPARENAMES(pnts->nts_ptElement->GetName(), strName)) {
  58. // return it
  59. return pnts;
  60. }
  61. }
  62. }
  63. // not found
  64. return NULL;
  65. }
  66. /* Set allocation parameters. */
  67. void CNameTable_TYPE::SetAllocationParameters(
  68. INDEX ctCompartments, INDEX ctSlotsPerComp, INDEX ctSlotsPerCompStep)
  69. {
  70. ASSERT(nt_ctCompartments==0 && nt_ctSlotsPerComp==0 && nt_ctSlotsPerCompStep==0);
  71. ASSERT(ctCompartments>0 && ctSlotsPerComp>0 && ctSlotsPerCompStep>0 );
  72. nt_ctCompartments = ctCompartments;
  73. nt_ctSlotsPerComp = ctSlotsPerComp;
  74. nt_ctSlotsPerCompStep = ctSlotsPerCompStep;
  75. nt_antsSlots.New(nt_ctCompartments*nt_ctSlotsPerComp);
  76. }
  77. // find an object by name
  78. TYPE *CNameTable_TYPE::Find(const CTString &strName)
  79. {
  80. ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0);
  81. CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName);
  82. if (pnts==NULL) return NULL;
  83. return pnts->nts_ptElement;
  84. }
  85. // expand the name table to next step
  86. void CNameTable_TYPE::Expand(void)
  87. {
  88. ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0);
  89. // if we are here -> the compartment has overflowed
  90. ASSERT(nt_ctSlotsPerCompStep>0);
  91. // move the array of slots
  92. CStaticArray<CNameTableSlot_TYPE > antsSlotsOld;
  93. antsSlotsOld.MoveArray(nt_antsSlots);
  94. // allocate new bigger array
  95. INDEX ctOldSlotsPerComp = nt_ctSlotsPerComp;
  96. nt_ctSlotsPerComp+=nt_ctSlotsPerCompStep;
  97. nt_antsSlots.New(nt_ctSlotsPerComp*nt_ctCompartments);
  98. // for each compartment
  99. for(INDEX iComp =0; iComp<nt_ctCompartments; iComp++) {
  100. // for each old slot in compartment
  101. for(INDEX iSlotInComp=0; iSlotInComp<ctOldSlotsPerComp; iSlotInComp++) {
  102. CNameTableSlot_TYPE &ntsOld = antsSlotsOld[iSlotInComp+iComp*ctOldSlotsPerComp];
  103. CNameTableSlot_TYPE &ntsNew = nt_antsSlots[iSlotInComp+iComp*nt_ctSlotsPerComp];
  104. // if it is used
  105. if (ntsOld.nts_ptElement!=NULL) {
  106. // copy it to new array
  107. ntsNew.nts_ptElement = ntsOld.nts_ptElement;
  108. ntsNew.nts_ulKey = ntsOld.nts_ulKey;
  109. }
  110. }
  111. }
  112. }
  113. static BOOL _bExpanding = FALSE; // check to prevend recursive expanding
  114. // add a new object
  115. void CNameTable_TYPE::Add(TYPE *ptNew)
  116. {
  117. ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0);
  118. ULONG ulKey = ptNew->GetName().GetHash();
  119. // find compartment number
  120. INDEX iComp = ulKey%nt_ctCompartments;
  121. // for each slot in the compartment
  122. INDEX iSlot = iComp*nt_ctSlotsPerComp;
  123. for(INDEX iSlotInComp=0; iSlotInComp<nt_ctSlotsPerComp; iSlotInComp++, iSlot++) {
  124. CNameTableSlot_TYPE *pnts = &nt_antsSlots[iSlot];
  125. // if it is empty
  126. if (pnts->nts_ptElement==NULL) {
  127. // put it here
  128. pnts->nts_ulKey = ulKey;
  129. pnts->nts_ptElement = ptNew;
  130. return;
  131. }
  132. // must not already exist
  133. //ASSERT(pnts->nts_ptElement->GetName()!=ptNew->GetName());
  134. }
  135. // if we are here -> the compartment has overflowed
  136. // expand the name table to next step
  137. ASSERT(!_bExpanding);
  138. _bExpanding = TRUE;
  139. Expand();
  140. // add the new element
  141. Add(ptNew);
  142. _bExpanding = FALSE;
  143. }
  144. // remove an object
  145. void CNameTable_TYPE::Remove(TYPE *ptOld)
  146. {
  147. ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0);
  148. // find its slot
  149. const CTString &strName = ptOld->GetName();
  150. CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName);
  151. if( pnts!=NULL) {
  152. // mark slot as unused
  153. ASSERT( pnts->nts_ptElement==ptOld);
  154. pnts->nts_ptElement = NULL;
  155. }
  156. }
  157. // remove all objects but keep slots
  158. void CNameTable_TYPE::Reset(void)
  159. {
  160. for(INDEX iSlot=0; iSlot<nt_antsSlots.Count(); iSlot++) {
  161. nt_antsSlots[iSlot].Clear();
  162. }
  163. }
  164. #undef NAMETABLE_CASESENSITIVE