/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMNSArray+Merge.m

http://macfuse.googlecode.com/ · Objective C · 111 lines · 72 code · 10 blank · 29 comment · 20 complexity · 6563bbd1bab936855c44c256f45e3ffd MD5 · raw file

  1. //
  2. // GTMNSArray+Merge.m
  3. //
  4. // Copyright 2008 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations
  16. // under the License.
  17. //
  18. #import "GTMNSArray+Merge.h"
  19. #import "GTMDefines.h"
  20. #if GTM_IPHONE_SDK
  21. #import <objc/message.h>
  22. #else // GTM_IPHONE_SDK
  23. #import <objc/objc-runtime.h>
  24. #endif // GTM_IPHONE_SDK
  25. @implementation NSArray (GTMNSArrayMergingAdditions)
  26. - (NSArray *)gtm_mergeArray:(NSArray *)newArray
  27. mergeSelector:(SEL)merger {
  28. return [self gtm_mergeArray:newArray
  29. compareSelector:@selector(compare:)
  30. mergeSelector:merger];
  31. }
  32. - (NSArray *)gtm_mergeArray:(NSArray *)newArray
  33. compareSelector:(SEL)comparer
  34. mergeSelector:(SEL)merger {
  35. // must have a compare selector
  36. if (!comparer) return nil;
  37. // Sort and merge the contents of |self| with |newArray|.
  38. NSArray *sortedMergedArray = nil;
  39. if ([self count] && [newArray count]) {
  40. NSMutableArray *mergingArray = [NSMutableArray arrayWithArray:self];
  41. [mergingArray sortUsingSelector:comparer];
  42. NSArray *sortedNewArray
  43. = [newArray sortedArrayUsingSelector:comparer];
  44. NSUInteger oldIndex = 0;
  45. NSUInteger oldCount = [mergingArray count];
  46. id oldItem = (oldIndex < oldCount)
  47. ? [mergingArray objectAtIndex:0]
  48. : nil;
  49. id newItem = nil;
  50. GTM_FOREACH_OBJECT(newItem, sortedNewArray) {
  51. BOOL stillLooking = YES;
  52. while (oldIndex < oldCount && stillLooking) {
  53. // We must take care here, since Intel leaves junk in high bytes of
  54. // return register for predicates that return BOOL.
  55. // For details see:
  56. // http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html
  57. // and
  58. // http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187
  59. NSComparisonResult result
  60. = ((NSComparisonResult (*)(id, SEL, id))objc_msgSend)(newItem, comparer, oldItem);
  61. if (result == NSOrderedSame && merger) {
  62. // It's a match!
  63. id repItem = [oldItem performSelector:merger
  64. withObject:newItem];
  65. [mergingArray replaceObjectAtIndex:oldIndex
  66. withObject:repItem];
  67. ++oldIndex;
  68. oldItem = (oldIndex < oldCount)
  69. ? [mergingArray objectAtIndex:oldIndex]
  70. : nil;
  71. stillLooking = NO;
  72. } else if (result == NSOrderedAscending
  73. || (result == NSOrderedSame && !merger)) {
  74. // This is either a new item and belongs right here, or it's
  75. // a match to an existing item but we're not merging.
  76. [mergingArray insertObject:newItem
  77. atIndex:oldIndex];
  78. ++oldIndex;
  79. ++oldCount;
  80. stillLooking = NO;
  81. } else {
  82. ++oldIndex;
  83. oldItem = (oldIndex < oldCount)
  84. ? [mergingArray objectAtIndex:oldIndex]
  85. : nil;
  86. }
  87. }
  88. if (stillLooking) {
  89. // Once we get here, the rest of the new items get appended.
  90. [mergingArray addObject:newItem];
  91. }
  92. }
  93. sortedMergedArray = mergingArray;
  94. } else if ([self count]) {
  95. sortedMergedArray = [self sortedArrayUsingSelector:comparer];
  96. } else if ([newArray count]) {
  97. sortedMergedArray = [newArray sortedArrayUsingSelector:comparer];
  98. }
  99. return sortedMergedArray;
  100. }
  101. @end