aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lib/queue_defs.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/lib/queue_defs.h')
-rw-r--r--src/nvim/lib/queue_defs.h106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/nvim/lib/queue_defs.h b/src/nvim/lib/queue_defs.h
new file mode 100644
index 0000000000..1f113a057a
--- /dev/null
+++ b/src/nvim/lib/queue_defs.h
@@ -0,0 +1,106 @@
+// Queue implemented by circularly-linked list.
+//
+// Adapted from libuv. Simpler and more efficient than klist.h for implementing
+// queues that support arbitrary insertion/removal.
+//
+// Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#pragma once
+
+#include <stddef.h>
+
+#include "nvim/func_attr.h"
+
+typedef struct queue {
+ struct queue *next;
+ struct queue *prev;
+} QUEUE;
+
+// Public macros.
+#define QUEUE_DATA(ptr, type, field) \
+ ((type *)((char *)(ptr) - offsetof(type, field)))
+
+// Important note: the node currently being processed can be safely deleted.
+// otherwise, mutating the list while QUEUE_FOREACH is iterating over its
+// elements results in undefined behavior.
+#define QUEUE_FOREACH(q, h, code) \
+ (q) = (h)->next; \
+ while ((q) != (h)) { \
+ QUEUE *next = q->next; \
+ code \
+ (q) = next; \
+ }
+
+// ffi.cdef is unable to swallow `bool` in place of `int` here.
+static inline int QUEUE_EMPTY(const QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
+
+static inline int QUEUE_EMPTY(const QUEUE *const q)
+{
+ return q == q->next;
+}
+
+#define QUEUE_HEAD(q) (q)->next
+
+static inline void QUEUE_INIT(QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_INIT(QUEUE *const q)
+{
+ q->next = q;
+ q->prev = q;
+}
+
+static inline void QUEUE_ADD(QUEUE *h, QUEUE *n)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_ADD(QUEUE *const h, QUEUE *const n)
+{
+ h->prev->next = n->next;
+ n->next->prev = h->prev;
+ h->prev = n->prev;
+ h->prev->next = h;
+}
+
+static inline void QUEUE_INSERT_HEAD(QUEUE *h, QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_INSERT_HEAD(QUEUE *const h, QUEUE *const q)
+{
+ q->next = h->next;
+ q->prev = h;
+ q->next->prev = q;
+ h->next = q;
+}
+
+static inline void QUEUE_INSERT_TAIL(QUEUE *h, QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_INSERT_TAIL(QUEUE *const h, QUEUE *const q)
+{
+ q->next = h;
+ q->prev = h->prev;
+ q->prev->next = q;
+ h->prev = q;
+}
+
+static inline void QUEUE_REMOVE(QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_REMOVE(QUEUE *const q)
+{
+ q->prev->next = q->next;
+ q->next->prev = q->prev;
+}