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 https://github.com/google/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;
394 GTM_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