ObjFW
 All Classes Functions Variables
macros.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012
3  * Jonathan Schleifer <js@webkeks.org>
4  *
5  * All rights reserved.
6  *
7  * This file is part of ObjFW. It may be distributed under the terms of the
8  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
9  * the packaging of this file.
10  *
11  * Alternatively, it may be distributed under the terms of the GNU General
12  * Public License, either version 2 or 3, which can be found in the file
13  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
14  * file.
15  */
16 
17 #import "OFObject.h"
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #if defined(OF_APPLE_RUNTIME)
25 # import <objc/runtime.h>
26 #endif
27 
28 #ifdef _PSP
29 # define INTMAX_MAX LONG_LONG_MAX
30 #endif
31 
32 #ifdef __GNUC__
33 # define OF_INLINE inline __attribute__((always_inline))
34 # define OF_LIKELY(cond) (__builtin_expect(!!(cond), 1))
35 # define OF_UNLIKELY(cond) (__builtin_expect(!!(cond), 0))
36 # define OF_CONST_FUNC __attribute__((const))
37 #else
38 # define OF_INLINE inline
39 # define OF_LIKELY(cond) cond
40 # define OF_UNLIKELY(cond) cond
41 # define OF_CONST_FUNC
42 #endif
43 
44 /* Required to build universal binaries on OS X */
45 #if __BIG_ENDIAN__ || __LITTLE_ENDIAN__
46 # if __BIG_ENDIAN__ && __LITTLE_ENDIAN__
47 # error __BIG_ENDIAN__ and __LITTLE_ENDIAN__ defined!
48 # endif
49 # undef OF_BIG_ENDIAN
50 # if __BIG_ENDIAN__
51 # define OF_BIG_ENDIAN
52 # endif
53 #endif
54 
55 #ifdef OF_BIG_ENDIAN
56 # define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_BIG_ENDIAN
57 #else
58 # define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_LITTLE_ENDIAN
59 #endif
60 
61 /* Hopefully no arch needs more than 16 bytes padding */
62 #ifndef __BIGGEST_ALIGNMENT__
63 # define __BIGGEST_ALIGNMENT__ 16
64 #endif
65 
66 #ifdef __GNUC__
67 # if defined(__amd64__) || defined(__x86_64__)
68 # define OF_AMD64_ASM
69 # elif defined(__i386__)
70 # define OF_X86_ASM
71 # elif defined(__ppc__) || defined(__PPC__)
72 # define OF_PPC_ASM
73 # elif defined(__arm__) || defined(__ARM__)
74 # define OF_ARM_ASM
75 # ifdef __ARM_ARCH_7__
76 # define OF_ARMV7_ASM
77 # endif
78 # ifdef __ARM_ARCH_7A__
79 # define OF_ARMV7_ASM
80 # endif
81 # ifdef __ARM_ARCH_7R__
82 # define OF_ARMV7_ASM
83 # endif
84 # ifdef __ARM_ARCH_7M__
85 # define OF_ARMV7_ASM
86 # endif
87 # ifdef __ARM_ARCH_7EM__
88 # define OF_ARMV7_ASM
89 # endif
90 # ifdef __ARM_ARCH_6__
91 # define OF_ARMV6_ASM
92 # endif
93 # ifdef __ARM_ARCH_6J__
94 # define OF_ARMV6_ASM
95 # endif
96 # ifdef __ARM_ARCH_6K__
97 # define OF_ARMV6_ASM
98 # endif
99 # ifdef __ARM_ARCH_6Z__
100 # define OF_ARMV6_ASM
101 # endif
102 # ifdef __ARM_ARCH_6ZK__
103 # define OF_ARMV6_ASM
104 # endif
105 # ifdef __ARM_ARCH_6T2__
106 # define OF_ARMV6_ASM
107 # endif
108 # ifdef OF_ARMV7_ASM
109 # define OF_ARMV6_ASM
110 # endif
111 # endif
112 #endif
113 
114 #define OF_ENSURE(cond) \
115  if (!(cond)) { \
116  fprintf(stderr, "Failed to ensure condition in " \
117  __FILE__ ":%d:\n" #cond "\n", __LINE__); \
118  abort(); \
119  }
120 
121 #ifdef OF_OBJFW_RUNTIME
122 # define objc_lookUpClass objc_lookup_class
123 #endif
124 
125 #ifndef _WIN32
126 # define OF_PATH_DELIMITER '/'
127 #else
128 # define OF_PATH_DELIMITER '\\'
129 #endif
130 #define OF_PATH_PARENT_DIR @".."
131 
132 extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL);
133 extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, signed char);
134 
135 #define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self)
136 #define OF_GETTER(ivar, atomic) \
137  return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic);
138 #define OF_SETTER(ivar, value, atomic, copy) \
139  objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy);
140 
141 static OF_INLINE uint16_t OF_CONST_FUNC
142 OF_BSWAP16_CONST(uint16_t i)
143 {
144  return (i & UINT16_C(0xFF00)) >> 8 |
145  (i & UINT16_C(0x00FF)) << 8;
146 }
147 
148 static OF_INLINE uint32_t OF_CONST_FUNC
149 OF_BSWAP32_CONST(uint32_t i)
150 {
151  return (i & UINT32_C(0xFF000000)) >> 24 |
152  (i & UINT32_C(0x00FF0000)) >> 8 |
153  (i & UINT32_C(0x0000FF00)) << 8 |
154  (i & UINT32_C(0x000000FF)) << 24;
155 }
156 
157 static OF_INLINE uint64_t OF_CONST_FUNC
158 OF_BSWAP64_CONST(uint64_t i)
159 {
160  return (i & UINT64_C(0xFF00000000000000)) >> 56 |
161  (i & UINT64_C(0x00FF000000000000)) >> 40 |
162  (i & UINT64_C(0x0000FF0000000000)) >> 24 |
163  (i & UINT64_C(0x000000FF00000000)) >> 8 |
164  (i & UINT64_C(0x00000000FF000000)) << 8 |
165  (i & UINT64_C(0x0000000000FF0000)) << 24 |
166  (i & UINT64_C(0x000000000000FF00)) << 40 |
167  (i & UINT64_C(0x00000000000000FF)) << 56;
168 }
169 
170 static OF_INLINE uint16_t OF_CONST_FUNC
171 OF_BSWAP16_NONCONST(uint16_t i)
172 {
173 #if defined(OF_X86_ASM) || defined(OF_AMD64_ASM)
174  __asm__ (
175  "xchgb %h0, %b0"
176  : "=Q"(i)
177  : "0"(i)
178  );
179 #elif defined(OF_PPC_ASM)
180  __asm__ (
181  "lhbrx %0, 0, %1"
182  : "=r"(i)
183  : "r"(&i), "m"(i)
184  );
185 #elif defined(OF_ARMV6_ASM)
186  __asm__ (
187  "rev16 %0, %0"
188  : "=r"(i)
189  : "0"(i)
190  );
191 #else
192  i = (i & UINT16_C(0xFF00)) >> 8 |
193  (i & UINT16_C(0x00FF)) << 8;
194 #endif
195  return i;
196 }
197 
198 static OF_INLINE uint32_t OF_CONST_FUNC
199 OF_BSWAP32_NONCONST(uint32_t i)
200 {
201 #if defined(OF_X86_ASM) || defined(OF_AMD64_ASM)
202  __asm__ (
203  "bswap %0"
204  : "=q"(i)
205  : "0"(i)
206  );
207 #elif defined(OF_PPC_ASM)
208  __asm__ (
209  "lwbrx %0, 0, %1"
210  : "=r"(i)
211  : "r"(&i), "m"(i)
212  );
213 #elif defined(OF_ARMV6_ASM)
214  __asm__ (
215  "rev %0, %0"
216  : "=r"(i)
217  : "0"(i)
218  );
219 #else
220  i = (i & UINT32_C(0xFF000000)) >> 24 |
221  (i & UINT32_C(0x00FF0000)) >> 8 |
222  (i & UINT32_C(0x0000FF00)) << 8 |
223  (i & UINT32_C(0x000000FF)) << 24;
224 #endif
225  return i;
226 }
227 
228 static OF_INLINE uint64_t OF_CONST_FUNC
229 OF_BSWAP64_NONCONST(uint64_t i)
230 {
231 #if defined(OF_AMD64_ASM)
232  __asm__ (
233  "bswap %0"
234  : "=r"(i)
235  : "0"(i)
236  );
237 #elif defined(OF_X86_ASM)
238  __asm__ (
239  "bswap %%eax\n\t"
240  "bswap %%edx\n\t"
241  "xchgl %%eax, %%edx"
242  : "=A"(i)
243  : "0"(i)
244  );
245 #else
246  i = (uint64_t)OF_BSWAP32_NONCONST((uint32_t)(i & 0xFFFFFFFF)) << 32 |
247  OF_BSWAP32_NONCONST((uint32_t)(i >> 32));
248 #endif
249  return i;
250 }
251 
252 #ifdef __GNUC__
253 # define OF_BSWAP16(i) \
254  (__builtin_constant_p(i) ? OF_BSWAP16_CONST(i) : OF_BSWAP16_NONCONST(i))
255 # define OF_BSWAP32(i) \
256  (__builtin_constant_p(i) ? OF_BSWAP32_CONST(i) : OF_BSWAP32_NONCONST(i))
257 # define OF_BSWAP64(i) \
258  (__builtin_constant_p(i) ? OF_BSWAP64_CONST(i) : OF_BSWAP64_NONCONST(i))
259 #else
260 # define OF_BSWAP16(i) OF_BSWAP16_CONST(i)
261 # define OF_BSWAP32(i) OF_BSWAP32_CONST(i)
262 # define OF_BSWAP64(i) OF_BSWAP64_CONST(i)
263 #endif
264 
265 static OF_INLINE float OF_CONST_FUNC
266 OF_BSWAP_FLOAT(float f)
267 {
268  union {
269  float f;
270  uint32_t i;
271  } u;
272 
273  u.f = f;
274  u.i = OF_BSWAP32(u.i);
275 
276  return u.f;
277 }
278 
279 static OF_INLINE double OF_CONST_FUNC
280 OF_BSWAP_DOUBLE(double d)
281 {
282  union {
283  double d;
284  uint64_t i;
285  } u;
286 
287  u.d = d;
288  u.i = OF_BSWAP64(u.i);
289 
290  return u.d;
291 }
292 
293 #ifdef OF_BIG_ENDIAN
294 # define OF_BSWAP16_IF_BE(i) OF_BSWAP16(i)
295 # define OF_BSWAP32_IF_BE(i) OF_BSWAP32(i)
296 # define OF_BSWAP64_IF_BE(i) OF_BSWAP64(i)
297 # define OF_BSWAP16_IF_LE(i) (i)
298 # define OF_BSWAP32_IF_LE(i) (i)
299 # define OF_BSWAP64_IF_LE(i) (i)
300 #else
301 # define OF_BSWAP16_IF_BE(i) (i)
302 # define OF_BSWAP32_IF_BE(i) (i)
303 # define OF_BSWAP64_IF_BE(i) (i)
304 # define OF_BSWAP16_IF_LE(i) OF_BSWAP16(i)
305 # define OF_BSWAP32_IF_LE(i) OF_BSWAP32(i)
306 # define OF_BSWAP64_IF_LE(i) OF_BSWAP64(i)
307 #endif
308 
309 #ifdef OF_FLOAT_BIG_ENDIAN
310 # define OF_BSWAP_FLOAT_IF_BE(i) OF_BSWAP_FLOAT(i)
311 # define OF_BSWAP_DOUBLE_IF_BE(i) OF_BSWAP_DOUBLE(i)
312 # define OF_BSWAP_FLOAT_IF_LE(i) (i)
313 # define OF_BSWAP_DOUBLE_IF_LE(i) (i)
314 #else
315 # define OF_BSWAP_FLOAT_IF_BE(i) (i)
316 # define OF_BSWAP_DOUBLE_IF_BE(i) (i)
317 # define OF_BSWAP_FLOAT_IF_LE(i) OF_BSWAP_FLOAT(i)
318 # define OF_BSWAP_DOUBLE_IF_LE(i) OF_BSWAP_DOUBLE(i)
319 #endif
320 
321 /*
322  * We define it here and not in objfw-defs.h, as it would be theoretically
323  * possible to build a universal binary for Mac OS X and iOS.
324  */
325 #if defined(__MACH__) && defined(__arm__)
326 # define OF_IOS
327 #endif
328 
329 #define OF_ROL(value, bits) \
330  (((value) << ((bits) % (sizeof(value) * 8))) | \
331  (value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8))))
332 
333 #define OF_HASH_INIT(hash) hash = 0
334 #define OF_HASH_ADD(hash, byte) \
335  { \
336  hash += (uint8_t)byte; \
337  hash += (hash << 10); \
338  hash ^= (hash >> 6); \
339  }
340 #define OF_HASH_FINALIZE(hash) \
341  { \
342  hash += (hash << 3); \
343  hash ^= (hash >> 11); \
344  hash += (hash << 15); \
345  }
346 #define OF_HASH_ADD_HASH(hash, other) \
347  { \
348  uint32_t otherCopy = other; \
349  OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF); \
350  OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF); \
351  OF_HASH_ADD(hash, (otherCopy >> 8) & 0xFF); \
352  OF_HASH_ADD(hash, otherCopy & 0xFF); \
353  }
354 
355 static OF_INLINE of_range_t
356 of_range(size_t start, size_t length)
357 {
358  of_range_t range = { start, length };
359 
360  return range;
361 }
362 
363 static OF_INLINE of_point_t
364 of_point(float x, float y)
365 {
366  of_point_t point = { x, y };
367 
368  return point;
369 }
370 
371 static OF_INLINE of_dimension_t
372 of_dimension(float width, float height)
373 {
374  of_dimension_t dimension = { width, height };
375 
376  return dimension;
377 }
378 
379 static OF_INLINE of_rectangle_t
380 of_rectangle(float x, float y, float width, float height)
381 {
382  of_rectangle_t rectangle = {
383  of_point(x, y),
384  of_dimension(width, height)
385  };
386 
387  return rectangle;
388 }