]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSSet.cpp
06c2d9037ad61872be13b2ba585597e3f4727d09
[apple/xnu.git] / libkern / c++ / OSSet.cpp
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
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
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* IOSet.m created by rsulack on Thu 11-Jun-1998 */
24
25 #include <libkern/c++/OSDictionary.h>
26 #include <libkern/c++/OSArray.h>
27 #include <libkern/c++/OSSerialize.h>
28 #include <libkern/c++/OSSet.h>
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
42 #define EXT_CAST(obj) \
43 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
44
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,
59 unsigned int inCapacity)
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,
84 unsigned int inCapacity)
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,
94 unsigned int inCapacity)
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)) {
104 me->release();
105 return 0;
106 }
107
108 return me;
109 }
110
111 OSSet *OSSet::withObjects(const OSObject *objects[],
112 unsigned int count,
113 unsigned int capacity)
114 {
115 OSSet *me = new OSSet;
116
117 if (me && !me->initWithObjects(objects, count, capacity)) {
118 me->release();
119 return 0;
120 }
121
122 return me;
123 }
124
125 OSSet *OSSet::withArray(const OSArray *array,
126 unsigned int capacity)
127 {
128 OSSet *me = new OSSet;
129
130 if (me && !me->initWithArray(array, capacity)) {
131 me->release();
132 return 0;
133 }
134
135 return me;
136 }
137
138 OSSet *OSSet::withSet(const OSSet *set,
139 unsigned int capacity)
140 {
141 OSSet *me = new OSSet;
142
143 if (me && !me->initWithSet(set, capacity)) {
144 me->release();
145 return 0;
146 }
147
148 return me;
149 }
150
151 void OSSet::free()
152 {
153 (void) members->super::setOptions(0, kImmutable);
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 {
215 return merge(set->members);
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 }
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 }