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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#include "internal.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void
list_free_list(struct list *list)
{
assert(list);
free(list->items);
list->allocated = list->count = 0;
list->items = NULL;
}
void
list_free_items(struct list *list, list_free_fun destructor)
{
assert(list);
for (uint32_t i = 0; i < list->count; ++i)
destructor(list->items[i]);
list_free_list(list);
}
void*
list_get_items(const struct list *list, uint32_t *out_nmemb)
{
assert(list);
if (out_nmemb)
*out_nmemb = list->count;
return list->items;
}
/** !!! Frees the old list, not items !!! */
bool
list_set_items_no_copy(struct list *list, void *items, uint32_t nmemb)
{
assert(list);
list_free_list(list);
if (!items || nmemb == 0) {
items = NULL;
nmemb = 0;
}
list->items = items;
list->allocated = list->count = nmemb;
return true;
}
/** !!! Frees the old items and list !!! */
bool
list_set_items(struct list *list, const void *items, uint32_t nmemb, list_free_fun destructor)
{
assert(list);
if (!items || nmemb == 0) {
list_free_items(list, destructor);
return true;
}
void *new_items;
if (!(new_items = calloc(sizeof(void*), nmemb)))
return false;
memcpy(new_items, items, sizeof(void*) * nmemb);
return list_set_items_no_copy(list, new_items, nmemb);
}
bool
list_grow(struct list *list, uint32_t step)
{
assert(list);
void *tmp;
uint32_t nsize = sizeof(void*) * (list->allocated + step);
if (!(tmp = realloc(list->items, nsize)))
return false;
list->items = tmp;
list->allocated += step;
memset(&list->items[list->count], 0, sizeof(void*) * (list->allocated - list->count));
return true;
}
bool
list_add_item_at(struct list *list, void *item, uint32_t index)
{
assert(list && item);
if ((!list->items || list->allocated <= list->count) && !list_grow(list, 32))
return false;
if (index + 1 != list->count) {
uint32_t i = index;
memmove(&list->items[i + 1], &list->items[i], sizeof(void*) * (list->count - i));
}
list->items[index] = item;
list->count++;
return true;
}
bool
list_add_item(struct list *list, void *item)
{
assert(list);
return list_add_item_at(list, item, list->count);
}
bool
list_remove_item_at(struct list *list, uint32_t index)
{
assert(list);
uint32_t i = index;
if (!list->items || list->count <= i)
return false;
memmove(&list->items[i], &list->items[i + 1], sizeof(void*) * (list->count - i));
list->count--;
return true;
}
bool
list_remove_item(struct list *list, const void *item)
{
assert(list && item);
uint32_t i;
for (i = 0; i < list->count && list->items[i] != item; ++i);
return list_remove_item_at(list, i);
}
void
list_sort(struct list *list, int (*compar)(const void *a, const void *b))
{
assert(list && compar);
qsort(list->items, list->count, sizeof(void*), compar);
}
/* vim: set ts=8 sw=4 tw=0 :*/
|