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