-
Notifications
You must be signed in to change notification settings - Fork 488
/
Copy pathFFlist.h
122 lines (101 loc) · 3.2 KB
/
FFlist.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#pragma once
#include "FFcheckmacros.h"
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#define FF_LIST_DEFAULT_ALLOC 16
typedef struct FFlist
{
uint8_t* data;
uint32_t elementSize;
uint32_t length;
uint32_t capacity;
} FFlist;
void* ffListAdd(FFlist* list);
// Removes the first element, and copy its value to `*result`
bool ffListShift(FFlist* list, void* result);
// Removes the last element, and copy its value to `*result`
bool ffListPop(FFlist* list, void* result);
static inline void ffListInit(FFlist* list, uint32_t elementSize)
{
assert(elementSize > 0);
list->elementSize = elementSize;
list->capacity = 0;
list->length = 0;
list->data = NULL;
}
static inline void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity)
{
ffListInit(list, elementSize);
list->capacity = capacity;
list->data = __builtin_expect(capacity == 0, 0) ? NULL : (uint8_t*) malloc((size_t)list->capacity * list->elementSize);
}
static inline FFlist ffListCreate(uint32_t elementSize)
{
FFlist result;
ffListInit(&result, elementSize);
return result;
}
static inline void* ffListGet(const FFlist* list, uint32_t index)
{
assert(list->capacity > index);
return list->data + (index * list->elementSize);
}
FF_C_NODISCARD static inline uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compFunc)(const void*, const void*))
{
for(uint32_t i = 0; i < list->length; i++)
{
if(compFunc(ffListGet(list, i), compElement))
return i;
}
return list->length;
}
static inline bool ffListContains(const FFlist* list, void* compElement, bool(*compFunc)(const void*, const void*))
{
return ffListFirstIndexComp(list, compElement, compFunc) != list->length;
}
static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void*))
{
qsort(list->data, list->length, list->elementSize, compar);
}
// Move the contents of `src` into `list`, and left `src` empty
static inline void ffListInitMove(FFlist* list, FFlist* src)
{
if (src)
{
list->elementSize = src->elementSize;
list->capacity = src->capacity;
list->length = src->length;
list->data = src->data;
ffListInit(src, list->elementSize);
}
else
{
ffListInit(list, 0);
}
}
static inline void ffListDestroy(FFlist* list)
{
if (!list->data) return;
//Avoid free-after-use. These 3 assignments are cheap so don't remove them
list->capacity = list->length = 0;
free(list->data);
list->data = NULL;
}
static inline void ffListClear(FFlist* list)
{
list->length = 0;
}
#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
assert(sizeof(itemType) == (listVar).elementSize); \
for(itemType* itemVarName = (itemType*)(listVar).data; \
itemVarName - (itemType*)(listVar).data < (intptr_t)(listVar).length; \
++itemVarName)
#define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy)))
#define FF_LIST_GET(itemType, listVar, index) \
({ \
assert(sizeof(itemType) == (listVar).elementSize); \
assert((listVar).capacity > (index)); \
(itemType*)(listVar).data + (index); \
})