xref: /xnu-11215/libkern/c++/OSSet.cpp (revision 14e3d835)
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 }
397