ScummVM API documentation
list.h
1
2/* ScummVM - Graphic Adventure Engine
3 *
4 * ScummVM is the legal property of its developers, whose names
5 * are too numerous to list here. Please refer to the COPYRIGHT
6 * file distributed with this source distribution.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef BAGEL_BOFLIB_LIST_H
24#define BAGEL_BOFLIB_LIST_H
25
26#include "common/scummsys.h"
27#include "bagel/boflib/misc.h"
28
29namespace Bagel {
30namespace SpaceBar {
31
32#define MIN_NODES 5 // Minimum # of pre-allocated nodes in node array
33
34template<class T>
36protected:
37 T _cItem; // Data contained at this node
38
39public:
40 CBofListNode() {
41 _pNext = _pPrev = nullptr;
42 }
43 CBofListNode(T cItem) {
44 _pNext = _pPrev = nullptr;
45 _cItem = cItem;
46 }
47
48 T getNodeItem() {
49 return _cItem;
50 }
51 void setNodeItem(T cItem) {
52 _cItem = cItem;
53 }
54
55 CBofListNode *_pNext; // Next node in list
56 CBofListNode *_pPrev; // Previous node in list
57};
58
59template<class T>
60class CBofList {
61private:
62 void newItemList() {
63 if (_pItemList != nullptr) {
64 bofFree(_pItemList);
65 _pItemList = nullptr;
66 }
67
68 if (_nNumItems != 0) {
69 _pItemList = (void **)bofAlloc(_nNumItems * sizeof(void *));
70 }
71 }
72
73 void killItemList() {
74 if (_pItemList != nullptr) {
75 bofFree(_pItemList);
76 _pItemList = nullptr;
77 }
78 }
79
80 void recalcItemList() {
81 // We only want to recalc if we're about to overflow what we have
82 if (_nNumItems >= _nItemsAllocated) {
83 if (_pItemList != nullptr) {
84 bofFree(_pItemList);
85 _pItemList = nullptr;
86 }
87
88 if (_nNumItems != 0) {
89 assert(_nItemsAllocated < 0x8000);
90 _nItemsAllocated *= 2;
91 if (_nItemsAllocated == 0)
92 _nItemsAllocated = MIN_NODES;
93
94 _pItemList = (void **)bofAlloc(_nItemsAllocated * sizeof(void *));
95 }
96 }
97
98 if (_nNumItems != 0) {
99 assert(_pItemList != nullptr);
100
101 int i = 0;
102 CBofListNode<T> *pNode = _pHead;
103
104 while (pNode != nullptr) {
105 *(_pItemList + i++) = pNode;
106 pNode = pNode->_pNext;
107 }
108 }
109 }
110
116 CBofListNode<T> *newNode(T cItem) {
117 CBofListNode<T> *pNewNode = new CBofListNode<T>(cItem);
118 return pNewNode;
119 }
120
127 CBofListNode<T> *getActualHead() {
128 CBofListNode<T> *pNode;
129 CBofListNode<T> *pLast = pNode = _pHead;
130
131 while (pNode != nullptr) {
132 pLast = pNode;
133 pNode = pNode->_pPrev;
134 }
135
136 return pLast;
137 }
138
145 CBofListNode<T> *getActualTail() {
146 CBofListNode<T> *pNode;
147 CBofListNode<T> *pLast = pNode = _pTail;
148
149 while (pNode != nullptr) {
150 pLast = pNode;
151 pNode = pLast->_pNext;
152 }
153
154 return pLast;
155 }
156
157protected:
158 uint32 _nNumItems;
159 uint32 _nItemsAllocated;
160 CBofListNode<T> *_pHead; // pointer to head of list
161 CBofListNode<T> *_pTail; // pointer to tail of list
162
163 void **_pItemList; // pointer to secondary node list
164
165public:
166 /*
167 * Constructor
168 */
169 CBofList() {
170 _nNumItems = 0;
171 _nItemsAllocated = 0;
172 _pHead = _pTail = nullptr;
173 _pItemList = nullptr;
174 }
175
179 virtual ~CBofList() {
180 removeAll();
181 killItemList();
182 assert(_nNumItems == 0);
183 }
184
185 int getCount() const {
186 return _nNumItems;
187 }
188
193 int getActualCount() const {
194 uint32 nCount = 0;
195 CBofListNode<T> *pNode = _pHead;
196 while (pNode != nullptr) {
197 nCount++;
198 pNode = pNode->_pNext;
199 }
200
201 // There should be no discrepancy
202 assert(_nNumItems == nCount);
203
204 return _nNumItems;
205 }
206
211 bool isEmpty() const {
212 return _pHead == nullptr;
213 }
214
220 inline T getNodeItem(int nNodeIndex) {
221 CBofListNode<T> *pNode = getNode(nNodeIndex);
222
223 assert(pNode != nullptr);
224
225 return pNode->getNodeItem();
226 }
227
228 void setNodeItem(int nNodeIndex, T tNewItem) {
229 CBofListNode<T> *pNode = getNode(nNodeIndex);
230
231 assert(pNode != nullptr);
232
233 pNode->setNodeItem(tNewItem);
234 }
235
236 T operator[](int nIndex) {
237 return getNodeItem(nIndex);
238 }
239
245 CBofListNode<T> *getNode(int nNodeIndex) {
246 assert(nNodeIndex >= 0 && nNodeIndex < getCount());
247
248 CBofListNode<T> *pNode;
249
250 if (_pItemList == nullptr) {
251
252 pNode = _pHead;
253 while (pNode != nullptr) {
254 if (nNodeIndex-- == 0)
255 break;
256 pNode = pNode->_pNext;
257 }
258
259 } else {
260 pNode = (CBofListNode<T> *)(*(_pItemList + nNodeIndex));
261 }
262
263 return pNode;
264 }
265
271 void insertBefore(int nNodeIndex, T cNewItem) {
272 assert(!isEmpty());
273 insertBefore(getNode(nNodeIndex), cNewItem);
274 }
275
281 void insertBefore(CBofListNode<T> *pNode, T cNewItem) {
282 assert(pNode != nullptr);
283 assert(!isEmpty());
284
285 if (pNode == _pHead) {
286 addToHead(cNewItem);
287 } else {
288
289 CBofListNode<T> *pNewNode = newNode(cNewItem);
290
291 pNewNode->_pPrev = pNode->_pPrev;
292 pNewNode->_pNext = pNode;
293
294 if (pNode->_pPrev != nullptr)
295 pNode->_pPrev->_pNext = pNewNode;
296
297 pNode->_pPrev = pNewNode;
298 }
299
300 // one more item in list
301 assert(_nNumItems != 0xFFFF);
302 _nNumItems++;
303
304 recalcItemList();
305 }
306
312 void insertAfter(int nNodeIndex, T cNewItem) {
313 assert(!isEmpty());
314 insertAfter(getNode(nNodeIndex), cNewItem);
315 }
316
322 void insertAfter(CBofListNode<T> *pNode, T cNewItem) {
323 assert(pNode != nullptr);
324 assert(!isEmpty());
325
326 if (pNode == _pTail) {
327 addToTail(cNewItem);
328 } else {
329
330 CBofListNode<T> *pNewNode = newNode(cNewItem);
331 pNewNode->_pPrev = pNode;
332 pNewNode->_pNext = pNode->_pNext;
333
334 if (pNode->_pNext != nullptr)
335 pNode->_pNext->_pPrev = pNewNode;
336
337 pNode->_pNext = pNewNode;
338 }
339
340 // one more item in list
341 assert(_nNumItems != 0xFFFF);
342 _nNumItems++;
343
344 recalcItemList();
345 }
346
353 assert(pNode != nullptr);
354
355 // One less item in list
356 _nNumItems--;
357
358 //assert(_nNumItems >= 0);
359
360 if (pNode != nullptr) {
361
362 T retVal = pNode->getNodeItem();
363
364 if (_pHead == pNode)
365 _pHead = _pHead->_pNext;
366
367 if (_pTail == pNode)
368 _pTail = _pTail->_pPrev;
369
370 if (pNode->_pPrev != nullptr)
371 pNode->_pPrev->_pNext = pNode->_pNext;
372
373 if (pNode->_pNext != nullptr)
374 pNode->_pNext->_pPrev = pNode->_pPrev;
375
376 delete pNode;
377
378 recalcItemList();
379 return retVal;
380 } else {
381 return T();
382 }
383 }
384
390 T remove(int nNodeIndex) {
391 return remove(getNode(nNodeIndex));
392 }
393
398 void removeAll() {
399 int i = getCount();
400
401 while (i-- != 0)
402 remove(0);
403 }
404
409 inline T removeHead() {
410 assert(_pHead != nullptr);
411
412 return remove(_pHead);
413 }
414
419 inline T removeTail() {
420 assert(_pTail != nullptr);
421 return remove(_pTail);
422 }
423
428 inline void addToHead(CBofListNode<T> *pNewNode) {
429 assert(pNewNode != nullptr);
430
431 pNewNode->_pNext = _pHead;
432 pNewNode->_pPrev = nullptr;
433 if (_pHead != nullptr)
434 _pHead->_pPrev = pNewNode;
435 _pHead = pNewNode;
436
437 if (_pTail == nullptr)
438 _pTail = _pHead;
439
440 // one less item in list
441 assert(_nNumItems != 0xFFFF);
442 _nNumItems++;
443
444 recalcItemList();
445 }
446
451 inline void addToHead(T cItem) {
452 addToHead(newNode(cItem));
453 }
454
459 void addToTail(CBofListNode<T> *pNewNode) {
460 assert(pNewNode != nullptr);
461
462 pNewNode->_pPrev = _pTail;
463 pNewNode->_pNext = nullptr;
464 if (_pTail != nullptr)
465 _pTail->_pNext = pNewNode;
466 _pTail = pNewNode;
467
468 if (_pHead == nullptr)
469 _pHead = _pTail;
470
471 // One more item in list
472 assert(_nNumItems != 0xFFFF);
473 _nNumItems++;
474 recalcItemList();
475 }
476
481 void addToTail(T cItem) {
482 addToTail(newNode(cItem));
483 }
484
485 CBofListNode<T> *getHead() const {
486 return _pHead;
487 }
488 CBofListNode<T> *getTail() const {
489 return _pTail;
490 }
491};
492
493} // namespace SpaceBar
494} // namespace Bagel
495
496#endif
Definition: list.h:60
T getNodeItem(int nNodeIndex)
Definition: list.h:220
void addToTail(CBofListNode< T > *pNewNode)
Definition: list.h:459
void insertAfter(CBofListNode< T > *pNode, T cNewItem)
Definition: list.h:322
void insertAfter(int nNodeIndex, T cNewItem)
Definition: list.h:312
void addToTail(T cItem)
Definition: list.h:481
virtual ~CBofList()
Definition: list.h:179
void addToHead(T cItem)
Definition: list.h:451
T remove(CBofListNode< T > *pNode)
Definition: list.h:352
CBofListNode< T > * getNode(int nNodeIndex)
Definition: list.h:245
void removeAll()
Definition: list.h:398
void insertBefore(CBofListNode< T > *pNode, T cNewItem)
Definition: list.h:281
T remove(int nNodeIndex)
Definition: list.h:390
void addToHead(CBofListNode< T > *pNewNode)
Definition: list.h:428
void insertBefore(int nNodeIndex, T cNewItem)
Definition: list.h:271
bool isEmpty() const
Definition: list.h:211
T removeTail()
Definition: list.h:419
T removeHead()
Definition: list.h:409
int getActualCount() const
Definition: list.h:193
Definition: list.h:35