Unreal Snake Game 1.0.0
List.h
1// Snake Game, Copyright LifeEXE. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Misc/AssertionMacros.h"
7
8namespace SnakeGame
9{
10
11template <class ContainerType>
13{
14public:
15 explicit TLinkedListIteratorBase(ContainerType* FirstLink) : CurrentLink(FirstLink) {}
16
20 FORCEINLINE void Next()
21 {
22 checkSlow(CurrentLink);
23 CurrentLink = (ContainerType*)CurrentLink->GetNextLink();
24 }
25
26 FORCEINLINE TLinkedListIteratorBase& operator++()
27 {
28 Next();
29 return *this;
30 }
31
32 FORCEINLINE TLinkedListIteratorBase operator++(int)
33 {
34 auto Tmp = *this;
35 Next();
36 return Tmp;
37 }
38
40 FORCEINLINE explicit operator bool() const { return CurrentLink != nullptr; }
41
42protected:
43 ContainerType* CurrentLink;
44
45 FORCEINLINE friend bool operator==(const TLinkedListIteratorBase& Lhs, const TLinkedListIteratorBase& Rhs)
46 {
47 return Lhs.CurrentLink == Rhs.CurrentLink;
48 }
49 FORCEINLINE friend bool operator!=(const TLinkedListIteratorBase& Lhs, const TLinkedListIteratorBase& Rhs)
50 {
51 return Lhs.CurrentLink != Rhs.CurrentLink;
52 }
53};
54
55template <class ContainerType, class ElementType>
56class TLinkedListIterator : public TLinkedListIteratorBase<ContainerType>
57{
59
60public:
61 explicit TLinkedListIterator(ContainerType* FirstLink) : Super(FirstLink) {}
62
63 // Accessors.
64 FORCEINLINE ElementType& operator->() const
65 {
66 checkSlow(this->CurrentLink);
67 return **(this->CurrentLink);
68 }
69
70 FORCEINLINE ElementType& operator*() const
71 {
72 checkSlow(this->CurrentLink);
73 return **(this->CurrentLink);
74 }
75};
76
77template <class ContainerType, class ElementType>
79{
81
82public:
83 explicit TIntrusiveLinkedListIterator(ElementType* FirstLink) : Super(FirstLink) {}
84
85 // Accessors.
86 FORCEINLINE ElementType& operator->() const
87 {
88 checkSlow(this->CurrentLink);
89 return *(this->CurrentLink);
90 }
91
92 FORCEINLINE ElementType& operator*() const
93 {
94 checkSlow(this->CurrentLink);
95 return *(this->CurrentLink);
96 }
97};
98
102template <class ContainerType, class ElementType, template <class, class> class IteratorType>
104{
105public:
109 typedef IteratorType<ContainerType, ElementType> TIterator;
110 typedef IteratorType<ContainerType, const ElementType> TConstIterator;
111
116
122 FORCEINLINE void Unlink()
123 {
124 if (NextLink)
125 {
126 NextLink->PrevLink = PrevLink;
127 }
128 if (PrevLink)
129 {
131 }
132 // Make it safe to call Unlink again.
133 NextLink = nullptr;
134 PrevLink = nullptr;
135 }
136
142 FORCEINLINE void LinkBefore(ContainerType* Before)
143 {
144 checkSlow(Before != NULL);
145
146 PrevLink = Before->PrevLink;
147 Before->PrevLink = &NextLink;
148
149 NextLink = Before;
150
151 if (PrevLink != NULL)
152 {
153 *PrevLink = (ContainerType*)this;
154 }
155 }
156
162 FORCEINLINE void LinkAfter(ContainerType* After)
163 {
164 checkSlow(After != NULL);
165
166 PrevLink = &After->NextLink;
168 *PrevLink = (ContainerType*)this;
169
170 if (NextLink != NULL)
171 {
172 NextLink->PrevLink = &NextLink;
173 }
174 }
175
182 FORCEINLINE void LinkReplace(ContainerType* Replace)
183 {
184 checkSlow(Replace != NULL);
185
186 ContainerType**& ReplacePrev = Replace->PrevLink;
187 ContainerType*& ReplaceNext = Replace->NextLink;
188
189 PrevLink = ReplacePrev;
190 NextLink = ReplaceNext;
191
192 if (PrevLink != NULL)
193 {
194 *PrevLink = (ContainerType*)this;
195 }
196
197 if (NextLink != NULL)
198 {
199 NextLink->PrevLink = &NextLink;
200 }
201
202 ReplacePrev = NULL;
203 ReplaceNext = NULL;
204 }
205
214 FORCEINLINE void LinkHead(ContainerType*& Head)
215 {
216 if (Head != NULL)
217 {
218 Head->PrevLink = &NextLink;
219 }
220
221 NextLink = Head;
222 PrevLink = &Head;
223 Head = (ContainerType*)this;
224 }
225
231 FORCEINLINE bool IsLinked() { return PrevLink != nullptr; }
232
233 FORCEINLINE ContainerType** GetPrevLink() const { return PrevLink; }
234
235 FORCEINLINE ContainerType* GetNextLink() const { return NextLink; }
236
237 FORCEINLINE ContainerType* Next() { return NextLink; }
238
239private:
241 ContainerType* NextLink;
242
244 ContainerType** PrevLink;
245
246 FORCEINLINE friend TIterator begin(ContainerType& List) { return TIterator(&List); }
247 FORCEINLINE friend TConstIterator begin(const ContainerType& List) { return TConstIterator(const_cast<ContainerType*>(&List)); }
248 FORCEINLINE friend TIterator end(ContainerType& List) { return TIterator(nullptr); }
249 FORCEINLINE friend TConstIterator end(const ContainerType& List) { return TConstIterator(nullptr); }
250};
251
257template <class ElementType>
258class TLinkedList : public TLinkedListBase<TLinkedList<ElementType>, ElementType, TLinkedListIterator>
259{
261
262public:
265
271 explicit TLinkedList(const ElementType& InElement) : Super(), Element(InElement) {}
272
273 // Accessors.
274 FORCEINLINE ElementType* operator->() { return &Element; }
275 FORCEINLINE const ElementType* operator->() const { return &Element; }
276 FORCEINLINE ElementType& operator*() { return Element; }
277 FORCEINLINE const ElementType& operator*() const { return Element; }
278
279private:
280 ElementType Element;
281};
282
300template <class ElementType>
301class TIntrusiveLinkedList : public TLinkedListBase<ElementType, ElementType, TIntrusiveLinkedListIterator>
302{
304
305public:
308};
309
310template <class NodeType, class ElementType>
312{
313public:
314 explicit TDoubleLinkedListIterator(NodeType* StartingNode) : CurrentNode(StartingNode) {}
315
317 FORCEINLINE explicit operator bool() const { return CurrentNode != nullptr; }
318
319 TDoubleLinkedListIterator& operator++()
320 {
321 checkSlow(CurrentNode);
322 CurrentNode = CurrentNode->GetNextNode();
323 return *this;
324 }
325
326 TDoubleLinkedListIterator operator++(int)
327 {
328 auto Tmp = *this;
329 ++(*this);
330 return Tmp;
331 }
332
333 TDoubleLinkedListIterator& operator--()
334 {
335 checkSlow(CurrentNode);
336 CurrentNode = CurrentNode->GetPrevNode();
337 return *this;
338 }
339
340 TDoubleLinkedListIterator operator--(int)
341 {
342 auto Tmp = *this;
343 --(*this);
344 return Tmp;
345 }
346
347 // Accessors.
348 ElementType& operator->() const
349 {
350 checkSlow(CurrentNode);
351 return CurrentNode->GetValue();
352 }
353
354 ElementType& operator*() const
355 {
356 checkSlow(CurrentNode);
357 return CurrentNode->GetValue();
358 }
359
360 NodeType* GetNode() const
361 {
362 checkSlow(CurrentNode);
363 return CurrentNode;
364 }
365
366private:
367 NodeType* CurrentNode;
368
369 friend bool operator==(const TDoubleLinkedListIterator& Lhs, const TDoubleLinkedListIterator& Rhs)
370 {
371 return Lhs.CurrentNode == Rhs.CurrentNode;
372 }
373 friend bool operator!=(const TDoubleLinkedListIterator& Lhs, const TDoubleLinkedListIterator& Rhs)
374 {
375 return Lhs.CurrentNode != Rhs.CurrentNode;
376 }
377};
378
384template <class ElementType>
386{
387public:
389 {
390 public:
391 friend class TDoubleLinkedList;
392
394 TDoubleLinkedListNode(const ElementType& InValue) : Value(InValue), NextNode(nullptr), PrevNode(nullptr) {}
395
396 const ElementType& GetValue() const { return Value; }
397
398 ElementType& GetValue() { return Value; }
399
400 TDoubleLinkedListNode* GetNextNode() { return NextNode; }
401
402 const TDoubleLinkedListNode* GetNextNode() const { return NextNode; }
403
404 TDoubleLinkedListNode* GetPrevNode() { return PrevNode; }
405
406 const TDoubleLinkedListNode* GetPrevNode() const { return PrevNode; }
407
408 protected:
409 ElementType Value;
410 TDoubleLinkedListNode* NextNode;
411 TDoubleLinkedListNode* PrevNode;
412 };
413
419
421 TDoubleLinkedList() : HeadNode(nullptr), TailNode(nullptr), ListSize(0) {}
422
424 virtual ~TDoubleLinkedList() { Empty(); }
425
426 // Adding/Removing methods
427
435 bool AddHead(const ElementType& InElement) { return AddHead(new TDoubleLinkedListNode(InElement)); }
436
437 bool AddHead(TDoubleLinkedListNode* NewNode)
438 {
439 if (NewNode == nullptr)
440 {
441 return false;
442 }
443
444 // have an existing head node - change the head node to point to this one
445 if (HeadNode != nullptr)
446 {
447 NewNode->NextNode = HeadNode;
448 HeadNode->PrevNode = NewNode;
449 HeadNode = NewNode;
450 }
451 else
452 {
453 HeadNode = TailNode = NewNode;
454 }
455
456 SetListSize(ListSize + 1);
457 return true;
458 }
459
467 bool AddTail(const ElementType& InElement) { return AddTail(new TDoubleLinkedListNode(InElement)); }
468
469 bool AddTail(TDoubleLinkedListNode* NewNode)
470 {
471 if (NewNode == nullptr)
472 {
473 return false;
474 }
475
476 if (TailNode != nullptr)
477 {
478 TailNode->NextNode = NewNode;
479 NewNode->PrevNode = TailNode;
480 TailNode = NewNode;
481 }
482 else
483 {
484 HeadNode = TailNode = NewNode;
485 }
486
487 SetListSize(ListSize + 1);
488 return true;
489 }
490
500 bool InsertNode(const ElementType& InElement, TDoubleLinkedListNode* NodeToInsertBefore = nullptr)
501 {
502 return InsertNode(new TDoubleLinkedListNode(InElement), NodeToInsertBefore);
503 }
504
505 bool InsertNode(TDoubleLinkedListNode* NewNode, TDoubleLinkedListNode* NodeToInsertBefore = nullptr)
506 {
507 if (NewNode == nullptr)
508 {
509 return false;
510 }
511
512 if (NodeToInsertBefore == nullptr || NodeToInsertBefore == HeadNode)
513 {
514 return AddHead(NewNode);
515 }
516
517 NewNode->PrevNode = NodeToInsertBefore->PrevNode;
518 NewNode->NextNode = NodeToInsertBefore;
519
520 NodeToInsertBefore->PrevNode->NextNode = NewNode;
521 NodeToInsertBefore->PrevNode = NewNode;
522
523 SetListSize(ListSize + 1);
524 return true;
525 }
526
533 void RemoveNode(const ElementType& InElement)
534 {
535 TDoubleLinkedListNode* ExistingNode = FindNode(InElement);
536 RemoveNode(ExistingNode);
537 }
538
545 void RemoveNode(TDoubleLinkedListNode* NodeToRemove, bool bDeleteNode = true)
546 {
547 if (NodeToRemove != nullptr)
548 {
549 // if we only have one node, just call Clear() so that we don't have to do lots of extra checks in the code below
550 if (Num() == 1)
551 {
552 checkSlow(NodeToRemove == HeadNode);
553 if (bDeleteNode)
554 {
555 Empty();
556 }
557 else
558 {
559 NodeToRemove->NextNode = NodeToRemove->PrevNode = nullptr;
560 HeadNode = TailNode = nullptr;
561 SetListSize(0);
562 }
563 return;
564 }
565
566 if (NodeToRemove == HeadNode)
567 {
568 HeadNode = HeadNode->NextNode;
569 HeadNode->PrevNode = nullptr;
570 }
571
572 else if (NodeToRemove == TailNode)
573 {
574 TailNode = TailNode->PrevNode;
575 TailNode->NextNode = nullptr;
576 }
577 else
578 {
579 NodeToRemove->NextNode->PrevNode = NodeToRemove->PrevNode;
580 NodeToRemove->PrevNode->NextNode = NodeToRemove->NextNode;
581 }
582
583 if (bDeleteNode)
584 {
585 delete NodeToRemove;
586 }
587 else
588 {
589 NodeToRemove->NextNode = NodeToRemove->PrevNode = nullptr;
590 }
591 SetListSize(ListSize - 1);
592 }
593 }
594
596 void Empty()
597 {
599 while (HeadNode != nullptr)
600 {
601 Node = HeadNode->NextNode;
602 delete HeadNode;
603 HeadNode = Node;
604 }
605
606 HeadNode = TailNode = nullptr;
607 SetListSize(0);
608 }
609
610 // Accessors.
611
618 TDoubleLinkedListNode* GetHead() const { return HeadNode; }
619
626 TDoubleLinkedListNode* GetTail() const { return TailNode; }
627
634 TDoubleLinkedListNode* FindNode(const ElementType& InElement)
635 {
636 TDoubleLinkedListNode* Node = HeadNode;
637 while (Node != nullptr)
638 {
639 if (Node->GetValue() == InElement)
640 {
641 break;
642 }
643
644 Node = Node->NextNode;
645 }
646
647 return Node;
648 }
649
650 bool Contains(const ElementType& InElement) { return (FindNode(InElement) != nullptr); }
651
658 bool IsEmpty() const { return ListSize == 0; }
659
665 int32 Num() const { return ListSize; }
666
667 void MoveTailAfterHead()
668 {
669 TailNode->PrevNode->NextNode = nullptr;
670 auto* NewTailNode = TailNode->PrevNode;
671
672 TailNode->NextNode = HeadNode->NextNode;
673 HeadNode->NextNode->PrevNode = TailNode;
674
675 TailNode->PrevNode = HeadNode;
676 HeadNode->NextNode = TailNode;
677
678 TailNode = NewTailNode;
679 }
680
681protected:
688 virtual void SetListSize(int32 NewListSize) { ListSize = NewListSize; }
689
690private:
691 TDoubleLinkedListNode* HeadNode;
692 TDoubleLinkedListNode* TailNode;
693 int32 ListSize;
694
696 // TDoubleLinkedList& operator=(const TDoubleLinkedList&);
697
698 friend TIterator begin(TDoubleLinkedList& List) { return TIterator(List.GetHead()); }
699 friend TConstIterator begin(const TDoubleLinkedList& List) { return TConstIterator(List.GetHead()); }
700 friend TIterator end(TDoubleLinkedList& List) { return TIterator(nullptr); }
701 friend TConstIterator end(const TDoubleLinkedList& List) { return TConstIterator(nullptr); }
702};
703
704/*----------------------------------------------------------------------------
705 TList.
706----------------------------------------------------------------------------*/
707
708//
709// Simple single-linked list template.
710//
711template <class ElementType>
712class TList
713{
714public:
715 ElementType Element;
716 TList<ElementType>* Next;
717
718 // Constructor.
719
720 TList(const ElementType& InElement, TList<ElementType>* InNext = nullptr)
721 {
722 Element = InElement;
723 Next = InNext;
724 }
725};
726
727} // namespace SnakeGame
TDoubleLinkedListNode(const ElementType &InValue)
Definition: List.h:394
Definition: List.h:386
TDoubleLinkedListIterator< TDoubleLinkedListNode, ElementType > TIterator
Definition: List.h:417
TDoubleLinkedList()
Definition: List.h:421
void RemoveNode(TDoubleLinkedListNode *NodeToRemove, bool bDeleteNode=true)
Definition: List.h:545
void RemoveNode(const ElementType &InElement)
Definition: List.h:533
int32 Num() const
Definition: List.h:665
bool AddTail(const ElementType &InElement)
Definition: List.h:467
virtual void SetListSize(int32 NewListSize)
Definition: List.h:688
bool InsertNode(const ElementType &InElement, TDoubleLinkedListNode *NodeToInsertBefore=nullptr)
Definition: List.h:500
void Empty()
Definition: List.h:596
TDoubleLinkedListNode * GetHead() const
Definition: List.h:618
bool AddHead(const ElementType &InElement)
Definition: List.h:435
virtual ~TDoubleLinkedList()
Definition: List.h:424
bool IsEmpty() const
Definition: List.h:658
TDoubleLinkedListNode * FindNode(const ElementType &InElement)
Definition: List.h:634
TDoubleLinkedListNode * GetTail() const
Definition: List.h:626
Definition: List.h:302
TIntrusiveLinkedList()
Definition: List.h:307
Definition: List.h:104
ContainerType * NextLink
Definition: List.h:241
TLinkedListBase()
Definition: List.h:115
FORCEINLINE void Unlink()
Definition: List.h:122
ContainerType ** PrevLink
Definition: List.h:244
FORCEINLINE void LinkBefore(ContainerType *Before)
Definition: List.h:142
FORCEINLINE void LinkAfter(ContainerType *After)
Definition: List.h:162
IteratorType< ContainerType, ElementType > TIterator
Definition: List.h:109
FORCEINLINE bool IsLinked()
Definition: List.h:231
FORCEINLINE void LinkReplace(ContainerType *Replace)
Definition: List.h:182
FORCEINLINE void LinkHead(ContainerType *&Head)
Definition: List.h:214
Definition: List.h:259
TLinkedList()
Definition: List.h:264
TLinkedList(const ElementType &InElement)
Definition: List.h:271
FORCEINLINE void Next()
Definition: List.h:20
Definition: List.h:57
Definition: List.h:713
Definition: SnakeGame.Build.cs:6