michael@0: // michael@0: // GTMDefines.h michael@0: // michael@0: // Copyright 2008 Google Inc. michael@0: // michael@0: // Licensed under the Apache License, Version 2.0 (the "License"); you may not michael@0: // use this file except in compliance with the License. You may obtain a copy michael@0: // of the License at michael@0: // michael@0: // http://www.apache.org/licenses/LICENSE-2.0 michael@0: // michael@0: // Unless required by applicable law or agreed to in writing, software michael@0: // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT michael@0: // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the michael@0: // License for the specific language governing permissions and limitations under michael@0: // the License. michael@0: // michael@0: michael@0: // ============================================================================ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #ifdef __OBJC__ michael@0: #include michael@0: #endif // __OBJC__ michael@0: michael@0: #if TARGET_OS_IPHONE michael@0: #include michael@0: #endif // TARGET_OS_IPHONE michael@0: michael@0: // Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs michael@0: #ifndef MAC_OS_X_VERSION_10_5 michael@0: #define MAC_OS_X_VERSION_10_5 1050 michael@0: #endif michael@0: #ifndef MAC_OS_X_VERSION_10_6 michael@0: #define MAC_OS_X_VERSION_10_6 1060 michael@0: #endif michael@0: #ifndef MAC_OS_X_VERSION_10_7 michael@0: #define MAC_OS_X_VERSION_10_7 1070 michael@0: #endif michael@0: michael@0: // Not all __IPHONE_X macros defined in past SDKs michael@0: #ifndef __IPHONE_3_0 michael@0: #define __IPHONE_3_0 30000 michael@0: #endif michael@0: #ifndef __IPHONE_3_1 michael@0: #define __IPHONE_3_1 30100 michael@0: #endif michael@0: #ifndef __IPHONE_3_2 michael@0: #define __IPHONE_3_2 30200 michael@0: #endif michael@0: #ifndef __IPHONE_4_0 michael@0: #define __IPHONE_4_0 40000 michael@0: #endif michael@0: #ifndef __IPHONE_4_3 michael@0: #define __IPHONE_4_3 40300 michael@0: #endif michael@0: #ifndef __IPHONE_5_0 michael@0: #define __IPHONE_5_0 50000 michael@0: #endif michael@0: michael@0: // ---------------------------------------------------------------------------- michael@0: // CPP symbols that can be overridden in a prefix to control how the toolbox michael@0: // is compiled. michael@0: // ---------------------------------------------------------------------------- michael@0: michael@0: michael@0: // By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and michael@0: // GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens michael@0: // when a validation fails. If you implement your own validators, you may want michael@0: // to control their internals using the same macros for consistency. michael@0: #ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT michael@0: #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 michael@0: #endif michael@0: michael@0: // Give ourselves a consistent way to do inlines. Apple's macros even use michael@0: // a few different actual definitions, so we're based off of the foundation michael@0: // one. michael@0: #if !defined(GTM_INLINE) michael@0: #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__) michael@0: #define GTM_INLINE static __inline__ __attribute__((always_inline)) michael@0: #else michael@0: #define GTM_INLINE static __inline__ michael@0: #endif michael@0: #endif michael@0: michael@0: // Give ourselves a consistent way of doing externs that links up nicely michael@0: // when mixing objc and objc++ michael@0: #if !defined (GTM_EXTERN) michael@0: #if defined __cplusplus michael@0: #define GTM_EXTERN extern "C" michael@0: #define GTM_EXTERN_C_BEGIN extern "C" { michael@0: #define GTM_EXTERN_C_END } michael@0: #else michael@0: #define GTM_EXTERN extern michael@0: #define GTM_EXTERN_C_BEGIN michael@0: #define GTM_EXTERN_C_END michael@0: #endif michael@0: #endif michael@0: michael@0: // Give ourselves a consistent way of exporting things if we have visibility michael@0: // set to hidden. michael@0: #if !defined (GTM_EXPORT) michael@0: #define GTM_EXPORT __attribute__((visibility("default"))) michael@0: #endif michael@0: michael@0: // Give ourselves a consistent way of declaring something as unused. This michael@0: // doesn't use __unused because that is only supported in gcc 4.2 and greater. michael@0: #if !defined (GTM_UNUSED) michael@0: #define GTM_UNUSED(x) ((void)(x)) michael@0: #endif michael@0: michael@0: // _GTMDevLog & _GTMDevAssert michael@0: // michael@0: // _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for michael@0: // developer level errors. This implementation simply macros to NSLog/NSAssert. michael@0: // It is not intended to be a general logging/reporting system. michael@0: // michael@0: // Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert michael@0: // for a little more background on the usage of these macros. michael@0: // michael@0: // _GTMDevLog log some error/problem in debug builds michael@0: // _GTMDevAssert assert if conditon isn't met w/in a method/function michael@0: // in all builds. michael@0: // michael@0: // To replace this system, just provide different macro definitions in your michael@0: // prefix header. Remember, any implementation you provide *must* be thread michael@0: // safe since this could be called by anything in what ever situtation it has michael@0: // been placed in. michael@0: // michael@0: michael@0: // We only define the simple macros if nothing else has defined this. michael@0: #ifndef _GTMDevLog michael@0: michael@0: #ifdef DEBUG michael@0: #define _GTMDevLog(...) NSLog(__VA_ARGS__) michael@0: #else michael@0: #define _GTMDevLog(...) do { } while (0) michael@0: #endif michael@0: michael@0: #endif // _GTMDevLog michael@0: michael@0: #ifndef _GTMDevAssert michael@0: // we directly invoke the NSAssert handler so we can pass on the varargs michael@0: // (NSAssert doesn't have a macro we can use that takes varargs) michael@0: #if !defined(NS_BLOCK_ASSERTIONS) michael@0: #define _GTMDevAssert(condition, ...) \ michael@0: do { \ michael@0: if (!(condition)) { \ michael@0: [[NSAssertionHandler currentHandler] \ michael@0: handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ michael@0: file:[NSString stringWithUTF8String:__FILE__] \ michael@0: lineNumber:__LINE__ \ michael@0: description:__VA_ARGS__]; \ michael@0: } \ michael@0: } while(0) michael@0: #else // !defined(NS_BLOCK_ASSERTIONS) michael@0: #define _GTMDevAssert(condition, ...) do { } while (0) michael@0: #endif // !defined(NS_BLOCK_ASSERTIONS) michael@0: michael@0: #endif // _GTMDevAssert michael@0: michael@0: // _GTMCompileAssert michael@0: // _GTMCompileAssert is an assert that is meant to fire at compile time if you michael@0: // want to check things at compile instead of runtime. For example if you michael@0: // want to check that a wchar is 4 bytes instead of 2 you would use michael@0: // _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) michael@0: // Note that the second "arg" is not in quotes, and must be a valid processor michael@0: // symbol in it's own right (no spaces, punctuation etc). michael@0: michael@0: // Wrapping this in an #ifndef allows external groups to define their own michael@0: // compile time assert scheme. michael@0: #ifndef _GTMCompileAssert michael@0: // We got this technique from here: michael@0: // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html michael@0: michael@0: #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg michael@0: #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) michael@0: #define _GTMCompileAssert(test, msg) \ michael@0: typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] michael@0: #endif // _GTMCompileAssert michael@0: michael@0: // ---------------------------------------------------------------------------- michael@0: // CPP symbols defined based on the project settings so the GTM code has michael@0: // simple things to test against w/o scattering the knowledge of project michael@0: // setting through all the code. michael@0: // ---------------------------------------------------------------------------- michael@0: michael@0: // Provide a single constant CPP symbol that all of GTM uses for ifdefing michael@0: // iPhone code. michael@0: #if TARGET_OS_IPHONE // iPhone SDK michael@0: // For iPhone specific stuff michael@0: #define GTM_IPHONE_SDK 1 michael@0: #if TARGET_IPHONE_SIMULATOR michael@0: #define GTM_IPHONE_SIMULATOR 1 michael@0: #else michael@0: #define GTM_IPHONE_DEVICE 1 michael@0: #endif // TARGET_IPHONE_SIMULATOR michael@0: // By default, GTM has provided it's own unittesting support, define this michael@0: // to use the support provided by Xcode, especially for the Xcode4 support michael@0: // for unittesting. michael@0: #ifndef GTM_IPHONE_USE_SENTEST michael@0: #define GTM_IPHONE_USE_SENTEST 0 michael@0: #endif michael@0: #else michael@0: // For MacOS specific stuff michael@0: #define GTM_MACOS_SDK 1 michael@0: #endif michael@0: michael@0: // Some of our own availability macros michael@0: #if GTM_MACOS_SDK michael@0: #define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE michael@0: #define GTM_AVAILABLE_ONLY_ON_MACOS michael@0: #else michael@0: #define GTM_AVAILABLE_ONLY_ON_IPHONE michael@0: #define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE michael@0: #endif michael@0: michael@0: // Provide a symbol to include/exclude extra code for GC support. (This mainly michael@0: // just controls the inclusion of finalize methods). michael@0: #ifndef GTM_SUPPORT_GC michael@0: #if GTM_IPHONE_SDK michael@0: // iPhone never needs GC michael@0: #define GTM_SUPPORT_GC 0 michael@0: #else michael@0: // We can't find a symbol to tell if GC is supported/required, so best we michael@0: // do on Mac targets is include it if we're on 10.5 or later. michael@0: #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 michael@0: #define GTM_SUPPORT_GC 0 michael@0: #else michael@0: #define GTM_SUPPORT_GC 1 michael@0: #endif michael@0: #endif michael@0: #endif michael@0: michael@0: // To simplify support for 64bit (and Leopard in general), we provide the type michael@0: // defines for non Leopard SDKs michael@0: #if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) michael@0: // NSInteger/NSUInteger and Max/Mins michael@0: #ifndef NSINTEGER_DEFINED michael@0: #if __LP64__ || NS_BUILD_32_LIKE_64 michael@0: typedef long NSInteger; michael@0: typedef unsigned long NSUInteger; michael@0: #else michael@0: typedef int NSInteger; michael@0: typedef unsigned int NSUInteger; michael@0: #endif michael@0: #define NSIntegerMax LONG_MAX michael@0: #define NSIntegerMin LONG_MIN michael@0: #define NSUIntegerMax ULONG_MAX michael@0: #define NSINTEGER_DEFINED 1 michael@0: #endif // NSINTEGER_DEFINED michael@0: // CGFloat michael@0: #ifndef CGFLOAT_DEFINED michael@0: #if defined(__LP64__) && __LP64__ michael@0: // This really is an untested path (64bit on Tiger?) michael@0: typedef double CGFloat; michael@0: #define CGFLOAT_MIN DBL_MIN michael@0: #define CGFLOAT_MAX DBL_MAX michael@0: #define CGFLOAT_IS_DOUBLE 1 michael@0: #else /* !defined(__LP64__) || !__LP64__ */ michael@0: typedef float CGFloat; michael@0: #define CGFLOAT_MIN FLT_MIN michael@0: #define CGFLOAT_MAX FLT_MAX michael@0: #define CGFLOAT_IS_DOUBLE 0 michael@0: #endif /* !defined(__LP64__) || !__LP64__ */ michael@0: #define CGFLOAT_DEFINED 1 michael@0: #endif // CGFLOAT_DEFINED michael@0: #endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 michael@0: michael@0: // Some support for advanced clang static analysis functionality michael@0: // See http://clang-analyzer.llvm.org/annotations.html michael@0: #ifndef __has_feature // Optional. michael@0: #define __has_feature(x) 0 // Compatibility with non-clang compilers. michael@0: #endif michael@0: michael@0: #ifndef NS_RETURNS_RETAINED michael@0: #if __has_feature(attribute_ns_returns_retained) michael@0: #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) michael@0: #else michael@0: #define NS_RETURNS_RETAINED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef NS_RETURNS_NOT_RETAINED michael@0: #if __has_feature(attribute_ns_returns_not_retained) michael@0: #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) michael@0: #else michael@0: #define NS_RETURNS_NOT_RETAINED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef CF_RETURNS_RETAINED michael@0: #if __has_feature(attribute_cf_returns_retained) michael@0: #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) michael@0: #else michael@0: #define CF_RETURNS_RETAINED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef CF_RETURNS_NOT_RETAINED michael@0: #if __has_feature(attribute_cf_returns_not_retained) michael@0: #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) michael@0: #else michael@0: #define CF_RETURNS_NOT_RETAINED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef NS_CONSUMED michael@0: #if __has_feature(attribute_ns_consumed) michael@0: #define NS_CONSUMED __attribute__((ns_consumed)) michael@0: #else michael@0: #define NS_CONSUMED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef CF_CONSUMED michael@0: #if __has_feature(attribute_cf_consumed) michael@0: #define CF_CONSUMED __attribute__((cf_consumed)) michael@0: #else michael@0: #define CF_CONSUMED michael@0: #endif michael@0: #endif michael@0: michael@0: #ifndef NS_CONSUMES_SELF michael@0: #if __has_feature(attribute_ns_consumes_self) michael@0: #define NS_CONSUMES_SELF __attribute__((ns_consumes_self)) michael@0: #else michael@0: #define NS_CONSUMES_SELF michael@0: #endif michael@0: #endif michael@0: michael@0: // Defined on 10.6 and above. michael@0: #ifndef NS_FORMAT_ARGUMENT michael@0: #define NS_FORMAT_ARGUMENT(A) michael@0: #endif michael@0: michael@0: // Defined on 10.6 and above. michael@0: #ifndef NS_FORMAT_FUNCTION michael@0: #define NS_FORMAT_FUNCTION(F,A) michael@0: #endif michael@0: michael@0: // Defined on 10.6 and above. michael@0: #ifndef CF_FORMAT_ARGUMENT michael@0: #define CF_FORMAT_ARGUMENT(A) michael@0: #endif michael@0: michael@0: // Defined on 10.6 and above. michael@0: #ifndef CF_FORMAT_FUNCTION michael@0: #define CF_FORMAT_FUNCTION(F,A) michael@0: #endif michael@0: michael@0: #ifndef GTM_NONNULL michael@0: #define GTM_NONNULL(x) __attribute__((nonnull(x))) michael@0: #endif michael@0: michael@0: // Invalidates the initializer from which it's called. michael@0: #ifndef GTMInvalidateInitializer michael@0: #if __has_feature(objc_arc) michael@0: #define GTMInvalidateInitializer() \ michael@0: do { \ michael@0: [self class]; /* Avoid warning of dead store to |self|. */ \ michael@0: _GTMDevAssert(NO, @"Invalid initializer."); \ michael@0: return nil; \ michael@0: } while (0) michael@0: #else michael@0: #define GTMInvalidateInitializer() \ michael@0: do { \ michael@0: [self release]; \ michael@0: _GTMDevAssert(NO, @"Invalid initializer."); \ michael@0: return nil; \ michael@0: } while (0) michael@0: #endif michael@0: #endif michael@0: michael@0: #ifdef __OBJC__ michael@0: michael@0: // Declared here so that it can easily be used for logging tracking if michael@0: // necessary. See GTMUnitTestDevLog.h for details. michael@0: @class NSString; michael@0: GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2); michael@0: michael@0: // Macro to allow you to create NSStrings out of other macros. michael@0: // #define FOO foo michael@0: // NSString *fooString = GTM_NSSTRINGIFY(FOO); michael@0: #if !defined (GTM_NSSTRINGIFY) michael@0: #define GTM_NSSTRINGIFY_INNER(x) @#x michael@0: #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x) michael@0: #endif michael@0: michael@0: // Macro to allow fast enumeration when building for 10.5 or later, and michael@0: // reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration michael@0: // does keys, so pick the right thing, nothing is done on the FastEnumeration michael@0: // side to be sure you're getting what you wanted. michael@0: #ifndef GTM_FOREACH_OBJECT michael@0: #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) michael@0: #define GTM_FOREACH_ENUMEREE(element, enumeration) \ michael@0: for (element in enumeration) michael@0: #define GTM_FOREACH_OBJECT(element, collection) \ michael@0: for (element in collection) michael@0: #define GTM_FOREACH_KEY(element, collection) \ michael@0: for (element in collection) michael@0: #else michael@0: #define GTM_FOREACH_ENUMEREE(element, enumeration) \ michael@0: for (NSEnumerator *_ ## element ## _enum = enumeration; \ michael@0: (element = [_ ## element ## _enum nextObject]) != nil; ) michael@0: #define GTM_FOREACH_OBJECT(element, collection) \ michael@0: GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator]) michael@0: #define GTM_FOREACH_KEY(element, collection) \ michael@0: GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator]) michael@0: #endif michael@0: #endif michael@0: michael@0: // ============================================================================ michael@0: michael@0: // To simplify support for both Leopard and Snow Leopard we declare michael@0: // the Snow Leopard protocols that we need here. michael@0: #if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) michael@0: #define GTM_10_6_PROTOCOLS_DEFINED 1 michael@0: @protocol NSConnectionDelegate michael@0: @end michael@0: @protocol NSAnimationDelegate michael@0: @end michael@0: @protocol NSImageDelegate michael@0: @end michael@0: @protocol NSTabViewDelegate michael@0: @end michael@0: #endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) michael@0: michael@0: // GTM_SEL_STRING is for specifying selector (usually property) names to KVC michael@0: // or KVO methods. michael@0: // In debug it will generate warnings for undeclared selectors if michael@0: // -Wunknown-selector is turned on. michael@0: // In release it will have no runtime overhead. michael@0: #ifndef GTM_SEL_STRING michael@0: #ifdef DEBUG michael@0: #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName)) michael@0: #else michael@0: #define GTM_SEL_STRING(selName) @#selName michael@0: #endif // DEBUG michael@0: #endif // GTM_SEL_STRING michael@0: michael@0: #endif // __OBJC__