PageRenderTime 149ms CodeModel.GetById 127ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 19#import "GTMNSArray+Merge.h"
 20
 21#import "GTMDefines.h"
 22
 23#if GTM_IPHONE_SDK
 24#import <objc/message.h>
 25#else  // GTM_IPHONE_SDK
 26#import <objc/objc-runtime.h>
 27#endif  // GTM_IPHONE_SDK
 28
 29@implementation NSArray (GTMNSArrayMergingAdditions)
 30
 31- (NSArray *)gtm_mergeArray:(NSArray *)newArray
 32              mergeSelector:(SEL)merger {
 33  return [self gtm_mergeArray:newArray
 34              compareSelector:@selector(compare:)
 35                mergeSelector:merger];
 36}
 37
 38- (NSArray *)gtm_mergeArray:(NSArray *)newArray
 39            compareSelector:(SEL)comparer
 40              mergeSelector:(SEL)merger {
 41  // must have a compare selector
 42  if (!comparer) return nil;
 43
 44  // Sort and merge the contents of |self| with |newArray|.
 45  NSArray *sortedMergedArray = nil;
 46  if ([self count] && [newArray count]) {
 47    NSMutableArray *mergingArray = [NSMutableArray arrayWithArray:self];
 48    [mergingArray sortUsingSelector:comparer];
 49    NSArray *sortedNewArray
 50      = [newArray sortedArrayUsingSelector:comparer];
 51    
 52    NSUInteger oldIndex = 0;
 53    NSUInteger oldCount = [mergingArray count];
 54    id oldItem = (oldIndex < oldCount)
 55                 ? [mergingArray objectAtIndex:0]
 56                 : nil;
 57    
 58    id newItem = nil;
 59    GTM_FOREACH_OBJECT(newItem, sortedNewArray) {
 60      BOOL stillLooking = YES;
 61      while (oldIndex < oldCount && stillLooking) {
 62        // We must take care here, since Intel leaves junk in high bytes of
 63        // return register for predicates that return BOOL.
 64        // For details see: 
 65        // http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_23.html
 66        // and
 67        // http://www.red-sweater.com/blog/320/abusing-objective-c-with-class#comment-83187
 68        NSComparisonResult result
 69          = ((NSComparisonResult (*)(id, SEL, id))objc_msgSend)(newItem, comparer, oldItem);
 70        if (result == NSOrderedSame && merger) {
 71          // It's a match!
 72          id repItem = [oldItem performSelector:merger
 73                                     withObject:newItem];
 74          [mergingArray replaceObjectAtIndex:oldIndex
 75                                  withObject:repItem];
 76          ++oldIndex;
 77          oldItem = (oldIndex < oldCount)
 78                    ? [mergingArray objectAtIndex:oldIndex]
 79                    : nil;
 80          stillLooking = NO;
 81        } else if (result == NSOrderedAscending
 82                   || (result == NSOrderedSame && !merger)) {
 83          // This is either a new item and belongs right here, or it's
 84          // a match to an existing item but we're not merging.
 85          [mergingArray insertObject:newItem
 86                             atIndex:oldIndex];
 87          ++oldIndex;
 88          ++oldCount;
 89          stillLooking = NO;
 90        } else {
 91          ++oldIndex;
 92          oldItem = (oldIndex < oldCount)
 93                    ? [mergingArray objectAtIndex:oldIndex]
 94                    : nil;
 95        }
 96      }
 97      if (stillLooking) {
 98        // Once we get here, the rest of the new items get appended.
 99        [mergingArray addObject:newItem];
100      }
101    }
102    sortedMergedArray = mergingArray;
103  } else if ([self count]) {
104    sortedMergedArray = [self sortedArrayUsingSelector:comparer];
105  } else if ([newArray count]) {
106    sortedMergedArray = [newArray sortedArrayUsingSelector:comparer];
107  }
108  return sortedMergedArray;
109}
110
111@end