libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_ring_list.h
Go to the documentation of this file.
1/*! \file
2 * \brief GblRingList structure and related functions
3 * \ingroup containers
4 * \todo
5 * - GblRingList_sort()
6 *
7 * \author Falco Girgis
8 */
9
10#ifndef GIMBAL_RING_LIST_H
11#define GIMBAL_RING_LIST_H
12
13#include "../core/gimbal_ctx.h"
15
16#define GBL_RING_LIST_NPOS GBL_NPOS
17#define GBL_SELF_TYPE GblRingList
18
20
22
23typedef GblBool (*GblRingListIterFn)(void* pValue, void* pClosure);
24typedef int (*GblRingListCmpFn) (const void* pVal1, const void* pVal2, void* pClosure);
25typedef void* (*GblRingListCopyFn)(const void* pValue, void* pClosure);
26typedef GBL_RESULT (*GblRingListDtorFn)(void* pValue, void* pClosure);
27
28/*! \brief Non-intrusive circularly doubly linked list with C++-style STL API
29 *
30 * GblRingList is a non-intrusive circular doubly-linked
31 * list with an API mirroring C++'s std::vector, or that of
32 * an abstract List from other languges. All values are stored
33 * in the form of void* pointers.
34 *
35 * Each entry within the list is maintained as a simple
36 * GblDoublyLinkedListNode connecting it to the prevous and next
37 * entries along with a void* as a data payload (with the list
38 * head storing its size in that union field instead). While
39 * these nodes are directly accessible, a higher-level API
40 * is presented, which manages allocations and node relationships
41 * internally.
42 *
43 * The GblRingList API has been tweaked for convenience within
44 * the C programming language. This is why many of the methods
45 * are provided as overridden macros implementing default values
46 * and function overloading for doing things such as inserting
47 * or removing multiple entries at once.
48 *
49 * Operation |Time Complexity
50 * ----------------------------------|------------------
51 * iteration | O(N)
52 * insertion/removal (middle) | O(N)
53 * insertion/removal (front or back) | O(1)
54 * access (front or back) | O(1)
55 * random access (middle) | O(N)
56 *
57 * \note
58 * As it's non-intrusive, every list entry must dynamically
59 * allocate a new node when a value is added to the list,
60 * which would normally result in lots of small, disjoint
61 * heap allocations, causing fragmentation. However, this
62 * is not the case with GblRingList. LibGimbal uses an
63 * arena allocator internally to efficiently allocate
64 * each node from contiguous blocks of data, also
65 * maintaining a free list to reuse nodes as they become
66 * available.
67 * \sa GblDoublyLinkedListNode
68 * \ingroup containers
69 */
70typedef struct GblRingList {
71 union { // Size (32-bit / 64-bit)
72 GblDoublyLinkedListNode listNode;
73 struct {
74 struct GblRingList* pNext; // 4/8 bytes
75 struct GblRingList* pPrev; // 4/8 bytes
76 } ringNode;
77 };
78 union {
79 uintptr_t size; // 4/8 bytes
80 void* pData;
81 };
82} GblRingList; // 12/24 total
83
84// === Regular Methods ====
85GBL_EXPORT GblRingList* GblRingList_createEmpty (void) GBL_NOEXCEPT;
86GBL_EXPORT GblRingList* GblRingList_create (void* pData, ...) GBL_NOEXCEPT;
87GBL_EXPORT GblRefCount GblRingList_unref (GBL_CSELF, GblRingListDtorFn pFnDtor, void* pCl)GBL_NOEXCEPT;
88GBL_EXPORT GblRingList* GblRingList_ref (GBL_CSELF) GBL_NOEXCEPT;
89GBL_EXPORT GblRingList* GblRingList_copy (GBL_CSELF, GblRingListCopyFn pFnCpy, void* pCl) GBL_NOEXCEPT;
90
91GBL_EXPORT GblRefCount GblRingList_refCount (GBL_CSELF) GBL_NOEXCEPT;
92GBL_EXPORT size_t GblRingList_size (GBL_CSELF) GBL_NOEXCEPT;
93GBL_EXPORT GblBool GblRingList_empty (GBL_CSELF) GBL_NOEXCEPT;
94
95GBL_EXPORT void* GblRingList_front (GBL_CSELF) GBL_NOEXCEPT;
96GBL_EXPORT void* GblRingList_back (GBL_CSELF) GBL_NOEXCEPT;
97GBL_EXPORT void* GblRingList_at (GBL_CSELF, intptr_t index) GBL_NOEXCEPT;
98
99GBL_EXPORT GBL_RESULT GblRingList_pushBack (GBL_SELF, ...) GBL_NOEXCEPT;
100GBL_EXPORT GBL_RESULT GblRingList_pushBackVaList (GBL_SELF, va_list* pList) GBL_NOEXCEPT;
101GBL_EXPORT GBL_RESULT GblRingList_pushFront (GBL_SELF, ...) GBL_NOEXCEPT;
102GBL_EXPORT GBL_RESULT GblRingList_pushFrontVaList (GBL_SELF, va_list* plist) GBL_NOEXCEPT;
103GBL_EXPORT GBL_RESULT GblRingList_insert (GBL_SELF, intptr_t index, ...) GBL_NOEXCEPT;
104GBL_EXPORT GBL_RESULT GblRingList_insertVaList (GBL_SELF, intptr_t index, va_list* pList) GBL_NOEXCEPT;
105GBL_EXPORT void* GblRingList_replace (GBL_SELF, intptr_t index, void* pData) GBL_NOEXCEPT;
106
107GBL_EXPORT GBL_RESULT GblRingList_insertSorted (GBL_SELF,
108 void* pData,
109 GblRingListCmpFn pFnCmp,
110 void* pCl) GBL_NOEXCEPT;
111
112GBL_EXPORT GblBool GblRingList_splice (GBL_SELF,
113 GblRingList* pOther,
114 int32_t index) GBL_NOEXCEPT;
115
116GBL_EXPORT void* GblRingList_popBack (GBL_SELF, size_t count) GBL_NOEXCEPT;
117GBL_EXPORT void* GblRingList_popFront (GBL_SELF, size_t count) GBL_NOEXCEPT;
118GBL_EXPORT void* GblRingList_remove (GBL_SELF, intptr_t index, size_t count) GBL_NOEXCEPT;
119GBL_EXPORT void* GblRingList_extract (GBL_SELF, GblRingList* pNode) GBL_NOEXCEPT;
120GBL_EXPORT GBL_RESULT GblRingList_clear (GBL_SELF) GBL_NOEXCEPT;
121
122GBL_EXPORT void GblRingList_sort (GBL_SELF, GblRingListCmpFn pFnCmp, void* pCl) GBL_NOEXCEPT;
123GBL_EXPORT void GblRingList_rotate (GBL_SELF, intptr_t n) GBL_NOEXCEPT;
124GBL_EXPORT void GblRingList_reverse (GBL_SELF) GBL_NOEXCEPT;
125GBL_EXPORT GblBool GblRingList_foreach (GBL_SELF, GblRingListIterFn pFnIt, void* pCl) GBL_NOEXCEPT;
126
127GBL_EXPORT size_t GblRingList_find (GBL_CSELF,
128 const void* pVal,
129 GblRingListCmpFn pFnCmp,
130 void* pCl) GBL_NOEXCEPT;
131
132// ==== Macro Overrides (for default arguments) ====
133#define GblRingList_create(...) (GblRingList_create)(__VA_ARGS__, GBL_NULL)
134#define GblRingList_copy(...) GblRingList_copyDefault_(__VA_ARGS__)
135#define GblRingList_unref(...) GblRingList_unrefDefault_(__VA_ARGS__)
136#define GblRingList_pushBack(self, ...) (GblRingList_pushBack)(self, __VA_ARGS__, GBL_NULL)
137#define GblRingList_pushFront(self, ...) (GblRingList_pushFront)(self, __VA_ARGS__, GBL_NULL)
138#define GblRingList_insert(self, ...) (GblRingList_insert)(self, __VA_ARGS__, GBL_NULL)
139#define GblRingList_insertSorted(...) GblRingList_insertSortedDefault_(__VA_ARGS__)
140#define GblRingList_splice(...) GblRingList_spliceDefault_(__VA_ARGS__)
141#define GblRingList_popBack(...) GblRingList_popBackDefault_(__VA_ARGS__)
142#define GblRingList_popFront(...) GblRingList_popFrontDefault_(__VA_ARGS__)
143#define GblRingList_remove(...) GblRingList_removeDefault_(__VA_ARGS__)
144#define GblRingList_sort(...) GblRingList_sortDefault_(__VA_ARGS__)
145#define GblRingList_foreach(...) GblRingList_foreachDefault_(__VA_ARGS__)
146#define GblRingList_find(...) GblRingList_findDefault_(__VA_ARGS__)
147
148// ===== IMPL =====
149
150/// \cond
151#define GblRingList_copyDefault_(...)
152 GblRingList_copyDefault__(__VA_ARGS__, GBL_NULL, GBL_NULL)
153#define GblRingList_copyDefault__(list, cpFn, cl, ...)
154 (GblRingList_copy)(list, cpFn, cl)
155
156#define GblRingList_unrefDefault_(...)
157 GblRingList_unrefDefault__(__VA_ARGS__, GBL_NULL, GBL_NULL)
158#define GblRingList_unrefDefault__(list, dtor, cl, ...)
159 (GblRingList_unref)(list, dtor, cl)
160
161#define GblRingList_insertSortedDefault_(...)
162 GblRingList_insertSortedDefault__(__VA_ARGS__, GBL_NULL, GBL_NULL)
163#define GblRingList_insertSortedDefault__(list, data, cmp, cl, ...)
164 (GblRingList_insertSorted)(list, data, cmp, cl)
165
166#define GblRingList_spliceDefault_(...)
167 GblRingList_spliceDefault__(__VA_ARGS__, -1)
168#define GblRingList_spliceDefault__(list1, list2, index, ...)
169 (GblRingList_splice)(list1, list2, index)
170
171#define GblRingList_popBackDefault_(...)
172 GblRingList_popBackDefault__(__VA_ARGS__, 1)
173#define GblRingList_popBackDefault__(list, count, ...)
174 (GblRingList_popBack)(list, count)
175
176#define GblRingList_popFrontDefault_(...)
177 GblRingList_popFrontDefault__(__VA_ARGS__, 1)
178#define GblRingList_popFrontDefault__(list, count, ...)
179 (GblRingList_popFront)(list, count)
180
181#define GblRingList_removeDefault_(...)
182 GblRingList_removeDefault__(__VA_ARGS__, 1)
183#define GblRingList_removeDefault__(list, idx, count, ...)
184 (GblRingList_remove)(list, idx, count)
185
186#define GblRingList_sortDefault_(...)
187 GblRingList_sortDefault__(__VA_ARGS__, GBL_NULL, GBL_NULL)
188#define GblRingList_sortDefault__(list, cmp, cl, ...)
189 (GblRingList_sort)(list, cmp, cl)
190
191#define GblRingList_foreachDefault_(...)
192 GblRingList_foreachDefault__(__VA_ARGS__, GBL_NULL)
193#define GblRingList_foreachDefault__(list, it, cl, ...)
194 (GblRingList_foreach)(list, it, cl)
195
196#define GblRingList_findDefault_(...)
197 GblRingList_findDefault__(__VA_ARGS__, GBL_NULL, GBL_NULL)
198#define GblRingList_findDefault__(list, val, cmp, cl, ...)
199 (GblRingList_find)(list, val, cmp, cl)
200/// \endcond
201
203
204#undef GBL_SELF_TYPE
205
206#endif // GIMBAL_RING_LIST_H
#define GBL_NULL
#define GBL_NOEXCEPT
#define GBL_DECLS_BEGIN
#define GBL_FORWARD_DECLARE_STRUCT(S)
#define GBL_EXPORT
#define GblRingList_create(...)
#define GblRingList_insert(self,...)
#define GblRingList_insertSorted(...)
#define GblRingList_popFront(...)
#define GblRingList_pushBack(self,...)
#define GblRingList_splice(...)
#define GblRingList_foreach(...)
#define GblRingList_unref(...)
#define GblRingList_remove(...)
#define GblRingList_copy(...)
#define GblRingList_pushFront(self,...)
#define GblRingList_find(...)
#define GblRingList_sort(...)
#define GblRingList_popBack(...)
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uint16_t GblRefCount
Type able to hold a reference counter across the codebase.
#define GBL_NPOS
Non-intrusive circularly doubly linked list with C++-style STL API.