diff --git a/Foundation/CPIndexPath.j b/Foundation/CPIndexPath.j new file mode 100644 index 000000000..87d9336fd --- /dev/null +++ b/Foundation/CPIndexPath.j @@ -0,0 +1,116 @@ + +@import +@import +@import +@import +@import + + +@implementation CPIndexPath : CPObject +{ + CPArray _indexes @accessors(property=indexes); +} + ++ (id)indexPathWithIndexes:(CPArray)indexes length:(int)length +{ + return [[self alloc] initWithIndexes:indexes length:length]; +} + ++ (id)indexPathWithIndexes:(CPArray)indexes +{ + return [[self alloc] initWithIndexes:indexes]; +} + +- (id)initWithIndexes:(CPArray)indexes length:(int)length +{ + self = [super init]; + + if(self) + { + _indexes = [indexes subarrayWithRange:CPMakeRange(0,length)]; + } + + return self; +} + +- (id)initWithIndexes:(CPArray)indexes +{ + self = [super init]; + + if(self) + { + _indexes = [indexes copy]; + } + + return self; +} + +- (CPString)description +{ + return [super description] + " " + _indexes; +} + +#pragma mark - +#pragma mark Accessing + +- (id)length +{ + return [_indexes count]; +} + +- (int)indexAtPosition:(int)position +{ + return [_indexes objectAtIndex:position]; +} + +#pragma mark - +#pragma mark Modification + +- (CPIndexPath)indexPathByAddingIndex:(int)index +{ + return [CPIndexPath indexPathWithIndexes:[_indexes arrayByAddingObject:index]]; +} + +- (CPIndexPath)indexPathByRemovingLastIndex +{ + return [CPIndexPath indexPathWithIndexes:_indexes length:[self length]]; +} + +#pragma mark - +#pragma mark Comparison + +- (BOOL)isEqual:(id)object +{ + if(![object class] === CPIndexPath) + return NO; + + return [_indexes isEqualToArray:[object indexes]]; +} + +- (CPComparisonResult)compare:(CPIndexPath)indexPath +{ + if(!indexPath) + [CPException raise:CPInvalidArgumentException reason:"indexPath to " + self + " was nil"]; + + var lhsIndexes = [self indexes], + rhsIndexes = [indexPath indexes]; + + var count = MIN([lhsIndexes count], [rhsIndexes count]); + + for(var i = 0; i < count; i++) { + var lhs = lhsIndexes[i], + rhs = rhsIndexes[i]; + + if(lhs < rhs) + return CPOrderedAscending; + else if(lhs > rhs) + return CPOrderedDescending; + } + + if([lhsIndexes count] == [rhsIndexes count]) + return CPOrderedSame; + + return ([lhsIndexes count] == count) ? CPOrderedAscending : CPOrderedDescending; +} + +@end diff --git a/Tests/Foundation/CPIndexPathTest.j b/Tests/Foundation/CPIndexPathTest.j new file mode 100644 index 000000000..cc62a8566 --- /dev/null +++ b/Tests/Foundation/CPIndexPathTest.j @@ -0,0 +1,70 @@ + +@import + + +@implementation CPIndexPathTest : OJTestCase +{ + CPIndexPath indexPath; +} + +- (void)setUp +{ + indexPath = [[CPIndexPath alloc] initWithIndexes:[1,5,3,7,3] length:3]; +} + +- (void)testIndexPathConstructed +{ + [self assertNotNull:indexPath]; +} + +- (void)testLength +{ + [self assert:3 equals:[indexPath length]]; +} + +- (void)testIndexAtPosition +{ + [self assert:5 equals:[indexPath indexAtPosition:1]]; +} + +- (void)testIndexPathByAddingIndex +{ + [self assert:[CPIndexPath indexPathWithIndexes:[[indexPath indexes] arrayByAddingObject:3]] + equals:[indexPath indexPathByAddingIndex:3]]; +} + +- (void)testIndexPathByRemovingLastIndex +{ + var ip = [indexPath indexes]; + [ip removeLastObject]; + + [self assert:[CPIndexPath indexPathWithIndexes:ip] + equals:[indexPath indexPathByRemovingLastIndex]]; +} + +- (void)testCompareThrowsOnNil +{ + [self assertThrows:function() { [indexPath compare:nil] }]; +} + +- (void)testCompare +{ + var comparisonIndexPath = [CPIndexPath indexPathWithIndexes:[CPArray arrayWithObjects:1,5,2]]; + [self assert:CPOrderedDescending equals:[indexPath compare:comparisonIndexPath]]; + + comparisonIndexPath = [CPIndexPath indexPathWithIndexes:[CPArray arrayWithObjects:1,4]]; + [self assert:CPOrderedDescending equals:[indexPath compare:comparisonIndexPath]]; + + + comparisonIndexPath = [CPIndexPath indexPathWithIndexes:[CPArray arrayWithObjects:1,5,3]]; + [self assert:CPOrderedSame equals:[indexPath compare:comparisonIndexPath]]; + + + comparisonIndexPath = [CPIndexPath indexPathWithIndexes:[CPArray arrayWithObjects:1,5,4]]; + [self assert:CPOrderedAscending equals:[indexPath compare:comparisonIndexPath]]; + + comparisonIndexPath = [CPIndexPath indexPathWithIndexes:[CPArray arrayWithObjects:1,6]]; + [self assert:CPOrderedAscending equals:[indexPath compare:comparisonIndexPath]]; +} + +@end