Objectively 1.0.0
Ultra-lightweight object oriented framework for GNU C.
Set.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 <assert.h>
25#include <stdarg.h>
26#include <stdlib.h>
27
28#include "Hash.h"
29#include "MutableArray.h"
30#include "MutableSet.h"
31#include "Set.h"
32#include "String.h"
33
34#define _Class _Set
35
36#pragma mark - Object
37
41static Object *copy(const Object *self) {
42
43 const Set *this = (Set *) self;
44
45 Set *that = $(alloc(Set), initWithSet, this);
46
47 return (Object *) that;
48}
49
53static void dealloc(Object *self) {
54
55 Set *this = (Set *) self;
56
57 for (size_t i = 0; i < this->capacity; i++) {
58 release(this->elements[i]);
59 }
60
61 free(this->elements);
62
63 super(Object, self, dealloc);
64}
65
69static String *description(const Object *self) {
70
71 const Array *array = $((Set *) self, allObjects);
72
73 return $((Object *) array, description);
74}
75
79static int hash(const Object *self) {
80
81 const Set *this = (Set *) self;
82
83 int hash = HashForInteger(HASH_SEED, this->count);
84
85 for (size_t i = 0; i < this->capacity; i++) {
86 if (this->elements[i]) {
87 hash = HashForObject(hash, this->elements[i]);
88 }
89 }
90
91 return hash;
92}
93
97static _Bool isEqual(const Object *self, const Object *other) {
98
99 if (super(Object, self, isEqual, other)) {
100 return true;
101 }
102
103 if (other && (self->clazz == other->clazz)) {
104
105 const Set *this = (Set *) self;
106 const Set *that = (Set *) other;
107
108 if (this->count == that->count) {
109
110 Array *objects = $(this, allObjects);
111
112 for (size_t i = 0; i < objects->count; i++) {
113 const ident obj = $(objects, objectAtIndex, i);
114
115 if ($(that, containsObject, obj) == false) {
116 release(objects);
117 return false;
118 }
119 }
120
121 release(objects);
122 return true;
123 }
124 }
125
126 return false;
127}
128
129#pragma mark - Set
130
136}
137
142static Array *allObjects(const Set *self) {
143
145
146 $(self, enumerateObjects, allObjects_enumerator, objects);
147
148 return (Array *) objects;
149}
150
155static _Bool containsObject(const Set *self, const ident obj) {
156
157 if (self->capacity) {
158 const size_t bin = HashForObject(HASH_SEED, obj) % self->capacity;
159
160 const Array *array = self->elements[bin];
161 if (array) {
162 return $(array, containsObject, obj);
163 }
164 }
165
166 return false;
167}
168
173static _Bool containsObjectMatching(const Set *self, Predicate predicate, ident data) {
174
175 assert(predicate);
176
177 for (size_t i = 0; i < self->capacity; i++) {
178
179 Array *array = self->elements[i];
180 if (array) {
181
182 for (size_t j = 0; j < array->count; j++) {
183 if (predicate($(array, objectAtIndex, j), data)) {
184 return true;
185 }
186 }
187 }
188 }
189
190 return false;
191}
192
197static void enumerateObjects(const Set *self, SetEnumerator enumerator, ident data) {
198
199 assert(enumerator);
200
201 for (size_t i = 0; i < self->capacity; i++) {
202
203 Array *array = self->elements[i];
204 if (array) {
205
206 for (size_t j = 0; j < array->count; j++) {
207 enumerator(self, $(array, objectAtIndex, j), data);
208 }
209 }
210 }
211}
212
217static Set *filteredSet(const Set *self, Predicate predicate, ident data) {
218
219 assert(predicate);
220
222
223 for (size_t i = 0; i < self->capacity; i++) {
224
225 Array *array = self->elements[i];
226 if (array) {
227
228 for (size_t j = 0; j < array->count; j++) {
229 ident obj = $(array, objectAtIndex, j);
230
231 if (predicate(obj, data)) {
232 $(set, addObject, obj);
233 }
234 }
235 }
236 }
237
238 return (Set *) set;
239}
240
246}
247
252static Set *initWithArray(Set *self, const Array *array) {
253
254 self = (Set *) super(Object, self, init);
255 if (self) {
256 if (array) {
258 }
259 }
260
261 return self;
262}
263
268static Set *initWithObjects(Set *self, ...) {
269
270 self = (Set *) super(Object, self, init);
271 if (self) {
272
273 va_list args;
274 va_start(args, self);
275
276 while (true) {
277
278 ident obj = va_arg(args, ident);
279 if (obj) {
280 $$(MutableSet, addObject, (MutableSet *) self, obj);
281 } else {
282 break;
283 }
284 }
285
286 va_end(args);
287 }
288
289 return self;
290}
291
297}
298
303static Set *initWithSet(Set *self, const Set *set) {
304
305 self = (Set *) super(Object, self, init);
306 if (self) {
307 if (set) {
309 }
310 }
311
312 return self;
313}
314
319static Set *mappedSet(const Set *self, Functor functor, ident data) {
320
321 assert(functor);
322
324 assert(set);
325
326 for (size_t i = 0; i < self->capacity; i++) {
327
328 const Array *array = self->elements[i];
329 if (array) {
330
331 for (size_t j = 0; j < array->count; j++) {
332
333 ident obj = functor(array->elements[j], data);
334
335 $(set, addObject, obj);
336
337 release(obj);
338 }
339 }
340 }
341
342 return (Set *) set;
343}
344
349static MutableSet *mutableCopy(const Set *self) {
350
352 assert(copy);
353
354 $(copy, addObjectsFromSet, self);
355 return copy;
356}
357
362static ident reduce(const Set *self, Reducer reducer, ident accumulator, ident data) {
363
364 assert(reducer);
365
366 for (size_t i = 0; i < self->capacity; i++) {
367
368 const Array *array = self->elements[i];
369 if (array) {
370
371 for (size_t j = 0; j < array->count; j++) {
372 accumulator = reducer(array->elements[j], accumulator, data);
373 }
374 }
375 }
376
377 return accumulator;
378}
379
384static Set *setWithArray(const Array *array) {
385
386 return $(alloc(Set), initWithArray, array);
387}
388
394
395 Set *set = (Set *) $((Object *) alloc(Set), init);
396 if (set) {
397
398 va_list args;
399 va_start(args, obj);
400
401 while (obj) {
403 obj = va_arg(args, ident);
404 }
405
406 va_end(args);
407 }
408
409 return set;
410}
411
416static Set *setWithSet(const Set *set) {
417
418 return $(alloc(Set), initWithSet, set);
419}
420
421#pragma mark - Class lifecycle
422
426static void initialize(Class *clazz) {
427
428 ((ObjectInterface *) clazz->interface)->copy = copy;
429 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
430 ((ObjectInterface *) clazz->interface)->description = description;
431 ((ObjectInterface *) clazz->interface)->hash = hash;
432 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
433
434 ((SetInterface *) clazz->interface)->allObjects = allObjects;
435 ((SetInterface *) clazz->interface)->containsObject = containsObject;
436 ((SetInterface *) clazz->interface)->containsObjectMatching = containsObjectMatching;
437 ((SetInterface *) clazz->interface)->enumerateObjects = enumerateObjects;
438 ((SetInterface *) clazz->interface)->filteredSet = filteredSet;
439 ((SetInterface *) clazz->interface)->initWithArray = initWithArray;
440 ((SetInterface *) clazz->interface)->initWithSet = initWithSet;
441 ((SetInterface *) clazz->interface)->initWithObjects = initWithObjects;
442 ((SetInterface *) clazz->interface)->mappedSet = mappedSet;
443 ((SetInterface *) clazz->interface)->mutableCopy = mutableCopy;
444 ((SetInterface *) clazz->interface)->reduce = reduce;
445 ((SetInterface *) clazz->interface)->setWithArray = setWithArray;
446 ((SetInterface *) clazz->interface)->setWithObjects = setWithObjects;
447 ((SetInterface *) clazz->interface)->setWithSet = setWithSet;
448}
449
454Class *_Set(void) {
455 static Class *clazz;
456 static Once once;
457
458 do_once(&once, {
459 clazz = _initialize(&(const ClassDef) {
460 .name = "Set",
461 .superclass = _Object(),
462 .instanceSize = sizeof(Set),
463 .interfaceOffset = offsetof(Set, interface),
464 .interfaceSize = sizeof(SetInterface),
466 });
467 });
468
469 return clazz;
470}
471
472#undef _Class
473
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
#define obj
#define alloc(type)
Allocate and initialize and instance of type.
Definition: Class.h:159
#define super(type, obj, method,...)
int HashForInteger(int hash, const long integer)
Accumulates the hash value of integer into hash.
Definition: Hash.c:62
int HashForObject(int hash, const ident obj)
Accumulates the hash value of object into hash.
Definition: Hash.c:66
Utilities for calculating hash values.
#define HASH_SEED
The hash seed value.
Definition: Hash.h:37
Mutable arrays.
Mutable sets.
static void initWithArray_enumerator(const Array *array, ident obj, ident data)
ArrayEnumerator for initWithArray.
Definition: Set.c:244
static void allObjects_enumerator(const Set *set, ident obj, ident data)
SetEnumerator for allObjects.
Definition: Set.c:134
static void initialize(Class *clazz)
Definition: Set.c:426
static void initWithSet_enumerator(const Set *set, ident obj, ident data)
SetEnumerator for initWithSet.
Definition: Set.c:295
Immutable sets.
void(* SetEnumerator)(const Set *set, ident obj, ident data)
A function pointer for Set enumeration (iteration).
Definition: Set.h:48
Immutable 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
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
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
Array * initWithObjects(Array *self,...)
Initializes this Array to contain the Objects in the NULL-terminated arguments list.
Definition: Array.c:312
ident reduce(const Array *self, Reducer reducer, ident accumulator, ident data)
Definition: Array.c:405
MutableArray * mutableCopy(const Array *self)
Definition: Array.c:381
void enumerateObjects(const Array *self, ArrayEnumerator enumerator, ident data)
Enumerate the elements of this Array with the given function.
Definition: Array.c:217
Array * initWithArray(Array *self, const Array *array)
Initializes this Array to contain the Objects in array.
Definition: Array.c:288
ident objectAtIndex(const Array *self, int index)
_Bool containsObject(const Array *self, const ident obj)
Definition: Array.c:208
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
Array * allObjects(const Dictionary *self)
Definition: Dictionary.c:189
Mutable arrays.
Definition: MutableArray.h:40
void addObject(MutableArray *self, const ident obj)
Adds the specified Object to this MutableArray.
Definition: MutableArray.c:99
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
MutableData * data(void)
Returns a new MutableData.
Definition: MutableData.c:75
Mutable sets.
Definition: MutableSet.h:40
void addObjectsFromSet(MutableSet *self, const Set *set)
Adds the Objects contained in set to this Set.
Definition: MutableSet.c:144
MutableSet * set(void)
Returns a new MutableSet.
Definition: MutableSet.c:259
Object is the root Class of The Objectively Class hierarchy.
Definition: Object.h:46
Class * clazz
Every instance of Object begins with a pointer to its Class.
Definition: Object.h:51
Class * _Object(void)
The Object archetype.
Definition: Object.c:136
Object * copy(const Object *self)
Creates a shallow copy of this Object.
Definition: Array.c:40
String * description(const Object *self)
Definition: Array.c:66
_Bool isEqual(const Object *self, const Object *other)
Tests equality of the other Object.
Definition: Array.c:96
int hash(const Object *self)
Definition: Array.c:80
void dealloc(Object *self)
Frees all resources held by this Object.
Definition: Array.c:50
Immutable sets.
Definition: Set.h:55
Set * setWithSet(const Set *set)
Returns a new Set with the contents of set.
Definition: Set.c:416
size_t count
The count of elements.
Definition: Set.h:77
Set * initWithObjects(Set *self,...)
Initializes this Set with the specified objects.
Definition: Set.c:268
Set * mappedSet(const Set *self, Functor functor, ident data)
Transforms the elements in this Set by functor.
Definition: Set.c:319
Set * initWithArray(Set *self, const Array *array)
Initializes this Set to contain the Objects in array.
Definition: Set.c:252
Set * initWithSet(Set *self, const Set *set)
Initializes this Set to contain the Objects in set.
Definition: Set.c:303
MutableSet * mutableCopy(const Set *self)
Definition: Set.c:349
Set * setWithObjects(ident obj,...)
Returns a new Set containing the specified Objects.
Definition: Set.c:393
Set * filteredSet(const Set *self, Predicate predicate, ident data)
Creates a new Set with elements that pass predicate.
Definition: Set.c:217
Class * _Set(void)
The Set archetype.
Definition: Set.c:454
_Bool containsObjectMatching(const Set *self, Predicate predicate, ident data)
Definition: Set.c:173
Set * setWithArray(const Array *array)
Returns a new Set with the contents of array.
Definition: Set.c:384
Immutable UTF-8 strings.
Definition: String.h:69