Oolite 1.91.0.7644-241112-7f5034b
Loading...
Searching...
No Matches
OODeepCopy.m
Go to the documentation of this file.
1/*
2
3OODeepCopy.m
4
5
6Copyright (C) 2009-2013 Jens Ayton
7
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in all
16copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24SOFTWARE.
25
26*/
27
28#import "OODeepCopy.h"
29
30
31id OODeepCopy(id object)
32{
33 NSAutoreleasePool *pool = nil;
34 NSMutableSet *objects = nil;
35
36 if (object == nil) return nil;
37
38 pool = [[NSAutoreleasePool alloc] init];
39 objects = [NSMutableSet set];
40
41 object = [object ooDeepCopyWithSharedObjects:objects];
42
43 [pool release];
44
45 return object;
46}
47
48
49@implementation NSObject (OODeepCopy)
50
51- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
52{
53 if ([self conformsToProtocol:@protocol(NSCopying)])
54 {
55 return [self copy];
56 }
57 else
58 {
59 return [self retain];
60 }
61}
62
63@end
64
65
66@implementation NSString (OODeepCopy)
67
68- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
69{
70 NSUInteger length = [self length];
71 if (length == 0) return [[NSString string] retain];
72 if (length > 128) return [self copy];
73
74 id object = [objects member:self];
75 if (object != nil && [object isKindOfClass:[NSString class]])
76 {
77 return [object retain];
78 }
79 else
80 {
81 object = [self copy];
82 [objects addObject:object];
83 return object;
84 }
85}
86
87@end
88
89
90@implementation NSValue (OODeepCopy) // Includes NSNumber
91
92- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
93{
94 id object = [objects member:self];
95 if (object != nil && [object isKindOfClass:[NSValue class]])
96 {
97 return [object retain];
98 }
99 else
100 {
101 object = [self copy];
102 [objects addObject:object];
103 return object;
104 }
105}
106
107@end
108
109
110@implementation NSArray (OODeepCopy)
111
112- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
113{
114 NSUInteger i, count;
115 id *members = NULL;
116 NSArray *result = nil;
117 BOOL tempObjects = NO;
118
119 count = [self count];
120 if (count == 0) return [[NSArray array] retain];
121
122 members = calloc(sizeof *members, count);
123 if (members == NULL)
124 {
125 [NSException raise:NSMallocException format:@"Failed to allocate space for %lu objects in %s.", (unsigned long)count, __PRETTY_FUNCTION__];
126 }
127
128 // Ensure there's an objects set even if passed nil.
129 if (objects == nil)
130 {
131 objects = [[NSMutableSet alloc] init];
132 tempObjects = YES;
133 }
134
135 [self getObjects:members];
136 @try
137 {
138 // Deep copy members.
139 for (i = 0; i < count; i++)
140 {
141 members[i] = [members[i] ooDeepCopyWithSharedObjects:objects];
142 }
143
144 // Make NSArray of results.
145 result = [[NSArray alloc] initWithObjects:members count:count];
146 }
147 @finally
148 {
149 // Release objects.
150 for (i = 0; i < count; i++)
151 {
152 [members[i] release];
153 }
154
155 free(members);
156 if (tempObjects) [objects release];
157 }
158
159 // Collections are not reused because comparing them is arbitrarily slow.
160 return result;
161}
162
163@end
164
165
166@implementation NSSet (OODeepCopy)
167
168- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
169{
170 NSUInteger i, count;
171 id *members = NULL;
172 NSSet *result = nil;
173 BOOL tempObjects = NO;
174
175 count = [self count];
176 if (count == 0) return [[NSSet set] retain];
177
178 members = malloc(sizeof *members * count);
179 if (members == NULL)
180 {
181 [NSException raise:NSMallocException format:@"Failed to allocate space for %lu objects in %s.", (unsigned long)count, __PRETTY_FUNCTION__];
182 }
183
184 // Ensure there's an objects set even if passed nil.
185 if (objects == nil)
186 {
187 objects = [[NSMutableSet alloc] init];
188 tempObjects = YES;
189 }
190
191 @try
192 {
193 i = 0;
194 id member = nil;
195 // Deep copy members.
196 foreach (member, self)
197 {
198 members[i] = [member ooDeepCopyWithSharedObjects:objects];
199 i++;
200 }
201
202 // Make NSSet of results.
203 result = [[NSSet alloc] initWithObjects:members count:count];
204 }
205 @finally
206 {
207 // Release objects.
208 for (i = 0; i < count; i++)
209 {
210 [members[i] release];
211 }
212
213 free(members);
214 if (tempObjects) [objects release];
215 }
216
217 // Collections are not reused because comparing them is arbitrarily slow.
218 return result;
219}
220
221@end
222
223
224@implementation NSDictionary (OODeepCopy)
225
226- (id) ooDeepCopyWithSharedObjects:(NSMutableSet *)objects
227{
228 NSUInteger i, count;
229 id *keys = NULL;
230 id *values = NULL;
231 NSDictionary *result = nil;
232 BOOL tempObjects = NO;
233
234 count = [self count];
235 if (count == 0) return [[NSDictionary dictionary] retain];
236
237 keys = malloc(sizeof *keys * count);
238 values = malloc(sizeof *values * count);
239 if (keys == NULL || values == NULL)
240 {
241 free(keys);
242 free(values);
243 [NSException raise:NSMallocException format:@"Failed to allocate space for %lu objects in %s.", (unsigned long)count, __PRETTY_FUNCTION__];
244 }
245
246 // Ensure there's an objects set even if passed nil.
247 if (objects == nil)
248 {
249 objects = [[NSMutableSet alloc] init];
250 tempObjects = YES;
251 }
252
253 @try
254 {
255 i = 0;
256 id key = nil;
257 // Deep copy members.
258 foreachkey (key, self)
259 {
260 keys[i] = [key ooDeepCopyWithSharedObjects:objects];
261 values[i] = [[self objectForKey:key] ooDeepCopyWithSharedObjects:objects];
262 i++;
263 }
264
265 // Make NSDictionary of results.
266 result = [[NSDictionary alloc] initWithObjects:values forKeys:keys count:count];
267 }
268 @finally
269 {
270 // Release objects.
271 for (i = 0; i < count; i++)
272 {
273 [keys[i] release];
274 [values[i] release];
275 }
276
277 free(keys);
278 free(values);
279 if (tempObjects) [objects release];
280 }
281
282 // Collections are not reused because comparing them is arbitrarily slow.
283 return result;
284}
285
286@end
#define foreachkey(VAR, DICT)
Definition OOCocoa.h:366
id OODeepCopy(id object)
Definition OODeepCopy.m:31
unsigned count
return nil