// // MPRange.m // MathPad // // Created by Kim Wittenburg on 18.04.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPRangePath.h" @implementation MPRangePath #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)rangePath { return [[self alloc] init]; } + (instancetype)rangePathWithRange:(NSRange)aRange { return [[self alloc] initWithRange:aRange]; } + (instancetype)rangePathWithLocation:(NSIndexPath *)location length:(NSUInteger)length { return [[self alloc] initWithLocation:location length:length]; } #pragma mark Properties - (NSIndexPath *)maxRangePath { 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)containsLocation:(NSIndexPath *)location { return [self containsRangePath:[[MPRangePath alloc] initWithLocation:location length:0]]; } - (BOOL)containsRangePath:(MPRangePath *)aRangePath { if (aRangePath.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 = [aRangePath.location indexAtPosition:pos]; if (selfIndex != otherIndex) { return NO; } } // Compare range at last index NSUInteger selfIndex = [self.location indexAtPosition:self.location.length-1]; NSUInteger otherIndex = [aRangePath.location indexAtPosition:self.location.length-1]; if (aRangePath.location.length > self.location.length) { return NSLocationInRange(otherIndex, self.rangeAtLastIndex); } else { return otherIndex >= selfIndex && NSMaxRange(aRangePath.rangeAtLastIndex) <= NSMaxRange(self.rangeAtLastIndex); } } - (BOOL)isEqual:(id)object { if (self == object) { return YES; } if (object == nil) { return NO; } if (![object isKindOfClass:[MPRangePath class]]) { return NO; } return [self isEqualToRangePath:(MPRangePath *)object]; } - (BOOL)isEqualToRangePath:(MPRangePath *)aRangePath { return [self.location isEqual:aRangePath.location] && self.length == aRangePath.length; } - (NSString *)description { NSMutableString *description = [[NSMutableString alloc] initWithString:@"MPRangePath 0) { [description appendFormat:@"%ld", [self.location indexAtPosition:0]]; } for (NSUInteger position = 1; position < self.location.length; position ++) { [description appendFormat:@",%ld", [self.location indexAtPosition:position]]; } [description appendFormat:@" length=%ld", self.length]; [description appendString:@">"]; return description.copy; } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { MPRangePath *copy = [[MPRangePath 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 @implementation MPExpression (MPRangeExtension) - (NSArray *)itemsInRangePath:(MPRangePath *)rangePath referenceFrame:(MPReferenceFrame)referenceFrame { MPExpression *targetExpression = [self elementAtIndexPath:[rangePath.location indexPathByRemovingLastIndex]]; return [targetExpression itemsInRange:rangePath.rangeAtLastIndex referenceFrame:referenceFrame]; } - (MPExpression *)subexpressionWithRangePath:(MPRangePath *)aRangePath referenceFrame:(MPReferenceFrame)referenceFrame { MPExpression *targetExpression = [self elementAtIndexPath:[aRangePath.location indexPathByRemovingLastIndex]]; if (![targetExpression isKindOfClass:[MPExpression class]]) { // TODO: Raise appropriate exception return nil; } return [targetExpression subexpressionWithRange:aRangePath.rangeAtLastIndex referenceFrame:referenceFrame]; } - (void)replaceItemsInRangePath:(MPRangePath *)rangePath referenceFrame:(MPReferenceFrame)referenceFrame withElements:(NSArray *)elements { MPExpression *targetExpression = [self elementAtIndexPath:[rangePath.location indexPathByRemovingLastIndex]]; [targetExpression replaceItemsInRange:rangePath.rangeAtLastIndex referenceFrame:referenceFrame withElements:elements]; } @end