ObjFW  Artifact [605fc19a18]

Artifact 605fc19a1822d3d893c4d04947505ded98a50b9be525727aa2ca7a09636be92a:

  • File src/macros.h — part of check-in [13ee56edf3] at 2014-06-21 21:43:43 on branch trunk — Move all macros from OFObject.h to macros.h

    This means that OFObject.h imports macros.h now, making it unnecessary
    to manually import macros.h in almost every file. And while at it, also
    import autorelease.h in OFObject.h, so that this doesn't need to be
    manually imported in almost every file as well. (user: js, size: 14324) [annotate] [blame] [check-ins using]


/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * 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 "objfw-defs.h"

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef OF_OBJFW_RUNTIME
# import "runtime.h"
#endif
#ifdef OF_APPLE_RUNTIME
# import <objc/objc.h>
# import <objc/runtime.h>
# import <objc/message.h>
#endif

#if defined(__GNUC__)
# define restrict __restrict__
#elif __STDC_VERSION__ < 199901L
# define restrict
#endif

#if __STDC_VERSION__ >= 201112L
# ifdef OF_HAVE_STDNORETURN_H
#  include <stdnoreturn.h>
# 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 <threads.h>
# 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))
# define OF_UNLIKELY(cond) (__builtin_expect(!!(cond), 0))
# define OF_CONST_FUNC __attribute__((__const__))
#else
# define OF_INLINE inline
# define OF_LIKELY(cond) cond
# define OF_UNLIKELY(cond) cond
# define OF_CONST_FUNC
#endif

/* Required to build universal binaries on OS X */
#ifdef OF_UNIVERSAL
# if __BIG_ENDIAN__
#  define OF_BIG_ENDIAN
#  define OF_FLOAT_BIG_ENDIAN
# elif !__LITTLE_ENDIAN__
#  error OF_UNIVERSAL defined, but neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__!
# endif
#endif

#ifdef OF_BIG_ENDIAN
# define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_BIG_ENDIAN
#else
# define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_LITTLE_ENDIAN
#endif

#if __STDC_VERSION__ >= 201112L && defined(OF_HAVE_MAX_ALIGN_T)
# define OF_BIGGEST_ALIGNMENT _Alignof(max_align_t)
#else
# ifdef __BIGGEST_ALIGNMENT__
#  define OF_BIGGEST_ALIGNMENT __BIGGEST_ALIGNMENT__
# 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__)
#  define OF_X86_ASM
# elif defined(__ppc__) || defined(__PPC__)
#  define OF_PPC_ASM
# elif defined(__arm__) || defined(__ARM__)
#  define OF_ARM_ASM
#  ifdef __ARM_ARCH_7__
#   define OF_ARMV7_ASM
#  endif
#  ifdef __ARM_ARCH_7A__
#   define OF_ARMV7_ASM
#  endif
#  ifdef __ARM_ARCH_7R__
#   define OF_ARMV7_ASM
#  endif
#  ifdef __ARM_ARCH_7M__
#   define OF_ARMV7_ASM
#  endif
#  ifdef __ARM_ARCH_7EM__
#   define OF_ARMV7_ASM
#  endif
#  ifdef __ARM_ARCH_6__
#   define OF_ARMV6_ASM
#  endif
#  ifdef __ARM_ARCH_6J__
#   define OF_ARMV6_ASM
#  endif
#  ifdef __ARM_ARCH_6K__
#   define OF_ARMV6_ASM
#  endif
#  ifdef __ARM_ARCH_6Z__
#   define OF_ARMV6_ASM
#  endif
#  ifdef __ARM_ARCH_6ZK__
#   define OF_ARMV6_ASM
#  endif
#  ifdef __ARM_ARCH_6T2__
#   define OF_ARMV6_ASM
#  endif
#  ifdef OF_ARMV7_ASM
#   define OF_ARMV6_ASM
#  endif
# elif defined(__arm64__) || defined(__aarch64__)
#  define OF_ARM64_ASM
# endif
#endif

#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 == '/')
#else
# define OF_PATH_DELIMITER '\\'
# define OF_PATH_DELIMITER_STRING @"\\"
# define OF_IS_PATH_DELIMITER(c) (c == '\\' || c == '/')
#endif
#define OF_PATH_CURRENT_DIRECTORY @"."
#define OF_PATH_PARENT_DIRECTORY @".."

