/ NSOrderedSet.m
NSOrderedSet.m
   1  //
   2  //  NSOrderedSet.m
   3  //  CoreFoundation
   4  //
   5  //  Copyright (c) 2014 Apportable. All rights reserved.
   6  //
   7  
   8  #import <Foundation/NSOrderedSet.h>
   9  
  10  #import <Foundation/NSArray.h>
  11  #import <Foundation/NSEnumerator.h>
  12  #import <Foundation/NSSet.h>
  13  #import <Foundation/NSIndexSet.h>
  14  #import <Foundation/NSLocale.h>
  15  
  16  #import <objc/message.h>
  17  
  18  #import "CFBasicHash.h"
  19  #import "ForFoundationOnly.h"
  20  
  21  #import "CFSortFunctions.h"
  22  #import "NSBasicHash.h"
  23  #import "NSFastEnumerationEnumerator.h"
  24  #import "NSObjectInternal.h"
  25  
  26  @interface __NSPlaceholderOrderedSet : NSMutableOrderedSet
  27  + (id)mutablePlaceholder;
  28  + (id)immutablePlaceholder;
  29  @end
  30  
  31  @interface __NSOrderedSetI : NSOrderedSet {
  32      unsigned int _used:26;
  33      unsigned int _szidx:6;
  34  }
  35  + (id)__new:(const id *)addr :(NSUInteger)count :(BOOL)tbd;
  36  @end
  37  
  38  @interface __NSOrderedSetM : NSMutableOrderedSet
  39  {
  40      NSUInteger _used;
  41      CFBasicHashRef _set;
  42      NSMutableArray *_array;
  43  }
  44  + (id)__new:(const id *)addr :(NSUInteger)count :(BOOL)tbd;
  45  @end
  46  
  47  @interface __NSOrderedSetArrayProxy : NSArray
  48  {
  49      NSOrderedSet *_orderedSet;
  50  }
  51  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet;
  52  @end
  53  
  54  @interface __NSOrderedSetSetProxy : NSSet
  55  {
  56      NSOrderedSet *_orderedSet;
  57  }
  58  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet;
  59  @end
  60  
  61  @interface __NSOrderedSetReversed : NSOrderedSet
  62  {
  63      NSOrderedSet *_orderedSet;
  64      NSUInteger _cnt;
  65  }
  66  @end
  67  
  68  @interface __NSOrderedSetReverseEnumerator : NSEnumerator
  69  {
  70      NSOrderedSet *_obj;
  71      NSUInteger _idx;
  72  }
  73  - (id)initWithObject:(id)object;
  74  @end
  75  
  76  @interface NSMutableArray ()
  77  - (void)_mutate;
  78  @end
  79  
  80  @interface NSSet ()
  81  - (void)getObjects:(id *)objects count:(NSUInteger)count;
  82  @end
  83  
  84  #define STACK_BUFFER_SIZE 256
  85  
  86  @implementation NSOrderedSet
  87  
  88  + (id)allocWithZone:(NSZone *)zone
  89  {
  90      if (self == [NSOrderedSet class])
  91      {
  92          return [__NSPlaceholderOrderedSet immutablePlaceholder];
  93      }
  94      else if (self == [NSMutableOrderedSet class])
  95      {
  96          return [__NSPlaceholderOrderedSet mutablePlaceholder];
  97      }
  98      else
  99      {
 100          return [super allocWithZone:zone];
 101      }
 102  }
 103  
 104  + (BOOL)supportsSecureCoding
 105  {
 106      return YES;
 107  }
 108  
 109  + (id)orderedSet
 110  {
 111      return [[[self alloc] initWithObjects:NULL count:0] autorelease];
 112  }
 113  
 114  + (id)orderedSetWithObject:(id)object
 115  {
 116      return [[[self alloc] initWithObjects:&object count:1] autorelease];
 117  }
 118  
 119  + (id)orderedSetWithObjects:(const id [])objects count:(NSUInteger)count
 120  {
 121      return [[[self alloc] initWithObjects:objects count:count] autorelease];
 122  }
 123  
 124  + (id)orderedSetWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION
 125  {
 126      NSUInteger argCount = 1;
 127  
 128      va_list args;
 129      va_list copy;
 130  
 131      va_start(args, firstObj);
 132      va_copy(copy, args);
 133  
 134      while (va_arg(args, id) != nil)
 135      {
 136          argCount++;
 137      }
 138  
 139      va_end(args);
 140  
 141      id *objects = malloc(argCount * sizeof(id));
 142  
 143      if (objects == NULL)
 144      {
 145          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
 146          return nil;
 147      }
 148  
 149      objects[0] = firstObj;
 150  
 151      for (NSUInteger idx = 1; idx < argCount; idx++)
 152      {
 153          objects[idx] = va_arg(copy, id);
 154      }
 155  
 156      va_end(copy);
 157  
 158      NSOrderedSet *orderedSet = [[[self alloc] initWithObjects:objects count:argCount] autorelease];
 159  
 160      free(objects);
 161  
 162      return orderedSet;
 163  }
 164  
 165  + (id)orderedSetWithOrderedSet:(NSOrderedSet *)orderedSet
 166  {
 167      NSRange range = NSMakeRange(0, [orderedSet count]);
 168      return [[[self alloc] initWithOrderedSet:orderedSet range:range copyItems:NO] autorelease];
 169  }
 170  
 171  + (id)orderedSetWithOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range copyItems:(BOOL)copyItems
 172  {
 173      return [[[self alloc] initWithOrderedSet:orderedSet range:range copyItems:copyItems] autorelease];
 174  }
 175  
 176  + (id)orderedSetWithArray:(NSArray *)array
 177  {
 178      NSRange range = NSMakeRange(0, [array count]);
 179      return [[[self alloc] initWithArray:array range:range copyItems:NO] autorelease];
 180  }
 181  
 182  + (id)orderedSetWithArray:(NSArray *)array range:(NSRange)range copyItems:(BOOL)copyItems
 183  {
 184      return [[[self alloc] initWithArray:array range:range copyItems:copyItems] autorelease];
 185  }
 186  
 187  + (id)orderedSetWithSet:(NSSet *)set
 188  {
 189      return [[[self alloc] initWithSet:set copyItems:NO] autorelease];
 190  }
 191  
 192  + (id)orderedSetWithSet:(NSSet *)set copyItems:(BOOL)copyItems
 193  {
 194      return [[[self alloc] initWithSet:set copyItems:copyItems] autorelease];
 195  }
 196  
 197  + (id)orderedSetWithOrderedSet:(NSOrderedSet *)orderedSet copyItems:(BOOL)copyItems
 198  {
 199      return [[[self alloc] initWithOrderedSet:orderedSet copyItems:copyItems] autorelease];
 200  }
 201  
 202  + (id)orderedSetWithOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range
 203  {
 204      return [[[self alloc] initWithOrderedSet:orderedSet range:range copyItems:NO] autorelease];
 205  }
 206  
 207  + (id)orderedSetWithArray:(NSArray *)array copyItems:(BOOL)copyItems
 208  {
 209      return [[[self alloc] initWithArray:array copyItems:copyItems] autorelease];
 210  }
 211  
 212  + (id)orderedSetWithArray:(NSArray *)array range:(NSRange)range
 213  {
 214      return [[[self alloc] initWithArray:array range:range copyItems:NO] autorelease];
 215  }
 216  
 217  + (id)newOrderedSetWithObjects:(const id *)objects count:(NSUInteger)count
 218  {
 219      if (self == [__NSOrderedSetI class])
 220      {
 221          return [[__NSOrderedSetI class] __new:objects :count :NO];
 222      }
 223  
 224      if (self == [__NSOrderedSetM class])
 225      {
 226          return [[__NSOrderedSetM class] __new:objects :count :NO];
 227      }
 228  
 229      NSRequestConcreteImplementation();
 230      return nil;
 231  }
 232  
 233  - (id)initWithObject:(id)object
 234  {
 235      return [self initWithObjects:&object count:1];
 236  }
 237  
 238  - (id)initWithObjects:(const id [])objects count:(NSUInteger)count
 239  {
 240      NSRequestConcreteImplementation();
 241      return nil;
 242  }
 243  
 244  - (id)initWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION
 245  {
 246      NSUInteger argCount = 1;
 247  
 248      va_list args;
 249      va_list copy;
 250  
 251      va_start(args, firstObj);
 252      va_copy(copy, args);
 253  
 254      while (va_arg(args, id) != nil)
 255      {
 256          argCount++;
 257      }
 258  
 259      va_end(args);
 260  
 261      id *objects = malloc(argCount * sizeof(id));
 262  
 263      if (objects == NULL)
 264      {
 265          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
 266          return nil;
 267      }
 268  
 269      objects[0] = firstObj;
 270  
 271      for (NSUInteger idx = 1; idx < argCount; idx++)
 272      {
 273          objects[idx] = va_arg(copy, id);
 274      }
 275  
 276      va_end(copy);
 277  
 278      self = [self initWithObjects:objects count:argCount];
 279  
 280      free(objects);
 281  
 282      return self;
 283  }
 284  
 285  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet
 286  {
 287      NSRange range = NSMakeRange(0, [orderedSet count]);
 288      return [self initWithOrderedSet:orderedSet range:range copyItems:NO];
 289  }
 290  
 291  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet copyItems:(BOOL)copyItems
 292  {
 293      NSRange range = NSMakeRange(0, [orderedSet count]);
 294      return [self initWithOrderedSet:orderedSet range:range copyItems:copyItems];
 295  }
 296  
 297  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range
 298  {
 299      return [self initWithOrderedSet:orderedSet range:range copyItems:NO];
 300  }
 301  
 302  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range copyItems:(BOOL)copyItems
 303  {
 304      if (NSMaxRange(range) > [orderedSet count])
 305      {
 306          [self release];
 307          [NSException raise:NSRangeException format:@"Range out of bounds for ordered set"];
 308          return nil;
 309      }
 310  
 311      if (orderedSet == nil && range.length > 0)
 312      {
 313          [self release];
 314          [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with nonzero range and nil ordered set"];
 315          return nil;
 316      }
 317  
 318      if (range.length == 0)
 319      {
 320          return [self initWithObjects:NULL count:0];
 321      }
 322  
 323      id *objects = malloc(range.length * sizeof(id));
 324      if (objects == NULL)
 325      {
 326          [self release];
 327          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
 328          return nil;
 329      }
 330  
 331      [orderedSet getObjects:objects range:range];
 332  
 333      if (copyItems)
 334      {
 335          for (NSUInteger idx = 0; idx < range.length; idx++)
 336          {
 337              objects[idx] = [objects[idx] copy];
 338          }
 339      }
 340  
 341      self = [self initWithObjects:objects count:range.length];
 342  
 343      if (copyItems)
 344      {
 345          for (NSUInteger idx = 0; idx < range.length; idx++)
 346          {
 347              [objects[idx] release];
 348          }
 349      }
 350  
 351      free(objects);
 352  
 353      return self;
 354  }
 355  
 356  - (id)initWithArray:(NSArray *)array
 357  {
 358      NSRange range = NSMakeRange(0, [array count]);
 359      return [self initWithArray:array range:range copyItems:NO];
 360  }
 361  
 362  - (id)initWithArray:(NSArray *)array copyItems:(BOOL)copyItems
 363  {
 364      NSRange range = NSMakeRange(0, [array count]);
 365      return [self initWithArray:array range:range copyItems:copyItems];
 366  }
 367  
 368  - (id)initWithArray:(NSArray *)array range:(NSRange)range
 369  {
 370      return [self initWithArray:array range:range copyItems:NO];
 371  }
 372  
 373  - (id)initWithArray:(NSArray *)array range:(NSRange)range copyItems:(BOOL)copyItems
 374  {
 375      if (NSMaxRange(range) > [array count])
 376      {
 377          [self release];
 378          [NSException raise:NSRangeException format:@"Range out of bounds for ordered set"];
 379          return nil;
 380      }
 381  
 382      if (array == nil && range.length > 0)
 383      {
 384          [self release];
 385          [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with nonzero range and nil ordered set"];
 386          return nil;
 387      }
 388  
 389      if (range.length == 0)
 390      {
 391          return [self initWithObjects:NULL count:0];
 392      }
 393  
 394      id *objects = malloc(range.length * sizeof(id));
 395  
 396      if (objects == NULL)
 397      {
 398          [self release];
 399          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
 400          return nil;
 401      }
 402  
 403      [array getObjects:objects range:range];
 404  
 405      if (copyItems)
 406      {
 407          for (NSUInteger idx = 0; idx < range.length; idx++)
 408          {
 409              objects[idx] = [objects[idx] copy];
 410          }
 411      }
 412  
 413      self = [self initWithObjects:objects count:range.length];
 414  
 415      if (copyItems)
 416      {
 417          for (NSUInteger idx = 0; idx < range.length; idx++)
 418          {
 419              [objects[idx] release];
 420          }
 421      }
 422  
 423      free(objects);
 424  
 425      return self;
 426  }
 427  
 428  - (id)initWithSet:(NSSet *)set
 429  {
 430      return [self initWithSet:set copyItems:NO];
 431  }
 432  
 433  - (id)initWithSet:(NSSet *)set copyItems:(BOOL)copyItems
 434  {
 435      if (set == nil)
 436      {
 437          return [self initWithObjects:NULL count:0];
 438      }
 439  
 440      NSUInteger count = [set count];
 441  
 442      if (count == 0)
 443      {
 444          return [self initWithObjects:NULL count:0];
 445      }
 446  
 447      id *objects = malloc(count * sizeof(id));
 448  
 449      if (objects == NULL)
 450      {
 451          [self release];
 452          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
 453          return nil;
 454      }
 455  
 456      [set getObjects:objects count:count];
 457  
 458      if (copyItems)
 459      {
 460          for (NSUInteger idx = 0; idx < count; idx++)
 461          {
 462              objects[idx] = [objects[idx] copy];
 463          }
 464      }
 465  
 466      self = [self initWithObjects:objects count:count];
 467  
 468      if (copyItems)
 469      {
 470          for (NSUInteger idx = 0; idx < count; idx++)
 471          {
 472              [objects[idx] release];
 473          }
 474      }
 475  
 476      free(objects);
 477  
 478      return self;
 479  }
 480  
 481  - (NSUInteger)count
 482  {
 483      NSRequestConcreteImplementation();
 484      return 0;
 485  }
 486  
 487  - (id)objectAtIndex:(NSUInteger)idx
 488  {
 489      NSRequestConcreteImplementation();
 490      return nil;
 491  }
 492  
 493  - (NSUInteger)indexOfObject:(id)object
 494  {
 495      NSRequestConcreteImplementation();
 496      return 0;
 497  }
 498  
 499  - (Class)classForCoder
 500  {
 501      return [NSOrderedSet class];
 502  }
 503  
 504  - (id)initWithCoder:(NSCoder *)decoder
 505  {
 506      if (![decoder allowsKeyedCoding])
 507      {
 508          [self release];
 509          [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with non keyed coder"];
 510          return nil;
 511      }
 512  
 513      NSUInteger capacity = 256;
 514      id *objects = malloc(capacity * sizeof(id));
 515  
 516      if (objects == NULL)
 517      {
 518          [self release];
 519          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
 520          return nil;
 521      }
 522  
 523      unsigned int idx = 0;
 524  
 525      while (YES)
 526      {
 527          if (idx == capacity)
 528          {
 529              capacity *= 2;
 530              id *newObjects = realloc(objects, capacity * sizeof(id));
 531  
 532              if (newObjects == NULL)
 533              {
 534                  for (unsigned int i = 0; i < idx; i++)
 535                  {
 536                      [objects[i] release];
 537                  }
 538  
 539                  free(objects);
 540                  [self release];
 541                  [NSException raise:NSMallocException format:@"Could not allocate buffer"];
 542                  return nil;
 543              }
 544  
 545              objects = newObjects;
 546          }
 547  
 548          CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("NS.object.%u"), idx);
 549          id obj = [decoder decodeObjectForKey:(NSString *)key];
 550          CFRelease(key);
 551  
 552          if (obj == nil)
 553          {
 554              break;
 555          }
 556  
 557          objects[idx] = obj;
 558          idx++;
 559      };
 560  
 561      [self initWithObjects:objects count:idx];
 562  
 563      free(objects);
 564  
 565      return self;
 566  }
 567  
 568  - (void)encodeWithCoder:(NSCoder *)coder
 569  {
 570      if (![coder allowsKeyedCoding])
 571      {
 572          [NSException raise:NSInvalidArgumentException format:@"Cannot encode ordered set with non keyed coder"];
 573          return;
 574      }
 575  
 576      unsigned int idx = 0;
 577  
 578      for (id object in self)
 579      {
 580          CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("NS.object.%u"), idx);
 581          [coder encodeObject:object forKey:(NSString *)key];
 582          CFRelease(key);
 583          idx++;
 584      }
 585  }
 586  
 587  - (id)mutableCopyWithZone:(NSZone *)zone
 588  {
 589      NSRange range = NSMakeRange(0, [self count]);
 590      return [[NSMutableOrderedSet alloc] initWithOrderedSet:self range:range copyItems:NO];
 591  }
 592  
 593  - (id)copyWithZone:(NSZone *)zone
 594  {
 595      NSRange range = NSMakeRange(0, [self count]);
 596      return [[NSOrderedSet alloc] initWithOrderedSet:self range:range copyItems:NO];
 597  }
 598  
 599  - (id)objectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 600  {
 601      if (test == nil)
 602      {
 603          [NSException raise:NSInvalidArgumentException format:@"Nil test"];
 604          return nil;
 605      }
 606  
 607      NSIndexSet *passingIndexes = [self indexesOfObjectsPassingTest:test];
 608      NSArray *objects = [self objectsAtIndexes:passingIndexes];
 609  
 610      return [NSOrderedSet orderedSetWithArray:objects];
 611  }
 612  
 613  - (id)objectsWithOptions:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 614  {
 615      if (test == nil)
 616      {
 617          [NSException raise:NSInvalidArgumentException format:@"Test cannot be nil"];
 618          return nil;
 619      }
 620  
 621      NSIndexSet *passingIndexes = [self indexesOfObjectsWithOptions:options passingTest:test];
 622      NSArray *objects = [self objectsAtIndexes:passingIndexes];
 623  
 624      return [NSOrderedSet orderedSetWithArray:objects];
 625  }
 626  
 627  - (id)objectsAtIndexes:(NSIndexSet *)indexes options:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 628  {
 629      if (test == nil)
 630      {
 631          [NSException raise:NSInvalidArgumentException format:@"Test cannot be nil"];
 632          return nil;
 633      }
 634  
 635      if (indexes == nil)
 636      {
 637          [NSException raise:NSInvalidArgumentException format:@"Indexes cannot be nil"];
 638          return nil;
 639      }
 640  
 641      NSIndexSet *passingIndexes = [self indexesOfObjectsAtIndexes:indexes options:options passingTest:test];
 642      NSArray *objects = [self objectsAtIndexes:passingIndexes];
 643  
 644      return [NSOrderedSet orderedSetWithArray:objects];
 645  }
 646  
 647  - (id)objectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 648  {
 649      if (test == nil)
 650      {
 651          [NSException raise:NSInvalidArgumentException format:@"Test cannot be nil"];
 652          return nil;
 653      }
 654  
 655      return [self objectWithOptions:0 passingTest:test];
 656  }
 657  
 658  - (id)objectWithOptions:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 659  {
 660      if (test == nil)
 661      {
 662          [NSException raise:NSInvalidArgumentException format:@"Test cannot be nil"];
 663          return nil;
 664      }
 665  
 666      NSUInteger idx = [self indexOfObjectWithOptions:options passingTest:test];
 667  
 668      if (idx == NSNotFound)
 669      {
 670          return nil;
 671      }
 672  
 673      return [self objectAtIndex:idx];
 674  }
 675  
 676  - (id)objectAtIndexes:(NSIndexSet *)indexes options:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
 677  {
 678      if (test == nil)
 679      {
 680          [NSException raise:NSInvalidArgumentException format:@"Test cannot be nil"];
 681          return nil;
 682      }
 683  
 684      if (indexes == nil)
 685      {
 686          [NSException raise:NSInvalidArgumentException format:@"Indexes cannot be nil"];
 687          return nil;
 688      }
 689  
 690      NSUInteger idx = [self indexOfObjectAtIndexes:indexes options:options passingTest:test];
 691  
 692      if (idx == NSNotFound)
 693      {
 694          return nil;
 695      }
 696  
 697      return [self objectAtIndex:idx];
 698  }
 699  
 700  - (BOOL)isEqual:(id)other
 701  {
 702      if (self == other)
 703      {
 704          return YES;
 705      }
 706      else if ([other isNSOrderedSet__])
 707      {
 708          return [self isEqualToOrderedSet:(NSOrderedSet *)other];
 709      }
 710      else
 711      {
 712          return NO;
 713      }
 714  }
 715  
 716  - (NSUInteger)indexOfObject:(id)object inRange:(NSRange)range
 717  {
 718      if (NSMaxRange(range) > [self count])
 719      {
 720          [NSException raise:NSRangeException format:@"Range out of bounds for ordered set"];
 721          return 0;
 722      }
 723  
 724      NSUInteger idx = [self indexOfObject:object];
 725  
 726      return NSLocationInRange(idx, range);
 727  }
 728  
 729  - (NSUInteger)hash
 730  {
 731      return [self count];
 732  }
 733  
 734  - (void)getObjects:(id *)addr
 735  {
 736      if (addr == NULL)
 737      {
 738          [NSException raise:NSInvalidArgumentException format:@"Cannot place objects from ordered set into NULL array"];
 739          return;
 740      }
 741  
 742      NSRange range = NSMakeRange(0, [self count]);
 743      return [self getObjects:addr range:range];
 744  }
 745  
 746  - (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range
 747  {
 748      if (objects == NULL && range.length > 0)
 749      {
 750          [NSException raise:NSInvalidArgumentException format:@"Range out of bounds of NULL array"];
 751          return;
 752      }
 753  
 754      if (NSMaxRange(range) > [self count])
 755      {
 756          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
 757          return;
 758      }
 759  
 760      if (range.length == 0)
 761      {
 762          return;
 763      }
 764  
 765      for (NSUInteger idx = 0; idx < range.length; idx++)
 766      {
 767          objects[idx] = [self objectAtIndex:(idx + range.location)];
 768      }
 769  }
 770  
 771  - (NSUInteger)countForObject:(id)object
 772  {
 773      NSUInteger idx = [self indexOfObject:object];
 774      if (idx == NSNotFound)
 775      {
 776          return 0;
 777      }
 778      else
 779      {
 780          return 1;
 781      }
 782  }
 783  
 784  - (NSUInteger)countForObject:(id)object inRange:(NSRange)range
 785  {
 786      if (NSMaxRange(range) > [self count])
 787      {
 788          [NSException raise:NSRangeException format:@"Range out of bounds for ordered set"];
 789          return NO;
 790      }
 791  
 792      NSUInteger idx = [self indexOfObject:object inRange:range];
 793  
 794      if (idx == NSNotFound)
 795      {
 796          return 0;
 797      }
 798      else
 799      {
 800          return 1;
 801      }
 802  }
 803  
 804  - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)objects count:(NSUInteger)count
 805  {
 806      if (state->state == -1)
 807      {
 808          return 0;
 809      }
 810  
 811      if (state->state == 0)
 812      {
 813          state->mutationsPtr = &state->extra[0];
 814          state->extra[0] = [self count];
 815      }
 816  
 817      state->itemsPtr = objects;
 818  
 819      NSUInteger returnedLength = MIN(state->extra[0] - state->state, count);
 820      if (returnedLength != 0)
 821      {
 822          [self getObjects:objects range:NSMakeRange(state->state, returnedLength)];
 823      }
 824  
 825      if (state->state + returnedLength >= state->extra[0])
 826      {
 827          state->state = -1;
 828      }
 829      else
 830      {
 831          state->state += returnedLength;
 832      }
 833  
 834      return returnedLength;
 835  }
 836  
 837  - (BOOL)containsObject:(id)object
 838  {
 839      NSUInteger idx = [self indexOfObject:object];
 840  
 841      return idx != NSNotFound;
 842  }
 843  
 844  - (BOOL)containsObject:(id)object inRange:(NSRange)range
 845  {
 846      if (NSMaxRange(range) > [self count])
 847      {
 848          [NSException raise:NSRangeException format:@"Range out of bounds for ordered set"];
 849          return NO;
 850      }
 851  
 852      NSUInteger idx = [self indexOfObject:object inRange:range];
 853  
 854      return idx != NSNotFound;
 855  }
 856  
 857  - (NSArray *)allObjects
 858  {
 859      NSUInteger count = [self count];
 860  
 861      if (count == 0)
 862      {
 863          return [NSArray array];
 864      }
 865  
 866      id *objects = malloc(count * sizeof(id));
 867  
 868      if (objects == NULL)
 869      {
 870          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
 871          return nil;
 872      }
 873  
 874      NSRange range = NSMakeRange(0, count);
 875      [self getObjects:objects range:range];
 876  
 877      NSArray *array = [NSArray arrayWithObjects:objects count:count];
 878  
 879      free(objects);
 880  
 881      return array;
 882  }
 883  
 884  - (BOOL)isNSOrderedSet__
 885  {
 886      return YES;
 887  }
 888  
 889  - (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes
 890  {
 891      if (indexes == nil)
 892      {
 893          [NSException raise:NSInvalidArgumentException format:@"Indexes cannot be nil"];
 894          return nil;
 895      }
 896  
 897      NSUInteger count = [indexes count];
 898  
 899      if (count == 0)
 900      {
 901          return [NSArray array];
 902      }
 903  
 904      if ([indexes lastIndex] >= [self count])
 905      {
 906          [NSException raise:NSInvalidArgumentException format:@"Indexes out of bounds of ordered set"];
 907          return nil;
 908      }
 909  
 910      id *objects = malloc(count * sizeof(id));
 911      if (objects == NULL)
 912      {
 913          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
 914          return nil;
 915      }
 916  
 917      __block id *currentObjectPtr = objects;
 918      [indexes enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
 919          [self getObjects:currentObjectPtr range:range];
 920          currentObjectPtr += range.length;
 921      }];
 922  
 923      NSArray *array = [NSArray arrayWithObjects:objects count:count];
 924  
 925      free(objects);
 926  
 927      return array;
 928  }
 929  
 930  - (id)firstObject
 931  {
 932      if (self.count == 0)
 933      {
 934          return nil;
 935      }
 936  
 937      return [self objectAtIndex:0];
 938  }
 939  
 940  - (id)lastObject
 941  {
 942      NSUInteger count = self.count;
 943  
 944      if (count == 0)
 945      {
 946          return nil;
 947      }
 948  
 949      return [self objectAtIndex:count - 1];
 950  }
 951  
 952  - (BOOL)isEqualToOrderedSet:(NSOrderedSet *)other
 953  {
 954      if ([self count] != [other count])
 955      {
 956          return NO;
 957      }
 958  
 959      if ([self count] == 0)
 960      {
 961          return YES;
 962      }
 963  
 964      NSUInteger idx = 0;
 965      for (id obj in self)
 966      {
 967          id otherObj = [other objectAtIndex:idx];
 968          if (obj != otherObj && ![obj isEqual:otherObj])
 969          {
 970              return NO;
 971          }
 972          idx++;
 973      }
 974  
 975      return YES;
 976  }
 977  
 978  - (BOOL)intersectsOrderedSet:(NSOrderedSet *)other
 979  {
 980      for (id obj in self)
 981      {
 982          if ([other containsObject:obj])
 983          {
 984              return YES;
 985          }
 986      }
 987  
 988      return NO;
 989  }
 990  
 991  - (BOOL)intersectsSet:(NSSet *)set
 992  {
 993      for (id obj in self)
 994      {
 995          if ([set containsObject:obj])
 996          {
 997              return YES;
 998          }
 999      }
1000  
1001      return NO;
1002  }
1003  
1004  - (BOOL)isSubsetOfOrderedSet:(NSOrderedSet *)other
1005  {
1006      for (id obj in self)
1007      {
1008          if (![other containsObject:obj])
1009          {
1010              return NO;
1011          }
1012      }
1013  
1014      return YES;
1015  }
1016  
1017  - (BOOL)isSubsetOfSet:(NSSet *)set
1018  {
1019      for (id obj in self)
1020      {
1021          if (![set containsObject:obj])
1022          {
1023              return NO;
1024          }
1025      }
1026  
1027      return YES;
1028  }
1029  
1030  - (id)objectAtIndexedSubscript:(NSUInteger)idx
1031  {
1032      return [self objectAtIndex:idx];
1033  }
1034  
1035  - (NSEnumerator *)objectEnumerator
1036  {
1037      return [[[__NSFastEnumerationEnumerator alloc] initWithObject:self] autorelease];
1038  }
1039  
1040  - (NSEnumerator *)reverseObjectEnumerator
1041  {
1042      return [[[__NSOrderedSetReverseEnumerator alloc] initWithObject:self] autorelease];
1043  }
1044  
1045  - (NSOrderedSet *)reversedOrderedSet
1046  {
1047      return [[[__NSOrderedSetReversed alloc] initWithOrderedSet:self] autorelease];
1048  }
1049  
1050  - (NSArray *)array
1051  {
1052      return [[[__NSOrderedSetArrayProxy alloc] initWithOrderedSet:self] autorelease];
1053  }
1054  
1055  - (NSSet *)set
1056  {
1057      return [[[__NSOrderedSetSetProxy alloc] initWithOrderedSet:self] autorelease];
1058  }
1059  
1060  - (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
1061  {
1062      [self enumerateObjectsWithOptions:0 usingBlock:block];
1063  }
1064  
1065  - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
1066  {
1067      NSUInteger len = [self count];
1068      if (opts & NSEnumerationConcurrent)
1069      {
1070          __block BOOL stop = NO;
1071  
1072          if (opts & NSEnumerationReverse)
1073          {
1074              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1075                  if (!stop)
1076                  {
1077                      NSUInteger i = len - 1 - iter;
1078                      block([self objectAtIndex:i], i, &stop);
1079                  }
1080              });
1081          }
1082          else
1083          {
1084              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1085                  if (!stop)
1086                  {
1087                      block([self objectAtIndex:iter], iter, &stop);
1088                  }
1089              });
1090          }
1091          return;
1092      }
1093      if (opts & NSEnumerationReverse)
1094      {
1095          for (int i = len - 1; i >= 0; i--)
1096          {
1097              BOOL stop = NO;
1098              block([self objectAtIndex:i], i, &stop);
1099  
1100              if (stop)
1101              {
1102                  return;
1103              }
1104          }
1105      }
1106      else
1107      {
1108          NSUInteger i = 0;
1109  
1110          for (id obj in self)
1111          {
1112              BOOL stop = NO;
1113              block(obj, i++, &stop);
1114  
1115              if (stop)
1116              {
1117                  return;
1118              }
1119          }
1120      }
1121  }
1122  
1123  - (void)enumerateObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
1124  {
1125      if (block == nil)
1126      {
1127          [NSException raise:NSInvalidArgumentException format:@"block is nil"];
1128          return;
1129      }
1130  
1131      [s enumerateIndexesWithOptions:opts usingBlock:^(NSUInteger idx, BOOL *stop) {
1132          block([self objectAtIndex:idx], idx, stop);
1133      }];
1134  }
1135  
1136  - (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1137  {
1138      return [self indexOfObjectWithOptions:0 passingTest:predicate];
1139  }
1140  
1141  - (NSUInteger)indexOfObjectWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1142  {
1143      NSUInteger len = [self count];
1144      __block NSUInteger found = NSNotFound;
1145      if (opts & NSEnumerationConcurrent)
1146      {
1147          __block BOOL stop = NO;
1148  
1149          if (opts & NSEnumerationReverse)
1150          {
1151              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1152                  if (!stop)
1153                  {
1154                      NSUInteger i = len - 1 - iter;
1155  
1156                      if (predicate([self objectAtIndex:i], i, &stop))
1157                      {
1158                          stop = YES;
1159                          found = i;
1160                      }
1161                  }
1162              });
1163          }
1164          else
1165          {
1166              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1167                  if (!stop)
1168                  {
1169                      if(predicate([self objectAtIndex:iter], iter, &stop))
1170                      {
1171                          stop = YES;
1172                          found = iter;
1173                      }
1174                  }
1175              });
1176          }
1177      }
1178      if (opts & NSEnumerationReverse)
1179      {
1180          for (int i = len - 1; i >= 0; i--)
1181          {
1182              BOOL stop = NO;
1183  
1184              if (predicate([self objectAtIndex:i], i, &stop))
1185              {
1186                  stop = YES;
1187                  found = i;
1188              }
1189              if (stop)
1190              {
1191                  break;
1192              }
1193          }
1194      }
1195      else
1196      {
1197          NSUInteger i = 0;
1198  
1199          for (id obj in self)
1200          {
1201              BOOL stop = NO;
1202  
1203              if (predicate(obj, i++, &stop))
1204              {
1205                  stop = YES;
1206                  found = i;
1207              }
1208              if (stop)
1209              {
1210                  break;
1211              }
1212          }
1213      }
1214      return found;
1215  }
1216  
1217  - (NSUInteger)indexOfObjectAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1218  {
1219      __block NSUInteger found = NSNotFound;
1220      [s enumerateIndexesWithOptions:opts usingBlock:^(NSUInteger idx, BOOL *stop) {
1221          if (predicate([self objectAtIndex:idx], idx, stop))
1222          {
1223              found = idx;
1224          }
1225      }];
1226      return found;
1227  }
1228  
1229  - (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1230  {
1231      NSObject *indexSet = [[objc_getClass("NSMutableIndexSet") alloc] init];
1232      NSUInteger len = [self count];
1233      BOOL stop = NO;
1234      for (NSUInteger i = 0; i < len; i++)
1235      {
1236          if (predicate([self objectAtIndex:i], i, &stop))
1237          {
1238              ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indexSet, @selector(addIndex:), i);
1239          }
1240          if (stop)
1241          {
1242              break;
1243          }
1244      }
1245      return (NSIndexSet *)[indexSet autorelease];
1246  }
1247  
1248  - (NSIndexSet *)indexesOfObjectsWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1249  {
1250      NSObject *indices = [[objc_getClass("NSMutableIndexSet") alloc] init];
1251      NSUInteger len = [self count];
1252  
1253      if (opts & NSEnumerationConcurrent)
1254      {
1255          __block BOOL stop = NO;
1256  
1257          if (opts & NSEnumerationReverse)
1258          {
1259              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1260                  if (!stop)
1261                  {
1262                      NSUInteger i = len - 1 - iter;
1263  
1264                      if (predicate([self objectAtIndex:i], i, &stop))
1265                      {
1266                          ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indices, @selector(addIndex:), i);
1267                      }
1268                  }
1269              });
1270          }
1271          else
1272          {
1273              dispatch_apply(len, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t iter){
1274                  if (!stop)
1275                  {
1276                      if(predicate([self objectAtIndex:iter], iter, &stop))
1277                      {
1278                          ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indices, @selector(addIndex:), iter);
1279                      }
1280                  }
1281              });
1282          }
1283      }
1284      if (opts & NSEnumerationReverse)
1285      {
1286          for (int i = len - 1; i >= 0; i--)
1287          {
1288              BOOL stop = NO;
1289  
1290              if (predicate([self objectAtIndex:i], i, &stop))
1291              {
1292                  ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indices, @selector(addIndex:), i);
1293              }
1294              if (stop)
1295              {
1296                  break;
1297              }
1298          }
1299      }
1300      else
1301      {
1302          NSUInteger i = 0;
1303          for (id obj in self)
1304          {
1305              BOOL stop = NO;
1306  
1307              if (predicate(obj, i++, &stop))
1308              {
1309                  ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indices, @selector(addIndex:), i);
1310              }
1311              if (stop)
1312              {
1313                  break;
1314              }
1315          }
1316      }
1317      return (NSIndexSet *)[indices autorelease];
1318  }
1319  
1320  - (NSIndexSet *)indexesOfObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
1321  {
1322      NSObject *indices = [[objc_getClass("NSMutableIndexSet") alloc] init];
1323      [s enumerateIndexesWithOptions:opts usingBlock:^(NSUInteger idx, BOOL *stop) {
1324          if (predicate([self objectAtIndex:idx], idx, stop))
1325          {
1326              ((void (*)(id, SEL, NSUInteger))objc_msgSend)(indices, @selector(addIndex:), idx);
1327          }
1328      }];
1329      return (NSIndexSet *)[indices autorelease];
1330  }
1331  
1332  - (NSUInteger)indexOfObject:(id)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts usingComparator:(NSComparator)comparator
1333  {
1334      NSUInteger minIndex = r.location;
1335      NSUInteger midIndex = ceil(r.length / 2.0) + r.location;
1336      NSUInteger maxIndex = NSMaxRange(r);
1337      id min = [self objectAtIndex:minIndex];
1338      id mid = min;
1339  
1340      if (r.length > 2)
1341      {
1342          mid = [self objectAtIndex:midIndex];
1343      }
1344  
1345      NSComparisonResult result = comparator(mid, obj);
1346  
1347      switch (result)
1348      {
1349          case NSOrderedAscending:
1350              if ((opts & NSBinarySearchingInsertionIndex) && midIndex == maxIndex)
1351              {
1352                  return maxIndex + 1;
1353              }
1354              else if (midIndex == maxIndex)
1355              {
1356                  return NSNotFound;
1357              }
1358              else
1359              {
1360                  return [self indexOfObject:obj inSortedRange:NSMakeRange(midIndex, maxIndex - minIndex) options:opts usingComparator:comparator];
1361              }
1362              break;
1363          case NSOrderedDescending:
1364              if ((opts & NSBinarySearchingInsertionIndex) && midIndex == minIndex)
1365              {
1366                  return minIndex;
1367              }
1368              else if (midIndex == minIndex)
1369              {
1370                  return NSNotFound;
1371              }
1372              else
1373              {
1374                  return [self indexOfObject:obj inSortedRange:NSMakeRange(minIndex, midIndex - minIndex) options:opts usingComparator:comparator];
1375              }
1376          case NSOrderedSame:
1377              if (opts & NSBinarySearchingFirstEqual)
1378              {
1379                  for (NSUInteger idx = midIndex; idx > 0; idx--)
1380                  {
1381                      mid = [self objectAtIndex:idx];
1382                      result = comparator(mid, obj);
1383  
1384                      if (result != NSOrderedSame)
1385                      {
1386                          return idx + 1;
1387                      }
1388                  }
1389                  return NSNotFound; // this is likely an error
1390              }
1391              else if (opts & NSBinarySearchingLastEqual)
1392              {
1393                  for (NSUInteger idx = midIndex; idx < [self count]; idx++)
1394                  {
1395                      mid = [self objectAtIndex:idx];
1396                      result = comparator(mid, obj);
1397  
1398                      if (result != NSOrderedSame)
1399                      {
1400                          return idx - 1;
1401                      }
1402                  }
1403                  return NSNotFound; // also likely to be an error
1404              }
1405              else
1406              {
1407                  return midIndex;
1408              }
1409              break;
1410      }
1411      return NSNotFound;
1412  }
1413  
1414  - (NSArray *)sortedArrayFromRange:(NSRange)range options:(NSSortOptions)opts usingComparator:(NSComparator)cmptr
1415  {
1416      if (cmptr == nil)
1417      {
1418          [self doesNotRecognizeSelector:_cmd];
1419          CFStringRef format = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("-[%s <null selector>] unrecognized selector 0x%x"), object_getClassName(self), self);
1420          [NSException raise:NSInvalidArgumentException format:(NSString *)format];
1421          CFRelease(format);
1422          return nil;
1423      }
1424  
1425      NSUInteger count = range.length;
1426      id objects[STACK_BUFFER_SIZE] = {0};
1427      CFIndex indices[STACK_BUFFER_SIZE] = {0};
1428      id *objs = &objects[0];
1429      CFIndex *indexes = &indices[0];
1430  
1431      if (count > STACK_BUFFER_SIZE)
1432      {
1433          objs = malloc(sizeof(id) * count);
1434  
1435          if (objs == NULL)
1436          {
1437              CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("unable to allocate space to store %d objects"), count);
1438              @throw [NSException exceptionWithName:NSMallocException reason:(NSString *)reason userInfo:nil];
1439              CFRelease(reason);
1440              return nil;
1441          }
1442          indexes = malloc(sizeof(CFIndex) * count);
1443          if (indexes == NULL)
1444          {
1445              free(objects);
1446              CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("unable to allocate space to store %d indices"), count);
1447              @throw [NSException exceptionWithName:NSMallocException reason:(NSString *)reason userInfo:nil];
1448              CFRelease(reason);
1449              return nil;
1450          }
1451      }
1452  
1453      [self getObjects:objs range:range];
1454      CFSortIndexes(indexes, count, opts, ^(CFIndex i1, CFIndex i2) {
1455          return (CFComparisonResult)cmptr(objs[i1], objs[i2]);
1456      });
1457      assert(sizeof(id) == sizeof(CFIndex));
1458  
1459      for (int i = 0; i < count; i++)
1460      {
1461          indexes[i] = (CFIndex)objs[indexes[i]]; // re-use indexes allocation
1462      }
1463  
1464      if (objs != objects)
1465      {
1466          free(objs);
1467      }
1468  
1469      // Note: the indexes is reused as an object store.
1470      NSArray *arr = [[NSArray alloc] initWithObjects:(id *)indexes count:count];
1471  
1472      if (indices != indexes)
1473      {
1474          free(indexes);
1475      }
1476  
1477      return [arr autorelease];
1478  }
1479  
1480  - (NSArray *)sortedArrayUsingComparator:(NSComparator)comparator
1481  {
1482      return [self sortedArrayWithOptions:NSSortStable usingComparator:comparator];
1483  }
1484  
1485  - (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)comparator
1486  {
1487      return [self sortedArrayFromRange:NSMakeRange(0, [self count]) options:opts usingComparator:comparator];
1488  }
1489  
1490  - (NSString *)description
1491  {
1492      return [self descriptionWithLocale:nil indent:0];
1493  }
1494  
1495  - (NSString *)descriptionWithLocale:(NSLocale *)locale
1496  {
1497      return [self descriptionWithLocale:locale indent:0];
1498  }
1499  
1500  - (NSString *)descriptionWithLocale:(NSLocale *)locale indent:(NSUInteger)level
1501  {
1502      CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0);
1503      CFStringAppendFormat(description, NULL, CFSTR("%*s{(\n"), (int)level * strlen(INDENT), "");
1504  
1505      NSUInteger count = [self count];
1506      NSUInteger idx = 1;
1507  
1508      for (id obj in self)
1509      {
1510          NSString *objDescription = nil;
1511          if ([obj respondsToSelector:@selector(descriptionWithLocale:indent:)])
1512          {
1513              objDescription = [obj descriptionWithLocale:locale indent:(level + 1)];
1514          }
1515          else if ([obj respondsToSelector:@selector(descriptionWithLocale:)])
1516          {
1517              objDescription = [obj descriptionWithLocale:locale];
1518          }
1519          else
1520          {
1521              objDescription = [obj description];
1522          }
1523  
1524          CFStringRef format;
1525  
1526          if (idx == count)
1527          {
1528              format = CFSTR("%*s%@\n");
1529          }
1530          else
1531          {
1532              format = CFSTR("%*s%@,\n");
1533          }
1534  
1535          CFStringAppendFormat(description, NULL, format, ((int)level + 1) * strlen(INDENT), "", objDescription);
1536  
1537          idx++;
1538      }
1539  
1540      CFStringAppendFormat(description, NULL, CFSTR("%*s)}"), (int)level * strlen(INDENT), "");
1541  
1542      CFStringRef desc = CFStringCreateCopy(kCFAllocatorDefault, description);
1543      CFRelease(description);
1544      return [(NSString *)desc autorelease];
1545  }
1546  
1547  @end
1548  
1549  @implementation NSMutableOrderedSet
1550  
1551  + (id)orderedSetWithCapacity:(NSUInteger)capacity
1552  {
1553      return [[[self alloc] initWithCapacity:capacity] autorelease];
1554  }
1555  
1556  - (id)initWithCapacity:(NSUInteger)capacity
1557  {
1558      NSRequestConcreteImplementation();
1559      return nil;
1560  }
1561  
1562  - (id)initWithObjects:(const id *)objects count:(NSUInteger)count
1563  {
1564      if (objects == NULL && count > 0)
1565      {
1566          [self release];
1567          [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with NULL array of and nonzero count"];
1568          return nil;
1569      }
1570  
1571      for (NSUInteger idx = 0; idx < count; idx++)
1572      {
1573          if (objects[idx] == nil)
1574          {
1575              [self release];
1576              [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with nil"];
1577              return nil;
1578          }
1579      }
1580  
1581      self = [self initWithCapacity:count];
1582      if (self != nil)
1583      {
1584          [self insertObjects:objects count:count atIndex:0];
1585      }
1586  
1587      return self;
1588  }
1589  
1590  - (Class)classForCoder
1591  {
1592      return [NSMutableOrderedSet class];
1593  }
1594  
1595  - (void)addObject:(id)object
1596  {
1597      if (object == nil)
1598      {
1599          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to orderded set"];
1600          return;
1601      }
1602  
1603      [self _mutate];
1604      [self insertObject:object atIndex:[self count]];
1605  }
1606  
1607  - (void)addObjects:(const id [])objects count:(NSUInteger)count
1608  {
1609      if (objects == NULL && count > 0)
1610      {
1611          [NSException raise:NSInvalidArgumentException format:@"Cannot add NULL array of objects with nonzero count to ordered set"];
1612          return;
1613      }
1614  
1615      for (NSUInteger idx = 0; idx < count; idx++)
1616      {
1617          id object = objects[idx];
1618          if (object == nil)
1619          {
1620              [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to ordered set"];
1621              return;
1622          }
1623      }
1624  
1625      [self _mutate];
1626      [self insertObjects:objects count:count atIndex:[self count]];
1627  }
1628  
1629  - (void)addObjectsFromSet:(NSSet *)set
1630  {
1631      [self _mutate];
1632      [self insertObjectsFromSet:set atIndex:[self count]];
1633  }
1634  
1635  - (void)addObjectsFromOrderedSet:(NSOrderedSet *)orderedSet
1636  {
1637      NSRange range = NSMakeRange(0, [orderedSet count]);
1638      [self _mutate];
1639      [self insertObjectsFromOrderedSet:orderedSet range:range atIndex:[self count]];
1640  }
1641  
1642  - (void)addObjectsFromOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range
1643  {
1644      if (NSMaxRange(range) > [orderedSet count])
1645      {
1646          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
1647          return;
1648      }
1649  
1650      [self _mutate];
1651      [self insertObjectsFromOrderedSet:orderedSet range:range atIndex:[self count]];
1652  }
1653  
1654  - (void)addObjectsFromArray:(NSArray *)array
1655  {
1656      NSRange range = NSMakeRange(0, [array count]);
1657      [self _mutate];
1658      [self insertObjectsFromArray:array range:range atIndex:[self count]];
1659  }
1660  
1661  - (void)addObjectsFromArray:(NSArray *)array range:(NSRange)range
1662  {
1663      if (NSMaxRange(range) > [array count])
1664      {
1665          [NSException raise:NSRangeException format:@"Range out of bounds of array"];
1666          return;
1667      }
1668  
1669      [self _mutate];
1670      [self insertObjectsFromArray:array range:range atIndex:[self count]];
1671  }
1672  
1673  - (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2
1674  {
1675      NSUInteger count = [self count];
1676  
1677      if (idx1 >= count || idx2 >= count)
1678      {
1679          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
1680          return;
1681      }
1682  
1683      id obj1 = [[self objectAtIndex:idx1] retain];
1684      id obj2 = [[self objectAtIndex:idx2] retain];
1685  
1686      [self _mutate];
1687  
1688      [self removeObjectAtIndex:idx1];
1689      [self insertObject:obj2 atIndex:idx1];
1690  
1691      [self removeObjectAtIndex:idx2];
1692      [self insertObject:obj1 atIndex:idx2];
1693  
1694      [obj1 release];
1695      [obj2 release];
1696  }
1697  
1698  - (void)moveObjectsAtIndexes:(NSIndexSet *)indexes toIndex:(NSUInteger)idx
1699  {
1700      NSUInteger count = [self count];
1701  
1702      if (idx >= count)
1703      {
1704          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
1705          return;
1706      }
1707  
1708      NSUInteger idxCount = [indexes count];
1709  
1710      if (idxCount == 0)
1711      {
1712          return;
1713      }
1714  
1715      if ([indexes lastIndex] >= count)
1716      {
1717          [NSException raise:NSInvalidArgumentException format:@"Indexes out of bounds of ordered set"];
1718          return;
1719      }
1720  
1721      NSArray *array = [self objectsAtIndexes:indexes];
1722  
1723      [self _mutate];
1724      [self removeObjectsAtIndexes:indexes];
1725  
1726      id *objects = malloc(idxCount * sizeof(id));
1727      if (objects == NULL)
1728      {
1729          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
1730          return;
1731      }
1732  
1733      NSRange range = NSMakeRange(0, idxCount);
1734      [array getObjects:objects range:range];
1735      [self insertObjects:objects count:idxCount atIndex:idx];
1736  
1737      free(objects);
1738  }
1739  
1740  - (void)setObject:(id)object
1741  {
1742      if (object == nil)
1743      {
1744          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to orderded set"];
1745          return;
1746      }
1747  
1748      NSUInteger idx = [self indexOfObject:object];
1749      if (idx == NSNotFound)
1750      {
1751          [NSException raise:NSInvalidArgumentException format:@"Object not in ordered set"];
1752          return;
1753      }
1754  
1755      [self _mutate];
1756      [self replaceObjectAtIndex:idx withObject:object];
1757  }
1758  
1759  - (void)setObject:(id)object atIndex:(NSUInteger)idx
1760  {
1761      if (object == nil)
1762      {
1763          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to orderded set"];
1764          return;
1765      }
1766  
1767      NSUInteger count = [self count];
1768  
1769      if (idx >= count)
1770      {
1771          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
1772          return;
1773      }
1774  
1775      [self _mutate];
1776  
1777      if (idx == count)
1778      {
1779          [self insertObject:object atIndex:idx];
1780      }
1781      else
1782      {
1783          [self replaceObjectAtIndex:idx withObject:object];
1784      }
1785  }
1786  
1787  - (void)setObject:(id)object atIndexedSubscript:(NSUInteger)idx
1788  {
1789      [self setObject:object atIndex:idx];
1790  }
1791  
1792  - (void)setSet:(NSSet *)set
1793  {
1794      [self _mutate];
1795      [self removeAllObjects];
1796      [self insertObjectsFromSet:set atIndex:0];
1797  }
1798  
1799  - (void)setOrderedSet:(NSOrderedSet *)orderedSet
1800  {
1801      [self _mutate];
1802      [self removeAllObjects];
1803      [self insertObjectsFromOrderedSet:orderedSet atIndex:0];
1804  }
1805  
1806  - (void)setArray:(NSArray *)array
1807  {
1808      [self _mutate];
1809      [self removeAllObjects];
1810      [self insertObjectsFromArray:array atIndex:0];
1811  }
1812  
1813  - (void)removeObjectAtIndex:(NSUInteger)idx
1814  {
1815      NSRequestConcreteImplementation();
1816  }
1817  
1818  - (void)removeObjectsInRange:(NSRange)range
1819  {
1820      NSUInteger maxRange = NSMaxRange(range);
1821  
1822      if (maxRange > [self count])
1823      {
1824          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
1825          return;
1826      }
1827  
1828      if (maxRange == 0)
1829      {
1830          return;
1831      }
1832  
1833      [self _mutate];
1834  
1835      NSUInteger idx = range.location;
1836  
1837      for (NSUInteger i = 0; i < range.length; i++)
1838      {
1839          [self removeObjectAtIndex:idx];
1840      }
1841  }
1842  
1843  - (void)removeObjectsAtIndexes:(NSIndexSet *)indexes
1844  {
1845      if (indexes == nil)
1846      {
1847          [NSException raise:NSInvalidArgumentException format:@"Index set cannot be nil"];
1848          return;
1849      }
1850  
1851      NSUInteger count = [indexes count];
1852  
1853      if (count > 0 && [indexes lastIndex] >= [self count])
1854      {
1855          [NSException raise:NSInvalidArgumentException format:@"Index set out of bounds of ordered set"];
1856          return;
1857      }
1858  
1859      if (count == 0)
1860      {
1861          return;
1862      }
1863  
1864      [self _mutate];
1865  
1866      [indexes enumerateRangesWithOptions:NSEnumerationReverse usingBlock:^(NSRange range, BOOL *stop) {
1867          [self removeObjectsInRange:range];
1868      }];
1869  }
1870  
1871  - (void)removeAllObjects
1872  {
1873      NSUInteger count = [self count];
1874  
1875      if (count == 0)
1876      {
1877          return;
1878      }
1879  
1880      [self _mutate];
1881  
1882      for (NSUInteger idx = count; idx > 0; idx--)
1883      {
1884          [self removeObjectAtIndex:idx - 1];
1885      }
1886  }
1887  
1888  - (void)removeObject:(id)object
1889  {
1890      NSUInteger idx = [self indexOfObject:object];
1891  
1892      if (idx == NSNotFound)
1893      {
1894          return;
1895      }
1896  
1897      [self _mutate];
1898  
1899      [self removeObjectAtIndex:idx];
1900  }
1901  
1902  - (void)removeObject:(id)object inRange:(NSRange)range
1903  {
1904      if (NSMaxRange(range) > [self count])
1905      {
1906          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
1907          return;
1908      }
1909  
1910      NSUInteger idx = [self indexOfObject:object inRange:range];
1911  
1912      if (idx == NSNotFound)
1913      {
1914          return;
1915      }
1916  
1917      [self _mutate];
1918  
1919      [self removeObjectAtIndex:idx];
1920  }
1921  
1922  - (void)removeObjectsInArray:(NSArray *)array
1923  {
1924      if ([array count] == 0)
1925      {
1926          return;
1927      }
1928  
1929      [self _mutate];
1930  
1931      for (id object in array)
1932      {
1933          NSUInteger idx = [self indexOfObject:object];
1934          if (idx != NSNotFound)
1935          {
1936              [self removeObjectAtIndex:idx];
1937          }
1938      }
1939  }
1940  
1941  - (void)removeObjectsInArray:(NSArray *)array range:(NSRange)arrayRange
1942  {
1943      NSUInteger arrayCount = [array count];
1944  
1945      if (NSMaxRange(arrayRange) > arrayCount)
1946      {
1947          [NSException raise:NSRangeException format:@"Range out of bounds of array"];
1948          return;
1949      }
1950  
1951      if (arrayCount == 0)
1952      {
1953          return;
1954      }
1955  
1956      [self _mutate];
1957  
1958      for (NSUInteger arrayIdx = arrayRange.length; arrayIdx < NSMaxRange(arrayRange); arrayIdx++)
1959      {
1960          id obj = [array objectAtIndex:arrayIdx];
1961          NSUInteger idx = [self indexOfObject:obj];
1962          if (idx != NSNotFound)
1963          {
1964              [self removeObjectAtIndex:idx];
1965          }
1966      }
1967  }
1968  
1969  - (void)removeObjectsInRange:(NSRange)range inArray:(NSArray *)array
1970  {
1971      if (NSMaxRange(range) > [self count])
1972      {
1973          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
1974          return;
1975      }
1976  
1977      if ([array count] == 0)
1978      {
1979          return;
1980      }
1981  
1982      [self _mutate];
1983  
1984      for (id object in array)
1985      {
1986          NSUInteger idx = [self indexOfObject:object inRange:range];
1987          if (idx != NSNotFound)
1988          {
1989              [self removeObjectAtIndex:idx];
1990          }
1991      }
1992  }
1993  
1994  - (void)removeObjectsInRange:(NSRange)range inArray:(NSArray *)array range:(NSRange)arrayRange
1995  {
1996      if (NSMaxRange(range) > [self count])
1997      {
1998          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
1999          return;
2000      }
2001  
2002      NSUInteger arrayCount = [array count];
2003  
2004      if (NSMaxRange(arrayRange) > arrayCount)
2005      {
2006          [NSException raise:NSRangeException format:@"Range out of bounds of array"];
2007          return;
2008      }
2009  
2010      if (arrayCount == 0)
2011      {
2012          return;
2013      }
2014  
2015      [self _mutate];
2016  
2017      for (NSUInteger arrayIdx = arrayRange.length; arrayIdx < NSMaxRange(arrayRange); arrayIdx++)
2018      {
2019          id obj = [array objectAtIndex:arrayIdx];
2020          NSUInteger idx = [self indexOfObject:obj inRange:range];
2021          if (idx != NSNotFound)
2022          {
2023              [self removeObjectAtIndex:idx];
2024          }
2025      }
2026  }
2027  
2028  - (void)removeObjectsInSet:(NSSet *)set
2029  {
2030      if ([set count] == 0)
2031      {
2032          return;
2033      }
2034  
2035      [self _mutate];
2036  
2037      for (id object in set)
2038      {
2039          NSUInteger idx = [self indexOfObject:object];
2040          if (idx != NSNotFound)
2041          {
2042              [self removeObjectAtIndex:idx];
2043          }
2044      }
2045  }
2046  
2047  - (void)removeObjectsInRange:(NSRange)range inSet:(NSSet *)set
2048  {
2049      if (NSMaxRange(range) > [self count])
2050      {
2051          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2052          return;
2053      }
2054  
2055      if (range.length == 0)
2056      {
2057          return;
2058      }
2059  
2060      for (id object in set)
2061      {
2062          NSUInteger idx = [self indexOfObject:object inRange:range];
2063          if (idx != NSNotFound)
2064          {
2065              [self removeObjectAtIndex:idx];
2066          }
2067      }
2068  }
2069  
2070  - (void)removeObjectsInOrderedSet:(NSOrderedSet *)orderedSet
2071  {
2072      if ([orderedSet count] == 0)
2073      {
2074          return;
2075      }
2076  
2077      [self _mutate];
2078  
2079      for (id object in orderedSet)
2080      {
2081          NSUInteger idx = [self indexOfObject:object];
2082          if (idx != NSNotFound)
2083          {
2084              [self removeObjectAtIndex:idx];
2085          }
2086      }
2087  }
2088  
2089  - (void)removeObjectsInOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)orderedSetRange
2090  {
2091      NSUInteger orderedSetCount = [orderedSet count];
2092  
2093      if (NSMaxRange(orderedSetRange) > orderedSetCount)
2094      {
2095          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2096          return;
2097      }
2098  
2099      if (orderedSetCount == 0)
2100      {
2101          return;
2102      }
2103  
2104      [self _mutate];
2105  
2106      for (NSUInteger orderedSetIdx = orderedSetRange.length; orderedSetIdx < NSMaxRange(orderedSetRange); orderedSetIdx++)
2107      {
2108          id obj = [orderedSet objectAtIndex:orderedSetIdx];
2109          NSUInteger idx = [self indexOfObject:obj];
2110          if (idx != NSNotFound)
2111          {
2112              [self removeObjectAtIndex:idx];
2113          }
2114      }
2115  }
2116  
2117  - (void)removeObjectsInRange:(NSRange)range inOrderedSet:(NSOrderedSet *)orderedSet
2118  {
2119      if (NSMaxRange(range) > [self count])
2120      {
2121          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2122          return;
2123      }
2124  
2125      if ([orderedSet count] == 0)
2126      {
2127          return;
2128      }
2129  
2130      [self _mutate];
2131  
2132      for (id obj in orderedSet)
2133      {
2134          NSUInteger idx = [self indexOfObject:obj inRange:range];
2135          if (idx != NSNotFound)
2136          {
2137              [self removeObjectAtIndex:idx];
2138          }
2139      }
2140  }
2141  
2142  - (void)removeObjectsInRange:(NSRange)range inOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)orderedSetRange
2143  {
2144      if (NSMaxRange(range) > [self count])
2145      {
2146          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2147          return;
2148      }
2149  
2150      NSUInteger orderedSetCount = [orderedSet count];
2151  
2152      if (NSMaxRange(orderedSetRange) > orderedSetCount)
2153      {
2154          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2155          return;
2156      }
2157  
2158      if (orderedSetCount == 0)
2159      {
2160          return;
2161      }
2162  
2163      [self _mutate];
2164  
2165      for (NSUInteger orderedSetIdx = orderedSetRange.length; orderedSetIdx < NSMaxRange(orderedSetRange); orderedSetIdx++)
2166      {
2167          id obj = [orderedSet objectAtIndex:orderedSetIdx];
2168          NSUInteger idx = [self indexOfObject:obj inRange:range];
2169          if (idx != NSNotFound)
2170          {
2171              [self removeObjectAtIndex:idx];
2172          }
2173      }
2174  }
2175  
2176  - (void)removeFirstObject
2177  {
2178      if ([self count] == 0)
2179      {
2180          return;
2181      }
2182  
2183      [self removeObjectAtIndex:0];
2184  }
2185  
2186  - (void)removeLastObject
2187  {
2188      NSUInteger count = [self count];
2189  
2190      if (count == 0)
2191      {
2192          return;
2193      }
2194  
2195      [self removeObjectAtIndex:count - 1];
2196  }
2197  
2198  - (void)removeObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
2199  {
2200      if (test == nil)
2201      {
2202          [NSException raise:NSInvalidArgumentException format:@"Test block cannot be nil"];
2203          return;
2204      }
2205  
2206      [self removeObjectsWithOptions:0 passingTest:test];
2207  }
2208  
2209  - (void)removeObjectsWithOptions:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
2210  {
2211  #warning TODO
2212      DEBUG_BREAK();
2213  }
2214  
2215  - (void)removeObjectsAtIndexes:(NSIndexSet *)indexes options:(NSEnumerationOptions)options passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))test
2216  {
2217      if (test == nil)
2218      {
2219          [NSException raise:NSInvalidArgumentException format:@"Test block cannot be nil"];
2220          return;
2221      }
2222  
2223  #warning TODO
2224      DEBUG_BREAK();
2225  }
2226  
2227  - (void)intersectOrderedSet:(NSOrderedSet *)orderedSet
2228  {
2229      id *objectsToRemove = malloc([self count] * sizeof(id));
2230      if (objectsToRemove == NULL)
2231      {
2232          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2233          return;
2234      }
2235  
2236      NSUInteger removalCount = 0;
2237  
2238      for (id obj in self)
2239      {
2240          if (![orderedSet containsObject:obj])
2241          {
2242              objectsToRemove[removalCount++] = obj;
2243          }
2244      }
2245  
2246      [self _mutate];
2247  
2248      for (NSUInteger idx = removalCount; idx > 0; idx--)
2249      {
2250          [self removeObjectAtIndex:idx - 1];
2251      }
2252  
2253      free(objectsToRemove);
2254  }
2255  
2256  - (void)minusOrderedSet:(NSOrderedSet *)orderedSet
2257  {
2258      [self _mutate];
2259  
2260      for (id obj in orderedSet)
2261      {
2262          [self removeObject:obj];
2263      }
2264  }
2265  
2266  - (void)unionOrderedSet:(NSOrderedSet *)orderedSet
2267  {
2268      [self _mutate];
2269  
2270      for (id obj in orderedSet)
2271      {
2272          [self addObject:obj];
2273      }
2274  }
2275  
2276  - (void)intersectSet:(NSSet *)set
2277  {
2278      id *objectsToRemove = malloc([self count] * sizeof(id));
2279  
2280      if (objectsToRemove == NULL)
2281      {
2282          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2283          return;
2284      }
2285  
2286      NSUInteger removalCount = 0;
2287  
2288      for (id obj in self)
2289      {
2290          if (![set containsObject:obj])
2291          {
2292              objectsToRemove[removalCount++] = obj;
2293          }
2294      }
2295  
2296      [self _mutate];
2297  
2298      for (NSUInteger idx = removalCount; idx > 0; idx--)
2299      {
2300          [self removeObjectAtIndex:idx - 1];
2301      }
2302  
2303      free(objectsToRemove);
2304  }
2305  
2306  - (void)minusSet:(NSSet *)set
2307  {
2308      [self _mutate];
2309  
2310      for (id obj in set)
2311      {
2312          [self removeObject:obj];
2313      }
2314  }
2315  
2316  - (void)unionSet:(NSSet *)set
2317  {
2318      [self _mutate];
2319  
2320      for (id obj in set)
2321      {
2322          [self addObject:obj];
2323      }
2324  }
2325  
2326  #if NS_BLOCKS_AVAILABLE
2327  
2328  - (void)sortUsingComparator:(NSComparator)comparator
2329  {
2330      if (comparator == nil)
2331      {
2332          [NSException raise:NSInvalidArgumentException format:@"Comparator cannot be nil"];
2333          return;
2334      }
2335  
2336      NSRange range = NSMakeRange(0, [self count]);
2337      [self sortRange:range options:0 usingComparator:comparator];
2338  }
2339  
2340  - (void)sortWithOptions:(NSSortOptions)options usingComparator:(NSComparator)comparator
2341  {
2342      if (comparator == nil)
2343      {
2344          [NSException raise:NSInvalidArgumentException format:@"Comparator cannot be nil"];
2345          return;
2346      }
2347  
2348      NSRange range = NSMakeRange(0, [self count]);
2349      [self sortRange:range options:options usingComparator:comparator];
2350  }
2351  
2352  - (void)sortRange:(NSRange)range options:(NSSortOptions)options usingComparator:(NSComparator)comparator
2353  {
2354      if (comparator == nil)
2355      {
2356          [NSException raise:NSInvalidArgumentException format:@"Comparator cannot be nil"];
2357          return;
2358      }
2359  
2360      NSUInteger count = [self count];
2361  
2362      if (NSMaxRange(range) > count)
2363      {
2364          [NSException raise:NSInvalidArgumentException format:@"Range out of bounds of ordered set"];
2365          return;
2366      }
2367  
2368      if (range.length == 0)
2369      {
2370          return;
2371      }
2372  
2373      CFIndex *indexes = malloc(range.length * sizeof(*indexes));
2374  
2375      if (indexes == NULL)
2376      {
2377          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2378          return;
2379      }
2380  
2381      id *objects = malloc(range.length * sizeof(id));
2382  
2383      if (objects == NULL)
2384      {
2385          free(indexes);
2386          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2387          return;
2388      }
2389  
2390      [self getObjects:objects range:range];
2391  
2392      CFSortIndexes(indexes, range.length, options, ^(CFIndex idx1, CFIndex idx2) {
2393          return (CFComparisonResult)comparator(objects[idx1], objects[idx2]);
2394      });
2395      
2396      assert(sizeof(id) == sizeof(CFIndex));
2397      
2398      for (int i = 0; i < count; i++)
2399      {
2400          indexes[i] = (CFIndex)objects[indexes[i]]; // re-use indexes allocation
2401      }
2402      
2403      [self replaceObjectsInRange:range withObjects:(id*)indexes count:range.length];
2404  
2405      free(indexes);
2406      free(objects);
2407  }
2408  
2409  #endif // NS_BLOCK_AVAILABLE
2410  
2411  - (void)rollObjectsInRange:(NSRange)range by:(NSInteger)rollAmount
2412  {
2413      if (NSMaxRange(range) > [self count])
2414      {
2415          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2416          return;
2417      }
2418  
2419      if (range.length == 0)
2420      {
2421          return;
2422      }
2423  
2424      rollAmount %= range.length;
2425  
2426      if (rollAmount == 0)
2427      {
2428          return;
2429      }
2430  
2431      id *objects = malloc(range.length * sizeof(id));
2432  
2433      if (objects == NULL)
2434      {
2435          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2436          return;
2437      }
2438  
2439      NSRange leftRange = NSMakeRange(range.location, range.length - rollAmount);
2440      NSRange rightRange = NSMakeRange(NSMaxRange(leftRange), rollAmount);
2441  
2442      id *rightObjects = objects;
2443      id *leftObjects = objects + rightRange.length;
2444  
2445      [self getObjects:leftObjects range:leftRange];
2446      [self getObjects:rightObjects range:rightRange];
2447  
2448      [self _mutate];
2449  
2450      [self removeObjectsInRange:range];
2451      [self insertObjects:objects count:range.length atIndex:range.location];
2452  
2453      for (NSUInteger idx = 0; idx < range.length; idx++)
2454      {
2455          [objects[idx] release];
2456      }
2457  
2458      free(objects);
2459  }
2460  
2461  - (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)object
2462  {
2463      NSRequestConcreteImplementation();
2464  }
2465  
2466  - (void)replaceObject:(id)object
2467  {
2468      if (object == nil)
2469      {
2470          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to ordered set"];
2471          return;
2472      }
2473  
2474      NSUInteger idx = [self indexOfObject:object];
2475  
2476      if (idx == NSNotFound)
2477      {
2478          return;
2479      }
2480  
2481      [self _mutate];
2482  
2483      [self replaceObjectAtIndex:idx withObject:object];
2484  }
2485  
2486  - (void)replaceObject:(id)object inRange:(NSRange)range
2487  {
2488      if (object == nil)
2489      {
2490          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to ordered set"];
2491          return;
2492      }
2493  
2494      if (NSMaxRange(range) > [self count])
2495      {
2496          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2497          return;
2498      }
2499  
2500      NSUInteger idx = [self indexOfObject:object inRange:range];
2501  
2502      if (idx == NSNotFound)
2503      {
2504          return;
2505      }
2506  
2507      [self _mutate];
2508  
2509      [self replaceObjectAtIndex:idx withObject:object];
2510  }
2511  
2512  - (void)replaceObjectsInRange:(NSRange)range withObjects:(const id [])objects count:(NSUInteger)count
2513  {
2514      if (objects == NULL && count > 0)
2515      {
2516          [NSException raise:NSInvalidArgumentException format:@"Cannot insert NULL objects with nonzero count into ordered set"];
2517          return;
2518      }
2519  
2520      if (NSMaxRange(range) > [self count])
2521      {
2522          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2523          return;
2524      }
2525  
2526      if (count == 0 && range.length == 0)
2527      {
2528          return;
2529      }
2530  
2531      for (NSUInteger idx = 0; idx < count; idx++)
2532      {
2533          if (objects[idx] == nil)
2534          {
2535              [NSException raise:NSInvalidArgumentException format:@"Cannot insert nil into ordered set"];
2536              return;
2537          }
2538      }
2539  
2540      for (NSUInteger idx = 0; idx < count; idx++)
2541      {
2542          [objects[idx] retain];
2543      }
2544  
2545      [self _mutate];
2546  
2547      [self removeObjectsInRange:range];
2548      [self insertObjects:objects count:count atIndex:range.location];
2549  
2550      for (NSUInteger idx = 0; idx < count; idx++)
2551      {
2552          [objects[idx] release];
2553      }
2554  }
2555  
2556  - (void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objectArray
2557  {
2558      NSUInteger indexCount = [indexes count];
2559  
2560      if (indexCount != [objectArray count])
2561      {
2562          [NSException raise:NSInvalidArgumentException format:@"Different numbers of indexes and objects"];
2563          return;
2564      }
2565  
2566      if (indexCount == 0)
2567      {
2568          return;
2569      }
2570  
2571      if ([indexes lastIndex] >= [self count])
2572      {
2573          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2574          return;
2575      }
2576  
2577      id *objects = malloc(indexCount * sizeof(id));
2578      if (objects == NULL)
2579      {
2580          [NSException raise:NSMallocException format:@"Could not allocate buffer"];
2581          return;
2582      }
2583  
2584      [objectArray getObjects:objects range:NSMakeRange(0, indexCount)];
2585  
2586      for (NSUInteger idx = 0; idx < indexCount; idx++)
2587      {
2588          if (objects[idx] == nil)
2589          {
2590              free(objects);
2591              [NSException raise:NSInvalidArgumentException format:@"Cannot add nil to ordered set"];
2592              return;
2593          }
2594      }
2595  
2596      for (NSUInteger idx = 0; idx < indexCount; idx++)
2597      {
2598          [objects[idx] retain];
2599      }
2600  
2601      [self _mutate];
2602  
2603      [indexes enumerateRangesWithOptions:NSEnumerationReverse usingBlock:^(NSRange range, BOOL *stop) {
2604          [self removeObjectsInRange:range];
2605      }];
2606  
2607      __block id *currentObjectPtr = objects;
2608      [indexes enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
2609          [self insertObjects:currentObjectPtr count:range.length atIndex:range.location];
2610          currentObjectPtr += range.length;
2611      }];
2612  
2613      for (NSUInteger idx = 0; idx < indexCount; idx++)
2614      {
2615          [objects[idx] release];
2616      }
2617  
2618      free(objects);
2619  }
2620  
2621  - (void)replaceObjectsInRange:(NSRange)range withObjectsFromSet:(NSSet *)set
2622  {
2623      if (NSMaxRange(range) > [self count])
2624      {
2625          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2626          return;
2627      }
2628  
2629      NSUInteger setCount = [set count];
2630  
2631      if (range.length == 0 && setCount == 0)
2632      {
2633          return;
2634      }
2635  
2636      id *objects = malloc(setCount * sizeof(id));
2637      if (objects == NULL)
2638      {
2639          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2640          return;
2641      }
2642  
2643      [set getObjects:objects count:setCount];
2644  
2645      [self _mutate];
2646      [self replaceObjectsInRange:range withObjects:objects count:setCount];
2647  
2648      free(objects);
2649  }
2650  
2651  - (void)replaceObjectsInRange:(NSRange)range withObjectsFromOrderedSet:(NSOrderedSet *)orderedSet
2652  {
2653      if (NSMaxRange(range) > [self count])
2654      {
2655          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2656          return;
2657      }
2658  
2659      NSUInteger orderedSetCount = [orderedSet count];
2660  
2661      if (range.length == 0 && orderedSetCount == 0)
2662      {
2663          return;
2664      }
2665  
2666      id *objects = malloc(orderedSetCount * sizeof(id));
2667      if (objects == NULL)
2668      {
2669          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2670          return;
2671      }
2672  
2673      [orderedSet getObjects:objects range:NSMakeRange(0, orderedSetCount)];
2674  
2675      [self _mutate];
2676      [self replaceObjectsInRange:range withObjects:objects count:orderedSetCount];
2677  
2678      free(objects);
2679  }
2680  
2681  - (void)replaceObjectsInRange:(NSRange)range withObjectsFromOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)newRange
2682  {
2683      if (NSMaxRange(range) > [self count])
2684      {
2685          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2686          return;
2687      }
2688  
2689      NSUInteger orderedSetCount = [orderedSet count];
2690  
2691      if (NSMaxRange(newRange) > orderedSetCount)
2692      {
2693          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2694          return;
2695      }
2696  
2697      if (range.length == 0 && orderedSetCount == 0)
2698      {
2699          return;
2700      }
2701  
2702      id *objects = malloc(orderedSetCount * sizeof(id));
2703      if (objects == NULL)
2704      {
2705          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2706          return;
2707      }
2708  
2709      [orderedSet getObjects:objects range:newRange];
2710  
2711      [self _mutate];
2712      [self replaceObjectsInRange:range withObjects:objects count:orderedSetCount];
2713  
2714      free(objects);
2715  }
2716  
2717  - (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)array
2718  {
2719      if (NSMaxRange(range) > [self count])
2720      {
2721          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2722          return;
2723      }
2724  
2725      NSUInteger arrayCount = [array count];
2726  
2727      if (range.length == 0 && arrayCount == 0)
2728      {
2729          return;
2730      }
2731  
2732      id *objects = malloc(arrayCount * sizeof(id));
2733      if (objects == NULL)
2734      {
2735          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2736          return;
2737      }
2738  
2739      [array getObjects:objects range:NSMakeRange(0, arrayCount)];
2740  
2741      [self _mutate];
2742      [self replaceObjectsInRange:range withObjects:objects count:arrayCount];
2743  
2744      free(objects);
2745  }
2746  
2747  - (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)array range:(NSRange)newRange
2748  {
2749      if (NSMaxRange(range) > [self count])
2750      {
2751          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
2752          return;
2753      }
2754  
2755      NSUInteger arrayCount = [array count];
2756  
2757      if (NSMaxRange(newRange) > arrayCount)
2758      {
2759          [NSException raise:NSRangeException format:@"Range out of bounds of array"];
2760          return;
2761      }
2762  
2763      if (range.length == 0 && arrayCount == 0)
2764      {
2765          return;
2766      }
2767  
2768      id *objects = malloc(arrayCount * sizeof(id));
2769      if (objects == NULL)
2770      {
2771          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2772          return;
2773      }
2774  
2775      [array getObjects:objects range:newRange];
2776  
2777      [self _mutate];
2778      [self replaceObjectsInRange:range withObjects:objects count:arrayCount];
2779  
2780      free(objects);
2781  }
2782  
2783  - (void)insertObject:(id)object atIndex:(NSUInteger)idx
2784  {
2785      NSRequestConcreteImplementation();
2786  }
2787  
2788  - (void)insertObjects:(NSArray *)array atIndexes:(NSIndexSet *)indexes
2789  {
2790      if (indexes == nil)
2791      {
2792          [NSException raise:NSInvalidArgumentException format:@"Index set cannot be nil"];
2793          return;
2794      }
2795  
2796      NSUInteger indexCount = [indexes count];
2797      NSUInteger arrayCount = [array count];
2798  
2799      if (indexCount > 0 && [indexes lastIndex] >= ([self count] + indexCount))
2800      {
2801          [NSException raise:NSInvalidArgumentException format:@"Index set out of bounds of ordered set"];
2802          return;
2803      }
2804  
2805      if (indexCount != arrayCount)
2806      {
2807          [NSException raise:NSInvalidArgumentException format:@"Differing numbers of indexes and array elements"];
2808          return;
2809      }
2810  
2811      if (arrayCount == 0)
2812      {
2813          return;
2814      }
2815  
2816      id *objects = malloc(arrayCount * sizeof(id));
2817  
2818      if (objects == NULL)
2819      {
2820          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2821          return;
2822      }
2823  
2824      NSRange range = NSMakeRange(0, arrayCount);
2825      [array getObjects:objects range:range];
2826  
2827      [self _mutate];
2828  
2829      __block id *currentObjectPtr = objects;
2830      [indexes enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
2831          [self insertObjects:currentObjectPtr count:range.length atIndex:range.location];
2832          currentObjectPtr += range.length;
2833      }];
2834      
2835      free(objects);
2836  }
2837  
2838  - (void)insertObjectsFromSet:(NSSet *)set atIndex:(NSUInteger)idx
2839  {
2840      if (idx > [self count])
2841      {
2842          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
2843          return;
2844      }
2845  
2846      NSUInteger count = [set count];
2847  
2848      if (count == 0)
2849      {
2850          return;
2851      }
2852  
2853      id *objects = malloc(count * sizeof(id));
2854  
2855      if (objects == NULL)
2856      {
2857          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2858          return;
2859      }
2860  
2861      [set getObjects:objects count:count];
2862  
2863      [self _mutate];
2864      [self insertObjects:objects count:count atIndex:idx];
2865  
2866      free(objects);
2867  }
2868  
2869  - (void)insertObjectsFromOrderedSet:(NSOrderedSet *)orderedSet atIndex:(NSUInteger)idx
2870  {
2871      if (idx > [self count])
2872      {
2873          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
2874          return;
2875      }
2876  
2877      NSUInteger count = [orderedSet count];
2878  
2879      if (count == 0)
2880      {
2881          return;
2882      }
2883  
2884      id *objects = malloc(count * sizeof(id));
2885  
2886      if (objects == NULL)
2887      {
2888          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2889          return;
2890      }
2891  
2892      NSRange range = NSMakeRange(0, count);
2893      [orderedSet getObjects:objects range:range];
2894  
2895      [self _mutate];
2896      [self insertObjects:objects count:count atIndex:idx];
2897  
2898      free(objects);
2899  }
2900  
2901  - (void)insertObjectsFromOrderedSet:(NSOrderedSet *)orderedSet range:(NSRange)range atIndex:(NSUInteger)idx
2902  {
2903      if (idx > [self count])
2904      {
2905          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
2906          return;
2907      }
2908  
2909      NSUInteger count = [orderedSet count];
2910  
2911      if (count == 0)
2912      {
2913          return;
2914      }
2915  
2916      id *objects = malloc(count * sizeof(id));
2917  
2918      if (objects == NULL)
2919      {
2920          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2921          return;
2922      }
2923  
2924      [orderedSet getObjects:objects range:range];
2925  
2926      [self _mutate];
2927      [self insertObjects:objects count:count atIndex:idx];
2928  
2929      free(objects);
2930  }
2931  
2932  - (void)insertObjectsFromArray:(NSArray *)array atIndex:(NSUInteger)idx
2933  {
2934      if (idx > [self count])
2935      {
2936          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
2937          return;
2938      }
2939  
2940      NSUInteger count = [array count];
2941  
2942      if (count == 0)
2943      {
2944          return;
2945      }
2946  
2947      id *objects = malloc(count * sizeof(id));
2948  
2949      if (objects == NULL)
2950      {
2951          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2952          return;
2953      }
2954  
2955      NSRange range = NSMakeRange(0, count);
2956      [array getObjects:objects range:range];
2957  
2958      [self _mutate];
2959      [self insertObjects:objects count:count atIndex:idx];
2960  
2961      free(objects);
2962  }
2963  
2964  - (void)insertObjectsFromArray:(NSArray *)array range:(NSRange)range atIndex:(NSUInteger)idx
2965  {
2966      if (idx > [self count])
2967      {
2968          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
2969          return;
2970      }
2971  
2972      NSUInteger count = [array count];
2973  
2974      if (count == 0)
2975      {
2976          return;
2977      }
2978  
2979      id *objects = malloc(count * sizeof(id));
2980  
2981      if (objects == NULL)
2982      {
2983          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
2984          return;
2985      }
2986  
2987      [array getObjects:objects range:range];
2988  
2989      [self _mutate];
2990      [self insertObjects:objects count:count atIndex:idx];
2991  
2992      free(objects);
2993  }
2994  
2995  - (void)insertObjects:(const id *)objects count:(NSUInteger)count atIndex:(NSUInteger)idx
2996  {
2997      if (objects == NULL && count > 0)
2998      {
2999          [NSException raise:NSInvalidArgumentException format:@"Cannot insert NULL objects with nonzero count into ordered set"];
3000          return;
3001      }
3002  
3003      if (idx > [self count])
3004      {
3005          [NSException raise:NSInvalidArgumentException format:@"Index out of bounds of ordered set"];
3006          return;
3007      }
3008  
3009      if (count == 0)
3010      {
3011          return;
3012      }
3013  
3014      [self _mutate];
3015      NSUInteger countBeforeLoop = [self count];
3016      for (NSUInteger objIdx = 0; objIdx < count; objIdx++)
3017      {
3018          id obj = objects[objIdx];
3019          if (obj == nil)
3020          {
3021              [NSException raise:NSInvalidArgumentException format:@"Cannot insert nil into ordered set"];
3022              return;
3023          }
3024          NSUInteger index = idx + [self count] - countBeforeLoop;
3025          [self insertObject:obj atIndex:index];
3026      }
3027  }
3028  
3029  - (void)_mutate
3030  {
3031  }
3032  
3033  @end
3034  
3035  @implementation __NSPlaceholderOrderedSet
3036  
3037  static __NSPlaceholderOrderedSet *immutablePlaceholder = nil;
3038  static __NSPlaceholderOrderedSet *mutablePlaceholder = nil;
3039  
3040  + (id)immutablePlaceholder
3041  {
3042      static dispatch_once_t once = 0L;
3043      dispatch_once(&once, ^{
3044          immutablePlaceholder = [__NSPlaceholderOrderedSet allocWithZone:nil];
3045      });
3046      return immutablePlaceholder;
3047  }
3048  
3049  + (id)mutablePlaceholder
3050  {
3051      static dispatch_once_t once = 0L;
3052      dispatch_once(&once, ^{
3053          mutablePlaceholder = [__NSPlaceholderOrderedSet allocWithZone:nil];
3054      });
3055      return mutablePlaceholder;
3056  }
3057  
3058  - (id)init
3059  {
3060      if (self == immutablePlaceholder)
3061      {
3062          return [self initWithObjects:NULL count:0];
3063      }
3064      else if (self == mutablePlaceholder)
3065      {
3066          return [self initWithCapacity:0];
3067      }
3068      else
3069      {
3070          DEBUG_BREAK();
3071          return nil;
3072      }
3073  }
3074  
3075  - (id)initWithCapacity:(NSUInteger)capacity
3076  {
3077      if (self != mutablePlaceholder)
3078      {
3079          DEBUG_BREAK();
3080          return nil;
3081      }
3082  
3083      NSCapacityCheck(capacity, 0x40000000, @"Please rethink the size of the capacity of the ordered set you are creating: %d seems a bit excessive", capacity);
3084      return (__NSPlaceholderOrderedSet *)[__NSOrderedSetM __new:NULL :capacity :NO];
3085  }
3086  
3087  - (id)initWithObjects:(const id *)objects count:(NSUInteger)count
3088  {
3089      if (self != immutablePlaceholder && self != mutablePlaceholder)
3090      {
3091          [self release];
3092          [NSException raise:NSInvalidArgumentException format:@"Cannot reinit ordered set"];
3093          return nil;
3094      }
3095  
3096      if (objects == NULL && count > 0)
3097      {
3098          [self release];
3099          [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with NULL objects and nonzero count"];
3100          return nil;
3101      }
3102  
3103      for (NSUInteger idx = 0; idx < count; idx++)
3104      {
3105          id obj = objects[idx];
3106          if (obj == nil)
3107          {
3108              [self release];
3109              [NSException raise:NSInvalidArgumentException format:@"Cannot init ordered set with nil object"];
3110              return nil;
3111          }
3112          [obj retain];
3113      }
3114  
3115      if (self == immutablePlaceholder)
3116      {
3117          if (count == 0)
3118          {
3119              static __NSOrderedSetI *__NSOrderedSetI0 = nil;
3120              static dispatch_once_t once = 0L;
3121              dispatch_once(&once, ^{
3122                  __NSOrderedSetI0 = [__NSOrderedSetI __new:NULL :0 :NO];
3123              });
3124              return (__NSPlaceholderOrderedSet *)[__NSOrderedSetI0 retain];
3125          }
3126          else
3127          {
3128              return (__NSPlaceholderOrderedSet *)[__NSOrderedSetI __new:objects :count :NO];
3129          }
3130      }
3131      else
3132      {
3133          return (__NSPlaceholderOrderedSet *)[__NSOrderedSetM __new:objects :count :NO];
3134      }
3135  }
3136  
3137  SINGLETON_RR()
3138  
3139  - (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)object
3140  {
3141      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3142      return;
3143  }
3144  
3145  - (void)removeObjectAtIndex:(NSUInteger)idx
3146  {
3147      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3148      return;
3149  }
3150  
3151  - (void)insertObject:(id)object atIndex:(NSUInteger)idx
3152  {
3153      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3154      return;
3155  }
3156  
3157  - (id)objectAtIndex:(NSUInteger)idx
3158  {
3159      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3160      return nil;
3161  }
3162  
3163  - (NSUInteger)indexOfObject:(id)object
3164  {
3165      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3166      return 0;
3167  }
3168  
3169  - (NSUInteger)count
3170  {
3171      [NSException raise:NSInvalidArgumentException format:@"Message sent to uninitialized ordered set"];
3172      return 0;
3173  }
3174  
3175  @end
3176  
3177  @implementation __NSOrderedSetI
3178  
3179  // Use the same capacities and sizes as CFBasicHash.c
3180  
3181  
3182  + (id)allocWithZone:(NSZone *)zone
3183  {
3184      return (__NSOrderedSetI *)[__NSPlaceholderOrderedSet allocWithZone:zone];
3185  }
3186  
3187  + (id)__new:(const id *)objects :(NSUInteger)count :(BOOL)tbd
3188  {
3189      NSUInteger sizeIdx = 0;
3190      NSUInteger primeSize = 0;
3191  
3192      id *uniqueObjects = NSBasicHashAllocate(count, 2 * sizeof(id), &primeSize, &sizeIdx, NO);
3193  
3194      if (uniqueObjects == NULL)
3195      {
3196          [NSException raise:NSMallocException format:@"Failed to allocate buffer"];
3197          return nil;
3198      }
3199  
3200      NSUInteger *uniqueIndexes = (NSUInteger *)uniqueObjects + primeSize;
3201  
3202      NSUInteger uniqueCount = 0;
3203  
3204      for (NSUInteger idx = 0; idx < count; idx++)
3205      {
3206          id obj = objects[idx];
3207          NSUInteger hash = [obj hash];
3208          NSUInteger bucket = hash % primeSize;
3209  
3210          if (uniqueIndexes[bucket] == 0)
3211          {
3212              uniqueIndexes[bucket] = idx + 1;
3213              uniqueObjects[uniqueCount++] = obj;
3214              continue;
3215          }
3216  
3217          BOOL unique = YES;
3218          for (NSUInteger uniqueIdx = 0; uniqueIdx < uniqueCount; uniqueIdx++)
3219          {
3220              id uniqueObj = uniqueObjects[uniqueIdx];
3221  
3222              if (uniqueObj == nil)
3223              {
3224                  continue;
3225              }
3226  
3227              if (obj == uniqueObj || (hash == [uniqueObj hash] && [obj isEqual:uniqueObj]))
3228              {
3229                  unique = NO;
3230                  break;
3231              }
3232          }
3233  
3234          if (unique)
3235          {
3236              uniqueObjects[uniqueCount++] = obj;
3237          }
3238      }
3239  
3240      size_t extraBytes = uniqueCount * sizeof(id) + primeSize * sizeof(NSUInteger);
3241      __NSOrderedSetI *orderedSet = ___CFAllocateObject2(self, extraBytes);
3242  
3243      id *indexedIvarObjects = object_getIndexedIvars(orderedSet);
3244      memmove(indexedIvarObjects, uniqueObjects, uniqueCount * sizeof(id));
3245  
3246      NSUInteger *indexedIvarIndexes = (NSUInteger *)indexedIvarObjects + uniqueCount;
3247      memmove(indexedIvarIndexes, uniqueIndexes, primeSize * sizeof(NSUInteger));
3248  
3249      orderedSet->_used = uniqueCount;
3250      orderedSet->_szidx = sizeIdx;
3251  
3252      NSBasicHashDeallocate(uniqueObjects);
3253  
3254      return orderedSet;
3255  }
3256  
3257  + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
3258  {
3259      return NO;
3260  }
3261  
3262  - (void)dealloc
3263  {
3264      if (self == (__NSOrderedSetI *)immutablePlaceholder)
3265      {
3266          DEBUG_BREAK();
3267          [super dealloc];
3268      }
3269  
3270      id *objects = object_getIndexedIvars(self);
3271  
3272      NSUInteger count = [self count];
3273  
3274      for (NSUInteger idx = 0; idx < count; idx++)
3275      {
3276          CFRelease(objects[idx]);
3277      }
3278  
3279      [super dealloc];
3280  }
3281  
3282  - (id)copyWithZone:(NSZone *)zone
3283  {
3284      return [self retain];
3285  }
3286  
3287  - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)options usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
3288  {
3289      if (block == nil)
3290      {
3291          [NSException raise:NSInvalidArgumentException format:@"Block must not be nil"];
3292          return;
3293      }
3294  
3295      NSUInteger count = [self count];
3296      id *objects = object_getIndexedIvars(self);
3297  
3298      if ((options & NSEnumerationConcurrent) != 0)
3299      {
3300          __block BOOL stop = NO;
3301  
3302          dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3303  
3304          void (^dispatchBlock)(size_t);
3305  
3306          if ((options & NSEnumerationReverse) != 0)
3307          {
3308              dispatchBlock = ^(size_t iter) {
3309                  if (!stop)
3310                  {
3311                      NSUInteger idx = count - iter - 1;
3312                      id obj = objects[idx];
3313                      block(obj, idx, &stop);
3314                  }
3315              };
3316          }
3317          else
3318          {
3319              dispatchBlock = ^(size_t idx) {
3320                  if (!stop)
3321                  {
3322                      id obj = objects[idx];
3323                      block(obj, idx, &stop);
3324                  }
3325              };
3326          }
3327  
3328          dispatch_apply(count, queue, dispatchBlock);
3329      }
3330      else
3331      {
3332          BOOL stop = NO;
3333          if ((options & NSEnumerationReverse) != 0)
3334          {
3335              for (NSUInteger idx = count; idx > 0; idx--)
3336              {
3337                  if (stop)
3338                  {
3339                      return;
3340                  }
3341                  block(objects[idx - 1], idx - 1, &stop);
3342              }
3343          }
3344          else
3345          {
3346              for (NSUInteger idx = 0; idx < count; idx++)
3347              {
3348                  if (stop)
3349                  {
3350                      return;
3351                  }
3352                  block(objects[idx], idx, &stop);
3353              }
3354          }
3355      }
3356  }
3357  
3358  - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)objects count:(NSUInteger)count
3359  {
3360      if (objects == NULL && count != 0)
3361      {
3362          [NSException raise:NSInvalidArgumentException format:@"Cannot enumerate into NULL buffer of nonzero length"];
3363          return 0;
3364      }
3365      
3366      if (state->state != 0)
3367      {
3368          return 0;
3369      }
3370      
3371      static const unsigned long const_mu = 1;
3372      state->mutationsPtr = (unsigned long *)&const_mu;
3373      state->state = -1;
3374      state->itemsPtr = object_getIndexedIvars(self);
3375  
3376      return _used;
3377  }
3378  
3379  - (void)getObjects:(id *)objects range:(NSRange)range
3380  {
3381      if (objects == NULL && range.length > 0)
3382      {
3383          [NSException raise:NSInvalidArgumentException format:@"Cannot place objects into NULL array"];
3384          return;
3385      }
3386  
3387      if (NSMaxRange(range) > [self count])
3388      {
3389          [NSException raise:NSRangeException format:@"Range exceeds bounds of ordered set"];
3390          return;
3391      }
3392  
3393      id *currentObjects = object_getIndexedIvars(self);
3394      memmove(objects, currentObjects + range.location, range.length * sizeof(id));
3395  }
3396  
3397  - (id)objectAtIndex:(NSUInteger)idx
3398  {
3399      if (idx >= [self count])
3400      {
3401          [NSException raise:NSRangeException format:@"Index out of bounds of ordered set"];
3402          return nil;
3403      }
3404  
3405      id *objects = object_getIndexedIvars(self);
3406      return objects[idx];
3407  }
3408  
3409  - (NSUInteger)indexOfObject:(id)object
3410  {
3411      if (object == nil)
3412      {
3413          return NSNotFound;
3414      }
3415  
3416      NSUInteger count = [self count];
3417  
3418      id *objects = object_getIndexedIvars(self);
3419      NSUInteger *indexes = (NSUInteger *)objects + count;
3420      NSUInteger hash = [object hash];
3421      NSUInteger bucket = hash % __NSBasicHashIPrimes[_szidx];
3422  
3423      NSUInteger possibleIdx = indexes[bucket];
3424  
3425      if (possibleIdx == 0)
3426      {
3427          return NSNotFound;
3428      }
3429  
3430      id possibleObject = objects[possibleIdx - 1];
3431  
3432      if (possibleObject == object || ([possibleObject hash] == hash && [possibleObject isEqual:object]))
3433      {
3434          return possibleIdx - 1;
3435      }
3436  
3437      NSUInteger foundIdx = NSNotFound;
3438  
3439      for (NSUInteger idx = 0; idx < count; idx++)
3440      {
3441          id obj = objects[idx];
3442          
3443          if (obj == nil)
3444          {
3445              continue;
3446          }
3447  
3448          if (obj == object || ([obj hash] == hash && [obj isEqual:object]))
3449          {
3450              foundIdx = idx;
3451              break;
3452          }
3453      }
3454  
3455      return foundIdx;
3456  }
3457  
3458  - (NSUInteger)count
3459  {
3460      return _used;
3461  }
3462  
3463  @end
3464  
3465  @implementation __NSOrderedSetM
3466  
3467  static Boolean __NSOrderedSetMEquateKeys(uintptr_t coll_key1, uintptr_t stack_key2)
3468  {
3469      if (coll_key1 == stack_key2)
3470      {
3471          return true;
3472      }
3473      return [(id)coll_key1 isEqual:(id)stack_key2] != NO;
3474  }
3475  
3476  static CFHashCode __NSOrderedSetMHashKey(uintptr_t stack_key)
3477  {
3478      return [(id)stack_key hash];
3479  }
3480  
3481  static uintptr_t __NSOrderedSetMRetainValue(CFAllocatorRef allocator, uintptr_t stack_value)
3482  {
3483      return stack_value;
3484  }
3485  
3486  static void __NSOrderedSetMReleaseValue(CFAllocatorRef allocator, uintptr_t stack_value)
3487  {
3488  }
3489  
3490  static uintptr_t __NSOrderedSetMGetIndirectKey(uintptr_t coll_value)
3491  {
3492      return coll_value;
3493  }
3494  
3495  static CFBasicHashCallbacks __NSOrderedSetMCallbacks = {
3496      .equateKeys = &__NSOrderedSetMEquateKeys,
3497      .hashKey = &__NSOrderedSetMHashKey,
3498      .retainValue = &__NSOrderedSetMRetainValue,
3499      .releaseValue = &__NSOrderedSetMReleaseValue,
3500      .getIndirectKey = &__NSOrderedSetMGetIndirectKey,
3501  };
3502  
3503  + (id)__new:(const id *)addr :(NSUInteger)count :(BOOL)cfRelease
3504  {
3505      __NSOrderedSetM *orderedSet = ___CFAllocateObject2(self, 0);
3506  
3507      CFOptionFlags flags = kCFBasicHashIndirectKeys | kCFBasicHashExponentialHashing;
3508      orderedSet->_set = CFBasicHashCreate(kCFAllocatorDefault, flags, &__NSOrderedSetMCallbacks);
3509      orderedSet->_array = [[NSMutableArray alloc] initWithCapacity:count];
3510      orderedSet->_used = 0;
3511  
3512      if (addr == NULL || count == 0)
3513      {
3514          return orderedSet;
3515      }
3516  
3517      for (NSUInteger idx = 0; idx < count; idx++)
3518      {
3519          const id object = addr[idx];
3520          CFBasicHashBucket bucket = CFBasicHashFindBucket(orderedSet->_set, (uintptr_t)object);
3521          if (bucket.count != 0)
3522          {
3523              continue;
3524          }
3525  
3526          orderedSet->_used++;
3527  
3528          CFBasicHashAddValue(orderedSet->_set, (uintptr_t)object, (uintptr_t)object);
3529  
3530          [orderedSet->_array _mutate];
3531          [orderedSet->_array addObject:object];
3532  
3533          if (cfRelease)
3534          {
3535              CFRelease(object);
3536          }
3537      }
3538  
3539      return orderedSet;
3540  }
3541  
3542  + (id)allocWithZone:(NSZone *)zone
3543  {
3544      return (__NSOrderedSetM *)[__NSPlaceholderOrderedSet allocWithZone:zone];
3545  }
3546  
3547  + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
3548  {
3549      return NO;
3550  }
3551  
3552  - (void)dealloc
3553  {
3554      if (self == (__NSOrderedSetM *)mutablePlaceholder)
3555      {
3556          DEBUG_BREAK();
3557          [super dealloc];
3558      }
3559  
3560      if (_set != NULL)
3561      {
3562          CFRelease(_set);
3563      }
3564      if (_array != nil)
3565      {
3566          [_array release];
3567      }
3568  
3569      [super dealloc];
3570  }
3571  
3572  - (void)setObject:(id)object atIndex:(NSUInteger)idx
3573  {
3574      if (object == nil)
3575      {
3576          [NSException raise:NSInvalidArgumentException format:@"Cannot set to nil object in ordered set"];
3577          return;
3578      }
3579  
3580      if (idx > _used)
3581      {
3582          [NSException raise:NSRangeException format:@"Index out of range of ordered set"];
3583          return;
3584      }
3585  
3586      CFBasicHashBucket bucket = CFBasicHashFindBucket(_set, (uintptr_t)object);
3587      if (bucket.count != 0)
3588      {
3589          return;
3590      }
3591  
3592      if (idx == _used)
3593      {
3594          _used++;
3595  
3596          CFBasicHashAddValue(_set, (uintptr_t)object, (uintptr_t)object);
3597  
3598          [_array _mutate];
3599          [_array insertObject:object atIndex:idx];
3600      }
3601      else
3602      {
3603          id currentObject = [_array objectAtIndex:idx];
3604          CFBasicHashRemoveValue(_set, (uintptr_t)currentObject);
3605          CFBasicHashAddValue(_set, (uintptr_t)object, (uintptr_t)object);
3606  
3607          [_array _mutate];
3608          [_array replaceObjectAtIndex:idx withObject:object];
3609      }
3610  }
3611  
3612  - (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)object
3613  {
3614      if (object == nil)
3615      {
3616          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil object to ordered set"];
3617          return;
3618      }
3619  
3620      if (idx >= _used)
3621      {
3622          [NSException raise:NSRangeException format:@"Index out of range of ordered set"];
3623          return;
3624      }
3625  
3626      CFBasicHashBucket bucket = CFBasicHashFindBucket(_set, (uintptr_t)object);
3627      if (bucket.count != 0)
3628      {
3629          return;
3630      }
3631  
3632      id currentObject = [_array objectAtIndex:idx];
3633      CFBasicHashRemoveValue(_set, (uintptr_t)currentObject);
3634      CFBasicHashAddValue(_set, (uintptr_t)object, (uintptr_t)object);
3635  
3636      [_array _mutate];
3637      [_array replaceObjectAtIndex:idx withObject:object];
3638  }
3639  
3640  - (void)removeObjectAtIndex:(NSUInteger)idx
3641  {
3642      if (idx >= _used)
3643      {
3644          [NSException raise:NSRangeException format:@"Index out of range of ordered set"];
3645          return;
3646      }
3647  
3648      id object = [_array objectAtIndex:idx];
3649  
3650      _used--;
3651  
3652      CFBasicHashRemoveValue(_set, (uintptr_t)object);
3653  
3654      [_array _mutate];
3655      [_array removeObjectAtIndex:idx];
3656  }
3657  
3658  - (void)insertObject:(id)object atIndex:(NSUInteger)idx
3659  {
3660      if (object == nil)
3661      {
3662          [NSException raise:NSInvalidArgumentException format:@"Cannot add nil object to ordered set"];
3663          return;
3664      }
3665  
3666      if (idx > _used)
3667      {
3668          [NSException raise:NSRangeException format:@"Index out of range of ordered set"];
3669          return;
3670      }
3671  
3672      CFBasicHashBucket bucket = CFBasicHashFindBucket(_set, (uintptr_t)object);
3673      if (bucket.count != 0)
3674      {
3675          return;
3676      }
3677  
3678      _used++;
3679  
3680      CFBasicHashAddValue(_set, (uintptr_t)object, (uintptr_t)object);
3681  
3682      [_array _mutate];
3683      [_array insertObject:object atIndex:idx];
3684  }
3685  
3686  - (void)_mutate
3687  {
3688      [_array _mutate];
3689  }
3690  
3691  - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)options usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
3692  {
3693      if (block == nil)
3694      {
3695          [NSException raise:NSInvalidArgumentException format:@"Block must not be nil"];
3696          return;
3697      }
3698  
3699      [_array enumerateObjectsWithOptions:options usingBlock:block];
3700  }
3701  
3702  - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)objects count:(NSUInteger)count
3703  {
3704      if (objects == NULL && count != 0)
3705      {
3706          [NSException raise:NSInvalidArgumentException format:@"Cannot enumerate NULL objects with non-zero count"];
3707          return 0;
3708      }
3709  
3710      return [_array countByEnumeratingWithState:state objects:objects count:count];
3711  }
3712  
3713  - (void)getObjects:(id *)objects range:(NSRange)range
3714  {
3715      if (objects == NULL && range.length != 0)
3716      {
3717          [NSException raise:NSRangeException format:@"Cannot place objects into NULL array with non-zero length"];
3718          return;
3719      }
3720  
3721      if (NSMaxRange(range) > _used)
3722      {
3723          [NSException raise:NSRangeException format:@"Range out of bounds of ordered set"];
3724          return;
3725      }
3726  
3727      [_array getObjects:objects range:range];
3728  }
3729  
3730  - (id)objectAtIndex:(NSUInteger)idx
3731  {
3732      if (idx >= _used)
3733      {
3734          [NSException raise:NSRangeException format:@"Index out of range"];
3735          return nil;
3736      }
3737  
3738      return [_array objectAtIndex:idx];
3739  }
3740  
3741  - (NSUInteger)indexOfObject:(id)object
3742  {
3743      if (object == nil)
3744      {
3745          return NSNotFound;
3746      }
3747  
3748      CFBasicHashBucket bucket = CFBasicHashFindBucket(_set, (uintptr_t)object);
3749      if (bucket.count == 0)
3750      {
3751          return NSNotFound;
3752      }
3753  
3754      return [_array indexOfObjectIdenticalTo:object];
3755  }
3756  
3757  - (NSUInteger)count
3758  {
3759      return _used;
3760  }
3761  
3762  @end
3763  
3764  @implementation __NSOrderedSetArrayProxy
3765  
3766  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet
3767  {
3768      self = [super init];
3769      if (self != nil)
3770      {
3771          _orderedSet = [orderedSet retain];
3772      }
3773      return self;
3774  }
3775  
3776  - (void)dealloc
3777  {
3778      [_orderedSet release];
3779      [super dealloc];
3780  }
3781  
3782  - (id)copyWithZone:(NSZone *)zone
3783  {
3784      return [[NSArray alloc] initWithArray:self];
3785  }
3786  
3787  - (id)objectAtIndex:(NSUInteger)idx
3788  {
3789      return [_orderedSet objectAtIndex:idx];
3790  }
3791  
3792  - (NSUInteger)count
3793  {
3794      return [_orderedSet count];
3795  }
3796  
3797  @end
3798  
3799  @implementation __NSOrderedSetSetProxy
3800  
3801  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet
3802  {
3803      self = [super init];
3804      if (self != nil)
3805      {
3806          _orderedSet = [orderedSet retain];
3807      }
3808      return self;
3809  }
3810  
3811  - (void)dealloc
3812  {
3813      [_orderedSet release];
3814      [super dealloc];
3815  }
3816  
3817  - (id)copyWithZone:(NSZone *)zone
3818  {
3819      return [[NSSet alloc] initWithSet:self];
3820  }
3821  
3822  - (id)objectEnumerator
3823  {
3824      return [_orderedSet objectEnumerator];
3825  }
3826  
3827  - (id)member:(id)object
3828  {
3829      NSUInteger idx = [_orderedSet indexOfObject:object];
3830  
3831      if (idx == NSNotFound)
3832      {
3833          return nil;
3834      }
3835  
3836      return [_orderedSet objectAtIndex:idx];
3837  }
3838  
3839  - (NSUInteger)count
3840  {
3841      return [_orderedSet count];
3842  }
3843  
3844  @end
3845  
3846  @implementation __NSOrderedSetReversed
3847  
3848  - (id)initWithOrderedSet:(NSOrderedSet *)orderedSet
3849  {
3850      self = [super init];
3851      if (self != nil)
3852      {
3853          _orderedSet = [orderedSet copy];
3854          _cnt = [_orderedSet count];
3855      }
3856      return self;
3857  }
3858  
3859  - (void)dealloc
3860  {
3861      [_orderedSet release];
3862      [super dealloc];
3863  }
3864  
3865  - (id)objectAtIndex:(NSUInteger)idx
3866  {
3867      NSUInteger reversedIdx = _cnt - idx - 1;
3868      return [_orderedSet objectAtIndex:reversedIdx];
3869  }
3870  
3871  - (NSUInteger)indexOfObject:(id)object
3872  {
3873      NSUInteger idx = [_orderedSet indexOfObject:object];
3874      if (idx == NSNotFound)
3875      {
3876          return NSNotFound;
3877      }
3878      return _cnt - idx - 1;
3879  }
3880  
3881  - (NSUInteger)count
3882  {
3883      return _cnt;
3884  }
3885  
3886  @end
3887  
3888  @implementation __NSOrderedSetReverseEnumerator
3889  
3890  - (id)initWithObject:(id)object
3891  {
3892      _obj = [object retain];
3893      _idx = [_obj count];
3894      return nil;
3895  }
3896  
3897  - (void)dealloc
3898  {
3899      if (_obj != nil)
3900      {
3901          [_obj release];
3902      }
3903      [super dealloc];
3904  }
3905  
3906  - (id)nextObject
3907  {
3908      if (_obj == nil)
3909      {
3910          return nil;
3911      }
3912  
3913      if (_idx == 0)
3914      {
3915          [_obj release];
3916          _obj = nil;
3917      }
3918  
3919      _idx--;
3920  
3921      return [_obj objectAtIndex:_idx];
3922  }
3923  
3924  @end