From f1953baafac9655af1453115aa6641f88cbb26de Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Mon, 21 Apr 2014 18:17:56 +0200 Subject: [PATCH] Added MPRange and Tests --- MathPad/MPRange.h | 39 ++++++++++ MathPad/MPRange.m | 140 ++++++++++++++++++++++++++++++++++++ MathPadTests/MPRangeTests.m | 95 ++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 MathPad/MPRange.h create mode 100644 MathPad/MPRange.m create mode 100644 MathPadTests/MPRangeTests.m diff --git a/MathPad/MPRange.h b/MathPad/MPRange.h new file mode 100644 index 0000000..8492ec2 --- /dev/null +++ b/MathPad/MPRange.h @@ -0,0 +1,39 @@ +// +// MPRange.h +// MathPad +// +// Created by Kim Wittenburg on 18.04.14. +// Copyright (c) 2014 Kim Wittenburg. All rights reserved. +// + +@interface MPRange : NSObject + +#pragma mark Creation Methods + +- (instancetype)init; +- (instancetype)initWithLocation:(NSIndexPath *)location + length:(NSUInteger)length; +- (instancetype)initWithRange:(NSRange)aRange; + ++ (instancetype)emptyRange; ++ (instancetype)rangeWithLocation:(NSIndexPath *)location + length:(NSUInteger)length; ++ (instancetype)rangeWithRange:(NSRange)aRange; + +#pragma mark Properties + +@property (nonatomic, strong) NSIndexPath *location; +@property (nonatomic) NSUInteger length; + +- (NSIndexPath *)maxRange; +- (NSRange)rangeAtLastIndex; + +#pragma mark Working with Ranges + +- (BOOL)containsRange:(MPRange *)aRange; +- (BOOL)containsLocation:(NSIndexPath *)location; + +- (BOOL)isEqual:(id)object; +- (BOOL)isEqualToRange:(MPRange *)aRange; + +@end \ No newline at end of file diff --git a/MathPad/MPRange.m b/MathPad/MPRange.m new file mode 100644 index 0000000..b85d0dd --- /dev/null +++ b/MathPad/MPRange.m @@ -0,0 +1,140 @@ +// +// MPRange.m +// MathPad +// +// Created by Kim Wittenburg on 18.04.14. +// Copyright (c) 2014 Kim Wittenburg. All rights reserved. +// + +#import "MPRange.h" + +@implementation MPRange + +#pragma mark Creation Methods + +- (instancetype)init +{ + return [self initWithLocation:[[NSIndexPath alloc] init] + length:0]; +} + +- (instancetype)initWithLocation:(NSIndexPath *)location + length:(NSUInteger)length +{ + self = [super init]; + if (self) { + _location = location; + _length = length; + } + return self; +} + +- (instancetype)initWithRange:(NSRange)aRange +{ + return [self initWithLocation:[[NSIndexPath alloc] initWithIndex:aRange.location] + length:aRange.length]; +} + ++ (instancetype)emptyRange +{ + return [[self alloc] init]; +} + ++ (instancetype)rangeWithLocation:(NSIndexPath *)location + length:(NSUInteger)length +{ + return [[self alloc] initWithLocation:location + length:length]; +} + ++ (instancetype)rangeWithRange:(NSRange)aRange +{ + return [[self alloc] initWithRange:aRange]; +} + +#pragma mark Properties + +- (NSIndexPath *)maxRange +{ + NSUInteger lastIndex = [self.location indexAtPosition:self.location.length-1]; + NSUInteger newLastIndex = lastIndex + self.length; + return [[self.location indexPathByRemovingLastIndex] indexPathByAddingIndex:newLastIndex]; +} + +- (NSRange)rangeAtLastIndex +{ + return NSMakeRange([self.location indexAtPosition:self.location.length-1], self.length); +} + +#pragma mark Working with Ranges + +- (BOOL)containsRange:(MPRange *)aRange +{ + if (aRange.location.length < self.location.length) { + return NO; + } + // Compare indices (except the last one) + for (NSUInteger pos = 0; pos < self.location.length-1; pos++) { + NSUInteger selfIndex = [self.location indexAtPosition:pos]; + NSUInteger otherIndex = [aRange.location indexAtPosition:pos]; + if (selfIndex != otherIndex) { + return NO; + } + } + // Compare range at last index + NSUInteger selfIndex = [self.location indexAtPosition:self.location.length-1]; + NSUInteger otherIndex = [aRange.location indexAtPosition:self.location.length-1]; + if (aRange.location.length > self.location.length) { + return NSLocationInRange(otherIndex, self.rangeAtLastIndex); + } else { + return otherIndex >= selfIndex && NSMaxRange(aRange.rangeAtLastIndex) <= NSMaxRange(self.rangeAtLastIndex); + } +} + +- (BOOL)containsLocation:(NSIndexPath *)location +{ + return [self containsRange:[[MPRange alloc] initWithLocation:location length:0]]; +} + +- (BOOL)isEqual:(id)object +{ + if (self == object) { + return YES; + } + if (object == nil) { + return NO; + } + if (![object isKindOfClass:[MPRange class]]) { + return NO; + } + return [self isEqualToRange:(MPRange *)object]; +} + +- (BOOL)isEqualToRange:(MPRange *)aRange +{ + return [self.location isEqual:aRange.location] && self.length == aRange.length; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone +{ + MPRange *copy = [[MPRange allocWithZone:zone] initWithLocation:self.location.copy length:self.length]; + return copy; +} + +#pragma mark - NSCoding + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + return [self initWithLocation:[aDecoder decodeObjectForKey:@"location"] + length:[aDecoder decodeIntegerForKey:@"length"]]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeObject:self.location forKey:@"location"]; + [aCoder encodeInteger:self.length forKey:@"length"]; +} + +@end diff --git a/MathPadTests/MPRangeTests.m b/MathPadTests/MPRangeTests.m new file mode 100644 index 0000000..7171cdc --- /dev/null +++ b/MathPadTests/MPRangeTests.m @@ -0,0 +1,95 @@ +// +// MPRangeTests.m +// MathPad +// +// Created by Kim Wittenburg on 21.04.14. +// Copyright (c) 2014 Kim Wittenburg. All rights reserved. +// + +#import + +#import "MPRange.h" + +@interface MPRangeTests : XCTestCase + +@end + +@implementation MPRangeTests + +- (void)testInitialization { + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndex:1] length:5]; + XCTAssertEqualObjects(range.location, [[NSIndexPath alloc] initWithIndex:1]); + XCTAssertEqual(range.length, 5); + + range = [[MPRange alloc] initWithRange:NSMakeRange(3, 2)]; + XCTAssertEqualObjects(range.location, [[NSIndexPath alloc] initWithIndex:3]); + XCTAssertEqual(range.length, 2); + + range = [MPRange emptyRange]; + XCTAssertEqualObjects(range.location, [[NSIndexPath alloc] init]); + XCTAssertEqual(range.length, 0); +} + +- (void)testMaxRange { + NSUInteger indexes[] = {5, 2, 7, 3}; + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:indexes length:4] length:5]; + NSUInteger expectedIndexes[] = {5, 2, 7, 8}; + XCTAssertEqualObjects([range maxRange], [[NSIndexPath alloc] initWithIndexes:expectedIndexes length:4]); +} + +- (void)testRangeAtLastIndex { + NSUInteger indexes[] = {5, 2, 7, 3}; + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:indexes length:4] length:5]; + XCTAssertTrue(NSEqualRanges(range.rangeAtLastIndex, NSMakeRange(3, 5))); +} + +- (void)testEquality { + NSUInteger indexes[] = {5, 2, 7, 3}; + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:indexes length:4] length:5]; + NSUInteger otherIndexes[] = {5, 2, 7, 3}; + MPRange *otherRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:otherIndexes length:4] length:5]; + NSUInteger yetOtherIndexes[] = {5, 2, 6, 3}; + MPRange *yetAnotherRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:yetOtherIndexes length:4] length:5]; + XCTAssertTrue([range isEqual:otherRange]); + XCTAssertFalse([range isEqual:yetAnotherRange]); +} + +- (void)testCopying { + NSUInteger indexes[] = {5, 2, 7, 3}; + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:indexes length:4] length:5]; + MPRange *copy = [range copy]; + XCTAssertNotEqual(range, copy); + XCTAssertEqualObjects(range, copy); +} + +- (void)testContainsRange { + NSUInteger indexes[] = {5, 2, 7, 3}; + MPRange *range = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:indexes length:4] length:5]; + + NSUInteger shorterPathIndexes[] = {5, 2}; + MPRange *shorterPathRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:shorterPathIndexes length:2] length:5]; + + NSUInteger longerPathIndexes[] = {5, 2, 7, 3, 5}; + MPRange *longerPathRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:longerPathIndexes length:5] length:5]; + + NSUInteger differentPathIndexes[] = {5, 3, 7, 3}; + MPRange *differentPathRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:differentPathIndexes length:4] length:5]; + + NSUInteger equalRangeIndexes[] = {5, 2, 7, 3}; + MPRange *equalRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:equalRangeIndexes length:4] length:5]; + + NSUInteger containedRangeIndexes[] = {5, 2, 7, 4}; + MPRange *containedRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:containedRangeIndexes length:4] length:2]; + + NSUInteger largerRangeIndexes[] = {5, 2, 7, 4}; + MPRange *largerRange = [[MPRange alloc] initWithLocation:[[NSIndexPath alloc] initWithIndexes:largerRangeIndexes length:4] length:7]; + + XCTAssertFalse([range containsRange:shorterPathRange]); + XCTAssertTrue([range containsRange:longerPathRange]); + XCTAssertFalse([range containsRange:differentPathRange]); + XCTAssertTrue([range containsRange:equalRange]); + XCTAssertTrue([range containsRange:containedRange]); + XCTAssertFalse([range containsRange:largerRange]); +} + +@end