Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
MutableArray.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 <stdarg.h>
28#include <stdlib.h>
29
30#include "MutableArray.h"
31
32#if defined(__APPLE__)
33
37static int _quicksort(void *data, const void *a, const void *b) {
38 return ((Comparator) data)(*((const ident *) a), *((const ident *) b));
39}
40
41void quicksort(ident base, size_t count, size_t size, Comparator comparator, ident data) {
42 qsort_r(base, count, size, comparator, _quicksort);
43}
44
45#elif defined(_WIN32)
46
50static int _quicksort(void *data, const void *a, const void *b) {
51 return ((Comparator) data)(*((const ident *) a), *((const ident *) b));
52}
53
54void quicksort(ident base, size_t count, size_t size, Comparator comparator, ident data) {
55 qsort_s(base, count, size, _quicksort, comparator);
56}
57
58#else
59
63static int _quicksort(const void *a, const void *b, void *data) {
64 return ((Comparator) data)(*((const ident *) a), *((const ident *) b));
65}
66
67void quicksort(ident base, size_t count, size_t size, Comparator comparator, ident data) {
68 qsort_r(base, count, size, _quicksort, comparator);
69}
70
71#endif
72
73#define _Class _MutableArray
74
75#define ARRAY_CHUNK_SIZE 64
76
77#pragma mark - Object
78
82static Object *copy(const Object *self) {
83
84 Array *this = (Array *) self;
85
87
88 $(copy, addObjectsFromArray, this);
89
90 return (Object *) copy;
91}
92
93#pragma mark - MutableArray
94
99static void addObject(MutableArray *self, const ident obj) {
100
101 Array *array = (Array *) self;
102 if (array->count == self->capacity) {
103
104 self->capacity += ARRAY_CHUNK_SIZE;
105
106 if (array->elements) {
107 array->elements = realloc(array->elements, self->capacity * sizeof(ident));
108 } else {
109 array->elements = calloc(self->capacity, sizeof(ident));
110 }
111
112 assert(array->elements);
113 }
114
115 array->elements[array->count++] = retain(obj);
116}
117
122static void addObjects(MutableArray *self, const ident obj, ...) {
123
124 va_list args;
125 va_start(args, obj);
126
127 ident object = obj;
128 while (object) {
129 $(self, addObject, object);
130 object = va_arg(args, ident);
131 }
132
133 va_end(args);
134}
135
140static void addObjectsFromArray(MutableArray *self, const Array *array) {
141
142 if (array) {
143 for (size_t i = 0; i < array->count; i++) {
144 $(self, addObject, array->elements[i]);
145 }
146 }
147}
148
153static MutableArray *array(void) {
154
155 return $(alloc(MutableArray), init);
156}
157
162static MutableArray *arrayWithCapacity(size_t capacity) {
163
164 return $(alloc(MutableArray), initWithCapacity, capacity);
165}
166
171static void filter(MutableArray *self, Predicate predicate, ident data) {
172
173 assert(predicate);
174
175 for (size_t i = 0; i < self->array.count; i++) {
176 if (predicate(self->array.elements[i], data) == false) {
177 $(self, removeObjectAtIndex, i--);
178 }
179 }
180}
181
187
188 return $(self, initWithCapacity, 0);
189}
190
195static MutableArray *initWithCapacity(MutableArray *self, size_t capacity) {
196
197 self = (MutableArray *) super(Object, self, init);
198 if (self) {
199
200 self->capacity = capacity;
201 if (self->capacity) {
202
203 self->array.elements = calloc(self->capacity, sizeof(ident));
204 assert(self->array.elements);
205 }
206 }
207
208 return self;
209}
210
215static void insertObjectAtIndex(MutableArray *self, ident obj, size_t index) {
216
217 assert(index <= self->array.count);
218
219 $(self, addObject, obj);
220
221 for (size_t i = self->array.count - 1; i > index; i--) {
222 self->array.elements[i] = self->array.elements[i - 1];
223 }
224
225 self->array.elements[index] = obj;
226}
227
232static void removeAllObjects(MutableArray *self) {
233
234 while (self->array.count) {
235 $(self, removeLastObject);
236 }
237}
238
244
245 assert(enumerator);
246
247 while (self->array.count) {
248
249 enumerator((Array *) self, $((Array *) self, lastObject), data);
250
251 $(self, removeLastObject);
252 }
253}
254
259static void removeLastObject(MutableArray *self) {
260
261 if (self->array.count) {
262 $(self, removeObjectAtIndex, self->array.count - 1);
263 }
264}
265
270static void removeObject(MutableArray *self, const ident obj) {
271
272 const ssize_t index = $((Array *) self, indexOfObject, obj);
273 if (index > -1) {
274 $(self, removeObjectAtIndex, index);
275 }
276}
277
282static void removeObjectAtIndex(MutableArray *self, size_t index) {
283
284 assert(index < self->array.count);
285
286 release(self->array.elements[index]);
287
288 for (size_t i = index; i < self->array.count - 1; i++) {
289 self->array.elements[i] = self->array.elements[i + 1];
290 }
291
292 self->array.count--;
293}
294
299static void setObjectAtIndex(MutableArray *self, const ident obj, size_t index) {
300
301 assert(index < self->array.count);
302
303 retain(obj);
304
305 release(self->array.elements[index]);
306
307 self->array.elements[index] = obj;
308}
309
314static void sort(MutableArray *self, Comparator comparator) {
315 quicksort(self->array.elements, self->array.count, sizeof(ident), comparator, NULL);
316}
317
318#pragma mark - Class lifecycle
319
323static void initialize(Class *clazz) {
324
325 ((ObjectInterface *) clazz->interface)->copy = copy;
326
327 ((MutableArrayInterface *) clazz->interface)->addObject = addObject;
328 ((MutableArrayInterface *) clazz->interface)->addObjects = addObjects;
329 ((MutableArrayInterface *) clazz->interface)->addObjectsFromArray = addObjectsFromArray;
330 ((MutableArrayInterface *) clazz->interface)->array = array;
331 ((MutableArrayInterface *) clazz->interface)->arrayWithCapacity = arrayWithCapacity;
332 ((MutableArrayInterface *) clazz->interface)->filter = filter;
333 ((MutableArrayInterface *) clazz->interface)->init = init;
334 ((MutableArrayInterface *) clazz->interface)->initWithCapacity = initWithCapacity;
335 ((MutableArrayInterface *) clazz->interface)->insertObjectAtIndex = insertObjectAtIndex;
336 ((MutableArrayInterface *) clazz->interface)->removeAllObjects = removeAllObjects;
337 ((MutableArrayInterface *) clazz->interface)->removeAllObjectsWithEnumerator = removeAllObjectsWithEnumerator;
338 ((MutableArrayInterface *) clazz->interface)->removeLastObject = removeLastObject;
339 ((MutableArrayInterface *) clazz->interface)->removeObject = removeObject;
340 ((MutableArrayInterface *) clazz->interface)->removeObjectAtIndex = removeObjectAtIndex;
341 ((MutableArrayInterface *) clazz->interface)->setObjectAtIndex = setObjectAtIndex;
342 ((MutableArrayInterface *) clazz->interface)->sort = sort;
343}
344
350 static Class *clazz;
351 static Once once;
352
353 do_once(&once, {
354 clazz = _initialize(&(const ClassDef) {
355 .name = "MutableArray",
356 .superclass = _Array(),
357 .instanceSize = sizeof(MutableArray),
358 .interfaceOffset = offsetof(MutableArray, interface),
359 .interfaceSize = sizeof(MutableArrayInterface),
361 });
362 });
363
364 return clazz;
365}
366
367#undef _Class
void(* ArrayEnumerator)(const Array *array, ident obj, ident data)
A function pointer for Array enumeration (iteration).
Definition: Array.h:49
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition: Class.c:196
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition: Class.c:91
ident retain(ident obj)
Atomically increment the given Object's reference count.
Definition: Class.c:211
#define obj
#define alloc(type)
Allocate and initialize and instance of type.
Definition: Class.h:159
#define super(type, obj, method,...)
void quicksort(ident base, size_t count, size_t size, Comparator comparator, ident data)
A portability wrapper around reentrant qsort.
Definition: MutableArray.c:67
#define ARRAY_CHUNK_SIZE
Definition: MutableArray.c:75
static int _quicksort(const void *a, const void *b, void *data)
GNU qsort_r.
Definition: MutableArray.c:63
static void initialize(Class *clazz)
Definition: MutableArray.c:323
Mutable arrays.
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
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
Immutable arrays.
Definition: Array.h:56
Class * _Array(void)
The Array archetype.
Definition: Array.c:470
ident lastObject(const Array *self)
Definition: Array.c:349
ssize_t indexOfObject(const Array *self, const ident obj)
Definition: Array.c:271
size_t count
The count of elements.
Definition: Array.h:72
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:95
ident interface
The interface of the Class.
Definition: Class.h:105
Condition * init(Condition *self)
Initializes this Condition.
Definition: Condition.c:67
Mutable arrays.
Definition: MutableArray.h:40
void removeAllObjectsWithEnumerator(MutableArray *self, ArrayEnumerator enumerator, ident data)
Removes all Objects from this MutableArray, invoking enumerator for each Object.
Definition: MutableArray.c:243
void removeObjectAtIndex(MutableArray *self, size_t index)
Removes the Object at the specified index.
Definition: MutableArray.c:282
void removeLastObject(MutableArray *self)
Removes the last Object from this MutableArray.
Definition: MutableArray.c:259
Array array
The superclass.
Definition: MutableArray.h:45
void filter(MutableArray *self, Predicate predicate, ident data)
Filters this MutableArray in place using predicate.
Definition: MutableArray.c:171
void setObjectAtIndex(MutableArray *self, const ident obj, size_t index)
Replaces the Object at the specified index.
Definition: MutableArray.c:299
MutableArray * arrayWithCapacity(size_t capacity)
Returns a new MutableArray with the given capacity.
Definition: MutableArray.c:162
void addObjects(MutableArray *self, const ident obj,...)
Adds the specified objects to this Array.
Definition: MutableArray.c:122
void addObject(MutableArray *self, const ident obj)
Adds the specified Object to this MutableArray.
Definition: MutableArray.c:99
void insertObjectAtIndex(MutableArray *self, ident obj, size_t index)
Inserts the Object at the specified index.
Definition: MutableArray.c:215
void sort(MutableArray *self, Comparator comparator)
Sorts this MutableArray in place using comparator.
Definition: MutableArray.c:314
void removeAllObjects(MutableArray *self)
Removes all Objects from this MutableArray.
Definition: MutableArray.c:232
void removeObject(MutableArray *self, const ident obj)
Removes the specified Object from this MutableArray.
Definition: MutableArray.c:270
Class * _MutableArray(void)
The MutableArray archetype.
Definition: MutableArray.c:349
MutableArray * array(void)
Returns a new MutableArray.
Definition: MutableArray.c:153
MutableArray * initWithCapacity(MutableArray *self, size_t capacity)
Initializes this MutableArray with the specified capacity.
Definition: MutableArray.c:195
void addObjectsFromArray(MutableArray *self, const Array *array)
Adds the Objects contained in array to this MutableArray.
Definition: MutableArray.c:140
MutableData * data(void)
Returns a new MutableData.
Definition: MutableData.c:75
Object is the root Class of The Objectively Class hierarchy.
Definition: Object.h:46
Object * copy(const Object *self)
Creates a shallow copy of this Object.
Definition: Array.c:40