Cogs.Core
List.h
1#pragma once
2#include <cassert>
3
4namespace Cogs::Core
5{
6
7 struct ListNode {
8 ListNode* next = nullptr;
9 ListNode* prev = nullptr;
10
11 bool isFree() { return next == nullptr && prev == nullptr; }
12 };
13
14
15 template<typename T, size_t offset>
16 struct List {
17
18 // Maintains next-pointer so that it is safe to delete curr inside a loop
19 struct Iterator
20 {
21 ListNode* curr = nullptr;
22 ListNode* next = nullptr;
23 bool operator!=(Iterator& other) { return curr != other.curr; }
24 Iterator& operator++() { curr = next; next = next->next; return *this; }
25 T* operator*() { return get(curr); }
26 };
27
28 List() {
29 head.next = &tail;
30 head.prev = nullptr;
31 tail.next = nullptr;
32 tail.prev = &head;
33 myself = this; // List doesn't support to be memmoved, so we verify that that hasn't happened.
34 count = 0;
35 assert(head.next != nullptr);
36 assert(tail.prev != nullptr);
37 }
38
39 static T* get(ListNode* n)
40 {
41 return reinterpret_cast<T*>(reinterpret_cast<char*>(n) - offset);
42 }
43
44 void remove(T* item) {
45 assert(myself == this);
46 assert(item);
47 assert(head.next != nullptr);
48 assert(tail.prev != nullptr);
49 auto* n = reinterpret_cast<ListNode*>(reinterpret_cast<char*>(item) + offset);
50
51 assert(n->next);
52 assert(n->next->prev == n);
53 assert(n->next->next != n);
54
55 assert(n->prev);
56 assert(n->prev->next == n);
57 assert(n->prev->prev != n);
58
59 auto* prev = n->prev;
60 auto* next = n->next;
61
62 next->prev = prev;
63 prev->next = next;
64
65 n->next = nullptr;
66 n->prev = nullptr;
67 assert(head.next != nullptr);
68 assert(tail.prev != nullptr);
69 }
70
71 T* push(T* item)
72 {
73 assert(myself == this);
74 assert(head.next != nullptr);
75 assert(tail.prev != nullptr);
76 auto* n = reinterpret_cast<ListNode*>(reinterpret_cast<char*>(item) + offset);
77
78 count++;
79 assert(n->next == nullptr);
80 assert(n->prev == nullptr);
81 auto* prev = tail.prev;
82 prev->next = n;
83 n->prev = prev;
84 tail.prev = n;
85 n->next = &tail;
86
87 assert(head.next != nullptr);
88 assert(tail.prev != nullptr);
89 return item;
90 }
91
92 T* shift()
93 {
94 assert(myself == this);
95 assert(head.next != nullptr);
96 assert(tail.prev != nullptr);
97 assert(0 < count);
98 count--;
99
100 auto* n = head.next;
101 assert(n != &tail);
102 head.next = n->next;
103 head.next->prev = n->prev;
104 n->next = nullptr;
105 n->prev = nullptr;
106 assert(head.next != nullptr);
107 assert(tail.prev != nullptr);
108 return get(n);
109 }
110
111 T* pop()
112 {
113 assert(myself == this);
114 assert(head.next != nullptr);
115 assert(tail.prev != nullptr);
116 assert(0 < count);
117 count--;
118 auto* n = tail.prev;
119 assert(n != &head);
120 tail.prev = n->prev;
121 tail.prev->next = n->next;
122 n->next = nullptr;
123 n->prev = nullptr;
124 assert(head.next != nullptr);
125 assert(tail.prev != nullptr);
126 return get(n);
127 }
128
129 bool empty() const {
130 assert(myself == this);
131 assert(head.next != nullptr);
132 assert(tail.prev != nullptr);
133 return head.next == &tail;
134 }
135
136 void swap(List& that)
137 {
138 assert(myself == this);
139 assert(head.next != nullptr);
140 assert(tail.prev != nullptr);
141 assert(that.head.next != nullptr);
142 assert(that.tail.prev != nullptr);
143
144 auto* thisHeadNext = head.next;
145 auto* thisTailPrev = tail.prev;
146 auto* thatHeadNext = that.head.next;
147 auto* thatTailPrev = that.tail.prev;
148
149 if (thatHeadNext == &that.tail) {
150 head.next = &tail;
151 tail.prev = &head;
152 }
153 else {
154 head.next = thatHeadNext;
155 tail.prev = thatTailPrev;
156 thatHeadNext->prev = &head;
157 thatTailPrev->next = &tail;
158 }
159
160 if (thisHeadNext == &tail) {
161 that.head.next = &that.tail;
162 that.tail.prev = &that.head;
163 }
164 else {
165 that.head.next = thisHeadNext;
166 that.tail.prev = thisTailPrev;
167 thisHeadNext->prev = &that.tail;
168 thisTailPrev->next = &that.head;
169 }
170 std::swap(count, that.count);
171 assert(head.next != nullptr);
172 assert(tail.prev != nullptr);
173 assert(that.head.next != nullptr);
174 assert(that.tail.prev != nullptr);
175 }
176
177 ListNode head;
178 ListNode tail;
179 List* myself = nullptr;
180 size_t count = 0;
181
182 T* front() {
183 assert(myself == this);
184 assert(head.next != &tail);
185 assert(head.next != nullptr);
186 assert(tail.prev != nullptr);
187 return get(head.next);
188 }
189
190 T* back() {
191 assert(myself == this);
192 assert(tail.prev != &head);
193 assert(head.next != nullptr);
194 assert(tail.prev != nullptr);
195 return get(tail.prev);
196 }
197
198 const T* front() const {
199 assert(myself == this);
200 assert(head.next != nullptr);
201 assert(tail.prev != nullptr);
202 assert(head.next != &tail);
203 return get(head.next);
204 }
205
206 const T* back() const {
207 assert(myself == this);
208 assert(tail.prev != &head);
209 assert(head.next != nullptr);
210 assert(tail.prev != nullptr);
211 return get(tail.prev);
212 }
213
214 Iterator begin() {
215 assert(myself == this);
216 assert(head.next != nullptr);
217 assert(tail.prev != nullptr);
218 return Iterator{ head.next, head.next->next };
219 }
220
221 Iterator end() {
222 assert(myself == this);
223 assert(head.next != nullptr);
224 assert(tail.prev != nullptr);
225 return Iterator{ &tail, nullptr };
226 }
227
228 };
229
230
231}
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....