Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implemented string version comparison (using proven code from the Spa…
…rkle project by Andy Matuschak) This was needed for TotalFinder which wants to safely check Finder versions. Finder uses OS version in its Info.plist like this: <key>CFBundleVersion</key> <string>10.6.4</string>
- Loading branch information
Showing
6 changed files
with
247 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
build | ||
.DS_Store | ||
rez/SIMBL.r | ||
.*\.xcodeproj/.*\.(mode*|pbxuser) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// SUStandardVersionComparator.h | ||
// Sparkle | ||
// | ||
// Created by Andy Matuschak on 12/21/07. | ||
// Copyright 2007 Andy Matuschak. All rights reserved. | ||
// | ||
|
||
#ifndef SUSTANDARDVERSIONCOMPARATOR_H | ||
#define SUSTANDARDVERSIONCOMPARATOR_H | ||
|
||
|
||
#import "SUVersionComparisonProtocol.h" | ||
|
||
/*! | ||
@class | ||
@abstract Sparkle's default version comparator. | ||
@discussion This comparator is adapted from MacPAD, by Kevin Ballard. It's "dumb" in that it does essentially string comparison, in components split by character type. | ||
*/ | ||
@interface SUStandardVersionComparator : NSObject <SUVersionComparison> { } | ||
|
||
/*! | ||
@method | ||
@abstract Returns a singleton instance of the comparator. | ||
*/ | ||
+ (SUStandardVersionComparator *)defaultComparator; | ||
|
||
/*! | ||
@method | ||
@abstract Compares version strings through textual analysis. | ||
@discussion See the implementation for more details. | ||
*/ | ||
- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; | ||
@end | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
// | ||
// SUStandardVersionComparator.m | ||
// Sparkle | ||
// | ||
// Created by Andy Matuschak on 12/21/07. | ||
// Copyright 2007 Andy Matuschak. All rights reserved. | ||
// | ||
|
||
// #import "Sparkle.h" | ||
#import "SUStandardVersionComparator.h" | ||
|
||
@implementation SUStandardVersionComparator | ||
|
||
+ (SUStandardVersionComparator *)defaultComparator | ||
{ | ||
static SUStandardVersionComparator *defaultComparator = nil; | ||
if (defaultComparator == nil) | ||
defaultComparator = [[SUStandardVersionComparator alloc] init]; | ||
return defaultComparator; | ||
} | ||
|
||
typedef enum { | ||
kNumberType, | ||
kStringType, | ||
kPeriodType | ||
} SUCharacterType; | ||
|
||
- (SUCharacterType)typeOfCharacter:(NSString *)character | ||
{ | ||
if ([character isEqualToString:@"."]) { | ||
return kPeriodType; | ||
} else if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[character characterAtIndex:0]]) { | ||
return kNumberType; | ||
} else { | ||
return kStringType; | ||
} | ||
} | ||
|
||
- (NSArray *)splitVersionString:(NSString *)version | ||
{ | ||
NSString *character; | ||
NSMutableString *s; | ||
NSUInteger i, n; | ||
SUCharacterType oldType, newType; | ||
NSMutableArray *parts = [NSMutableArray array]; | ||
if ([version length] == 0) { | ||
// Nothing to do here | ||
return parts; | ||
} | ||
s = [[[version substringToIndex:1] mutableCopy] autorelease]; | ||
oldType = [self typeOfCharacter:s]; | ||
n = [version length] - 1; | ||
for (i = 1; i <= n; ++i) { | ||
character = [version substringWithRange:NSMakeRange(i, 1)]; | ||
newType = [self typeOfCharacter:character]; | ||
if (oldType != newType || oldType == kPeriodType) { | ||
// We've reached a new segment | ||
NSString *aPart = [[[NSString alloc] initWithString:s] autorelease]; | ||
[parts addObject:aPart]; | ||
[s setString:character]; | ||
} else { | ||
// Add character to string and continue | ||
[s appendString:character]; | ||
} | ||
oldType = newType; | ||
} | ||
|
||
// Add the last part onto the array | ||
[parts addObject:[NSString stringWithString:s]]; | ||
return parts; | ||
} | ||
|
||
- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; | ||
{ | ||
NSArray *partsA = [self splitVersionString:versionA]; | ||
NSArray *partsB = [self splitVersionString:versionB]; | ||
|
||
NSString *partA, *partB; | ||
NSUInteger i, n; | ||
int intA, intB; | ||
SUCharacterType typeA, typeB; | ||
|
||
n = MIN([partsA count], [partsB count]); | ||
for (i = 0; i < n; ++i) { | ||
partA = [partsA objectAtIndex:i]; | ||
partB = [partsB objectAtIndex:i]; | ||
|
||
typeA = [self typeOfCharacter:partA]; | ||
typeB = [self typeOfCharacter:partB]; | ||
|
||
// Compare types | ||
if (typeA == typeB) { | ||
// Same type; we can compare | ||
if (typeA == kNumberType) { | ||
intA = [partA intValue]; | ||
intB = [partB intValue]; | ||
if (intA > intB) { | ||
return NSOrderedDescending; | ||
} else if (intA < intB) { | ||
return NSOrderedAscending; | ||
} | ||
} else if (typeA == kStringType) { | ||
NSComparisonResult result = [partA compare:partB]; | ||
if (result != NSOrderedSame) { | ||
return result; | ||
} | ||
} | ||
} else { | ||
// Not the same type? Now we have to do some validity checking | ||
if (typeA != kStringType && typeB == kStringType) { | ||
// typeA wins | ||
return NSOrderedDescending; | ||
} else if (typeA == kStringType && typeB != kStringType) { | ||
// typeB wins | ||
return NSOrderedAscending; | ||
} else { | ||
// One is a number and the other is a period. The period is invalid | ||
if (typeA == kNumberType) { | ||
return NSOrderedDescending; | ||
} else { | ||
return NSOrderedAscending; | ||
} | ||
} | ||
} | ||
} | ||
// The versions are equal up to the point where they both still have parts | ||
// Lets check to see if one is larger than the other | ||
if ([partsA count] != [partsB count]) { | ||
// Yep. Lets get the next part of the larger | ||
// n holds the index of the part we want. | ||
NSString *missingPart; | ||
SUCharacterType missingType; | ||
NSComparisonResult shorterResult, largerResult; | ||
|
||
if ([partsA count] > [partsB count]) { | ||
missingPart = [partsA objectAtIndex:n]; | ||
shorterResult = NSOrderedAscending; | ||
largerResult = NSOrderedDescending; | ||
} else { | ||
missingPart = [partsB objectAtIndex:n]; | ||
shorterResult = NSOrderedDescending; | ||
largerResult = NSOrderedAscending; | ||
} | ||
|
||
missingType = [self typeOfCharacter:missingPart]; | ||
// Check the type | ||
if (missingType == kStringType) { | ||
// It's a string. Shorter version wins | ||
return shorterResult; | ||
} else { | ||
// It's a number/period. Larger version wins | ||
return largerResult; | ||
} | ||
} | ||
|
||
// The 2 strings are identical | ||
return NSOrderedSame; | ||
} | ||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// SUVersionComparisonProtocol.h | ||
// Sparkle | ||
// | ||
// Created by Andy Matuschak on 12/21/07. | ||
// Copyright 2007 Andy Matuschak. All rights reserved. | ||
// | ||
|
||
#ifndef SUVERSIONCOMPARISONPROTOCOL_H | ||
#define SUVERSIONCOMPARISONPROTOCOL_H | ||
|
||
/*! | ||
@protocol | ||
@abstract Implement this protocol to provide version comparison facilities for Sparkle. | ||
*/ | ||
@protocol SUVersionComparison | ||
|
||
/*! | ||
@method | ||
@abstract An abstract method to compare two version strings. | ||
@discussion Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, and NSOrderedSame if they are equivalent. | ||
*/ | ||
- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; | ||
|
||
@end | ||
|
||
#endif |