1/* 2 File: CList.c 3 4 Contains: Implementation of the CList class 5 6*/ 7 8#include "CList.h" 9#include "CListIterator.h" 10#include "CItemComparer.h" 11#include "IrDALog.h" 12 13#if (hasTracing > 0 && hasCListTracing > 0) 14 15enum TraceCodes { 16 kLogNew = 1, 17 kLogFree, 18 kLogInit 19}; 20 21static 22EventTraceCauseDesc TraceEvents[] = { 23 {kLogNew, "CList: new, obj="}, 24 {kLogFree, "CList: free, obj="}, 25 {kLogInit, "CList: init, obj="} 26}; 27#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, TraceEvents, true ) 28#else 29#define XTRACE(x, y, z) ((void) 0) 30#endif 31 32 33//-------------------------------------------------------------------------------- 34#define super CDynamicArray 35 OSDefineMetaClassAndStructors(CList, CDynamicArray); 36//-------------------------------------------------------------------------------- 37 38 39CList * 40CList::cList(ArrayIndex chunkSize) 41{ 42 CList *obj = new CList; 43 44 XTRACE(kLogNew, 0, obj); 45 46 if (obj && !obj->init(chunkSize)) { 47 obj->release(); 48 obj = nil; 49 } 50 return obj; 51} 52 53Boolean CList::init(ArrayIndex size) 54{ 55 XTRACE(kLogInit, 0, this); 56 57 return super::init(kDefaultElementSize, size); 58} 59 60void CList::free(void) 61{ 62 XTRACE(kLogFree, 0, this); 63 64 super::free(); 65} 66 67//---------------------------------------------------------------------------- 68// CList::At 69//---------------------------------------------------------------------------- 70void* CList::At(ArrayIndex index) 71{ 72 uintptr_t * itemPtr = (uintptr_t *)SafeElementPtrAt(index); 73 return (itemPtr == nil) ? nil : (void*) (*itemPtr); 74 75} // CList::At 76 77 78//---------------------------------------------------------------------------- 79// CList::InsertAt 80//---------------------------------------------------------------------------- 81IrDAErr CList::InsertAt(ArrayIndex index, void* item) 82{ 83 uintptr_t data = (uintptr_t) item; 84 85 return InsertElementsBefore(index, &data, 1); 86 87} // CList::InsertBefore 88 89 90//---------------------------------------------------------------------------- 91// CList::Remove 92//---------------------------------------------------------------------------- 93IrDAErr CList::Remove(void* item) 94{ 95 IrDAErr result; 96 ArrayIndex index = GetIdentityIndex(item); 97 98 if (index != kEmptyIndex) 99 result = RemoveAt(index); 100 else 101 { 102 result = errRangeCheck; 103 //XPRINT(("CList::Remove: can't find item in list\n")); 104 } 105 106 return result; 107 108} // CList::Remove 109 110 111//---------------------------------------------------------------------------- 112// CList::InsertUnique 113//---------------------------------------------------------------------------- 114Boolean CList::InsertUnique(void* add) 115 { 116 Boolean result = !Contains(add); 117 if (result) 118 { 119 IrDAErr ignored = InsertLast(add); 120 XASSERTNOT(ignored); 121 } 122 return result; 123 } 124 125 126//---------------------------------------------------------------------------- 127// CList::Replace 128//---------------------------------------------------------------------------- 129IrDAErr CList::Replace(void* oldItem, void* newItem) 130{ 131 IrDAErr result; 132 ArrayIndex index = GetIdentityIndex(oldItem); 133 134 if (index != kEmptyIndex) 135 result = ReplaceAt(index, newItem); 136 else 137 { 138 result = errRangeCheck; 139 //XPRINT(("CList::Replace: can't find oldItem in list\n")); 140 } 141 142 return result; 143 144} // CList::Replace 145 146 147//---------------------------------------------------------------------------- 148// CList::ReplaceAt 149//---------------------------------------------------------------------------- 150IrDAErr CList::ReplaceAt(ArrayIndex index, void* newItem) 151{ 152 uintptr_t data = (uintptr_t) newItem; 153 154 return ReplaceElementsAt(index, &data, 1); 155} 156 157//---------------------------------------------------------------------------- 158// CList::GetIdentityIndex 159//---------------------------------------------------------------------------- 160ArrayIndex CList::GetIdentityIndex(void* item) 161{ 162 ArrayIndex index = -1; 163 CItemComparer *test = CItemComparer::cItemComparer(item, nil); // default comparer tests for identity 164 165 require(test, Fail); 166 167 (void) Search(test, index); 168 169 test->release(); 170 171Fail: 172 return index; 173 174} // CList::GetIdentityIndex 175 176 177//---------------------------------------------------------------------------- 178// CList::Search 179//---------------------------------------------------------------------------- 180void* CList::Search(CItemComparer* test, ArrayIndex& index) 181/* 182 Performs a linear search on the list. 183 Returns the index and value of the item for which 184 CItemTester::TestItem returns kItemEqualCriteria, 185 or kEmptyIndex and nil respectively. 186*/ 187{ 188 CListIterator *iter = CListIterator::cListIterator(this); 189 index = kEmptyIndex; 190 void* result = nil; 191 void* item = nil; 192 193 require(iter, Fail); 194 195 for (item = iter->FirstItem(); iter->More(); item = iter->NextItem()) 196 if (test->TestItem(item) == kItemEqualCriteria) 197 { 198 result = item; 199 index = iter->fCurrentIndex; 200 break; 201 } 202 203 iter->release(); 204 205Fail: 206 return result; 207 208} // CList::Search 209 210