X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Flib%2Flinkedlist.qh;h=6afc862ed0a6306b97e2ad5ca02702b3a79a4817;hb=b31c13cbd4fb79981e881e0599caf01d9d8dfd62;hp=be57bb5bf9c890b6b5abd90f6cdcd701ed93a2e4;hpb=9dd43f196ca7bc0979f94a0fb0f87cdd82a951c7;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/lib/linkedlist.qh b/qcsrc/lib/linkedlist.qh index be57bb5bf..6afc862ed 100644 --- a/qcsrc/lib/linkedlist.qh +++ b/qcsrc/lib/linkedlist.qh @@ -1,57 +1,84 @@ -#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, NULL) + ATTRIB(LinkedListNode, ll_prev, LinkedListNode, NULL) + ATTRIB(LinkedListNode, ll_next, LinkedListNode, NULL) ENDCLASS(LinkedListNode) CLASS(LinkedList, Object) - ATTRIB(LinkedList, ll_head, LinkedListNode, NULL); - ATTRIB(LinkedList, ll_tail, LinkedListNode, NULL); + ATTRIB(LinkedList, ll_head, LinkedListNode, NULL); + ATTRIB(LinkedList, ll_tail, LinkedListNode, NULL); 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; + remove(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 \ + remove(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); \ + remove(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