#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				\
	@try {						\
		[self doesNotRecognizeSelector: _cmd];	\
	} @catch (id e) {				\
		[self release];				\
		@throw e;				\
	}						\
							\
	abort();

#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;
}

static OF_INLINE uint32_t OF_CONST_FUNC
OF_BSWAP32_CONST(uint32_t i)
{
	return (i & UINT32_C(0xFF000000)) >> 24 |
	    (i & UINT32_C(0x00FF0000)) >>  8 |
	    (i & UINT32_C(0x0000FF00)) <<  8 |
	    (i & UINT32_C(0x000000FF)) << 24;
}

static OF_INLINE uint64_t OF_CONST_FUNC
OF_BSWAP64_CONST(uint64_t i)
{
	return (i & UINT64_C(0xFF00000000000000)) >> 56 |
	    (i & UINT64_C(0x00FF000000000000)) >> 40 |
	    (i & UINT64_C(0x0000FF0000000000)) >> 24 |
	    (i & UINT64_C(0x000000FF00000000)) >>  8 |
	    (i & UINT64_C(0x00000000FF000000)) <<  8 |
	    (i & UINT64_C(0x0000000000FF0000)) << 24 |
	    (i & UINT64_C(0x000000000000FF00)) << 40 |
	    (i & UINT64_C(0x00000000000000FF)) << 56;
}

static OF_INLINE uint16_t OF_CONST_FUNC
OF_BSWAP16_NONCONST(uint16_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP16)
	return __builtin_bswap16(i);
#elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
	__asm__ (
	    "xchgb	%h0, %b0"
	    : "=Q"(i)
	    : "0"(i)
	);
#elif defined(OF_PPC_ASM)
	__asm__ (
	    "lhbrx	%0, 0, %1"
	    : "=r"(i)
	    : "r"(&i), "m"(i)
	);
#elif defined(OF_ARMV6_ASM)
	__asm__ (
	    "rev16	%0, %0"
	    : "=r"(i)
	    : "0"(i)
	);
#else
	i = (i & UINT16_C(0xFF00)) >> 8 |
	    (i & UINT16_C(0x00FF)) << 8;
#endif
	return i;
}

static OF_INLINE uint32_t OF_CONST_FUNC
OF_BSWAP32_NONCONST(uint32_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP32)
	return __builtin_bswap32(i);
#elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
	__asm__ (
	    "bswap	%0"
	    : "=q"(i)
	    : "0"(i)
	);
#elif defined(OF_PPC_ASM)
	__asm__ (
	    "lwbrx	%0, 0, %1"
	    : "=r"(i)
	    : "r"(&i), "m"(i)
	);
#elif defined(OF_ARMV6_ASM)
	__asm__ (
	    "rev	%0, %0"
	    : "=r"(i)
	    : "0"(i)
	);
#else
	i = (i & UINT32_C(0xFF000000)) >> 24 |
	    (i & UINT32_C(0x00FF0000)) >>  8 |
	    (i & UINT32_C(0x0000FF00)) <<  8 |
	    (i & UINT32_C(0x000000FF)) << 24;
#endif
	return i;
}

static OF_INLINE uint64_t OF_CONST_FUNC
OF_BSWAP64_NONCONST(uint64_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP64)
	return __builtin_bswap64(i);
#elif defined(OF_X86_64_ASM)
	__asm__ (
	    "bswap	%0"
	    : "=r"(i)
	    : "0"(i)
	);
#elif defined(OF_X86_ASM)
	__asm__ (
	    "bswap	%%eax\n\t"
	    "bswap	%%edx\n\t"
	    "xchgl	%%eax, %%edx"
	    : "=A"(i)
	    : "0"(i)
	);
#else
	i = (uint64_t)OF_BSWAP32_NONCONST((uint32_t)(i & 0xFFFFFFFF)) << 32 |
	    OF_BSWAP32_NONCONST((uint32_t)(i >> 32));
#endif
	return i;
}

#ifdef __GNUC__
# define OF_BSWAP16(i) \
	(__builtin_constant_p(i) ? OF_BSWAP16_CONST(i) : OF_BSWAP16_NONCONST(i))
