list.c (4206B) download
1#include "list.h"
2
3#include <dirent.h>
4#include <errno.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/types.h>
9
10#define DIE_RETURN(err) \
11 { \
12 errno = (err); \
13 return -1; \
14 }
15
16#define DIE_RETURN_NULL(err) \
17 { \
18 errno = (err); \
19 return NULL; \
20 }
21
22
23struct list {
24 size_t length;
25 size_t capacity;
26 size_t element_size;
27 char* array;
28
29 list_malloc_t malloc;
30 list_realloc_t realloc;
31 list_free_t free;
32};
33
34struct list_iter {
35 list_t* list;
36 size_t current;
37};
38
39static size_t translate_index(list_t* this, ssize_t index) {
40 if (index >= 0)
41 return index;
42
43 return this->length + index;
44}
45
46list_t* list(size_t element_size, list_malloc_t list_malloc, list_realloc_t list_realloc, list_free_t list_free) {
47 list_t* this;
48
49 if ((this = list_malloc(sizeof(list_t))) == NULL)
50 return NULL;
51
52 this->length = 0;
53 this->capacity = LIST_DEFAULT_CAPACITY;
54 this->element_size = element_size;
55
56 this->malloc = list_malloc;
57 this->realloc = list_realloc;
58 this->free = list_free;
59
60 if ((this->array = this->malloc(this->capacity)) == NULL)
61 DIE_RETURN_NULL(ENOMEM);
62
63 return this;
64}
65
66list_t* list_default_alloc(size_t element_size) {
67 list_t* this;
68
69 if ((this = malloc(sizeof(list_t))) == NULL)
70 return NULL;
71
72 this->length = 0;
73 this->capacity = LIST_DEFAULT_CAPACITY;
74 this->element_size = element_size;
75
76 this->malloc = malloc;
77 this->realloc = realloc;
78 this->free = free;
79
80 if ((this->array = this->malloc(this->capacity)) == NULL)
81 DIE_RETURN_NULL(ENOMEM);
82
83 return this;
84}
85
86void list_free(list_t* this) {
87 list_free_t list_free = this->free;
88
89 list_free(this->array);
90 list_free(this);
91}
92
93int list_grow(list_t* this, size_t new_length) {
94 if (new_length <= this->capacity)
95 return 0;
96
97 void* new_array;
98
99 if ((new_array = realloc(this->array, this->capacity * LIST_GROW)) == NULL)
100 DIE_RETURN(ENOMEM);
101
102 this->capacity *= LIST_GROW;
103 this->array = new_array;
104
105 return 0;
106}
107
108int list_add(list_t* this, void* element) {
109 if (list_grow(this, this->length + 1) == -1)
110 return -1;
111
112 memcpy(&this->array[this->length++ * this->element_size], element, this->element_size);
113
114 return 0;
115}
116
117
118void* list_get(list_t* this, ssize_t index) {
119 index = translate_index(this, index);
120
121 return &this->array[index * this->element_size];
122}
123
124void* list_get_copy(list_t* this, ssize_t index) {
125 void* element;
126
127 index = translate_index(this, index);
128
129 if ((element = this->malloc(this->element_size)) == NULL)
130 DIE_RETURN_NULL(ENOMEM);
131
132 memcpy(element, list_get(this, index), this->element_size);
133
134 return element;
135}
136
137int list_shrink(list_t* this, size_t new_length) {
138 if (new_length >= this->capacity / LIST_GROW)
139 return 0;
140
141 void* new_array;
142
143 if ((new_array = realloc(this->array, this->capacity / LIST_GROW)) == NULL)
144 DIE_RETURN(ENOMEM);
145
146 this->capacity /= LIST_GROW;
147 this->array = new_array;
148
149 return 0;
150}
151
152int list_remove(list_t* this, ssize_t index) {
153 index = translate_index(this, index);
154
155 memmove(list_get(this, index + 1), list_get(this, index + 1), --this->length - index);
156
157 return list_shrink(this, this->length);
158}
159
160void* list_remove_copy(list_t* this, ssize_t index) {
161 void* element;
162
163 index = translate_index(this, index);
164
165 if ((element = list_get_copy(this, index)) == NULL)
166 return NULL;
167
168 memmove(list_get(this, index + 1), list_get(this, index + 1), --this->length - index);
169
170 if (list_shrink(this, this->length) == -1)
171 return NULL;
172
173 return element;
174}
175
176
177size_t list_length(list_t* this) {
178 return this->length;
179}
180
181size_t list_capacity(list_t* this) {
182 return this->capacity;
183}
184
185list_iter_t* list_iter(list_t* this) {
186 list_iter_t* iter;
187
188 if ((iter = malloc(sizeof(list_iter_t))) == NULL)
189 return NULL;
190
191 iter->list = this;
192 iter->current = 0;
193
194 return iter;
195}
196
197int list_iter_has_next(list_iter_t* iter) {
198 return iter->current < iter->list->length;
199}
200
201void* list_iter_next(list_iter_t* iter) {
202 return list_get(iter->list, iter->current++);
203}
204
205void* list_iter_next_copy(list_iter_t* iter) {
206 return list_get_copy(iter->list, iter->current++);
207}
208
209void list_iter_free(list_iter_t* iter) {
210 list_free_t list_free = iter->list->free;
211
212 list_free(iter);
213}