1//
2// GTMDefines.h
3//
4//  Copyright 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// ============================================================================
20
21#include <AvailabilityMacros.h>
22#include <TargetConditionals.h>
23
24#ifdef __OBJC__
25#include <Foundation/NSObjCRuntime.h>
26#endif  // __OBJC__
27
28#if TARGET_OS_IPHONE
29#include <Availability.h>
30#endif  // TARGET_OS_IPHONE
31
32// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
33#ifndef MAC_OS_X_VERSION_10_5
34  #define MAC_OS_X_VERSION_10_5 1050
35#endif
36#ifndef MAC_OS_X_VERSION_10_6
37  #define MAC_OS_X_VERSION_10_6 1060
38#endif
39#ifndef MAC_OS_X_VERSION_10_7
40  #define MAC_OS_X_VERSION_10_7 1070
41#endif
42
43// Not all __IPHONE_X macros defined in past SDKs
44#ifndef __IPHONE_3_0
45  #define __IPHONE_3_0 30000
46#endif
47#ifndef __IPHONE_3_1
48  #define __IPHONE_3_1 30100
49#endif
50#ifndef __IPHONE_3_2
51  #define __IPHONE_3_2 30200
52#endif
53#ifndef __IPHONE_4_0
54  #define __IPHONE_4_0 40000
55#endif
56#ifndef __IPHONE_4_3
57  #define __IPHONE_4_3 40300
58#endif
59#ifndef __IPHONE_5_0
60  #define __IPHONE_5_0 50000
61#endif
62
63// ----------------------------------------------------------------------------
64// CPP symbols that can be overridden in a prefix to control how the toolbox
65// is compiled.
66// ----------------------------------------------------------------------------
67
68
69// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
70// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
71// when a validation fails. If you implement your own validators, you may want
72// to control their internals using the same macros for consistency.
73#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
74  #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
75#endif
76
77// Give ourselves a consistent way to do inlines.  Apple's macros even use
78// a few different actual definitions, so we're based off of the foundation
79// one.
80#if !defined(GTM_INLINE)
81  #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
82    #define GTM_INLINE static __inline__ __attribute__((always_inline))
83  #else
84    #define GTM_INLINE static __inline__
85  #endif
86#endif
87
88// Give ourselves a consistent way of doing externs that links up nicely
89// when mixing objc and objc++
90#if !defined (GTM_EXTERN)
91  #if defined __cplusplus
92    #define GTM_EXTERN extern "C"
93    #define GTM_EXTERN_C_BEGIN extern "C" {
94    #define GTM_EXTERN_C_END }
95  #else
96    #define GTM_EXTERN extern
97    #define GTM_EXTERN_C_BEGIN
98    #define GTM_EXTERN_C_END
99  #endif
100#endif
101
102// Give ourselves a consistent way of exporting things if we have visibility
103// set to hidden.
104#if !defined (GTM_EXPORT)
105  #define GTM_EXPORT __attribute__((visibility("default")))
106#endif
107
108// Give ourselves a consistent way of declaring something as unused. This
109// doesn't use __unused because that is only supported in gcc 4.2 and greater.
110#if !defined (GTM_UNUSED)
111#define GTM_UNUSED(x) ((void)(x))
112#endif
113
114// _GTMDevLog & _GTMDevAssert
115//
116// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
117// developer level errors.  This implementation simply macros to NSLog/NSAssert.
118// It is not intended to be a general logging/reporting system.
119//
120// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
121// for a little more background on the usage of these macros.
122//
123//    _GTMDevLog           log some error/problem in debug builds
124//    _GTMDevAssert        assert if conditon isn't met w/in a method/function
125//                           in all builds.
126//
127// To replace this system, just provide different macro definitions in your
128// prefix header.  Remember, any implementation you provide *must* be thread
129// safe since this could be called by anything in what ever situtation it has
130// been placed in.
131//
132
133// We only define the simple macros if nothing else has defined this.
134#ifndef _GTMDevLog
135
136#ifdef DEBUG
137  #define _GTMDevLog(...) NSLog(__VA_ARGS__)
138#else
139  #define _GTMDevLog(...) do { } while (0)
140#endif
141
142#endif // _GTMDevLog
143
144#ifndef _GTMDevAssert
145// we directly invoke the NSAssert handler so we can pass on the varargs
146// (NSAssert doesn't have a macro we can use that takes varargs)
147#if !defined(NS_BLOCK_ASSERTIONS)
148  #define _GTMDevAssert(condition, ...)                                       \
149    do {                                                                      \
150      if (!(condition)) {                                                     \
151        [[NSAssertionHandler currentHandler]                                  \
152            handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
153                               file:[NSString stringWithUTF8String:__FILE__]  \
154                         lineNumber:__LINE__                                  \
155                        description:__VA_ARGS__];                             \
156      }                                                                       \
157    } while(0)
158#else // !defined(NS_BLOCK_ASSERTIONS)
159  #define _GTMDevAssert(condition, ...) do { } while (0)
160#endif // !defined(NS_BLOCK_ASSERTIONS)
161
162#endif // _GTMDevAssert
163
164// _GTMCompileAssert
165// _GTMCompileAssert is an assert that is meant to fire at compile time if you
166// want to check things at compile instead of runtime. For example if you
167// want to check that a wchar is 4 bytes instead of 2 you would use
168// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
169// Note that the second "arg" is not in quotes, and must be a valid processor
170// symbol in it's own right (no spaces, punctuation etc).
171
172// Wrapping this in an #ifndef allows external groups to define their own
173// compile time assert scheme.
174#ifndef _GTMCompileAssert
175  // We got this technique from here:
176  // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
177
178  #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
179  #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
180  #define _GTMCompileAssert(test, msg) \
181    typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
182#endif // _GTMCompileAssert
183
184// ----------------------------------------------------------------------------
185// CPP symbols defined based on the project settings so the GTM code has
186// simple things to test against w/o scattering the knowledge of project
187// setting through all the code.
188// ----------------------------------------------------------------------------
189
190// Provide a single constant CPP symbol that all of GTM uses for ifdefing
191// iPhone code.
192#if TARGET_OS_IPHONE // iPhone SDK
193  // For iPhone specific stuff
194  #define GTM_IPHONE_SDK 1
195  #if TARGET_IPHONE_SIMULATOR
196    #define GTM_IPHONE_DEVICE 0
197    #define GTM_IPHONE_SIMULATOR 1
198  #else
199    #define GTM_IPHONE_DEVICE 1
200    #define GTM_IPHONE_SIMULATOR 0
201  #endif  // TARGET_IPHONE_SIMULATOR
202  // By default, GTM has provided it's own unittesting support, define this
203  // to use the support provided by Xcode, especially for the Xcode4 support
204  // for unittesting.
205  #ifndef GTM_IPHONE_USE_SENTEST
206    #define GTM_IPHONE_USE_SENTEST 0
207  #endif
208  #define GTM_MACOS_SDK 0
209#else
210  // For MacOS specific stuff
211  #define GTM_MACOS_SDK 1
212  #define GTM_IPHONE_SDK 0
213  #define GTM_IPHONE_SIMULATOR 0
214  #define GTM_IPHONE_DEVICE 0
215  #define GTM_IPHONE_USE_SENTEST 0
216#endif
217
218// Some of our own availability macros
219#if GTM_MACOS_SDK
220#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
221#define GTM_AVAILABLE_ONLY_ON_MACOS
222#else
223#define GTM_AVAILABLE_ONLY_ON_IPHONE
224#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
225#endif
226
227// GC was dropped by Apple, define the old constant incase anyone still keys
228// off of it.
229#ifndef GTM_SUPPORT_GC
230  #define GTM_SUPPORT_GC 0
231#endif
232
233// To simplify support for 64bit (and Leopard in general), we provide the type
234// defines for non Leopard SDKs
235#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
236 // NSInteger/NSUInteger and Max/Mins
237  #ifndef NSINTEGER_DEFINED
238    #if (defined(__LP64__) && __LP64__) || NS_BUILD_32_LIKE_64
239      typedef long NSInteger;
240      typedef unsigned long NSUInteger;
241    #else
242      typedef int NSInteger;
243      typedef unsigned int NSUInteger;
244    #endif
245    #define NSIntegerMax    LONG_MAX
246    #define NSIntegerMin    LONG_MIN
247    #define NSUIntegerMax   ULONG_MAX
248    #define NSINTEGER_DEFINED 1
249  #endif  // NSINTEGER_DEFINED
250  // CGFloat
251  #ifndef CGFLOAT_DEFINED
252    #if defined(__LP64__) && __LP64__
253      // This really is an untested path (64bit on Tiger?)
254      typedef double CGFloat;
255      #define CGFLOAT_MIN DBL_MIN
256      #define CGFLOAT_MAX DBL_MAX
257      #define CGFLOAT_IS_DOUBLE 1
258    #else /* !defined(__LP64__) || !__LP64__ */
259      typedef float CGFloat;
260      #define CGFLOAT_MIN FLT_MIN
261      #define CGFLOAT_MAX FLT_MAX
262      #define CGFLOAT_IS_DOUBLE 0
263    #endif /* !defined(__LP64__) || !__LP64__ */
264    #define CGFLOAT_DEFINED 1
265  #endif // CGFLOAT_DEFINED
266#endif  // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
267
268// Some support for advanced clang static analysis functionality
269// See http://clang-analyzer.llvm.org/annotations.html
270#ifndef __has_feature      // Optional.
271  #define __has_feature(x) 0 // Compatibility with non-clang compilers.
272#endif
273
274#ifndef NS_RETURNS_RETAINED
275  #if __has_feature(attribute_ns_returns_retained)
276    #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
277  #else
278    #define NS_RETURNS_RETAINED
279  #endif
280#endif
281
282#ifndef NS_RETURNS_NOT_RETAINED
283  #if __has_feature(attribute_ns_returns_not_retained)
284    #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
285  #else
286    #define NS_RETURNS_NOT_RETAINED
287  #endif
288#endif
289
290#ifndef CF_RETURNS_RETAINED
291  #if __has_feature(attribute_cf_returns_retained)
292    #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
293  #else
294    #define CF_RETURNS_RETAINED
295  #endif
296#endif
297
298#ifndef CF_RETURNS_NOT_RETAINED
299  #if __has_feature(attribute_cf_returns_not_retained)
300    #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
301  #else
302    #define CF_RETURNS_NOT_RETAINED
303  #endif
304#endif
305
306#ifndef NS_CONSUMED
307  #if __has_feature(attribute_ns_consumed)
308    #define NS_CONSUMED __attribute__((ns_consumed))
309  #else
310    #define NS_CONSUMED
311  #endif
312#endif
313
314#ifndef CF_CONSUMED
315  #if __has_feature(attribute_cf_consumed)
316    #define CF_CONSUMED __attribute__((cf_consumed))
317  #else
318    #define CF_CONSUMED
319  #endif
320#endif
321
322#ifndef NS_CONSUMES_SELF
323  #if __has_feature(attribute_ns_consumes_self)
324    #define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
325  #else
326    #define NS_CONSUMES_SELF
327  #endif
328#endif
329
330// Defined on 10.6 and above.
331#ifndef NS_FORMAT_ARGUMENT
332  #define NS_FORMAT_ARGUMENT(A)
333#endif
334
335// Defined on 10.6 and above.
336#ifndef NS_FORMAT_FUNCTION
337  #define NS_FORMAT_FUNCTION(F,A)
338#endif
339
340// Defined on 10.6 and above.
341#ifndef CF_FORMAT_ARGUMENT
342  #define CF_FORMAT_ARGUMENT(A)
343#endif
344
345// Defined on 10.6 and above.
346#ifndef CF_FORMAT_FUNCTION
347  #define CF_FORMAT_FUNCTION(F,A)
348#endif
349
350#ifndef GTM_NONNULL
351  #if defined(__has_attribute)
352    #if __has_attribute(nonnull)
353      #define GTM_NONNULL(x) __attribute__((nonnull x))
354    #else
355      #define GTM_NONNULL(x)
356    #endif
357  #else
358    #define GTM_NONNULL(x)
359  #endif
360#endif
361
362// Invalidates the initializer from which it's called.
363#ifndef GTMInvalidateInitializer
364  #if __has_feature(objc_arc)
365    #define GTMInvalidateInitializer() \
366      do { \
367        [self class]; /* Avoid warning of dead store to |self|. */ \
368        _GTMDevAssert(NO, @"Invalid initializer."); \
369        return nil; \
370      } while (0)
371  #else
372    #define GTMInvalidateInitializer() \
373      do { \
374        [self release]; \
375        _GTMDevAssert(NO, @"Invalid initializer."); \
376        return nil; \
377      } while (0)
378  #endif
379#endif
380
381#ifndef GTMCFAutorelease
382  #if __has_feature(objc_arc)
383    #define GTMCFAutorelease(x) CFBridgingRelease(x)
384  #else
385    #define GTMCFAutorelease(x) ([(id)x autorelease])
386  #endif
387#endif
388
389#ifdef __OBJC__
390
391// Declared here so that it can easily be used for logging tracking if
392// necessary. See GTMUnitTestDevLog.h for details.
393@class NSString;
394GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
395
396// Macro to allow you to create NSStrings out of other macros.
397// #define FOO foo
398// NSString *fooString = GTM_NSSTRINGIFY(FOO);
399#if !defined (GTM_NSSTRINGIFY)
400  #define GTM_NSSTRINGIFY_INNER(x) @#x
401  #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
402#endif
403
404// Macro to allow fast enumeration when building for 10.5 or later, and
405// reliance on NSEnumerator for 10.4.  Remember, NSDictionary w/ FastEnumeration
406// does keys, so pick the right thing, nothing is done on the FastEnumeration
407// side to be sure you're getting what you wanted.
408#ifndef GTM_FOREACH_OBJECT
409  #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
410    #define GTM_FOREACH_ENUMEREE(element, enumeration) \
411      for (element in enumeration)
412    #define GTM_FOREACH_OBJECT(element, collection) \
413      for (element in collection)
414    #define GTM_FOREACH_KEY(element, collection) \
415      for (element in collection)
416  #else
417    #define GTM_FOREACH_ENUMEREE(element, enumeration) \
418      for (NSEnumerator *_ ## element ## _enum = enumeration; \
419           (element = [_ ## element ## _enum nextObject]) != nil; )
420    #define GTM_FOREACH_OBJECT(element, collection) \
421      GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
422    #define GTM_FOREACH_KEY(element, collection) \
423      GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
424  #endif
425#endif
426
427// ============================================================================
428
429// To simplify support for both Leopard and Snow Leopard we declare
430// the Snow Leopard protocols that we need here.
431#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
432#define GTM_10_6_PROTOCOLS_DEFINED 1
433@protocol NSConnectionDelegate
434@end
435@protocol NSAnimationDelegate
436@end
437@protocol NSImageDelegate
438@end
439@protocol NSTabViewDelegate
440@end
441#endif  // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
442
443// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
444// or KVO methods.
445// In debug it will generate warnings for undeclared selectors if
446// -Wunknown-selector is turned on.
447// In release it will have no runtime overhead.
448#ifndef GTM_SEL_STRING
449  #ifdef DEBUG
450    #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
451  #else
452    #define GTM_SEL_STRING(selName) @#selName
453  #endif  // DEBUG
454#endif  // GTM_SEL_STRING
455
456#endif  // __OBJC__
457