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