BFLibCPP 0.1
CPP Library
Loading...
Searching...
No Matches
list.hpp
Go to the documentation of this file.
1
6#ifndef LIST_HPP
7#define LIST_HPP
8
9#include "access.hpp"
10#include "object.hpp"
11#include <iostream>
12#include <initializer_list>
13
14namespace BF {
15
24
40template <typename L, typename S = int>
41class List : public Object {
42public:
43
47 class Node : public Object {
48 friend List<L, S>;
49 public:
50 Node * next() const {
51 return this->right;
52 }
53
54 Node * prev() const {
55 return this->left;
56 }
57
58 L object() const {
59 return this->obj;
60 }
61
62 private:
63 Node() : Object() {
64 this->left = 0;
65 this->right = 0;
66 this->obj = 0;
67 this->list = NULL;
68 }
69
70 virtual ~Node() {
71 if (this->list && this->list->_nodeObjectCleanUpCallback) {
72 this->list->_nodeObjectCleanUpCallback(this->obj);
73 }
74
75 this->left = 0;
76 this->right = 0;
77 }
78
79 Node * left;
80 Node * right;
81 L obj;
82
83 const List * list;
84 };
85
86public:
87
88 List() : Object() {
89 this->_head = 0;
90 this->_tail = 0;
91 this->_count = 0;
92 this->_nodeObjectCleanUpCallback = 0;
93 this->_compareCallback = 0;
94 }
95
96 List(const std::initializer_list<L> & list) : List() {
97 this->set(list);
98 }
99
100 virtual ~List() {
101 this->deleteAll();
102 }
103
104 S count() const { return this->_count; }
105
106 // Adds obj at tail end of list
107 int add(L obj) {
108 int result = 0;
109
110 Node * n = new Node;
111 n->obj = obj;
112 n->list = this;
113
114 // If we are first adding something
115 if (!this->_head && !this->_tail) {
116 this->_head = n;
117 this->_tail = n;
118
119 // If we already have a list of things
120 } else if (this->_head && this->_tail) {
121 n->left = this->_tail;
122 this->_tail->right = n;
123 this->_tail = n;
124
125 // this case shouldn't happen
126 } else {
127 result = 1;
128 }
129
130 if (!result)
131 this->_count++;
132
133 return result;
134 }
135
141 int pluckObject(L obj) {
142 for (Node * n = this->first(); n; n = n->next()) {
143 if (!this->runCompare(obj, n->object())) {
144 return this->deleteNode(n);
145 }
146 }
147
148 return 2;
149 }
150
156 int deleteObjectAtIndex(S index) {
157 if ((index >= 0) && (index < this->_count))
158 return this->deleteObjectAtIndex(index, this->_head, 0);
159 else return 1;
160 }
161
167 int insertObjectAtIndex(L obj, S index) {
168 if ((index >= 0) && (index < this->_count)) {
169 return this->insertObjectAtIndex(obj, index, this->_head, 0);
170 } else {
171 return 1;
172 }
173 }
174
175 // Deletes every object in list
176 void deleteAll() {
177 Node * node = this->_head;
178 while (node) {
179 Node * tmp = node->right;
180 delete node;
181 node = tmp;
182 this->_count--;
183 }
184
185 this->_head = NULL;
186 this->_tail = NULL;
187 }
188
189 // returns object at index
190 // returns 0 if an error ocurred
191 L objectAtIndex(S index) const {
192 Node * n = this->nodeAtIndex(index, this->_head, 0);
193 if (n) return n->object();
194 else return 0;
195 }
196
200 [[deprecated("please use the setReleaseCallback")]]
201 void setDeallocateCallback(void (* callback)(L obj)) {
202 this->_nodeObjectCleanUpCallback = callback;
203 }
204
208 void setReleaseCallback(void (* callback) (L obj)) {
209 this->_nodeObjectCleanUpCallback = callback;
210 }
211
215 void setCompareCallback(int (* callback) (L a, L b)) {
216 this->_compareCallback = callback;
217 }
218
225 Node * first() const {
226 return this->_head;
227 }
228
229 Node * last() const {
230 return this->_tail;
231 }
232
236 bool contains(const L obj) {
237 return this->getNodeForObject(obj, this->_head) != NULL;
238 }
239
243 void print() {
244 std::cout << std::endl;
245 std::cout << "[";
246
247 this->print(this->_head, NULL);
248
249 std::cout << "]";
250 std::cout << std::endl;
251 }
252
256 int sort() {
257 return this->sort(kListSortOptionsDefault);
258 }
259
260 int sort(const ListSortOptions option) {
261 return this->sortNodeToNode(this->_head, this->_tail, this->_count, option);
262 }
263
267 int shuffle() {
268 srand(time(0));
269 Node * n = this->_tail; // get last
270 int i = this->count() - 1; // get last's index
271 for (; n; n = n->prev()) {
272 // Get random node
273 int r = rand() % (i + 1);
274 Node * tmp = this->nodeAtIndex(r, this->_head, 0);
275 int err = this->swap(n, tmp); // swap nodes
276 if (err) return err; // leave if there was an error in swapping
277 i--;
278 }
279
280 return 0;
281 }
282
283protected:
284
288 int deleteNode(Node * node) {
289 // If currNode is the tail, reset the tail var
290 // to the currNode's left
291 if (this->_tail == node) this->_tail = node->left;
292 if (this->_head == node) this->_head = node->right;
293
294 // Close connection
295 if (node->left)
296 node->left->right = node->right;
297
298 if (node->right)
299 node->right->left = node->left;
300
301 // This method does not delete the object memory
302 node->list = NULL;
303
304 // Delete this node at index
305 delete node;
306
307 this->_count--;
308
309 return 0;
310 }
311
312private:
313
317 static int swap(Node * a, Node * b) {
318 // Don't continue with this if a or b are null
319 if (!a || !b) return -1;
320 else {
321 L obj = a->obj;
322 a->obj = b->obj;
323 b->obj = obj;
324 return 0;
325 }
326 }
327
331 int sortNodeToNode(Node * first, Node * last, S distance, const ListSortOptions option) {
332 int result = 0;
333 List<L,S> tmp;
334 Node * mid = 0, * t0 = 0, * t1 = 0;
335 const S halfDistance = distance / 2;
336
337 if (!first && !last) {
338 result = 2;
339 } else {
340 if (distance < 3) {
341 // We only worry about swapping
342 if (distance == 2) {
343 if (option == kListSortOptionsDescending) {
344 if (this->runCompare(first->obj, last->obj) < 0) {
345 result = this->swap(first, last);
346 }
347 } else {
348 if (this->runCompare(first->obj, last->obj) > 0) {
349 result = this->swap(first, last);
350 }
351 }
352 }
353 } else {
354 mid = first;
355 // Find mid node
356 for (S i = 0; i < (halfDistance - 1); i++)
357 mid = mid->next();
358
359 t0 = first;
360 t1 = mid->next();
361
362 // Sort the first half
363 result = this->sortNodeToNode(first, mid, halfDistance, option);
364
365 // Then sort the last half
366 if (!result)
367 result = this->sortNodeToNode(mid->next(), last, distance - halfDistance, option);
368
369 // Merge the two halves
370 if (!result) {
371 while (t0 && (t0 != mid->next()) && t1 && (t1 != last->next())) {
372 int res = this->runCompare(t0->obj, t1->obj);
373 switch (option) {
375 if (res < 0) {
376 tmp.add(t1->obj);
377 t1 = t1->next();
378 } else if (res > 0) {
379 tmp.add(t0->obj);
380 t0 = t0->next();
381 } else {
382 tmp.add(t0->obj);
383 tmp.add(t1->obj);
384 t0 = t0->next();
385 t1 = t1->next();
386 }
387
388 break;
390 default:
391 if (res < 0) {
392 tmp.add(t0->obj);
393 t0 = t0->next();
394 } else if (res > 0) {
395 tmp.add(t1->obj);
396 t1 = t1->next();
397 } else {
398 tmp.add(t0->obj);
399 tmp.add(t1->obj);
400 t0 = t0->next();
401 t1 = t1->next();
402 }
403
404 break;
405 }
406 }
407
408 // Merge in leftovers
409
410 while (t0 && (t0 != mid->next())) {
411 tmp.add(t0->obj);
412 t0 = t0->next();
413 }
414
415 while (t1 && (t1 != last->next())) {
416 tmp.add(t1->obj);
417 t1 = t1->next();
418 }
419
420 // Reset our data with the sorted data
421 for (Node * n0 = tmp.first(), * n1 = first;
422 n0 && n1 && (n1 != last->next());
423 n0 = n0->next(), n1 = n1->next()) {
424 n1->obj = n0->obj;
425 }
426 }
427 }
428 }
429
430 return result;
431 }
432
438 void set(const std::initializer_list<L> & list) {
439 this->deleteAll();
440 typename std::initializer_list<L>::iterator itr;
441 for (itr = list.begin(); itr != list.end(); ++itr) {
442 this->add(*itr);
443 }
444 }
445
449 void set(L * rawArray, S size) {
450 if (!rawArray) return; // don't do anything
451 this->deleteAll();
452 for (S i = 0; i < size; i++) {
453 this->add(rawArray[i]);
454 }
455 }
456
460 Node * nodeAtIndex(S reqIndex, Node * node, S currIndex) const {
461 if (node) {
462 if (currIndex == reqIndex) {
463 return node;
464 } else {
465 return this->nodeAtIndex(reqIndex, node->right, ++currIndex);
466 }
467 } else return 0;
468 }
469
478 int insertObjectAtIndex(L obj, S reqIndex, Node * currNode, S currIndex) {
479 if (currNode == 0) {
480 return 2; // We assume we are inserting within the range of the current list
481 } else {
482 if (currIndex < reqIndex) {
483 return this->insertObjectAtIndex(obj, reqIndex, currNode->right, ++currIndex);
484 } else {
485 Node * n = new Node;
486 n->obj = obj;
487 n->list = this;
488
489 // Make new connection
490 if (currNode->left) currNode->left->right = n;
491 n->left = currNode->left;
492 n->right = currNode;
493 currNode->left = n;
494
495 this->_count++;
496
497 return 0;
498 }
499 }
500 }
501
507 int deleteObjectAtIndex(S reqIndex, Node * currNode, S currIndex) {
508 if (currNode == 0) return 2;
509 else {
510 if (currIndex < reqIndex) {
511 return this->deleteObjectAtIndex(reqIndex, currNode->right, ++currIndex);
512 } else {
513 L object = currNode->object();
514 if (this->_nodeObjectCleanUpCallback) this->_nodeObjectCleanUpCallback(object);
515 return this->deleteNode(currNode);
516 }
517 }
518 }
519
525 Node * getNodeForObject(L obj, Node * node) {
526 if (!node) return NULL;
527 else {
528 if (node->obj == obj) return node; // First matching object
529 else {
530 return this->getNodeForObject(obj, node->right); // Keep traversing
531 }
532 }
533 }
534
535 void print(Node * node, Node * end) {
536 if (node) {
537 std::cout << " " << node->object() << " ";
538
539 if (node != end)
540 this->print(node->right, end);
541 }
542 }
543
549 int runCompare(L a, L b) {
550 if (this->_compareCallback) return this->_compareCallback(a, b);
551 else {
552 if (a < b) return -1;
553 else if (a > b) return 1;
554 else return 0;
555 }
556 }
557
558 // Holds the first node
559 Node * _head;
560
561 // Holds the last node in list
562 Node * _tail;
563
564 // Keeps count of how many nodes are linked
565 S _count;
566
571 void (* _nodeObjectCleanUpCallback)(L obj);
572
579 int (* _compareCallback) (L a, L b);
580
581public:
582
583 void operator=(const std::initializer_list<L> & list) {
584 this->set(list);
585 }
586
587public:
588
593 class Iterator {
594 private:
595 Node * _curr;
596 public:
597 Iterator(Node * n) : _curr(n) {}
598 L operator*() const {
599 return this->_curr->object();
600 }
601 Iterator & operator++() { // pre-inc
602 this->_curr = this->_curr->next();
603 return *this;
604 }
605 Iterator operator++(int) { // post-inc
606 Iterator old = *this;
607 this->operator++();
608 return old;
609 }
610 bool operator!=(const Iterator& i) {
611 return !(*this == i);
612 }
613 bool operator==(const Iterator& i) {
614 return this->_curr == i._curr;
615 }
616 };
617
619 Iterator begin() { return this->first(); }
620 Iterator end() { return NULL; }
621};
622
623} // namespace BF
624
625#endif // LIST_HPP
626
Definition list.hpp:593
bool operator!=(const Iterator &i)
Definition list.hpp:610
Iterator(Node *n)
Definition list.hpp:597
L operator*() const
Definition list.hpp:598
bool operator==(const Iterator &i)
Definition list.hpp:613
Iterator & operator++()
Definition list.hpp:601
Iterator operator++(int)
Definition list.hpp:605
Definition list.hpp:47
L object() const
Definition list.hpp:58
Node * next() const
Definition list.hpp:50
Node * prev() const
Definition list.hpp:54
Definition list.hpp:41
int sort()
Definition list.hpp:256
int sort(const ListSortOptions option)
Definition list.hpp:260
List()
Definition list.hpp:88
void setDeallocateCallback(void(*callback)(L obj))
Definition list.hpp:201
L objectAtIndex(S index) const
Definition list.hpp:191
int insertObjectAtIndex(L obj, S index)
Definition list.hpp:167
int shuffle()
Definition list.hpp:267
void setCompareCallback(int(*callback)(L a, L b))
Definition list.hpp:215
List(const std::initializer_list< L > &list)
Definition list.hpp:96
S count() const
Definition list.hpp:104
void operator=(const std::initializer_list< L > &list)
Definition list.hpp:583
Node * last() const
Definition list.hpp:229
virtual ~List()
Definition list.hpp:100
void print()
Definition list.hpp:243
int deleteObjectAtIndex(S index)
Definition list.hpp:156
bool contains(const L obj)
Definition list.hpp:236
Iterator end()
Definition list.hpp:620
void deleteAll()
Definition list.hpp:176
int add(L obj)
Definition list.hpp:107
Node * first() const
Definition list.hpp:225
int deleteNode(Node *node)
Definition list.hpp:288
int pluckObject(L obj)
Definition list.hpp:141
void setReleaseCallback(void(*callback)(L obj))
Definition list.hpp:208
Iterator begin()
required interfaces: begin() & end()
Definition list.hpp:619
Definition object.hpp:21
Definition array.hpp:18
ListSortOptions
Definition list.hpp:19
@ kListSortOptionsDescending
Definition list.hpp:21
@ kListSortOptionsAscending
Definition list.hpp:20
@ kListSortOptionsDefault
Definition list.hpp:22