]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
ff6e181a A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
1c79356b | 12 | * |
ff6e181a A |
13 | * The Original Code and all software distributed under the License are |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
ff6e181a A |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
1c79356b A |
20 | * |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | /* IOSet.m created by rsulack on Thu 11-Jun-1998 */ | |
24 | ||
91447636 | 25 | #include <libkern/c++/OSDictionary.h> |
1c79356b A |
26 | #include <libkern/c++/OSArray.h> |
27 | #include <libkern/c++/OSSerialize.h> | |
91447636 | 28 | #include <libkern/c++/OSSet.h> |
1c79356b A |
29 | |
30 | #define super OSCollection | |
31 | ||
32 | OSDefineMetaClassAndStructors(OSSet, OSCollection) | |
33 | OSMetaClassDefineReservedUnused(OSSet, 0); | |
34 | OSMetaClassDefineReservedUnused(OSSet, 1); | |
35 | OSMetaClassDefineReservedUnused(OSSet, 2); | |
36 | OSMetaClassDefineReservedUnused(OSSet, 3); | |
37 | OSMetaClassDefineReservedUnused(OSSet, 4); | |
38 | OSMetaClassDefineReservedUnused(OSSet, 5); | |
39 | OSMetaClassDefineReservedUnused(OSSet, 6); | |
40 | OSMetaClassDefineReservedUnused(OSSet, 7); | |
41 | ||
91447636 A |
42 | #define EXT_CAST(obj) \ |
43 | reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj)) | |
44 | ||
1c79356b A |
45 | bool OSSet::initWithCapacity(unsigned int inCapacity) |
46 | { | |
47 | if ( !super::init() ) | |
48 | return false; | |
49 | ||
50 | members = OSArray::withCapacity(inCapacity); | |
51 | if (!members) | |
52 | return false; | |
53 | ||
54 | return true; | |
55 | } | |
56 | ||
57 | bool OSSet::initWithObjects(const OSObject *inObjects[], | |
58 | unsigned int inCount, | |
55e303ae | 59 | unsigned int inCapacity) |
1c79356b A |
60 | { |
61 | unsigned int capacity = inCount; | |
62 | ||
63 | if ( inCapacity ) { | |
64 | if ( inCount > inCapacity ) | |
65 | return false; | |
66 | ||
67 | capacity = inCapacity; | |
68 | } | |
69 | ||
70 | if (!inObjects || !initWithCapacity(capacity)) | |
71 | return false; | |
72 | ||
73 | for ( unsigned int i = 0; i < inCount; i++ ) { | |
74 | if (members->getCount() < inCapacity) | |
75 | setObject(inObjects[i]); | |
76 | else | |
77 | return false; | |
78 | } | |
79 | ||
80 | return true; | |
81 | } | |
82 | ||
83 | bool OSSet::initWithArray(const OSArray *inArray, | |
55e303ae | 84 | unsigned int inCapacity) |
1c79356b A |
85 | { |
86 | if ( !inArray ) | |
87 | return false; | |
88 | ||
89 | return initWithObjects((const OSObject **) inArray->array, | |
90 | inArray->count, inCapacity); | |
91 | } | |
92 | ||
93 | bool OSSet::initWithSet(const OSSet *inSet, | |
55e303ae | 94 | unsigned int inCapacity) |
1c79356b A |
95 | { |
96 | return initWithArray(inSet->members, inCapacity); | |
97 | } | |
98 | ||
99 | OSSet *OSSet::withCapacity(unsigned int capacity) | |
100 | { | |
101 | OSSet *me = new OSSet; | |
102 | ||
103 | if (me && !me->initWithCapacity(capacity)) { | |
55e303ae | 104 | me->release(); |
1c79356b A |
105 | return 0; |
106 | } | |
107 | ||
108 | return me; | |
109 | } | |
110 | ||
111 | OSSet *OSSet::withObjects(const OSObject *objects[], | |
112 | unsigned int count, | |
55e303ae | 113 | unsigned int capacity) |
1c79356b A |
114 | { |
115 | OSSet *me = new OSSet; | |
116 | ||
117 | if (me && !me->initWithObjects(objects, count, capacity)) { | |
55e303ae | 118 | me->release(); |
1c79356b A |
119 | return 0; |
120 | } | |
121 | ||
122 | return me; | |
123 | } | |
124 | ||
125 | OSSet *OSSet::withArray(const OSArray *array, | |
55e303ae | 126 | unsigned int capacity) |
1c79356b A |
127 | { |
128 | OSSet *me = new OSSet; | |
129 | ||
130 | if (me && !me->initWithArray(array, capacity)) { | |
55e303ae | 131 | me->release(); |
1c79356b A |
132 | return 0; |
133 | } | |
134 | ||
135 | return me; | |
136 | } | |
137 | ||
138 | OSSet *OSSet::withSet(const OSSet *set, | |
55e303ae | 139 | unsigned int capacity) |
1c79356b A |
140 | { |
141 | OSSet *me = new OSSet; | |
142 | ||
143 | if (me && !me->initWithSet(set, capacity)) { | |
55e303ae | 144 | me->release(); |
1c79356b A |
145 | return 0; |
146 | } | |
147 | ||
148 | return me; | |
149 | } | |
150 | ||
151 | void OSSet::free() | |
152 | { | |
91447636 | 153 | (void) members->super::setOptions(0, kImmutable); |
1c79356b A |
154 | if (members) |
155 | members->release(); | |
156 | ||
157 | super::free(); | |
158 | } | |
159 | ||
160 | unsigned int OSSet::getCount() const | |
161 | { | |
162 | return members->count; | |
163 | } | |
164 | ||
165 | unsigned int OSSet::getCapacity() const | |
166 | { | |
167 | return members->capacity; | |
168 | } | |
169 | ||
170 | unsigned int OSSet::getCapacityIncrement() const | |
171 | { | |
172 | return members->capacityIncrement; | |
173 | } | |
174 | ||
175 | unsigned int OSSet::setCapacityIncrement(unsigned int increment) | |
176 | { | |
177 | return members->setCapacityIncrement(increment); | |
178 | } | |
179 | ||
180 | unsigned int OSSet::ensureCapacity(unsigned int newCapacity) | |
181 | { | |
182 | return members->ensureCapacity(newCapacity); | |
183 | } | |
184 | ||
185 | void OSSet::flushCollection() | |
186 | { | |
187 | haveUpdated(); | |
188 | members->flushCollection(); | |
189 | } | |
190 | ||
191 | bool OSSet::setObject(const OSMetaClassBase *anObject) | |
192 | { | |
193 | if (containsObject(anObject)) | |
194 | return false; | |
195 | else { | |
196 | haveUpdated(); | |
197 | return members->setObject(anObject); | |
198 | } | |
199 | } | |
200 | ||
201 | bool OSSet::merge(const OSArray *array) | |
202 | { | |
203 | const OSMetaClassBase *anObject; | |
204 | bool retVal = false; | |
205 | ||
206 | for (int i = 0; (anObject = array->getObject(i)); i++) | |
207 | if (setObject(anObject)) | |
208 | retVal = true; | |
209 | ||
210 | return retVal; | |
211 | } | |
212 | ||
213 | bool OSSet::merge(const OSSet *set) | |
214 | { | |
91447636 | 215 | return merge(set->members); |
1c79356b A |
216 | } |
217 | ||
218 | void OSSet::removeObject(const OSMetaClassBase *anObject) | |
219 | { | |
220 | const OSMetaClassBase *probeObject; | |
221 | ||
222 | for (int i = 0; (probeObject = members->getObject(i)); i++) | |
223 | if (probeObject == anObject) { | |
224 | haveUpdated(); | |
225 | members->removeObject(i); | |
226 | return; | |
227 | } | |
228 | } | |
229 | ||
230 | ||
231 | bool OSSet::containsObject(const OSMetaClassBase *anObject) const | |
232 | { | |
233 | return anObject && member(anObject); | |
234 | } | |
235 | ||
236 | bool OSSet::member(const OSMetaClassBase *anObject) const | |
237 | { | |
238 | OSMetaClassBase *probeObject; | |
239 | ||
240 | for (int i = 0; (probeObject = members->getObject(i)); i++) | |
241 | if (probeObject == anObject) | |
242 | return true; | |
243 | ||
244 | return false; | |
245 | } | |
246 | ||
247 | OSObject *OSSet::getAnyObject() const | |
248 | { | |
249 | return members->getObject(0); | |
250 | } | |
251 | ||
252 | bool OSSet::isEqualTo(const OSSet *aSet) const | |
253 | { | |
254 | unsigned int count; | |
255 | unsigned int i; | |
256 | const OSMetaClassBase *obj1; | |
257 | const OSMetaClassBase *obj2; | |
258 | ||
259 | if ( this == aSet ) | |
260 | return true; | |
261 | ||
262 | count = members->count; | |
263 | if ( count != aSet->getCount() ) | |
264 | return false; | |
265 | ||
266 | for ( i = 0; i < count; i++ ) { | |
267 | obj1 = aSet->members->getObject(i); | |
268 | obj2 = members->getObject(i); | |
269 | if ( !obj1 || !obj2 ) | |
270 | return false; | |
271 | ||
272 | if ( !obj1->isEqualTo(obj2) ) | |
273 | return false; | |
274 | } | |
275 | ||
276 | return true; | |
277 | } | |
278 | ||
279 | bool OSSet::isEqualTo(const OSMetaClassBase *anObject) const | |
280 | { | |
281 | OSSet *otherSet; | |
282 | ||
283 | otherSet = OSDynamicCast(OSSet, anObject); | |
284 | if ( otherSet ) | |
285 | return isEqualTo(otherSet); | |
286 | else | |
287 | return false; | |
288 | } | |
289 | ||
290 | unsigned int OSSet::iteratorSize() const | |
291 | { | |
292 | return sizeof(unsigned int); | |
293 | } | |
294 | ||
295 | bool OSSet::initIterator(void *inIterator) const | |
296 | { | |
297 | unsigned int *iteratorP = (unsigned int *) inIterator; | |
298 | ||
299 | *iteratorP = 0; | |
300 | return true; | |
301 | } | |
302 | ||
303 | bool OSSet::getNextObjectForIterator(void *inIterator, OSObject **ret) const | |
304 | { | |
305 | unsigned int *iteratorP = (unsigned int *) inIterator; | |
306 | unsigned int index = (*iteratorP)++; | |
307 | ||
308 | if (index < members->count) | |
309 | *ret = members->getObject(index); | |
310 | else | |
311 | *ret = 0; | |
312 | ||
313 | return (*ret != 0); | |
314 | } | |
315 | ||
316 | bool OSSet::serialize(OSSerialize *s) const | |
317 | { | |
318 | const OSMetaClassBase *o; | |
319 | ||
320 | if (s->previouslySerialized(this)) return true; | |
321 | ||
322 | if (!s->addXMLStartTag(this, "set")) return false; | |
323 | ||
324 | for (int i = 0; (o = members->getObject(i)); i++) { | |
325 | if (!o->serialize(s)) return false; | |
326 | } | |
327 | ||
328 | return s->addXMLEndTag("set"); | |
329 | } | |
91447636 A |
330 | |
331 | unsigned OSSet::setOptions(unsigned options, unsigned mask, void *) | |
332 | { | |
333 | unsigned old = super::setOptions(options, mask); | |
334 | if ((old ^ options) & mask) | |
335 | members->setOptions(options, mask); | |
336 | ||
337 | return old; | |
338 | } | |
339 | ||
340 | OSCollection * OSSet::copyCollection(OSDictionary *cycleDict) | |
341 | { | |
342 | bool allocDict = !cycleDict; | |
343 | OSCollection *ret = 0; | |
344 | OSSet *newSet = 0; | |
345 | ||
346 | if (allocDict) { | |
347 | cycleDict = OSDictionary::withCapacity(16); | |
348 | if (!cycleDict) | |
349 | return 0; | |
350 | } | |
351 | ||
352 | do { | |
353 | // Check for a cycle | |
354 | ret = super::copyCollection(cycleDict); | |
355 | if (ret) | |
356 | continue; // Found it | |
357 | ||
358 | newSet = OSSet::withCapacity(members->capacity); | |
359 | if (!newSet) | |
360 | continue; // Couldn't create new set abort | |
361 | ||
362 | // Insert object into cycle Dictionary | |
363 | cycleDict->setObject((const OSSymbol *) this, newSet); | |
364 | ||
365 | OSArray *newMembers = newSet->members; | |
366 | newMembers->capacityIncrement = members->capacityIncrement; | |
367 | ||
368 | // Now copy over the contents into the new duplicate | |
369 | for (unsigned int i = 0; i < members->count; i++) { | |
370 | OSObject *obj = EXT_CAST(members->array[i]); | |
371 | OSCollection *coll = OSDynamicCast(OSCollection, obj); | |
372 | if (coll) { | |
373 | OSCollection *newColl = coll->copyCollection(cycleDict); | |
374 | if (newColl) { | |
375 | obj = newColl; // Rely on cycleDict ref for a bit | |
376 | newColl->release(); | |
377 | } | |
378 | else | |
379 | goto abortCopy; | |
380 | }; | |
381 | newMembers->setObject(obj); | |
382 | }; | |
383 | ||
384 | ret = newSet; | |
385 | newSet = 0; | |
386 | ||
387 | } while(false); | |
388 | ||
389 | abortCopy: | |
390 | if (newSet) | |
391 | newSet->release(); | |
392 | ||
393 | if (allocDict) | |
394 | cycleDict->release(); | |
395 | ||
396 | return ret; | |
397 | } |