Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
Vector.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#include <string.h>
29
30#include "Hash.h"
31#include "Vector.h"
32
33#define _Class _Vector
34
35#define VECTOR_CHUNK_SIZE 64
36
37#pragma mark - Object
38
42static Object *copy(const Object *self) {
43
44 const Vector *this = (Vector *) self;
45
46 Vector *that = $(alloc(Vector), initWithSize, this->size);
47
48 free(that->elements);
49 that->elements = malloc(this->capacity * this->size);
50 assert(that->elements);
51 memcpy(that->elements, this->elements, this->count * this->size);
52 that->count = this->count;
53 that->capacity = this->capacity;
54 that->destroy = this->destroy;
55
56 return (Object *) that;
57}
58
62static void dealloc(Object *self) {
63
64 Vector *this = (Vector *) self;
65
66 $(this, removeAll);
67
68 free(this->elements);
69
70 super(Object, self, dealloc);
71}
72
76static int hash(const Object *self) {
77
78 Vector *this = (Vector *) self;
79
80 const Range range = {
81 .location = 0,
82 .length = this->count * this->size
83 };
84
85 return HashForBytes(HASH_SEED, this->elements, range);
86}
87
91static bool isEqual(const Object *self, const Object *other) {
92
93 if (super(Object, self, isEqual, other)) {
94 return true;
95 }
96
97 if (other && $(other, isKindOfClass, _Vector())) {
98
99 const Vector *this = (Vector *) self;
100 const Vector *that = (Vector *) other;
101
102 if (this->count == that->count) {
103 return memcmp(this->elements, that->elements, this->count * this->size) == 0;
104 }
105 }
106
107 return false;
108}
109
110#pragma mark - Vector
111
116static void add(Vector *self, const ident element) {
117
118 if (self->count == self->capacity) {
119
121
122 if (self->elements) {
123 self->elements = realloc(self->elements, self->capacity * self->size);
124 } else {
125 self->elements = calloc(self->capacity, self->size);
126 }
127
128 assert(self->elements);
129 }
130
131 memcpy(self->elements + self->count * self->size, element, self->size);
132 self->count++;
133}
134
139static void enumerate(const Vector *self, VectorEnumerator enumerator, ident data) {
140
141 assert(enumerator);
142
143 for (size_t i = 0; i < self->count; i++) {
144 enumerator(self, self->elements + i * self->size, data);
145 }
146}
147
152static void filter(Vector *self, Predicate predicate, ident data) {
153
154 assert(predicate);
155
156 for (size_t i = 0; i < self->count; i++) {
157 if (!predicate(self->elements + i * self->size, data)) {
158 $(self, removeAt, i);
159 }
160 }
161}
162
167static ident find(const Vector *self, Predicate predicate, ident data) {
168
169 assert(predicate);
170
171 for (size_t i = 0; i < self->count; i++) {
172 if (predicate(self->elements + i * self->size, data)) {
173 return self->elements + i * self->size;
174 }
175 }
176
177 return NULL;
178}
179
184static ssize_t indexOf(const Vector *self, const ident element) {
185
186 for (size_t i = 0; i < self->count; i++) {
187 if (memcmp(self->elements + i * self->size, element, self->size) == 0) {
188 return i;
189 }
190 }
191
192 return -1;
193}
194
199static Vector *initWithElements(Vector *self, size_t size, size_t count, ident elements) {
200
201 self = $(self, initWithSize, size);
202 if (self) {
203 self->count = count;
204 self->elements = elements;
205 }
206
207 return self;
208}
209
214static Vector *initWithSize(Vector *self, size_t size) {
215
216 self = (Vector *) super(Object, self, init);
217 if (self) {
218 self->size = size;
219 assert(self->size);
220 }
221 return self;
222}
223
228static void insert(Vector *self, const ident element, size_t index) {
229
230 assert(index <= self->count);
231
232 $(self, add, element);
233
234 for (size_t i = self->count - 1; i > index; i--) {
235 memcpy(self->elements + i * self->size, self->elements + (i - 1) * self->size, self->size);
236 }
237
238 memcpy(self->elements + index * self->size, element, self->size);
239}
240
245static Vector *mappedVector(const Vector *self, Functor functor, ident data) {
246
247 assert(functor);
248
249 Vector *vector = $(alloc(Vector), initWithSize, self->size);
250 for (size_t i = 0; i < self->count; i++) {
251 ident result = functor(self->elements + i * self->size, data);
252 $(vector, add, result);
253 }
254 return vector;
255}
256
261static ident reduce(const Vector *self, Reducer reducer, ident accumulator, ident data) {
262
263 assert(reducer);
264
265 for (size_t i = 0; i < self->count; i++) {
266 accumulator = reducer(self->elements + i * self->size, accumulator, data);
267 }
268
269 return accumulator;
270}
271
276static void removeAll(Vector *self) {
277
278 if (self->destroy) {
279 for (size_t i = 0; i < self->count; i++) {
280 self->destroy(self->elements + i * self->size);
281 }
282 }
283
284 self->count = 0;
285}
286
291static void removeAt(Vector *self, size_t index) {
292
293 assert(index < self->count);
294
295 if (self->destroy) {
296 self->destroy(self->elements + index * self->size);
297 }
298
299 const size_t size = (self->count - index - 1) * self->size;
300
301 memmove(self->elements + index * self->size, self->elements + (index + 1) * self->size, size);
302
303 self->count--;
304}
305
310static void resize(Vector *self, size_t capacity) {
311
312 if (self->destroy) {
313 for (size_t i = capacity; i < self->count; i++) {
314 self->destroy(self->elements + i * self->size);
315 }
316 }
317
318 self->elements = realloc(self->elements, capacity * self->size);
319 assert(self->elements);
320
321 self->capacity = capacity;
322 self->count = min(self->count, self->capacity);
323}
324
325#if defined(__APPLE__)
326
330static int _sort(void *data, const void *a, const void *b) {
331 return ((Comparator) data)((const ident) a, (const ident) b);
332}
333
338static void sort(Vector *self, Comparator comparator) {
339 qsort_r(self->elements, self->count, self->size, comparator, _sort);
340}
341
342#elif defined(_WIN32)
343
347static int _sort(void *data, const void *a, const void *b) {
348 return ((Comparator) data)(((const ident) a), ((const ident) b));
349}
350
355static void sort(Vector *self, Comparator comparator) {
356 qsort_s(self->elements, self->count, self->size, _sort, comparator);
357}
358
359#else
360
364static int _sort(const void *a, const void *b, void *data) {
365 return ((Comparator) data)(((const ident) a), ((const ident) b));
366}
367
372static void sort(Vector *self, Comparator comparator) {
373 qsort_r(self->elements, self->count, self->size, _sort, comparator);
374}
375
376#endif
377
382static Vector *vectorWithElements(size_t size, size_t count, ident elements) {
383 return $(alloc(Vector), initWithElements, size, count, elements);
384}
385
390static Vector *vectorWithSize(size_t size) {
391 return $(alloc(Vector), initWithSize, size);
392}
393
394#pragma mark - Class lifecycle
395
399static void initialize(Class *clazz) {
400
401 ((ObjectInterface *) clazz->interface)->copy = copy;
402 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
403 ((ObjectInterface *) clazz->interface)->hash = hash;
404 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
405
406 ((VectorInterface *) clazz->interface)->add = add;
407 ((VectorInterface *) clazz->interface)->enumerate = enumerate;
408 ((VectorInterface *) clazz->interface)->filter = filter;
409 ((VectorInterface *) clazz->interface)->find = find;
410 ((VectorInterface *) clazz->interface)->indexOf = indexOf;
411 ((VectorInterface *) clazz->interface)->initWithElements = initWithElements;
412 ((VectorInterface *) clazz->interface)->initWithSize = initWithSize;
413 ((VectorInterface *) clazz->interface)->insert = insert;
414 ((VectorInterface *) clazz->interface)->mappedVector = mappedVector;
415 ((VectorInterface *) clazz->interface)->reduce = reduce;
416 ((VectorInterface *) clazz->interface)->removeAll = removeAll;
417 ((VectorInterface *) clazz->interface)->removeAt = removeAt;
418 ((VectorInterface *) clazz->interface)->resize = resize;
419 ((VectorInterface *) clazz->interface)->sort = sort;
420 ((VectorInterface *) clazz->interface)->vectorWithElements = vectorWithElements;
421 ((VectorInterface *) clazz->interface)->vectorWithSize = vectorWithSize;
422}
423
429 static Class *clazz;
430 static Once once;
431
432 do_once(&once, {
433 clazz = _initialize(&(const ClassDef) {
434 .name = "Vector",
435 .superclass = _Object(),
436 .instanceSize = sizeof(Vector),
437 .interfaceOffset = offsetof(Vector, interface),
438 .interfaceSize = sizeof(VectorInterface),
440 });
441 });
442
443 return clazz;
444}
445
446#undef _Class
static Array * init(Array *self)
Definition Array.c:420
static void destroy(Class *clazz)
Definition Boole.c:102
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:86
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:176
#define super(type, obj, method,...)
static Data * data(void)
Definition Data.c:286
int HashForBytes(int hash, const uint8_t *bytes, const Range range)
Accumulates the hash value of bytes into hash.
Definition Hash.c:28
Utilities for calculating hash values.
#define HASH_SEED
The hash seed value.
Definition Hash.h:37
static bool isKindOfClass(const Object *self, const Class *clazz)
Definition Object.c:101
Class * _Object(void)
Definition Object.c:136
UTF-8 strings.
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
#define min(a, b)
Definition Types.h:159
ident(* Reducer)(const ident obj, ident accumulator, ident data)
The Reducer function type for reducing collections.
Definition Types.h:127
static ident reduce(const Vector *self, Reducer reducer, ident accumulator, ident data)
Definition Vector.c:261
static ident find(const Vector *self, Predicate predicate, ident data)
Definition Vector.c:167
static void removeAt(Vector *self, size_t index)
Definition Vector.c:291
static void add(Vector *self, const ident element)
Definition Vector.c:116
static bool isEqual(const Object *self, const Object *other)
Definition Vector.c:91
static void removeAll(Vector *self)
Definition Vector.c:276
static void resize(Vector *self, size_t capacity)
Definition Vector.c:310
static Vector * initWithSize(Vector *self, size_t size)
Definition Vector.c:214
static void filter(Vector *self, Predicate predicate, ident data)
Definition Vector.c:152
static Vector * initWithElements(Vector *self, size_t size, size_t count, ident elements)
Definition Vector.c:199
static ssize_t indexOf(const Vector *self, const ident element)
Definition Vector.c:184
Class * _Vector(void)
Definition Vector.c:428
static void enumerate(const Vector *self, VectorEnumerator enumerator, ident data)
Definition Vector.c:139
static Vector * vectorWithElements(size_t size, size_t count, ident elements)
Definition Vector.c:382
static Vector * vectorWithSize(size_t size)
Definition Vector.c:390
static void insert(Vector *self, const ident element, size_t index)
Definition Vector.c:228
static void dealloc(Object *self)
Definition Vector.c:62
static Vector * mappedVector(const Vector *self, Functor functor, ident data)
Definition Vector.c:245
static int _sort(const void *a, const void *b, void *data)
qsort_r comparator.
Definition Vector.c:364
static Object * copy(const Object *self)
Definition Vector.c:42
static void initialize(Class *clazz)
Definition Vector.c:399
#define VECTOR_CHUNK_SIZE
Definition Vector.c:35
static void sort(Vector *self, Comparator comparator)
Definition Vector.c:372
static int hash(const Object *self)
Definition Vector.c:76
Mutable contiguous storage for C types.
void(* VectorEnumerator)(const Vector *vector, ident obj, ident data)
The VectorEnumerator function type.
Definition Vector.h:44
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:95
ident interface
The interface of the Class.
Definition Class.h:105
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
A location and length into contiguous collections.
Definition Types.h:54
ssize_t location
The location.
Definition Types.h:59
Vectors.
Definition Vector.h:51
ident reduce(const Vector *self, Reducer reducer, ident accumulator, ident data)
Definition Vector.c:261
Consumer destroy
Optional destructor called when an element is removed.
Definition Vector.h:90
Vector * vectorWithSize(size_t size)
Creates a new Vector with the specified element size.
Definition Vector.c:390
void insert(Vector *self, const ident element, size_t index)
Inserts the element at the specified index.
Definition Vector.c:228
Vector * initWithSize(Vector *self, size_t size)
Initializes this Vector with the specified element size.
Definition Vector.c:214
size_t count
The count of elements.
Definition Vector.h:72
size_t capacity
The capacity.
Definition Vector.h:67
ident elements
The elements.
Definition Vector.h:82
size_t size
The size of each element.
Definition Vector.h:77