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