/MapView/GTM/GTMSystemVersion.m
Objective C | 228 lines | 162 code | 28 blank | 38 comment | 39 complexity | 52f4c5b49edb8987218238a394df9ff0 MD5 | raw file
1// 2// GTMSystemVersion.m 3// 4// Copyright 2007-2008 Google Inc. 5// 6// Licensed under the Apache License, Version 2.0 (the "License"); you may not 7// use this file except in compliance with the License. You may obtain a copy 8// of the License at 9// 10// http://www.apache.org/licenses/LICENSE-2.0 11// 12// Unless required by applicable law or agreed to in writing, software 13// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15// License for the specific language governing permissions and limitations under 16// the License. 17// 18 19#import "GTMSystemVersion.h" 20#import "GTMGarbageCollection.h" 21#if GTM_MACOS_SDK 22#import <CoreServices/CoreServices.h> 23#endif 24 25static SInt32 sGTMSystemVersionMajor = 0; 26static SInt32 sGTMSystemVersionMinor = 0; 27static SInt32 sGTMSystemVersionBugFix = 0; 28static NSString *sBuild = nil; 29 30NSString *const kGTMArch_iPhone = @"iPhone"; 31NSString *const kGTMArch_ppc = @"ppc"; 32NSString *const kGTMArch_ppc64 = @"ppc64"; 33NSString *const kGTMArch_x86_64 = @"x86_64"; 34NSString *const kGTMArch_i386 = @"i386"; 35 36static NSString *const kSystemVersionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist"; 37 38@implementation GTMSystemVersion 39+ (void)initialize { 40 if (self == [GTMSystemVersion class]) { 41 // Gestalt is the recommended way of getting the OS version (despite a 42 // comment to the contrary in the 10.4 headers and docs; see 43 // <http://lists.apple.com/archives/carbon-dev/2007/Aug/msg00089.html>). 44 // The iPhone doesn't have Gestalt though, so use the plist there. 45#if GTM_MACOS_SDK 46 require_noerr(Gestalt(gestaltSystemVersionMajor, &sGTMSystemVersionMajor), failedGestalt); 47 require_noerr(Gestalt(gestaltSystemVersionMinor, &sGTMSystemVersionMinor), failedGestalt); 48 require_noerr(Gestalt(gestaltSystemVersionBugFix, &sGTMSystemVersionBugFix), failedGestalt); 49 50 return; 51 52 failedGestalt: 53 ; 54#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3 55 // gestaltSystemVersionMajor et al are only on 10.4 and above, so they 56 // could fail when running on 10.3. 57 SInt32 binaryCodedDec; 58 OSStatus err = err = Gestalt(gestaltSystemVersion, &binaryCodedDec); 59 _GTMDevAssert(!err, @"Unable to get version from Gestalt"); 60 61 // Note that this code will return x.9.9 for any system rev parts that are 62 // greater than 9 (i.e., 10.10.10 will be 10.9.9). This shouldn't ever be a 63 // problem as the code above takes care of 10.4+. 64 SInt32 msb = (binaryCodedDec & 0x0000F000L) >> 12; 65 msb *= 10; 66 SInt32 lsb = (binaryCodedDec & 0x00000F00L) >> 8; 67 sGTMSystemVersionMajor = msb + lsb; 68 sGTMSystemVersionMinor = (binaryCodedDec & 0x000000F0L) >> 4; 69 sGTMSystemVersionBugFix = (binaryCodedDec & 0x0000000FL); 70#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3 71 72#else // GTM_MACOS_SDK 73 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 74 NSDictionary *systemVersionPlist 75 = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath]; 76 NSString *version = [systemVersionPlist objectForKey:@"ProductVersion"]; 77 _GTMDevAssert(version, @"Unable to get version"); 78 NSArray *versionInfo = [version componentsSeparatedByString:@"."]; 79 NSUInteger length = [versionInfo count]; 80 _GTMDevAssert(length > 1 && length < 4, 81 @"Unparseable version %@", version); 82 sGTMSystemVersionMajor = [[versionInfo objectAtIndex:0] intValue]; 83 _GTMDevAssert(sGTMSystemVersionMajor != 0, 84 @"Unknown version for %@", version); 85 sGTMSystemVersionMinor = [[versionInfo objectAtIndex:1] intValue]; 86 if (length == 3) { 87 sGTMSystemVersionBugFix = [[versionInfo objectAtIndex:2] intValue]; 88 } 89 [pool release]; 90#endif // GTM_MACOS_SDK 91 } 92} 93 94+ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix { 95 if (major) { 96 *major = sGTMSystemVersionMajor; 97 } 98 if (minor) { 99 *minor = sGTMSystemVersionMinor; 100 } 101 if (bugFix) { 102 *bugFix = sGTMSystemVersionBugFix; 103 } 104} 105 106+ (NSString*)build { 107 @synchronized(self) { 108 // Not cached at initialization time because we don't expect "real" 109 // software to want this, and it costs a bit to get at startup. 110 // This will mainly be for unit test cases. 111 if (!sBuild) { 112 NSDictionary *systemVersionPlist 113 = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath]; 114 sBuild = [[systemVersionPlist objectForKey:@"ProductBuildVersion"] retain]; 115 GTMNSMakeUncollectable(sBuild); 116 _GTMDevAssert(sBuild, @"Unable to get build version"); 117 } 118 } 119 return sBuild; 120} 121 122+ (BOOL)isBuildLessThan:(NSString*)build { 123 NSComparisonResult result 124 = [[self build] compare:build 125 options:NSNumericSearch | NSCaseInsensitiveSearch]; 126 return result == NSOrderedAscending; 127} 128 129+ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build { 130 NSComparisonResult result 131 = [[self build] compare:build 132 options:NSNumericSearch | NSCaseInsensitiveSearch]; 133 return result != NSOrderedDescending; 134} 135 136+ (BOOL)isBuildGreaterThan:(NSString*)build { 137 NSComparisonResult result 138 = [[self build] compare:build 139 options:NSNumericSearch | NSCaseInsensitiveSearch]; 140 return result == NSOrderedDescending; 141} 142 143+ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build { 144 NSComparisonResult result 145 = [[self build] compare:build 146 options:NSNumericSearch | NSCaseInsensitiveSearch]; 147 return result != NSOrderedAscending; 148} 149 150+ (BOOL)isBuildEqualTo:(NSString *)build { 151 NSComparisonResult result 152 = [[self build] compare:build 153 options:NSNumericSearch | NSCaseInsensitiveSearch]; 154 return result == NSOrderedSame; 155} 156 157#if GTM_MACOS_SDK 158+ (BOOL)isPanther { 159 return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 3; 160} 161 162+ (BOOL)isTiger { 163 return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 4; 164} 165 166+ (BOOL)isLeopard { 167 return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 5; 168} 169 170+ (BOOL)isSnowLeopard { 171 return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 6; 172} 173 174+ (BOOL)isPantherOrGreater { 175 return (sGTMSystemVersionMajor > 10) || 176 (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 3); 177} 178 179+ (BOOL)isTigerOrGreater { 180 return (sGTMSystemVersionMajor > 10) || 181 (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 4); 182} 183 184+ (BOOL)isLeopardOrGreater { 185 return (sGTMSystemVersionMajor > 10) || 186 (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 5); 187} 188 189+ (BOOL)isSnowLeopardOrGreater { 190 return (sGTMSystemVersionMajor > 10) || 191 (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 6); 192} 193 194#endif // GTM_MACOS_SDK 195 196+ (NSString *)runtimeArchitecture { 197 NSString *architecture = nil; 198#if GTM_IPHONE_SDK 199 architecture = kGTMArch_iPhone; 200#else // !GTM_IPHONE_SDK 201 // In reading arch(3) you'd thing this would work: 202 // 203 // const NXArchInfo *localInfo = NXGetLocalArchInfo(); 204 // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo"); 205 // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0); 206 // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo"); 207 // extensions[0] = [NSString stringWithFormat:@".%s", genericInfo->name]; 208 // 209 // but on 64bit it returns the same things as on 32bit, so... 210#if __POWERPC__ 211#if __LP64__ 212 architecture = kGTMArch_ppc64; 213#else // !__LP64__ 214 architecture = kGTMArch_ppc; 215#endif // __LP64__ 216#else // !__POWERPC__ 217#if __LP64__ 218 architecture = kGTMArch_x86_64; 219#else // !__LP64__ 220 architecture = kGTMArch_i386; 221#endif // __LP64__ 222#endif // !__POWERPC__ 223 224#endif // GTM_IPHONE_SDK 225 return architecture; 226} 227 228@end