]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSSet.cpp
xnu-4903.270.47.tar.gz
[apple/xnu.git] / libkern / c++ / OSSet.cpp
CommitLineData
1c79356b 1/*
fe8ab488 2 * Copyright (c) 2000, 2014 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
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. 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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* IOSet.m created by rsulack on Thu 11-Jun-1998 */
29
91447636 30#include <libkern/c++/OSDictionary.h>
1c79356b
A
31#include <libkern/c++/OSArray.h>
32#include <libkern/c++/OSSerialize.h>
91447636 33#include <libkern/c++/OSSet.h>
1c79356b
A
34
35#define super OSCollection
36
37OSDefineMetaClassAndStructors(OSSet, OSCollection)
38OSMetaClassDefineReservedUnused(OSSet, 0);
39OSMetaClassDefineReservedUnused(OSSet, 1);
40OSMetaClassDefineReservedUnused(OSSet, 2);
41OSMetaClassDefineReservedUnused(OSSet, 3);
42OSMetaClassDefineReservedUnused(OSSet, 4);
43OSMetaClassDefineReservedUnused(OSSet, 5);
44OSMetaClassDefineReservedUnused(OSSet, 6);
45OSMetaClassDefineReservedUnused(OSSet, 7);
46
91447636
A
47#define EXT_CAST(obj) \
48 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
49
0a7de745
A
50bool
51OSSet::initWithCapacity(unsigned int inCapacity)
1c79356b 52{
0a7de745
A
53 if (!super::init()) {
54 return false;
55 }
1c79356b 56
0a7de745
A
57 members = OSArray::withCapacity(inCapacity);
58 if (!members) {
59 return false;
60 }
1c79356b 61
0a7de745 62 return true;
1c79356b
A
63}
64
0a7de745
A
65bool
66OSSet::initWithObjects(const OSObject *inObjects[],
67 unsigned int inCount,
68 unsigned int inCapacity)
1c79356b 69{
0a7de745 70 unsigned int capacity = inCount;
1c79356b 71
0a7de745
A
72 if (inCapacity) {
73 if (inCount > inCapacity) {
74 return false;
75 }
1c79356b 76
0a7de745
A
77 capacity = inCapacity;
78 }
1c79356b 79
0a7de745
A
80 if (!inObjects || !initWithCapacity(capacity)) {
81 return false;
82 }
1c79356b 83
0a7de745 84 for (unsigned int i = 0; i < inCount; i++) {
b0d623f7 85// xx-review: no test here for failure of setObject()
0a7de745
A
86 if (members->getCount() < capacity) {
87 setObject(inObjects[i]);
88 } else {
89 return false;
90 }
91 }
1c79356b 92
0a7de745 93 return true;
1c79356b
A
94}
95
0a7de745
A
96bool
97OSSet::initWithArray(const OSArray *inArray,
98 unsigned int inCapacity)
1c79356b 99{
0a7de745
A
100 if (!inArray) {
101 return false;
102 }
103
104 return initWithObjects((const OSObject **) inArray->array,
105 inArray->count, inCapacity);
1c79356b
A
106}
107
0a7de745
A
108bool
109OSSet::initWithSet(const OSSet *inSet,
110 unsigned int inCapacity)
1c79356b 111{
0a7de745 112 return initWithArray(inSet->members, inCapacity);
1c79356b
A
113}
114
0a7de745
A
115OSSet *
116OSSet::withCapacity(unsigned int capacity)
1c79356b 117{
0a7de745 118 OSSet *me = new OSSet;
1c79356b 119
0a7de745
A
120 if (me && !me->initWithCapacity(capacity)) {
121 me->release();
122 return 0;
123 }
1c79356b 124
0a7de745 125 return me;
1c79356b
A
126}
127
0a7de745
A
128OSSet *
129OSSet::withObjects(const OSObject *objects[],
130 unsigned int count,
131 unsigned int capacity)
1c79356b 132{
0a7de745 133 OSSet *me = new OSSet;
1c79356b 134
0a7de745
A
135 if (me && !me->initWithObjects(objects, count, capacity)) {
136 me->release();
137 return 0;
138 }
1c79356b 139
0a7de745 140 return me;
1c79356b
A
141}
142
0a7de745
A
143OSSet *
144OSSet::withArray(const OSArray *array,
145 unsigned int capacity)
1c79356b 146{
0a7de745 147 OSSet *me = new OSSet;
1c79356b 148
0a7de745
A
149 if (me && !me->initWithArray(array, capacity)) {
150 me->release();
151 return 0;
152 }
1c79356b 153
0a7de745 154 return me;
1c79356b
A
155}
156
0a7de745
A
157OSSet *
158OSSet::withSet(const OSSet *set,
159 unsigned int capacity)
1c79356b 160{
0a7de745 161 OSSet *me = new OSSet;
1c79356b 162
0a7de745
A
163 if (me && !me->initWithSet(set, capacity)) {
164 me->release();
165 return 0;
166 }
1c79356b 167
0a7de745 168 return me;
1c79356b
A
169}
170
0a7de745
A
171void
172OSSet::free()
1c79356b 173{
0a7de745
A
174 if (members) {
175 (void) members->super::setOptions(0, kImmutable);
176 members->release();
177 }
1c79356b 178
0a7de745 179 super::free();
1c79356b
A
180}
181
0a7de745
A
182unsigned int
183OSSet::getCount() const
1c79356b 184{
0a7de745 185 return members->count;
1c79356b
A
186}
187
0a7de745
A
188unsigned int
189OSSet::getCapacity() const
1c79356b 190{
0a7de745 191 return members->capacity;
1c79356b
A
192}
193
0a7de745
A
194unsigned int
195OSSet::getCapacityIncrement() const
1c79356b 196{
0a7de745 197 return members->capacityIncrement;
1c79356b
A
198}
199
0a7de745
A
200unsigned int
201OSSet::setCapacityIncrement(unsigned int increment)
1c79356b 202{
0a7de745 203 return members->setCapacityIncrement(increment);
1c79356b
A
204}
205
0a7de745
A
206unsigned int
207OSSet::ensureCapacity(unsigned int newCapacity)
1c79356b 208{
0a7de745 209 return members->ensureCapacity(newCapacity);
1c79356b
A
210}
211
0a7de745
A
212void
213OSSet::flushCollection()
1c79356b 214{
0a7de745
A
215 haveUpdated();
216 members->flushCollection();
1c79356b
A
217}
218
0a7de745
A
219bool
220OSSet::setObject(const OSMetaClassBase *anObject)
1c79356b 221{
0a7de745
A
222 if (containsObject(anObject)) {
223 return false;
224 } else {
225 haveUpdated();
226 return members->setObject(anObject);
227 }
1c79356b
A
228}
229
0a7de745
A
230bool
231OSSet::merge(const OSArray * array)
1c79356b 232{
0a7de745
A
233 const OSMetaClassBase * anObject = 0;
234 bool result = true;
235
236 for (int i = 0; (anObject = array->getObject(i)); i++) {
237 /* setObject() returns false if the object is already in the set,
238 * so we have to check beforehand here with containsObject().
239 */
240 if (containsObject(anObject)) {
241 continue;
242 }
243 if (!setObject(anObject)) {
244 result = false;
245 }
246 }
247
248 return result;
1c79356b
A
249}
250
0a7de745
A
251bool
252OSSet::merge(const OSSet * set)
1c79356b 253{
0a7de745 254 return merge(set->members);
1c79356b
A
255}
256
0a7de745
A
257void
258OSSet::removeObject(const OSMetaClassBase *anObject)
1c79356b 259{
0a7de745
A
260 const OSMetaClassBase *probeObject;
261
262 for (int i = 0; (probeObject = members->getObject(i)); i++) {
263 if (probeObject == anObject) {
264 haveUpdated();
265 members->removeObject(i);
266 return;
267 }
268 }
1c79356b
A
269}
270
271
0a7de745
A
272bool
273OSSet::containsObject(const OSMetaClassBase *anObject) const
1c79356b 274{
0a7de745 275 return anObject && member(anObject);
1c79356b
A
276}
277
0a7de745
A
278bool
279OSSet::member(const OSMetaClassBase *anObject) const
1c79356b 280{
0a7de745 281 OSMetaClassBase *probeObject;
1c79356b 282
0a7de745
A
283 for (int i = 0; (probeObject = members->getObject(i)); i++) {
284 if (probeObject == anObject) {
285 return true;
286 }
287 }
1c79356b 288
0a7de745 289 return false;
1c79356b
A
290}
291
0a7de745
A
292OSObject *
293OSSet::getAnyObject() const
1c79356b 294{
0a7de745 295 return members->getObject(0);
1c79356b
A
296}
297
0a7de745
A
298bool
299OSSet::isEqualTo(const OSSet *aSet) const
1c79356b 300{
0a7de745
A
301 unsigned int count;
302 unsigned int i;
303 const OSMetaClassBase *obj1;
304 const OSMetaClassBase *obj2;
305
306 if (this == aSet) {
307 return true;
308 }
309
310 count = members->count;
311 if (count != aSet->getCount()) {
312 return false;
313 }
314
315 for (i = 0; i < count; i++) {
316 obj1 = aSet->members->getObject(i);
317 if (containsObject(obj1)) {
318 continue;
319 }
320 obj2 = members->getObject(i);
321 if (!obj1 || !obj2) {
322 return false;
323 }
324
325 if (!obj1->isEqualTo(obj2)) {
326 return false;
327 }
328 }
329
330 return true;
1c79356b
A
331}
332
0a7de745
A
333bool
334OSSet::isEqualTo(const OSMetaClassBase *anObject) const
1c79356b 335{
0a7de745
A
336 OSSet *otherSet;
337
338 otherSet = OSDynamicCast(OSSet, anObject);
339 if (otherSet) {
340 return isEqualTo(otherSet);
341 } else {
342 return false;
343 }
1c79356b
A
344}
345
0a7de745
A
346unsigned int
347OSSet::iteratorSize() const
1c79356b 348{
0a7de745 349 return sizeof(unsigned int);
1c79356b
A
350}
351
0a7de745
A
352bool
353OSSet::initIterator(void *inIterator) const
1c79356b 354{
0a7de745 355 unsigned int *iteratorP = (unsigned int *) inIterator;
1c79356b 356
0a7de745
A
357 *iteratorP = 0;
358 return true;
1c79356b
A
359}
360
0a7de745
A
361bool
362OSSet::getNextObjectForIterator(void *inIterator, OSObject **ret) const
1c79356b 363{
0a7de745
A
364 unsigned int *iteratorP = (unsigned int *) inIterator;
365 unsigned int index = (*iteratorP)++;
1c79356b 366
0a7de745
A
367 if (index < members->count) {
368 *ret = members->getObject(index);
369 } else {
370 *ret = 0;
371 }
1c79356b 372
0a7de745 373 return *ret != 0;
1c79356b
A
374}
375
0a7de745
A
376bool
377OSSet::serialize(OSSerialize *s) const
1c79356b 378{
0a7de745
A
379 const OSMetaClassBase *o;
380
381 if (s->previouslySerialized(this)) {
382 return true;
383 }
1c79356b 384
0a7de745
A
385 if (!s->addXMLStartTag(this, "set")) {
386 return false;
387 }
1c79356b 388
0a7de745
A
389 for (int i = 0; (o = members->getObject(i)); i++) {
390 if (!o->serialize(s)) {
391 return false;
392 }
393 }
1c79356b 394
0a7de745 395 return s->addXMLEndTag("set");
1c79356b 396}
91447636 397
0a7de745
A
398unsigned
399OSSet::setOptions(unsigned options, unsigned mask, void *)
91447636 400{
0a7de745
A
401 unsigned old = super::setOptions(options, mask);
402 if ((old ^ options) & mask) {
403 members->setOptions(options, mask);
404 }
91447636 405
0a7de745 406 return old;
91447636
A
407}
408
0a7de745
A
409OSCollection *
410OSSet::copyCollection(OSDictionary *cycleDict)
91447636 411{
0a7de745
A
412 bool allocDict = !cycleDict;
413 OSCollection *ret = 0;
414 OSSet *newSet = 0;
415
416 if (allocDict) {
417 cycleDict = OSDictionary::withCapacity(16);
418 if (!cycleDict) {
419 return 0;
91447636 420 }
0a7de745 421 }
91447636 422
0a7de745
A
423 do {
424 // Check for a cycle
425 ret = super::copyCollection(cycleDict);
426 if (ret) {
427 continue; // Found it
428 }
429 newSet = OSSet::withCapacity(members->capacity);
430 if (!newSet) {
431 continue; // Couldn't create new set abort
432 }
433 // Insert object into cycle Dictionary
434 cycleDict->setObject((const OSSymbol *) this, newSet);
435
436 OSArray *newMembers = newSet->members;
437 newMembers->capacityIncrement = members->capacityIncrement;
438
439 // Now copy over the contents into the new duplicate
440 for (unsigned int i = 0; i < members->count; i++) {
441 OSObject *obj = EXT_CAST(members->array[i]);
442 OSCollection *coll = OSDynamicCast(OSCollection, obj);
443 if (coll) {
444 OSCollection *newColl = coll->copyCollection(cycleDict);
445 if (newColl) {
446 obj = newColl; // Rely on cycleDict ref for a bit
447 newColl->release();
448 } else {
449 goto abortCopy;
450 }
451 }
452 ;
453 newMembers->setObject(obj);
454 }
455 ;
91447636 456
0a7de745
A
457 ret = newSet;
458 newSet = 0;
459 } while (false);
91447636
A
460
461abortCopy:
0a7de745
A
462 if (newSet) {
463 newSet->release();
464 }
91447636 465
0a7de745
A
466 if (allocDict) {
467 cycleDict->release();
468 }
91447636 469
0a7de745 470 return ret;
91447636 471}