/core/externals/google-toolbox-for-mac/Foundation/GTMSystemVersion.m

http://macfuse.googlecode.com/ · Objective C · 280 lines · 203 code · 30 blank · 47 comment · 45 complexity · 29f4ab79bddf41d518b075d03fedc800 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. #import "GTMSystemVersion.h"
  19. #import "GTMObjC2Runtime.h"
  20. #if GTM_MACOS_SDK
  21. #import <CoreServices/CoreServices.h>
  22. #else
  23. // On iOS we cheat and pull in the header for UIDevice to get the selectors,
  24. // but call it via runtime since GTMSystemVersion is supposed to only depend on
  25. // Foundation.
  26. #import "UIKit/UIDevice.h"
  27. #endif
  28. static SInt32 sGTMSystemVersionMajor = 0;
  29. static SInt32 sGTMSystemVersionMinor = 0;
  30. static SInt32 sGTMSystemVersionBugFix = 0;
  31. static NSString *sBuild = nil;
  32. NSString *const kGTMArch_iPhone = @"iPhone";
  33. NSString *const kGTMArch_ppc = @"ppc";
  34. NSString *const kGTMArch_ppc64 = @"ppc64";
  35. NSString *const kGTMArch_x86_64 = @"x86_64";
  36. NSString *const kGTMArch_i386 = @"i386";
  37. static NSString *const kSystemVersionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist";
  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. return;
  50. failedGestalt:
  51. ;
  52. #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
  53. // gestaltSystemVersionMajor et al are only on 10.4 and above, so they
  54. // could fail when running on 10.3.
  55. SInt32 binaryCodedDec;
  56. OSStatus err = err = Gestalt(gestaltSystemVersion, &binaryCodedDec);
  57. _GTMDevAssert(!err, @"Unable to get version from Gestalt");
  58. // Note that this code will return x.9.9 for any system rev parts that are
  59. // greater than 9 (i.e., 10.10.10 will be 10.9.9). This shouldn't ever be a
  60. // problem as the code above takes care of 10.4+.
  61. SInt32 msb = (binaryCodedDec & 0x0000F000L) >> 12;
  62. msb *= 10;
  63. SInt32 lsb = (binaryCodedDec & 0x00000F00L) >> 8;
  64. sGTMSystemVersionMajor = msb + lsb;
  65. sGTMSystemVersionMinor = (binaryCodedDec & 0x000000F0L) >> 4;
  66. sGTMSystemVersionBugFix = (binaryCodedDec & 0x0000000FL);
  67. #endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
  68. #else // GTM_MACOS_SDK
  69. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  70. NSString *version = nil;
  71. // The intent is for this file to be Foundation level, so don't directly
  72. // call out to UIDevice, but try to get it at runtime before falling back
  73. // to the plist. The problem with using the plist on the Simulator is that
  74. // the path will be on the host system, and give us a MacOS (10.x.y)
  75. // version number instead of an iOS version number.
  76. Class uideviceClass = NSClassFromString(@"UIDevice");
  77. if (uideviceClass) {
  78. id currentDevice = objc_msgSend(uideviceClass, @selector(currentDevice));
  79. version = [currentDevice performSelector:@selector(systemVersion)];
  80. }
  81. if (!version) {
  82. // Fall back to the info in the Plist.
  83. NSDictionary *systemVersionPlist
  84. = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
  85. version = [systemVersionPlist objectForKey:@"ProductVersion"];
  86. }
  87. _GTMDevAssert(version, @"Unable to get version");
  88. NSArray *versionInfo = [version componentsSeparatedByString:@"."];
  89. NSUInteger length = [versionInfo count];
  90. _GTMDevAssert(length > 1 && length < 4,
  91. @"Unparseable version %@", version);
  92. sGTMSystemVersionMajor = [[versionInfo objectAtIndex:0] intValue];
  93. _GTMDevAssert(sGTMSystemVersionMajor != 0,
  94. @"Unknown version for %@", version);
  95. sGTMSystemVersionMinor = [[versionInfo objectAtIndex:1] intValue];
  96. if (length == 3) {
  97. sGTMSystemVersionBugFix = [[versionInfo objectAtIndex:2] intValue];
  98. }
  99. [pool release];
  100. #endif // GTM_MACOS_SDK
  101. }
  102. }
  103. + (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix {
  104. if (major) {
  105. *major = sGTMSystemVersionMajor;
  106. }
  107. if (minor) {
  108. *minor = sGTMSystemVersionMinor;
  109. }
  110. if (bugFix) {
  111. *bugFix = sGTMSystemVersionBugFix;
  112. }
  113. }
  114. + (NSString*)build {
  115. @synchronized(self) {
  116. // Not cached at initialization time because we don't expect "real"
  117. // software to want this, and it costs a bit to get at startup.
  118. // This will mainly be for unit test cases.
  119. if (!sBuild) {
  120. NSDictionary *systemVersionPlist
  121. = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
  122. sBuild = [[systemVersionPlist objectForKey:@"ProductBuildVersion"] retain];
  123. _GTMDevAssert(sBuild, @"Unable to get build version");
  124. }
  125. }
  126. return sBuild;
  127. }
  128. + (BOOL)isBuildLessThan:(NSString*)build {
  129. NSComparisonResult result
  130. = [[self build] compare:build
  131. options:NSNumericSearch | NSCaseInsensitiveSearch];
  132. return result == NSOrderedAscending;
  133. }
  134. + (BOOL)isBuildLessThanOrEqualTo:(NSString*)build {
  135. NSComparisonResult result
  136. = [[self build] compare:build
  137. options:NSNumericSearch | NSCaseInsensitiveSearch];
  138. return result != NSOrderedDescending;
  139. }
  140. + (BOOL)isBuildGreaterThan:(NSString*)build {
  141. NSComparisonResult result
  142. = [[self build] compare:build
  143. options:NSNumericSearch | NSCaseInsensitiveSearch];
  144. return result == NSOrderedDescending;
  145. }
  146. + (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build {
  147. NSComparisonResult result
  148. = [[self build] compare:build
  149. options:NSNumericSearch | NSCaseInsensitiveSearch];
  150. return result != NSOrderedAscending;
  151. }
  152. + (BOOL)isBuildEqualTo:(NSString *)build {
  153. NSComparisonResult result
  154. = [[self build] compare:build
  155. options:NSNumericSearch | NSCaseInsensitiveSearch];
  156. return result == NSOrderedSame;
  157. }
  158. #if GTM_MACOS_SDK
  159. + (BOOL)isPanther {
  160. #if defined(__MAC_10_4) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_4
  161. return NO;
  162. #else
  163. return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 3;
  164. #endif
  165. }
  166. + (BOOL)isTiger {
  167. #if defined(__MAC_10_5) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_5
  168. return NO;
  169. #else
  170. return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 4;
  171. #endif
  172. }
  173. + (BOOL)isLeopard {
  174. #if defined(__MAC_10_6) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6
  175. return NO;
  176. #else
  177. return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 5;
  178. #endif
  179. }
  180. + (BOOL)isSnowLeopard {
  181. #if defined(__MAC_10_7) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7
  182. return NO;
  183. #else
  184. return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 6;
  185. #endif
  186. }
  187. + (BOOL)isPantherOrGreater {
  188. #if defined(__MAC_10_3) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_3
  189. return YES;
  190. #else
  191. return (sGTMSystemVersionMajor > 10) ||
  192. (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 3);
  193. #endif
  194. }
  195. + (BOOL)isTigerOrGreater {
  196. #if defined(__MAC_10_4) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_4
  197. return YES;
  198. #else
  199. return (sGTMSystemVersionMajor > 10) ||
  200. (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 4);
  201. #endif
  202. }
  203. + (BOOL)isLeopardOrGreater {
  204. #if defined(__MAC_10_5) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_5
  205. return YES;
  206. #else
  207. return (sGTMSystemVersionMajor > 10) ||
  208. (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 5);
  209. #endif
  210. }
  211. + (BOOL)isSnowLeopardOrGreater {
  212. #if defined(__MAC_10_6) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6
  213. return YES;
  214. #else
  215. return (sGTMSystemVersionMajor > 10) ||
  216. (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 6);
  217. #endif
  218. }
  219. #endif // GTM_MACOS_SDK
  220. + (NSString *)runtimeArchitecture {
  221. NSString *architecture = nil;
  222. #if GTM_IPHONE_SDK
  223. architecture = kGTMArch_iPhone;
  224. #else // !GTM_IPHONE_SDK
  225. // In reading arch(3) you'd thing this would work:
  226. //
  227. // const NXArchInfo *localInfo = NXGetLocalArchInfo();
  228. // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo");
  229. // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0);
  230. // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo");
  231. // extensions[0] = [NSString stringWithFormat:@".%s", genericInfo->name];
  232. //
  233. // but on 64bit it returns the same things as on 32bit, so...
  234. #if __POWERPC__
  235. #if __LP64__
  236. architecture = kGTMArch_ppc64;
  237. #else // !__LP64__
  238. architecture = kGTMArch_ppc;
  239. #endif // __LP64__
  240. #else // !__POWERPC__
  241. #if __LP64__
  242. architecture = kGTMArch_x86_64;
  243. #else // !__LP64__
  244. architecture = kGTMArch_i386;
  245. #endif // __LP64__
  246. #endif // !__POWERPC__
  247. #endif // GTM_IPHONE_SDK
  248. return architecture;
  249. }
  250. @end