-#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