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