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