UFO: Alien Invasion
Loading...
Searching...
No Matches
list.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "list.h"
27#include "common.h"
28#include "mem.h"
29#include <assert.h>
30#include <string.h>
31
32static linkedList_t* LIST_AllocateEntry(void* const data, linkedList_t* const next = 0)
33{
35 e->data = data;
36 e->next = next;
37 return e;
38}
39
41static void LIST_AppendEntry(linkedList_t** list, linkedList_t* const entry)
42{
43 while (*list) list = &(*list)->next;
44 *list = entry;
45}
46
54linkedList_t* LIST_Add (linkedList_t** listDest, void const* data, size_t length)
55{
56 assert(listDest);
57 assert(data);
58
59 void* const dataCopy = memcpy(Mem_PoolAllocTypeN(byte, length, com_genericPool), data, length);
60 linkedList_t* const newEntry = LIST_AllocateEntry(dataCopy);
61
62 LIST_AppendEntry(listDest, newEntry);
63
64 return newEntry;
65}
66
73const linkedList_t* LIST_ContainsString (const linkedList_t* list, const char* string)
74{
75 while ((string != nullptr) && (list != nullptr)) {
76 if (Q_streq(static_cast<char const*>(list->data), string))
77 return list;
78 list = list->next;
79 }
80
81 return nullptr;
82}
83
92{
93 while ((data != nullptr) && (list != nullptr)) {
94 if (list->data == data)
95 return list;
96 list = list->next;
97 }
98
99 return nullptr;
100}
101
102static linkedList_t* LIST_AllocateString(char const* data, linkedList_t* const next = 0)
103{
104 return LIST_AllocateEntry(Mem_StrDup(data), next);
105}
106
107void LIST_AddStringSorted (linkedList_t** listDest, const char* data)
108{
109 assert(listDest);
110 assert(data);
111
112 for (; *listDest; listDest = &(*listDest)->next) {
113 if (Q_StringSort(data, static_cast<char const*>((*listDest)->data)) < 0)
114 break;
115 }
116
117 *listDest = LIST_AllocateString(data, *listDest);
118}
119
127void LIST_PrependString (linkedList_t** listDest, const char* data)
128{
129 *listDest = LIST_AllocateString(data, *listDest);
130}
131
139void LIST_AddString (linkedList_t** listDest, const char* data)
140{
141 assert(listDest);
142 assert(data);
143
145}
146
153void LIST_AddPointer (linkedList_t** listDest, void* data)
154{
155 assert(listDest);
156 assert(data);
157
158 linkedList_t* const newEntry = LIST_AllocateEntry(data);
159 newEntry->ptr = true;
160
161 LIST_AppendEntry(listDest, newEntry);
162}
163
173{
174 assert(list);
175 assert(entry);
176
177 for (; *list; list = &(*list)->next) {
178 if (*list == entry) {
179 /* Unlink the entry. */
180 *list = entry->next;
181 /* Delete the entry. */
182 if (!entry->ptr) Mem_Free(entry->data);
183 Mem_Free(entry);
184 return true;
185 }
186 }
187
188 return false;
189}
190
196{
197 linkedList_t* l = *list;
198
199 while (l) {
200 linkedList_t* next = l->next;
201 if (!l->ptr)
202 Mem_Free(l->data);
203 Mem_Free(l);
204 l = next;
205 }
206 *list = nullptr;
207}
208
213bool LIST_Remove (linkedList_t** list, const void* data)
214{
215 linkedList_t* l = LIST_GetPointer(*list, data);
216 if (l != nullptr)
217 return LIST_RemoveEntry(list, l);
218 return false;
219}
220
227static linkedList_t* _LIST_Sort (linkedList_t* list, linkedListSort_t sorter, const void* userData)
228{
229 linkedList_t* e;
230
231 /*
232 * Silly special case: if `list' was passed in as nullptr, return
233 * nullptr immediately.
234 */
235 if (!list)
236 return nullptr;
237
238 int insize = 1;
239
240 while (1) {
241 linkedList_t* p = list;
242 list = nullptr;
243 linkedList_t* tail = nullptr;
244 int nmerges = 0; /* count number of merges we do in this pass */
245
246 while (p) {
247 nmerges++; /* there exists a merge to be done */
248 /* step `insize' places along from p */
249 linkedList_t* q = p;
250 int psize = 0;
251 for (int i = 0; i < insize; i++) {
252 psize++;
253 q = q->next;
254 if (!q)
255 break;
256 }
257
258 /* if q hasn't fallen off end, we have two lists to merge */
259 int qsize = insize;
260
261 /* now we have two lists; merge them */
262 while (psize > 0 || (qsize > 0 && q)) {
263 /* decide whether next element of merge comes from p or q */
264 if (psize == 0) {
265 /* p is empty; e must come from q. */
266 e = q;
267 q = q->next;
268 qsize--;
269 } else if (qsize == 0 || !q) {
270 /* q is empty; e must come from p. */
271 e = p;
272 p = p->next;
273 psize--;
274 } else if (sorter(p, q, userData) <= 0) {
275 /* First element of p is lower (or same);
276 * e must come from p. */
277 e = p;
278 p = p->next;
279 psize--;
280 } else {
281 /* First element of q is lower; e must come from q. */
282 e = q;
283 q = q->next;
284 qsize--;
285 }
286
287 /* add the next element to the merged list */
288 if (tail) {
289 tail->next = e;
290 } else {
291 list = e;
292 }
293 tail = e;
294 }
295
296 /* now p has stepped `insize' places along, and q has too */
297 p = q;
298 }
299 tail->next = nullptr;
300
301 /* If we have done only one merge, we're finished. */
302 if (nmerges <= 1) /* allow for nmerges==0, the empty list case */
303 return list;
304
305 /* Otherwise repeat, merging lists twice the size */
306 insize *= 2;
307 }
308}
309
310void LIST_Sort (linkedList_t** list, linkedListSort_t sorter, const void* userData)
311{
312 if (LIST_IsEmpty(*list))
313 return;
314 *list = _LIST_Sort(*list, sorter, userData);
315}
316
322{
323 linkedList_t* dest = nullptr;
324 LIST_Foreach(src, void, data) {
326 }
327 return dest;
328}
329
335bool LIST_IsEmpty (const linkedList_t* list)
336{
337 return list == nullptr;
338}
339
344int LIST_Count (const linkedList_t* list)
345{
346 const linkedList_t* l = list;
347 int count = 0;
348
349 while (l) {
350 count++;
351 l = l->next;
352 }
353 return count;
354}
355
363{
364 if (LIST_IsEmpty(list))
365 return nullptr;
366
367 if (index < 0)
368 return nullptr;
369
370 int i = 0;
371 while (list) {
372 if (i == index)
373 return list->data;
374 i++;
375 list = list->next;
376 }
377
378 return nullptr;
379}
380
382{
383 const int elements = LIST_Count(list);
384 if (elements == 0)
385 return nullptr;
386
387 const int element = rand() % elements;
388 return LIST_GetByIdx(list, element);
389}
memPool_t * com_genericPool
Definition common.cpp:72
definitions common between client and server, but not game lib
linkedList_t * LIST_GetPointer(linkedList_t *list, const void *data)
Searches for the first occurrence of a given pointer.
Definition list.cpp:91
static linkedList_t * _LIST_Sort(linkedList_t *list, linkedListSort_t sorter, const void *userData)
This is the actual sort function. Notice that it returns the new head of the list....
Definition list.cpp:227
static void LIST_AppendEntry(linkedList_t **list, linkedList_t *const entry)
Definition list.cpp:41
void LIST_AddStringSorted(linkedList_t **listDest, const char *data)
Definition list.cpp:107
void LIST_AddString(linkedList_t **listDest, const char *data)
Adds an string to a new or to an already existing linked list. The string is copied here.
Definition list.cpp:139
linkedList_t * LIST_CopyStructure(linkedList_t *src)
Copies the list structure data - but not the content from the original list. We are only using pointe...
Definition list.cpp:321
static linkedList_t * LIST_AllocateString(char const *data, linkedList_t *const next=0)
Definition list.cpp:102
void * LIST_GetRandom(linkedList_t *list)
Definition list.cpp:381
void LIST_Delete(linkedList_t **list)
Definition list.cpp:195
bool LIST_RemoveEntry(linkedList_t **list, linkedList_t *entry)
Removes one entry from the linked list.
Definition list.cpp:172
void LIST_Sort(linkedList_t **list, linkedListSort_t sorter, const void *userData)
Definition list.cpp:310
void * LIST_GetByIdx(linkedList_t *list, int index)
Get an entry of a linked list by its index in the list.
Definition list.cpp:362
int LIST_Count(const linkedList_t *list)
Definition list.cpp:344
void LIST_AddPointer(linkedList_t **listDest, void *data)
Adds just a pointer to a new or to an already existing linked list.
Definition list.cpp:153
bool LIST_Remove(linkedList_t **list, const void *data)
Definition list.cpp:213
bool LIST_IsEmpty(const linkedList_t *list)
Checks whether the given list is empty.
Definition list.cpp:335
const linkedList_t * LIST_ContainsString(const linkedList_t *list, const char *string)
Searches for the first occurrence of a given string.
Definition list.cpp:73
static linkedList_t * LIST_AllocateEntry(void *const data, linkedList_t *const next=0)
Definition list.cpp:32
void LIST_PrependString(linkedList_t **listDest, const char *data)
Adds a string as first entry to a linked list.
Definition list.cpp:127
linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
Adds an entry to a new or to an already existing linked list.
Definition list.cpp:54
LINKED LIST interface.
int(* linkedListSort_t)(linkedList_t *entry1, linkedList_t *entry2, const void *userData)
Definition list.h:36
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
Definition list.h:41
Memory handling with sentinel checking and pools with tags for grouped free'ing.
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_PoolAllocType(type, pool)
Definition mem.h:43
#define Mem_StrDup(in)
Definition mem.h:48
QGL_EXTERN GLenum GLuint * dest
Definition r_gl.h:101
QGL_EXTERN GLuint count
Definition r_gl.h:99
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLuint index
Definition r_gl.h:110
QGL_EXTERN GLint i
Definition r_gl.h:113
#define Q_streq(a, b)
Definition shared.h:136
int Q_StringSort(const void *string1, const void *string2)
Compare two strings.
Definition shared.cpp:385
void * data
Definition list.h:31
linkedList_t * next
Definition list.h:32
bool ptr
Definition list.h:33