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