@@ -12,20 +12,77 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#import "OFObject.h" +#import "objfw-defs.h" + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #include #include #include #include -#if defined(OF_APPLE_RUNTIME) +#ifdef OF_OBJFW_RUNTIME +# import "runtime.h" +#endif +#ifdef OF_APPLE_RUNTIME +# import # import +# import +#endif + +#if defined(__GNUC__) +# define restrict __restrict__ +#elif __STDC_VERSION__ < 199901L +# define restrict +#endif + +#if __STDC_VERSION__ >= 201112L +# ifdef OF_HAVE_STDNORETURN_H +# include +# else +# define noreturn _Noreturn +# endif +#elif defined(__GNUC__) +# define noreturn __attribute__((__noreturn__)) +#else +# define noreturn +#endif + +/* + * Work around Apple's libc headers breaking by defining noreturn. + * They use __attribute__((noreturn)) where they should be using + * __attribute__((__noreturn__)). + */ +#if defined(__APPLE__) && defined(__dead2) +# undef __dead2 +# define __dead2 __attribute__((__noreturn__)) +#endif + +#if __STDC_VERSION__ >= 201112L && !defined(static_assert) +/* C11 compiler, but old libc */ +# define static_assert _Static_assert +#endif + +#if defined(OF_HAVE__THREAD_LOCAL) +# define OF_HAVE_COMPILER_TLS +# ifdef OF_HAVE_THREADS_H +# include +# else +# define thread_local _Thread_local +# endif +#elif defined(OF_HAVE___THREAD) +# define OF_HAVE_COMPILER_TLS +# define thread_local __thread #endif #ifdef __GNUC__ # define OF_INLINE inline __attribute__((__always_inline__)) # define OF_LIKELY(cond) (__builtin_expect(!!(cond), 1)) @@ -62,10 +119,83 @@ # else # /* Hopefully no arch needs more than 16 byte alignment */ # define OF_BIGGEST_ALIGNMENT 16 # endif #endif + +#ifdef __GNUC__ +# define __GCC_VERSION__ (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define __GCC_VERSION__ 0 +#endif + +#if defined(__clang__) || __GCC_VERSION__ >= 406 || defined(OBJC_NEW_PROPERTIES) +# define OF_HAVE_PROPERTIES +# define OF_HAVE_OPTIONAL_PROTOCOLS +# if defined(__clang__) || __GCC_VERSION__ >= 406 || defined(OF_APPLE_RUNTIME) +# define OF_HAVE_FAST_ENUMERATION +# endif +# define OF_HAVE_CLASS_EXTENSIONS +# define OF_PRIVATE_CATEGORY +#else +# define OF_PRIVATE_CATEGORY Private +#endif + +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#if !__has_feature(objc_instancetype) +# define instancetype id +#endif + +#if __has_feature(blocks) +# define OF_HAVE_BLOCKS +#endif + +#if __has_feature(objc_bool) +# undef YES +# define YES __objc_yes +# undef NO +# define NO __objc_no +# ifndef __cplusplus +# undef true +# define true ((bool)1) +# undef false +# define false ((bool)0) +# endif +#endif + +#if defined(__clang__) || __GCC_VERSION__ >= 405 +# define OF_UNREACHABLE __builtin_unreachable(); +#else +# define OF_UNREACHABLE abort(); +#endif + +#if defined(__clang__) || __GCC_VERSION__ >= 406 +# define OF_SENTINEL __attribute__((__sentinel__)) +# define OF_METHOD_NORETURN __attribute__((__noreturn__)) +#else +# define OF_SENTINEL +# define OF_METHOD_NORETURN +#endif + +#if __has_attribute(__objc_requires_super__) +# define OF_REQUIRES_SUPER __attribute__((__objc_requires_super__)) +#else +# define OF_REQUIRES_SUPER +#endif + +#if __has_attribute(__objc_root_class__) +# define OF_ROOT_CLASS __attribute__((__objc_root_class__)) +#else +# define OF_ROOT_CLASS +#endif #ifdef __GNUC__ # if defined(__x86_64__) || defined(__amd64__) # define OF_X86_64_ASM # elif defined(__i386__) @@ -113,21 +243,63 @@ # elif defined(__arm64__) || defined(__aarch64__) # define OF_ARM64_ASM # endif #endif -#define OF_ENSURE(cond) \ - if (!(cond)) { \ - fprintf(stderr, "Failed to ensure condition in " \ - __FILE__ ":%d:\n" #cond "\n", __LINE__); \ - abort(); \ - } - -#if __STDC_VERSION__ >= 201112L && !defined(static_assert) -/* C11 compiler, but old libc */ -# define static_assert _Static_assert +#ifdef OF_APPLE_RUNTIME +# if defined(__x86_64__) || defined(__i386__) || defined(__ARM64_ARCH_8__) || \ + defined(__arm__) || defined(__ppc__) +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +# endif +#else +# if defined(__ELF__) +# if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) || \ + defined(__arm__) || defined(__ARM__) || defined(__ppc__) || \ + defined(__PPC__) +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR +# if __OBJFW_RUNTIME_ABI__ >= 800 +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +# endif +# endif +# if (defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32) || \ + (defined(__mips_eabi) && _MIPS_SZPTR == 32) +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR +# if __OBJFW_RUNTIME_ABI__ >= 800 +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +# endif +# endif +# elif defined(_WIN32) +# if defined(__x86_64__) || defined(__i386__) +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR +# if __OBJFW_RUNTIME_ABI__ >= 800 +# define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +# endif +# endif +# endif +#endif + +#if __has_feature(objc_arc) +# define OF_RETURNS_RETAINED __attribute__((__ns_returns_retained__)) +# define OF_RETURNS_NOT_RETAINED __attribute__((__ns_returns_not_retained__)) +# define OF_RETURNS_INNER_POINTER \ + __attribute__((__objc_returns_inner_pointer__)) +# define OF_CONSUMED __attribute__((__ns_consumed__)) +# define OF_WEAK_UNAVAILABLE __attribute__((__objc_arc_weak_unavailable__)) +#else +# define OF_RETURNS_RETAINED +# define OF_RETURNS_NOT_RETAINED +# define OF_RETURNS_INNER_POINTER +# define OF_CONSUMED +# define OF_WEAK_UNAVAILABLE +# define __unsafe_unretained +# define __bridge +# define __autoreleasing #endif + +#define OF_RETAIN_COUNT_MAX UINT_MAX +#define OF_NOT_FOUND SIZE_MAX #if !defined(_WIN32) && !defined(__DJGPP__) # define OF_PATH_DELIMITER '/' # define OF_PATH_DELIMITER_STRING @"/" # define OF_IS_PATH_DELIMITER(c) (c == '/') @@ -137,24 +309,16 @@ # define OF_IS_PATH_DELIMITER(c) (c == '\\' || c == '/') #endif #define OF_PATH_CURRENT_DIRECTORY @"." #define OF_PATH_PARENT_DIRECTORY @".." -extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL); -extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, signed char); - -#define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self) -#define OF_GETTER(ivar, atomic) \ - return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic); -#define OF_SETTER(ivar, value, atomic, copy) \ - objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy); - -#if defined(__clang__) || __GCC_VERSION__ >= 405 -# define OF_UNREACHABLE __builtin_unreachable(); -#else -# define OF_UNREACHABLE abort(); -#endif +#define OF_ENSURE(cond) \ + if (!(cond)) { \ + fprintf(stderr, "Failed to ensure condition in " \ + __FILE__ ":%d:\n" #cond "\n", __LINE__); \ + abort(); \ + } #define OF_UNRECOGNIZED_SELECTOR \ [self doesNotRecognizeSelector: _cmd]; \ OF_UNREACHABLE #define OF_INVALID_INIT_METHOD \ @@ -165,16 +329,25 @@ @throw e; \ } \ \ abort(); -#ifdef OF_HAVE_CLASS_EXTENSIONS -# define OF_PRIVATE_CATEGORY -#else -# define OF_PRIVATE_CATEGORY Private +#ifdef __cplusplus +extern "C" { +#endif +extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL); +extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, signed char); +#ifdef __cplusplus +} #endif +#define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self) +#define OF_GETTER(ivar, atomic) \ + return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic); +#define OF_SETTER(ivar, value, atomic, copy) \ + objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy); + static OF_INLINE uint16_t OF_CONST_FUNC OF_BSWAP16_CONST(uint16_t i) { return (i & UINT16_C(0xFF00)) >> 8 | (i & UINT16_C(0x00FF)) << 8; @@ -388,45 +561,10 @@ OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF); \ OF_HASH_ADD(hash, (otherCopy >> 8) & 0xFF); \ OF_HASH_ADD(hash, otherCopy & 0xFF); \ } -static OF_INLINE of_range_t OF_CONST_FUNC -of_range(size_t start, size_t length) -{ - of_range_t range = { start, length }; - - return range; -} - -static OF_INLINE of_point_t OF_CONST_FUNC -of_point(float x, float y) -{ - of_point_t point = { x, y }; - - return point; -} - -static OF_INLINE of_dimension_t OF_CONST_FUNC -of_dimension(float width, float height) -{ - of_dimension_t dimension = { width, height }; - - return dimension; -} - -static OF_INLINE of_rectangle_t OF_CONST_FUNC -of_rectangle(float x, float y, float width, float height) -{ - of_rectangle_t rectangle = { - of_point(x, y), - of_dimension(width, height) - }; - - return rectangle; -} - static OF_INLINE char* of_strdup(const char *string) { char *copy; size_t length = strlen(string);