source: trunk/Sparkle/SUStandardVersionComparator.m @ 1046

Revision 128, 5.0 KB checked in by speck, 4 years ago (diff)

Fixed missing display of update notes in Sparkle. Embedded Sparkle so subversion has the proper version instead of having to download Sparkle and apply several patches.

Line 
1//
2//  SUStandardVersionComparator.m
3//  Sparkle
4//
5//  Created by Andy Matuschak on 12/21/07.
6//  Copyright 2007 Andy Matuschak. All rights reserved.
7//
8
9#import "Sparkle.h"
10#import "SUStandardVersionComparator.h"
11
12@implementation SUStandardVersionComparator
13
14+ (SUStandardVersionComparator *)defaultComparator
15{
16    static SUStandardVersionComparator *defaultComparator = nil;
17    if (defaultComparator == nil)
18        defaultComparator = [[SUStandardVersionComparator alloc] init];
19    return defaultComparator;
20}
21
22typedef enum {
23    kNumberType,
24    kStringType,
25    kPeriodType
26} SUCharacterType;
27
28- (SUCharacterType)typeOfCharacter:(NSString *)character
29{
30    if ([character isEqualToString:@"."]) {
31        return kPeriodType;
32    } else if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[character characterAtIndex:0]]) {
33        return kNumberType;
34    } else {
35        return kStringType;
36    }   
37}
38
39- (NSArray *)splitVersionString:(NSString *)version
40{
41    NSString *character;
42    NSMutableString *s;
43    NSInteger i, n, oldType, newType;
44    NSMutableArray *parts = [NSMutableArray array];
45    if ([version length] == 0) {
46        // Nothing to do here
47        return parts;
48    }
49    s = [[[version substringToIndex:1] mutableCopy] autorelease];
50    oldType = [self typeOfCharacter:s];
51    n = [version length] - 1;
52    for (i = 1; i <= n; ++i) {
53        character = [version substringWithRange:NSMakeRange(i, 1)];
54        newType = [self typeOfCharacter:character];
55        if (oldType != newType || oldType == kPeriodType) {
56            // We've reached a new segment
57            NSString *aPart = [[NSString alloc] initWithString:s];
58            [parts addObject:aPart];
59            [aPart release];
60            [s setString:character];
61        } else {
62            // Add character to string and continue
63            [s appendString:character];
64        }
65        oldType = newType;
66    }
67   
68    // Add the last part onto the array
69    [parts addObject:[NSString stringWithString:s]];
70    return parts;
71}
72
73- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB;
74{
75    NSArray *partsA = [self splitVersionString:versionA];
76    NSArray *partsB = [self splitVersionString:versionB];
77   
78    NSString *partA, *partB;
79    NSInteger i, n, typeA, typeB, intA, intB;
80   
81    n = MIN([partsA count], [partsB count]);
82    for (i = 0; i < n; ++i) {
83        partA = [partsA objectAtIndex:i];
84        partB = [partsB objectAtIndex:i];
85       
86        typeA = [self typeOfCharacter:partA];
87        typeB = [self typeOfCharacter:partB];
88       
89        // Compare types
90        if (typeA == typeB) {
91            // Same type; we can compare
92            if (typeA == kNumberType) {
93                intA = [partA intValue];
94                intB = [partB intValue];
95                if (intA > intB) {
96                    return NSOrderedDescending;
97                } else if (intA < intB) {
98                    return NSOrderedAscending;
99                }
100            } else if (typeA == kStringType) {
101                NSComparisonResult result = [partA compare:partB];
102                if (result != NSOrderedSame) {
103                    return result;
104                }
105            }
106        } else {
107            // Not the same type? Now we have to do some validity checking
108            if (typeA != kStringType && typeB == kStringType) {
109                // typeA wins
110                return NSOrderedDescending;
111            } else if (typeA == kStringType && typeB != kStringType) {
112                // typeB wins
113                return NSOrderedAscending;
114            } else {
115                // One is a number and the other is a period. The period is invalid
116                if (typeA == kNumberType) {
117                    return NSOrderedDescending;
118                } else {
119                    return NSOrderedAscending;
120                }
121            }
122        }
123    }
124    // The versions are equal up to the point where they both still have parts
125    // Lets check to see if one is larger than the other
126    if ([partsA count] != [partsB count]) {
127        // Yep. Lets get the next part of the larger
128        // n holds the index of the part we want.
129        NSString *missingPart;
130        SUCharacterType missingType;
131        NSComparisonResult shorterResult, largerResult;
132       
133        if ([partsA count] > [partsB count]) {
134            missingPart = [partsA objectAtIndex:n];
135            shorterResult = NSOrderedAscending;
136            largerResult = NSOrderedDescending;
137        } else {
138            missingPart = [partsB objectAtIndex:n];
139            shorterResult = NSOrderedDescending;
140            largerResult = NSOrderedAscending;
141        }
142       
143        missingType = [self typeOfCharacter:missingPart];
144        // Check the type
145        if (missingType == kStringType) {
146            // It's a string. Shorter version wins
147            return shorterResult;
148        } else {
149            // It's a number/period. Larger version wins
150            return largerResult;
151        }
152    }
153   
154    // The 2 strings are identical
155    return NSOrderedSame;
156}
157
158
159@end
Note: See TracBrowser for help on using the repository browser.