# define OF_BSWAP32(i) \
	(__builtin_constant_p(i) ? OF_BSWAP32_CONST(i) : OF_BSWAP32_NONCONST(i))
# define OF_BSWAP64(i) \
	(__builtin_constant_p(i) ? OF_BSWAP64_CONST(i) : OF_BSWAP64_NONCONST(i))
#else
# define OF_BSWAP16(i) OF_BSWAP16_CONST(i)
# define OF_BSWAP32(i) OF_BSWAP32_CONST(i)
# define OF_BSWAP64(i) OF_BSWAP64_CONST(i)
#endif

static OF_INLINE float OF_CONST_FUNC
OF_BSWAP_FLOAT(float f)
{
	union {
		float f;
		uint32_t i;
	} u;

	u.f = f;
	u.i = OF_BSWAP32(u.i);

	return u.f;
}

static OF_INLINE double OF_CONST_FUNC
OF_BSWAP_DOUBLE(double d)
{
	union {
		double d;
		uint64_t i;
	} u;

	u.d = d;
	u.i = OF_BSWAP64(u.i);

	return u.d;
}

#ifdef OF_BIG_ENDIAN
# define OF_BSWAP16_IF_BE(i) OF_BSWAP16(i)
# define OF_BSWAP32_IF_BE(i) OF_BSWAP32(i)
# define OF_BSWAP64_IF_BE(i) OF_BSWAP64(i)
# define OF_BSWAP16_IF_LE(i) (i)
# define OF_BSWAP32_IF_LE(i) (i)
# define OF_BSWAP64_IF_LE(i) (i)
#else
# define OF_BSWAP16_IF_BE(i) (i)
# define OF_BSWAP32_IF_BE(i) (i)
# define OF_BSWAP64_IF_BE(i) (i)
# define OF_BSWAP16_IF_LE(i) OF_BSWAP16(i)
# define OF_BSWAP32_IF_LE(i) OF_BSWAP32(i)
# define OF_BSWAP64_IF_LE(i) OF_BSWAP64(i)
#endif

#ifdef OF_FLOAT_BIG_ENDIAN
# define OF_BSWAP_FLOAT_IF_BE(i) OF_BSWAP_FLOAT(i)
# define OF_BSWAP_DOUBLE_IF_BE(i) OF_BSWAP_DOUBLE(i)
# define OF_BSWAP_FLOAT_IF_LE(i) (i)
# define OF_BSWAP_DOUBLE_IF_LE(i) (i)
#else
# define OF_BSWAP_FLOAT_IF_BE(i) (i)
# define OF_BSWAP_DOUBLE_IF_BE(i) (i)
# define OF_BSWAP_FLOAT_IF_LE(i) OF_BSWAP_FLOAT(i)
# define OF_BSWAP_DOUBLE_IF_LE(i) OF_BSWAP_DOUBLE(i)
#endif

#define OF_ROL(value, bits)						   \
	(((value) << ((bits) % (sizeof(value) * 8))) |			   \
	((value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))))
#define OF_ROR(value, bits)						   \
	(((value) >> ((bits) % (sizeof(value) * 8))) |			   \
	((value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))))

#define OF_ROUND_UP_POW2(pow2, value) (((value) + (pow2) - 1) & ~((pow2) - 1))

#define OF_HASH_INIT(hash) hash = of_hash_seed;
#define OF_HASH_ADD(hash, byte)			\
	{					\
		hash += (uint8_t)(byte);	\
		hash += (hash << 10);		\
		hash ^= (hash >> 6);		\
	}
#define OF_HASH_FINALIZE(hash)		\
	{				\
		hash += (hash << 3);	\
		hash ^= (hash >> 11);	\
		hash += (hash << 15);	\
	}
#define OF_HASH_ADD_HASH(hash, other)				\
	{							\
		uint32_t otherCopy = other;			\
		OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF);	\
		OF_HASH_ADD(hash, (otherCopy >>  8) & 0xFF);	\
		OF_HASH_ADD(hash, otherCopy & 0xFF);		\
	}

static OF_INLINE char*
of_strdup(const char *string)
{
	char *copy;
	size_t length = strlen(string);

	if ((copy = (char*)malloc(length + 1)) == NULL)
		return NULL;

	memcpy(copy, string, length + 1);

	return copy;
}