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