ObjFW
|
00001 /* 00002 * Copyright (c) 2008, 2009, 2010, 2011, 2012 00003 * Jonathan Schleifer <js@webkeks.org> 00004 * 00005 * All rights reserved. 00006 * 00007 * This file is part of ObjFW. It may be distributed under the terms of the 00008 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in 00009 * the packaging of this file. 00010 * 00011 * Alternatively, it may be distributed under the terms of the GNU General 00012 * Public License, either version 2 or 3, which can be found in the file 00013 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this 00014 * file. 00015 */ 00016 00017 #import "OFObject.h" 00018 00019 #include <stddef.h> 00020 #include <stdint.h> 00021 00022 #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) 00023 # import <objc/runtime.h> 00024 #elif defined(OF_OLD_GNU_RUNTIME) 00025 # import <objc/objc-api.h> 00026 #endif 00027 00028 #ifdef _PSP 00029 # define INTMAX_MAX LONG_LONG_MAX 00030 #endif 00031 00032 #ifdef __GNUC__ 00033 # define OF_INLINE inline __attribute__((always_inline)) 00034 # define OF_LIKELY(cond) __builtin_expect(!!(cond), 1) 00035 # define OF_UNLIKELY(cond) __builtin_expect(!!(cond), 0) 00036 # define OF_CONST_FUNC __attribute__((const)) 00037 #else 00038 # define OF_INLINE inline 00039 # define OF_LIKELY(cond) cond 00040 # define OF_UNLIKELY(cond) cond 00041 # define OF_CONST_FUNC 00042 #endif 00043 00044 #if defined(__GNUC__) 00045 # define restrict __restrict__ 00046 #elif __STDC_VERSION__ < 199901L 00047 # define restrict 00048 #endif 00049 00050 /* Required to build universal binaries on OS X */ 00051 #if __BIG_ENDIAN__ || __LITTLE_ENDIAN__ 00052 # if __BIG_ENDIAN__ && __LITTLE_ENDIAN__ 00053 # error __BIG_ENDIAN__ and __LITTLE_ENDIAN__ defined! 00054 # endif 00055 # undef OF_BIG_ENDIAN 00056 # if __BIG_ENDIAN__ 00057 # define OF_BIG_ENDIAN 00058 # endif 00059 #endif 00060 00061 #ifdef OF_BIG_ENDIAN 00062 # define OF_ENDIANESS_NATIVE OF_ENDIANESS_BIG_ENDIAN 00063 #else 00064 # define OF_ENDIANESS_NATIVE OF_ENDIANESS_LITTLE_ENDIAN 00065 #endif 00066 00067 #ifdef __GNUC__ 00068 # if defined(__amd64__) || defined(__x86_64__) 00069 # define OF_AMD64_ASM 00070 # elif defined(__i386__) 00071 # define OF_X86_ASM 00072 # elif defined(__ppc__) || defined(__PPC__) 00073 # define OF_PPC_ASM 00074 # elif defined(__arm__) || defined(__ARM__) 00075 # define OF_ARM_ASM 00076 # endif 00077 #endif 00078 00079 #if defined(OF_OLD_GNU_RUNTIME) || defined(OF_OBJFW_RUNTIME) 00080 # define objc_lookUpClass objc_lookup_class 00081 #endif 00082 00083 #ifdef OF_OLD_GNU_RUNTIME 00084 # define class_getInstanceSize class_get_instance_size 00085 # define class_getName class_get_class_name 00086 # define class_getSuperclass class_get_super_class 00087 # define sel_getName sel_get_name 00088 # define sel_registerName sel_get_uid 00089 #endif 00090 00091 #ifndef _WIN32 00092 # define OF_PATH_DELIMITER '/' 00093 #else 00094 # define OF_PATH_DELIMITER '\\' 00095 #endif 00096 00097 #define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self) 00098 #define OF_GETTER(ivar, atomic) \ 00099 return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic); 00100 #define OF_SETTER(ivar, value, atomic, copy) \ 00101 objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy); 00102 00103 static OF_INLINE uint16_t OF_CONST_FUNC 00104 of_bswap16_const(uint16_t i) 00105 { 00106 return (i & UINT16_C(0xFF00)) >> 8 | 00107 (i & UINT16_C(0x00FF)) << 8; 00108 } 00109 00110 static OF_INLINE uint32_t OF_CONST_FUNC 00111 of_bswap32_const(uint32_t i) 00112 { 00113 return (i & UINT32_C(0xFF000000)) >> 24 | 00114 (i & UINT32_C(0x00FF0000)) >> 8 | 00115 (i & UINT32_C(0x0000FF00)) << 8 | 00116 (i & UINT32_C(0x000000FF)) << 24; 00117 } 00118 00119 static OF_INLINE uint64_t OF_CONST_FUNC 00120 of_bswap64_const(uint64_t i) 00121 { 00122 return (i & UINT64_C(0xFF00000000000000)) >> 56 | 00123 (i & UINT64_C(0x00FF000000000000)) >> 40 | 00124 (i & UINT64_C(0x0000FF0000000000)) >> 24 | 00125 (i & UINT64_C(0x000000FF00000000)) >> 8 | 00126 (i & UINT64_C(0x00000000FF000000)) << 8 | 00127 (i & UINT64_C(0x0000000000FF0000)) << 24 | 00128 (i & UINT64_C(0x000000000000FF00)) << 40 | 00129 (i & UINT64_C(0x00000000000000FF)) << 56; 00130 } 00131 00132 static OF_INLINE uint16_t OF_CONST_FUNC 00133 of_bswap16_nonconst(uint16_t i) 00134 { 00135 #if defined(OF_X86_ASM) || defined(OF_AMD64_ASM) 00136 __asm__ ( 00137 "xchgb %h0, %b0" 00138 : "=Q"(i) 00139 : "0"(i) 00140 ); 00141 #elif defined(OF_PPC_ASM) 00142 __asm__ ( 00143 "lhbrx %0, 0, %1" 00144 : "=r"(i) 00145 : "r"(&i), "m"(i) 00146 ); 00147 #elif defined(OF_ARM_ASM) 00148 __asm__ ( 00149 "rev16 %0, %0" 00150 : "=r"(i) 00151 : "0"(i) 00152 ); 00153 #else 00154 i = (i & UINT16_C(0xFF00)) >> 8 | 00155 (i & UINT16_C(0x00FF)) << 8; 00156 #endif 00157 return i; 00158 } 00159 00160 static OF_INLINE uint32_t OF_CONST_FUNC 00161 of_bswap32_nonconst(uint32_t i) 00162 { 00163 #if defined(OF_X86_ASM) || defined(OF_AMD64_ASM) 00164 __asm__ ( 00165 "bswap %0" 00166 : "=q"(i) 00167 : "0"(i) 00168 ); 00169 #elif defined(OF_PPC_ASM) 00170 __asm__ ( 00171 "lwbrx %0, 0, %1" 00172 : "=r"(i) 00173 : "r"(&i), "m"(i) 00174 ); 00175 #elif defined(OF_ARM_ASM) 00176 __asm__ ( 00177 "rev %0, %0" 00178 : "=r"(i) 00179 : "0"(i) 00180 ); 00181 #else 00182 i = (i & UINT32_C(0xFF000000)) >> 24 | 00183 (i & UINT32_C(0x00FF0000)) >> 8 | 00184 (i & UINT32_C(0x0000FF00)) << 8 | 00185 (i & UINT32_C(0x000000FF)) << 24; 00186 #endif 00187 return i; 00188 } 00189 00190 static OF_INLINE uint64_t OF_CONST_FUNC 00191 of_bswap64_nonconst(uint64_t i) 00192 { 00193 #if defined(OF_AMD64_ASM) 00194 __asm__ ( 00195 "bswap %0" 00196 : "=r"(i) 00197 : "0"(i) 00198 ); 00199 #elif defined(OF_X86_ASM) 00200 __asm__ ( 00201 "bswap %%eax\n\t" 00202 "bswap %%edx\n\t" 00203 "xchgl %%eax, %%edx" 00204 : "=A"(i) 00205 : "0"(i) 00206 ); 00207 #else 00208 i = (uint64_t)of_bswap32_nonconst((uint32_t)(i & 0xFFFFFFFF)) << 32 | 00209 of_bswap32_nonconst((uint32_t)(i >> 32)); 00210 #endif 00211 return i; 00212 } 00213 00214 #ifdef __GNUC__ 00215 # define of_bswap16(i) \ 00216 (__builtin_constant_p(i) ? of_bswap16_const(i) : of_bswap16_nonconst(i)) 00217 # define of_bswap32(i) \ 00218 (__builtin_constant_p(i) ? of_bswap32_const(i) : of_bswap32_nonconst(i)) 00219 # define of_bswap64(i) \ 00220 (__builtin_constant_p(i) ? of_bswap64_const(i) : of_bswap64_nonconst(i)) 00221 #else 00222 # define of_bswap16(i) of_bswap16_const(i) 00223 # define of_bswap32(i) of_bswap32_const(i) 00224 # define of_bswap64(i) of_bswap64_const(i) 00225 #endif 00226 00227 static OF_INLINE float OF_CONST_FUNC 00228 of_bswap_float(float f) 00229 { 00230 union { 00231 float f; 00232 uint32_t i; 00233 } u; 00234 00235 u.f = f; 00236 u.i = of_bswap32(u.i); 00237 00238 return u.f; 00239 } 00240 00241 static OF_INLINE double OF_CONST_FUNC 00242 of_bswap_double(double d) 00243 { 00244 union { 00245 double d; 00246 uint64_t i; 00247 } u; 00248 00249 u.d = d; 00250 u.i = of_bswap64(u.i); 00251 00252 return u.d; 00253 } 00254 00255 static OF_INLINE void 00256 of_bswap32_vec(uint32_t *buffer, size_t length) 00257 { 00258 while (length--) { 00259 *buffer = of_bswap32(*buffer); 00260 buffer++; 00261 } 00262 } 00263 00264 #ifdef OF_BIG_ENDIAN 00265 # define of_bswap16_if_be(i) of_bswap16(i) 00266 # define of_bswap32_if_be(i) of_bswap32(i) 00267 # define of_bswap64_if_be(i) of_bswap64(i) 00268 # define of_bswap16_if_le(i) (i) 00269 # define of_bswap32_if_le(i) (i) 00270 # define of_bswap64_if_le(i) (i) 00271 # define of_bswap32_vec_if_be(buffer, length) of_bswap32_vec(buffer, length) 00272 #else 00273 # define of_bswap16_if_be(i) (i) 00274 # define of_bswap32_if_be(i) (i) 00275 # define of_bswap64_if_be(i) (i) 00276 # define of_bswap16_if_le(i) of_bswap16(i) 00277 # define of_bswap32_if_le(i) of_bswap32(i) 00278 # define of_bswap64_if_le(i) of_bswap64(i) 00279 # define of_bswap32_vec_if_be(buffer, length) 00280 #endif 00281 00282 #ifdef OF_FLOAT_BIG_ENDIAN 00283 # define of_bswap_float_if_be(i) of_bswap_float(i) 00284 # define of_bswap_double_if_be(i) of_bswap_double(i) 00285 # define of_bswap_float_if_le(i) (i) 00286 # define of_bswap_double_if_le(i) (i) 00287 #else 00288 # define of_bswap_float_if_be(i) (i) 00289 # define of_bswap_double_if_be(i) (i) 00290 # define of_bswap_float_if_le(i) of_bswap_float(i) 00291 # define of_bswap_double_if_le(i) of_bswap_double(i) 00292 #endif 00293 00294 /* 00295 * We define it here and not in objfw-defs.h, as it would be theoretically 00296 * possible to build a universal binary for Mac OS X and iOS. 00297 */ 00298 #if defined(__MACH__) && defined(__arm__) 00299 # define OF_IOS 00300 #endif 00301 00302 #define OF_ROL(value, bits) \ 00303 (((value) << ((bits) % (sizeof(value) * 8))) | \ 00304 (value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) 00305 00306 #define OF_HASH_INIT(hash) hash = 0 00307 #define OF_HASH_ADD(hash, byte) \ 00308 { \ 00309 hash += (uint8_t)byte; \ 00310 hash += (hash << 10); \ 00311 hash ^= (hash >> 6); \ 00312 } 00313 #define OF_HASH_FINALIZE(hash) \ 00314 { \ 00315 hash += (hash << 3); \ 00316 hash ^= (hash >> 11); \ 00317 hash += (hash << 15); \ 00318 } 00319 #define OF_HASH_ADD_HASH(hash, other) \ 00320 { \ 00321 uint32_t otherCopy = other; \ 00322 OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF); \ 00323 OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF); \ 00324 OF_HASH_ADD(hash, (otherCopy >> 8) & 0xFF); \ 00325 OF_HASH_ADD(hash, otherCopy & 0xFF); \ 00326 } 00327 00328 static OF_INLINE of_range_t 00329 of_range(size_t start, size_t length) 00330 { 00331 of_range_t range = { start, length }; 00332 00333 return range; 00334 } 00335 00336 static OF_INLINE of_point_t 00337 of_point(int x, int y) 00338 { 00339 of_point_t point = { x, y }; 00340 00341 return point; 00342 } 00343 00344 static OF_INLINE of_dimension_t 00345 of_dimension(int width, int height) 00346 { 00347 of_dimension_t dimension = { width, height }; 00348 00349 return dimension; 00350 } 00351 00352 static OF_INLINE of_rectangle_t 00353 of_rectangle(int x, int y, int width, int height) 00354 { 00355 of_rectangle_t rectangle = { 00356 of_point(x, y), 00357 of_dimension(width, height) 00358 }; 00359 00360 return rectangle; 00361 }