X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Flib%2Flinkedlist.qh;h=e2194f574c39a4e41235633ceaaa61ef2e49729f;hb=0e19b9b07dd56ba346b5b0b298e2448fdd2e53c2;hp=4946daddee31ab90b326390d07ea43964ddc3e5c;hpb=1cbef966e133966c5b5f0f5b58fbd1a5851ed35b;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/lib/linkedlist.qh b/qcsrc/lib/linkedlist.qh index 4946dadde..e2194f574 100644 --- a/qcsrc/lib/linkedlist.qh +++ b/qcsrc/lib/linkedlist.qh @@ -1,15 +1,14 @@ -#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) @@ -21,6 +20,7 @@ ENDCLASS(LinkedList) */ 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; @@ -33,25 +33,49 @@ entity LL_PUSH(LinkedList this, entity 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) prev.ll_next = NULL; + if (prev) (this.ll_tail = prev).ll_next = NULL; else this.ll_head = this.ll_tail = NULL; + delete(n); return e; } +#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 + #define LL_EACH(list, cond, body) \ - do \ - { \ + MACRO_BEGIN \ noref int i = 0; \ for (entity _it = list.ll_head; _it; (_it = _it.ll_next, ++i)) \ { \ - noref entity it = _it.ll_data; \ + ITER_CONST noref entity it = _it.ll_data; \ if (cond) { body } \ } \ - } \ - while (0) - -#endif + MACRO_END