| #import "DDRange.h" |
| #import "DDNumber.h" |
| |
| DDRange DDUnionRange(DDRange range1, DDRange range2) |
| { |
| DDRange result; |
| |
| result.location = MIN(range1.location, range2.location); |
| result.length = MAX(DDMaxRange(range1), DDMaxRange(range2)) - result.location; |
| |
| return result; |
| } |
| |
| DDRange DDIntersectionRange(DDRange range1, DDRange range2) |
| { |
| DDRange result; |
| |
| if((DDMaxRange(range1) < range2.location) || (DDMaxRange(range2) < range1.location)) |
| { |
| return DDMakeRange(0, 0); |
| } |
| |
| result.location = MAX(range1.location, range2.location); |
| result.length = MIN(DDMaxRange(range1), DDMaxRange(range2)) - result.location; |
| |
| return result; |
| } |
| |
| NSString *DDStringFromRange(DDRange range) |
| { |
| return [NSString stringWithFormat:@"{%qu, %qu}", range.location, range.length]; |
| } |
| |
| DDRange DDRangeFromString(NSString *aString) |
| { |
| DDRange result = DDMakeRange(0, 0); |
| |
| // NSRange will ignore '-' characters, but not '+' characters |
| NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]; |
| |
| NSScanner *scanner = [NSScanner scannerWithString:aString]; |
| [scanner setCharactersToBeSkipped:[cset invertedSet]]; |
| |
| NSString *str1 = nil; |
| NSString *str2 = nil; |
| |
| BOOL found1 = [scanner scanCharactersFromSet:cset intoString:&str1]; |
| BOOL found2 = [scanner scanCharactersFromSet:cset intoString:&str2]; |
| |
| if(found1) [NSNumber parseString:str1 intoUInt64:&result.location]; |
| if(found2) [NSNumber parseString:str2 intoUInt64:&result.length]; |
| |
| return result; |
| } |
| |
| NSInteger DDRangeCompare(DDRangePointer pDDRange1, DDRangePointer pDDRange2) |
| { |
| // Comparison basis: |
| // Which range would you encouter first if you started at zero, and began walking towards infinity. |
| // If you encouter both ranges at the same time, which range would end first. |
| |
| if(pDDRange1->location < pDDRange2->location) |
| { |
| return NSOrderedAscending; |
| } |
| if(pDDRange1->location > pDDRange2->location) |
| { |
| return NSOrderedDescending; |
| } |
| if(pDDRange1->length < pDDRange2->length) |
| { |
| return NSOrderedAscending; |
| } |
| if(pDDRange1->length > pDDRange2->length) |
| { |
| return NSOrderedDescending; |
| } |
| |
| return NSOrderedSame; |
| } |
| |
| @implementation NSValue (NSValueDDRangeExtensions) |
| |
| + (NSValue *)valueWithDDRange:(DDRange)range |
| { |
| return [NSValue valueWithBytes:&range objCType:@encode(DDRange)]; |
| } |
| |
| - (DDRange)ddrangeValue |
| { |
| DDRange result; |
| [self getValue:&result]; |
| return result; |
| } |
| |
| - (NSInteger)ddrangeCompare:(NSValue *)other |
| { |
| DDRange r1 = [self ddrangeValue]; |
| DDRange r2 = [other ddrangeValue]; |
| |
| return DDRangeCompare(&r1, &r2); |
| } |
| |
| @end |