Added MPRange and Tests
This commit is contained in:
39
MathPad/MPRange.h
Normal file
39
MathPad/MPRange.h
Normal file
@@ -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 <NSCopying, NSCoding>
|
||||
|
||||
#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
|
||||
140
MathPad/MPRange.m
Normal file
140
MathPad/MPRange.m
Normal file
@@ -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
|
||||
95
MathPadTests/MPRangeTests.m
Normal file
95
MathPadTests/MPRangeTests.m
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// MPRangeTests.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 21.04.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#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
|
||||
Reference in New Issue
Block a user