Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOWeakSet.m
Go to the documentation of this file.
1/*
2
3OOWeakSet.m
4
5Written by Jens Ayton in 2012 for Oolite.
6This code is hereby placed in the public domain.
7
8*/
9
10#import "OOWeakSet.h"
11
12
13
14@interface OOWeakRefUnpackingEnumerator: NSEnumerator
15{
16@private
17 NSEnumerator *_enumerator;
18}
19
20- (id) initWithEnumerator:(NSEnumerator *)enumerator;
21
22+ (instancetype) enumeratorWithCollection:(id)collection; // Collection must implement -objectEnumerator
23
24@end
25
26
27@interface OOWeakSet (OOPrivate)
28
29- (void) compact; // Remove any zeroed entries.
30
31@end
32
33
34@implementation OOWeakSet
35
36- (id) init
37{
38 return [self initWithCapacity:0];
39}
40
41
42- (id) initWithCapacity:(NSUInteger)capacity
43{
44 if ((self = [super init]))
45 {
46 _objects = [[NSMutableSet alloc] initWithCapacity:capacity];
47 if (_objects == NULL)
48 {
49 [self release];
50 return nil;
51 }
52 }
53 return self;
54}
55
56
57+ (instancetype) set
58{
59 return [[[self alloc] init] autorelease];
60}
61
62
63+ (instancetype) setWithCapacity:(NSUInteger)capacity
64{
65 return [[[self alloc] initWithCapacity:capacity] autorelease];
66}
67
68
69- (void) dealloc
70{
71 DESTROY(_objects);
72
73 [super dealloc];
74}
75
76
77- (NSString *) description
78{
79 NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p>{", [self class], self];
80 NSEnumerator *selfEnum = [self objectEnumerator];
81 id object = nil;
82 BOOL first = YES;
83 while ((object = [selfEnum nextObject]))
84 {
85 if (!first) [result appendString:@", "];
86 else first = NO;
87
88 NSString *desc = nil;
89 if ([object respondsToSelector:@selector(shortDescription)]) desc = [object shortDescription];
90 else desc = [object description];
91
92 [result appendString:desc];
93 }
94
95 [result appendString:@"}"];
96 return result;
97}
98
99
100// MARK: Protocol conformance
101
102- (id) copyWithZone:(NSZone *)zone
103{
104 [self compact];
105 OOWeakSet *result = [[OOWeakSet allocWithZone:zone] init];
106 [result addObjectsByEnumerating:[self objectEnumerator]];
107 return result;
108}
109
110
111- (id) mutableCopyWithZone:(NSZone *)zone
112{
113 return [self copyWithZone:zone];
114}
115
116
117- (BOOL) isEqual:(id)other
118{
119 if (![other isKindOfClass:[OOWeakSet class]]) return NO;
120 if ([self count] != [other count]) return NO;
121
122 BOOL result = YES;
123 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
124 NSEnumerator *selfEnum = [self objectEnumerator];
125 id object = nil;
126 while ((object = [selfEnum nextObject]))
127 {
128 if (![other containsObject:object])
129 {
130 result = NO;
131 break;
132 }
133 }
134 DESTROY(pool);
135
136 return result;
137}
138
139
140// MARK: Meat and potatoes
141
142- (NSUInteger) count
143{
144 [self compact];
145 return [_objects count];
146}
147
148
149- (BOOL) containsObject:(id<OOWeakReferenceSupport>)object
150{
151 [self compact];
152 OOWeakReference *weakObj = [object weakRetain];
153 BOOL result = [_objects containsObject:weakObj];
154 [weakObj release];
155 return result;
156}
157
158
159- (NSEnumerator *) objectEnumerator
160{
162}
163
164
165- (void) addObject:(id<OOWeakReferenceSupport>)object
166{
167 if (object == nil) return;
168 NSAssert([object conformsToProtocol:@protocol(OOWeakReferenceSupport)], @"Attempt to add object to OOWeakSet which does not conform to OOWeakReferenceSupport.");
169
170 OOWeakReference *weakObj = [object weakRetain];
171 [_objects addObject:weakObj];
172 [weakObj release];
173}
174
175
176- (void) removeObject:(id<OOWeakReferenceSupport>)object
177{
178 OOWeakReference *weakObj = [object weakRetain];
179 [_objects removeObject:weakObj];
180 [weakObj release];
181}
182
183
184- (void) addObjectsByEnumerating:(NSEnumerator *)enumerator
185{
186 id object = nil;
187 [self compact];
188 while ((object = [enumerator nextObject]))
189 {
190 [self addObject:object];
191 }
192}
193
194
195- (void) makeObjectsPerformSelector:(SEL)selector
196{
197 OOWeakReference *weakRef = nil;
198 foreach (weakRef, _objects)
199 {
200 [[weakRef weakRefUnderlyingObject] performSelector:selector];
201 }
202}
203
204
205- (void) makeObjectsPerformSelector:(SEL)selector withObject:(id)argument
206{
207 OOWeakReference *weakRef = nil;
208 foreach (weakRef, _objects)
209 {
210 [[weakRef weakRefUnderlyingObject] performSelector:selector withObject:argument];
211 }
212}
213
214
215- (NSArray *) allObjects
216{
217 NSMutableArray *result = [NSMutableArray arrayWithCapacity:[_objects count]];
218 OOWeakReference *weakRef = nil;
219 foreach (weakRef, _objects)
220 {
221 id object = [weakRef weakRefUnderlyingObject];
222 if (object != nil) [result addObject:object];
223 }
224
225#ifdef NDEBUG
226 return result;
227#else
228 return [NSArray arrayWithArray:result];
229#endif
230}
231
232
233- (void) removeAllObjects
234{
235 [_objects removeAllObjects];
236}
237
238
239- (void) compact
240{
241 OOWeakReference *weakRef = nil;
242 BOOL compactRequired = NO;
243 foreach (weakRef, _objects)
244 {
245 if ([weakRef weakRefUnderlyingObject] == nil)
246 {
247 compactRequired = YES;
248 break;
249 }
250 }
251
252 if (compactRequired)
253 {
254 NSMutableSet *newObjects = [[NSMutableSet alloc] initWithCapacity:[_objects count]];
255 foreach (weakRef, _objects)
256 {
257 if ([weakRef weakRefUnderlyingObject] != nil)
258 {
259 [newObjects addObject:weakRef];
260 }
261 }
262
263 [_objects release];
264 _objects = newObjects;
265 }
266}
267
268@end
269
270
271@implementation OOWeakRefUnpackingEnumerator
272
273- (id) initWithEnumerator:(NSEnumerator *)enumerator
274{
275 if (enumerator == nil)
276 {
277 [self release];
278 return nil;
279 }
280
281 if ((self = [super init]))
282 {
283 _enumerator = [enumerator retain];
284 }
285
286 return self;
287}
288
289
290+ (instancetype) enumeratorWithCollection:(id)collection
291{
292 return [[[self alloc] initWithEnumerator:[collection objectEnumerator]] autorelease];
293}
294
295
296- (void) dealloc
297{
298 [_enumerator release];
299
300 [super dealloc];
301}
302
303
304- (id) nextObject
305{
306 id next = nil;
307 while ((next = [_enumerator nextObject]))
308 {
309 next = [next weakRefUnderlyingObject];
310 if (next != nil) return next;
311 }
312
313 return nil;
314}
315
316@end
#define DESTROY(x)
Definition OOCocoa.h:77
unsigned count
return nil
instancetype enumeratorWithCollection:(id collection)
Definition OOWeakSet.m:290
NSEnumerator * _enumerator
Definition OOWeakSet.m:17
void addObjectsByEnumerating:(NSEnumerator *enumerator)
Definition OOWeakSet.m:184
id initWithCapacity:(NSUInteger capacity)
Definition OOWeakSet.m:42