]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/linkedlist.qh
Merge branch 'master' into terencehill/translated_keys
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / linkedlist.qh
index be57bb5bf9c890b6b5abd90f6cdcd701ed93a2e4..aa7d7c9517179a05d06e16ff93788b42f4d4929e 100644 (file)
@@ -1,57 +1,81 @@
-#ifndef LINKEDLIST_H
-#define LINKEDLIST_H
+#pragma once
 
 CLASS(LinkedListNode, Object)
-    ATTRIB(LinkedListNode, ll_data, entity, NULL)
-    ATTRIB(LinkedListNode, ll_prev, LinkedListNode, NULL)
-    ATTRIB(LinkedListNode, ll_next, LinkedListNode, NULL)
+       ATTRIB(LinkedListNode, ll_data, entity);
+       ATTRIB(LinkedListNode, ll_prev, LinkedListNode);
+       ATTRIB(LinkedListNode, ll_next, LinkedListNode);
 ENDCLASS(LinkedListNode)
 
 CLASS(LinkedList, Object)
-    ATTRIB(LinkedList, ll_head, LinkedListNode, NULL);
-    ATTRIB(LinkedList, ll_tail, LinkedListNode, NULL);
+       ATTRIB(LinkedList, ll_head, LinkedListNode);
+       ATTRIB(LinkedList, ll_tail, LinkedListNode);
 ENDCLASS(LinkedList)
 
 #define LL_NEW() NEW(LinkedList)
 
+#define LL_EMPTY(ll) (ll.ll_head == NULL)
+
 /**
  * Push to tail
  */
-entity LL_PUSH(LinkedList this, entity e) {
-    LinkedListNode n = NEW(LinkedListNode);
-    n.ll_data = e;
-    n.ll_prev = this.ll_tail;
-    LinkedListNode tail = this.ll_tail;
-    if (tail) {
-        tail.ll_next = n;
-    } else {
-        this.ll_head = this.ll_tail = n;
-    }
-    return e;
+entity LL_PUSH(LinkedList this, entity e)
+{
+       assert(this);
+       LinkedListNode n = NEW(LinkedListNode);
+       n.ll_data = e;
+       LinkedListNode tail = n.ll_prev = this.ll_tail;
+       this.ll_tail = (tail) ? tail.ll_next = n : this.ll_head = n;
+       return e;
 }
 
 /**
  * Pop from tail
  */
-entity LL_POP(LinkedList this) {
-    if (!this.ll_tail) return NULL;
-    LinkedListNode n = this.ll_tail;
-    entity e = n.ll_data;
-    LinkedListNode prev = n.ll_prev;
-    if (prev) {
-        prev.ll_next = NULL;
-    } else {
-        this.ll_head = this.ll_tail = NULL;
-    }
-    return e;
+entity LL_POP(LinkedList this)
+{
+       assert(this);
+       if (!this.ll_tail) return NULL;
+       LinkedListNode n = this.ll_tail;
+       entity e = n.ll_data;
+       LinkedListNode prev = n.ll_prev;
+       if (prev) (this.ll_tail = prev).ll_next = NULL;
+       else this.ll_head = this.ll_tail = NULL;
+       delete(n);
+       return e;
 }
 
-#define LL_EACH(list, cond, body) do {                                  \
-    noref int i = 0;                                                    \
-    for (entity _it = list.ll_head; _it; (_it = _it.ll_next, ++i)) {    \
-        noref entity it = _it.ll_data;                                  \
-        if (cond) { body }                                              \
-    }                                                                   \
-} while(0)
+#define LL_CLEAR(...) EVAL_LL_CLEAR(OVERLOAD(LL_CLEAR, __VA_ARGS__))
+#define EVAL_LL_CLEAR(...) __VA_ARGS__
+#define LL_CLEAR_1(this) LL_CLEAR_2(this, LAMBDA())
+#define LL_CLEAR_2(this, dtor) \
+       MACRO_BEGIN \
+               LinkedList _ll = this; \
+               assert(_ll); \
+               while (_ll.ll_tail) \
+               { \
+                       entity it = LL_POP(_ll); \
+                       if (!it) continue; \
+                       dtor \
+                       delete(it); \
+               } \
+       MACRO_END
+
+#define LL_DELETE(...) EVAL_LL_DELETE(OVERLOAD(LL_DELETE, __VA_ARGS__))
+#define EVAL_LL_DELETE(...) __VA_ARGS__
+#define LL_DELETE_1(this) LL_DELETE_2(this, LAMBDA())
+#define LL_DELETE_2(this, dtor) \
+       MACRO_BEGIN \
+               LL_CLEAR_2(this, dtor); \
+               delete(this); \
+               this = NULL; \
+       MACRO_END
 
-#endif
+#define LL_EACH(list, cond, body) \
+       MACRO_BEGIN                                                         \
+               noref int i = 0;                                                \
+               for (entity _it = list.ll_head; _it; (_it = _it.ll_next, ++i))  \
+               {                                                               \
+                       ITER_CONST noref entity it = _it.ll_data;                   \
+                       if (cond) { body }                                          \
+               }                                                               \
+       MACRO_END