Objectively
Object oriented framework for C.
Loading...
Searching...
No Matches
List.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include "Config.h"
25
26#include <assert.h>
27#include <stdlib.h>
28
29#include "List.h"
30
31#define _Class _List
32
33#pragma mark - Object
34
41static Object *copy(const Object *self) {
42
43 const List *this = (List *) self;
44
45 List *copy = $(alloc(List), init);
46 assert(copy);
47
48 for (ListNode *node = this->head; node; node = node->next) {
49 $(copy, append, node->element);
50 }
51
52 return (Object *) copy;
53}
54
58static void dealloc(Object *self) {
59
60 List *this = (List *) self;
61 $(this, removeAll);
62
63 super(Object, self, dealloc);
64}
65
66#pragma mark - List
67
72static void append(List *self, const ident element) {
73
74 ListNode *node = calloc(1, sizeof(ListNode));
75 assert(node);
76
77 node->element = element;
78 node->prev = self->tail;
79
80 if (self->tail) {
81 self->tail->next = node;
82 } else {
83 self->head = node;
84 }
85
86 self->tail = node;
87 self->count++;
88}
89
94static bool contains(const List *self, const ident element) {
95 return $(self, nodeForElement, element) != NULL;
96}
97
102static void enumerate(const List *self, ListEnumerator enumerator, ident element) {
103
104 assert(enumerator);
105
106 for (ListNode *node = self->head; node; ) {
107 ListNode *next = node->next;
108 if (enumerator(self, node, element)) {
109 break;
110 }
111 node = next;
112 }
113}
114
119static void filter(List *self, Predicate predicate, ident data) {
120
121 assert(predicate);
122
123 for (ListNode *node = self->head; node; ) {
124 ListNode *next = node->next;
125 if (!predicate(node->element, data)) {
126 $(self, removeNode, node);
127 }
128 node = next;
129 }
130}
131
136static List *filteredList(const List *self, Predicate predicate, ident data) {
137
138 assert(predicate);
139
140 List *list = $(alloc(List), init);
141 for (ListNode *node = self->head; node; node = node->next) {
142 if (predicate(node->element, data)) {
143 $(list, append, node->element);
144 }
145 }
146
147 return list;
148}
149
154static ident find(const List *self, Predicate predicate, ident data) {
155
156 assert(predicate);
157
158 for (ListNode *node = self->head; node; node = node->next) {
159 if (predicate(node->element, data)) {
160 return node->element;
161 }
162 }
163
164 return NULL;
165}
166
167
168
173static List *init(List *self) {
174
175 self = (List *) super(Object, self, init);
176 return self;
177}
178
183static void insertAfter(List *self, ListNode *node, const ident element) {
184
185 if (node == NULL || node == self->tail) {
186 $(self, append, element);
187 return;
188 }
189
190 ListNode *newNode = calloc(1, sizeof(ListNode));
191 assert(newNode);
192
193 newNode->element = element;
194 newNode->prev = node;
195 newNode->next = node->next;
196
197 if (node->next) {
198 node->next->prev = newNode;
199 }
200 node->next = newNode;
201
202 self->count++;
203}
204
209static void map(List *self, Functor functor, ident data) {
210
211 assert(functor);
212
213 for (ListNode *node = self->head; node; node = node->next) {
214 node->element = functor(node->element, data);
215 }
216}
217
222static List *mappedList(const List *self, Functor functor, ident data) {
223
224 assert(functor);
225
226 List *list = $(alloc(List), init);
227 for (ListNode *node = self->head; node; node = node->next) {
228 $(list, append, functor(node->element, data));
229 }
230
231 return list;
232}
233
238static ListNode *nodeForElement(const List *self, const ident element) {
239
240 for (ListNode *node = self->head; node; node = node->next) {
241 if (node->element == element) {
242 return node;
243 }
244 }
245
246 return NULL;
247}
248
253static void prepend(List *self, const ident element) {
254
255 ListNode *node = calloc(1, sizeof(ListNode));
256 assert(node);
257
258 node->element = element;
259 node->next = self->head;
260
261 if (self->head) {
262 self->head->prev = node;
263 } else {
264 self->tail = node;
265 }
266
267 self->head = node;
268 self->count++;
269}
270
275static ident reduce(const List *self, Reducer reducer, ident accumulator, ident data) {
276
277 assert(reducer);
278
279 for (ListNode *node = self->head; node; node = node->next) {
280 accumulator = reducer(node->element, accumulator, data);
281 }
282
283 return accumulator;
284}
285
290static void removeAll(List *self) {
291
292 ListNode *node = self->head;
293 while (node) {
294 ListNode *next = node->next;
295 if (self->destroy) {
296 self->destroy(node->element);
297 }
298 free(node);
299 node = next;
300 }
301
302 self->head = self->tail = NULL;
303 self->count = 0;
304}
305
310static void _remove(List *self, const ident element) {
311
312 ListNode *node = $(self, nodeForElement, element);
313 if (node) {
314 $(self, removeNode, node);
315 }
316}
317
322static void removeNode(List *self, ListNode *node) {
323
324 assert(node);
325
326 if (node->prev) {
327 node->prev->next = node->next;
328 } else {
329 self->head = node->next;
330 }
331
332 if (node->next) {
333 node->next->prev = node->prev;
334 } else {
335 self->tail = node->prev;
336 }
337
338 if (self->destroy) {
339 self->destroy(node->element);
340 }
341
342 free(node);
343 self->count--;
344}
345
350static void _sort(List *self, Comparator comparator) {
351
352 assert(comparator);
353
354 if (self->count < 2) {
355 return;
356 }
357
358 for (ListNode *node = self->head->next; node; ) {
359 ListNode *next = node->next;
360 ident key = node->element;
361
362 ListNode *j = node->prev;
363 while (j && comparator(j->element, key) > OrderSame) {
364 j->next->element = j->element;
365 j = j->prev;
366 }
367
368 (j ? j->next : self->head)->element = key;
369 node = next;
370 }
371}
372
373#pragma mark - Class lifecycle
374
378static void initialize(Class *clazz) {
379
380 ((ObjectInterface *) clazz->interface)->copy = copy;
381 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
382
383 ((ListInterface *) clazz->interface)->append = append;
384 ((ListInterface *) clazz->interface)->contains = contains;
385 ((ListInterface *) clazz->interface)->enumerate = enumerate;
386 ((ListInterface *) clazz->interface)->filter = filter;
387 ((ListInterface *) clazz->interface)->filteredList = filteredList;
388 ((ListInterface *) clazz->interface)->find = find;
389 ((ListInterface *) clazz->interface)->init = init;
390 ((ListInterface *) clazz->interface)->insertAfter = insertAfter;
391 ((ListInterface *) clazz->interface)->map = map;
392 ((ListInterface *) clazz->interface)->mappedList = mappedList;
393 ((ListInterface *) clazz->interface)->nodeForElement = nodeForElement;
394 ((ListInterface *) clazz->interface)->prepend = prepend;
395 ((ListInterface *) clazz->interface)->reduce = reduce;
396 ((ListInterface *) clazz->interface)->removeAll = removeAll;
397 ((ListInterface *) clazz->interface)->remove = _remove;
398 ((ListInterface *) clazz->interface)->removeNode = removeNode;
399 ((ListInterface *) clazz->interface)->sort = _sort;
400}
401
406Class *_List(void) {
407 static Class *clazz;
408 static Once once;
409
410 do_once(&once, {
411 clazz = _initialize(&(const ClassDef) {
412 .name = "List",
413 .superclass = _Object(),
414 .instanceSize = sizeof(List),
415 .interfaceSize = sizeof(ListInterface),
416 .initialize = initialize,
417 });
418 });
419
420 return clazz;
421}
422
423#undef _Class
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:151
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:226
#define super(type, obj, method,...)
static Data * data(void)
Definition Data.c:286
static void prepend(List *self, const ident element)
Definition List.c:253
static bool contains(const List *self, const ident element)
Definition List.c:94
static List * init(List *self)
Definition List.c:173
Class * _List(void)
Definition List.c:406
static ident find(const List *self, Predicate predicate, ident data)
Definition List.c:154
static void _remove(List *self, const ident element)
Definition List.c:310
static List * mappedList(const List *self, Functor functor, ident data)
Definition List.c:222
static void removeAll(List *self)
Definition List.c:290
static void insertAfter(List *self, ListNode *node, const ident element)
Definition List.c:183
static void removeNode(List *self, ListNode *node)
Definition List.c:322
static void map(List *self, Functor functor, ident data)
Definition List.c:209
static void filter(List *self, Predicate predicate, ident data)
Definition List.c:119
static void _sort(List *self, Comparator comparator)
Definition List.c:350
static void dealloc(Object *self)
Definition List.c:58
static ListNode * nodeForElement(const List *self, const ident element)
Definition List.c:238
static void append(List *self, const ident element)
Definition List.c:72
static ident reduce(const List *self, Reducer reducer, ident accumulator, ident data)
Definition List.c:275
static void enumerate(const List *self, ListEnumerator enumerator, ident element)
Definition List.c:102
static Object * copy(const Object *self)
Definition List.c:41
static void initialize(Class *clazz)
Definition List.c:378
static List * filteredList(const List *self, Predicate predicate, ident data)
Definition List.c:136
Doubly-linked lists of raw C pointers.
bool(* ListEnumerator)(const List *list, ListNode *node, ident data)
The ListEnumerator function type.
Definition List.h:44
Class * _Object(void)
Definition Object.c:136
static int head(RESTClient *self, const char *url, const char **headers)
Definition RESTClient.c:188
static Unicode next(StringReader *self, StringReaderMode mode)
void * ident
The identity type, similar to Objective-C id.
Definition Types.h:49
bool(* Predicate)(const ident obj, ident data)
The Predicate function type for filtering Objects.
Definition Types.h:111
Order(* Comparator)(const ident obj1, const ident obj2)
The Comparator function type for ordering Objects.
Definition Types.h:82
ident(* Functor)(const ident obj, ident data)
The Functor function type for transforming Objects.
Definition Types.h:103
ident(* Reducer)(const ident obj, ident accumulator, ident data)
The Reducer function type for reducing collections.
Definition Types.h:127
@ OrderSame
Definition Types.h:72
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
The runtime representation of a Class.
Definition Class.h:90
ident interface
The interface of the Class.
Definition Class.h:100
Doubly-linked lists of raw C pointers.
Definition List.h:60
ident find(const List *self, Predicate predicate, ident data)
Definition List.c:154
ListNode * head
The head node.
Definition List.h:81
size_t count
The number of elements.
Definition List.h:76
Consumer destroy
Optional destructor called when an element is removed.
Definition List.h:91
ListNode * tail
The tail node.
Definition List.h:86
ListNode * nodeForElement(const List *self, const ident element)
Definition List.c:238
void insertAfter(List *self, ListNode *node, const ident element)
Inserts an element after the given node.
Definition List.c:183
A node in a List.
Definition List.h:49
ListNode * prev
Definition List.h:51
ident element
Definition List.h:50
ListNode * next
Definition List.h:52
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
void dealloc(Object *self)
Frees all resources held by this Object.
Definition Array.c:99