ObjFW
macros.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
3  * Jonathan Schleifer <js@heap.zone>
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 #include "objfw-defs.h"
18 
19 #ifndef __STDC_LIMIT_MACROS
20 # define __STDC_LIMIT_MACROS
21 #endif
22 #ifndef __STDC_CONSTANT_MACROS
23 # define __STDC_CONSTANT_MACROS
24 #endif
25 
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "platform.h"
34 
35 #ifdef OF_OBJFW_RUNTIME
36 # ifdef OF_COMPILING_OBJFW
37 # import "ObjFW-RT.h"
38 # else
39 # import <ObjFW-RT/ObjFW-RT.h>
40 # endif
41 #endif
42 #ifdef OF_APPLE_RUNTIME
43 # import <objc/objc.h>
44 # import <objc/runtime.h>
45 # import <objc/message.h>
46 #endif
47 
48 #if defined(__GNUC__)
49 # define restrict __restrict__
50 #elif __STDC_VERSION__ < 199901L
51 # define restrict
52 #endif
53 
54 #if __STDC_VERSION__ >= 201112L && !defined(static_assert)
55 /* C11 compiler, but old libc */
56 # define static_assert _Static_assert
57 #endif
58 
59 #if defined(OF_HAVE__THREAD_LOCAL)
60 # define OF_HAVE_COMPILER_TLS
61 # ifdef OF_HAVE_THREADS_H
62 # include <threads.h>
63 # else
64 # define thread_local _Thread_local
65 # endif
66 #elif defined(OF_HAVE___THREAD)
67 # define OF_HAVE_COMPILER_TLS
68 # define thread_local __thread
69 #endif
70 
71 #ifdef __GNUC__
72 # define OF_INLINE inline __attribute__((__always_inline__))
73 # define OF_LIKELY(cond) (__builtin_expect(!!(cond), 1))
74 # define OF_UNLIKELY(cond) (__builtin_expect(!!(cond), 0))
75 # define OF_CONST_FUNC __attribute__((__const__))
76 # define OF_NO_RETURN_FUNC __attribute__((__noreturn__))
77 # define OF_WEAK_REF(sym) __attribute__((__weakref__(sym)))
78 #else
79 # define OF_INLINE inline
80 # define OF_LIKELY(cond) cond
81 # define OF_UNLIKELY(cond) cond
82 # define OF_CONST_FUNC
83 # define OF_NO_RETURN_FUNC
84 # define OF_WEAK_REF(sym)
85 #endif
86 
87 #ifdef OF_BIG_ENDIAN
88 # define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_BIG_ENDIAN
89 #else
90 # define OF_BYTE_ORDER_NATIVE OF_BYTE_ORDER_LITTLE_ENDIAN
91 #endif
92 
93 #if __STDC_VERSION__ >= 201112L
94 # define OF_ALIGNAS(type) _Alignas(type)
95 #else
96 # define OF_ALIGNAS(type) __attribute__((__aligned__(sizeof(type))))
97 #endif
98 
99 #if __STDC_VERSION__ >= 201112L && defined(OF_HAVE_MAX_ALIGN_T)
100 # define OF_BIGGEST_ALIGNMENT _Alignof(max_align_t)
101 #else
102 # ifdef __BIGGEST_ALIGNMENT__
103 # define OF_BIGGEST_ALIGNMENT __BIGGEST_ALIGNMENT__
104 # else
105 # /* Hopefully no arch needs more than 16 byte alignment */
106 # define OF_BIGGEST_ALIGNMENT 16
107 # endif
108 #endif
109 
110 #ifdef __GNUC__
111 # define __GCC_VERSION__ (__GNUC__ * 100 + __GNUC_MINOR__)
112 #else
113 # define __GCC_VERSION__ 0
114 #endif
115 
116 #ifndef __has_feature
117 # define __has_feature(x) 0
118 #endif
119 
120 #ifndef __has_attribute
121 # define __has_attribute(x) 0
122 #endif
123 
124 #if __has_feature(objc_bool)
125 # undef YES
126 # define YES __objc_yes
127 # undef NO
128 # define NO __objc_no
129 # ifndef __cplusplus
130 # undef true
131 # define true ((bool)1)
132 # undef false
133 # define false ((bool)0)
134 # endif
135 #endif
136 
137 #if !__has_feature(objc_instancetype)
138 # define instancetype id
139 #endif
140 
141 #if __has_feature(blocks)
142 # define OF_HAVE_BLOCKS
143 #endif
144 
145 #if __has_feature(objc_arc)
146 # define OF_RETURNS_RETAINED __attribute__((__ns_returns_retained__))
147 # define OF_RETURNS_NOT_RETAINED __attribute__((__ns_returns_not_retained__))
148 # define OF_RETURNS_INNER_POINTER \
149  __attribute__((__objc_returns_inner_pointer__))
150 # define OF_CONSUMED __attribute__((__ns_consumed__))
151 # define OF_WEAK_UNAVAILABLE __attribute__((__objc_arc_weak_unavailable__))
152 #else
153 # define OF_RETURNS_RETAINED
154 # define OF_RETURNS_NOT_RETAINED
155 # define OF_RETURNS_INNER_POINTER
156 # define OF_CONSUMED
157 # define OF_WEAK_UNAVAILABLE
158 /*
159  * undef them first, as new Clang versions have these as built-in defines even
160  * when ARC is disabled.
161  */
162 # undef __unsafe_unretained
163 # undef __bridge
164 # undef __autoreleasing
165 # define __unsafe_unretained
166 # define __bridge
167 # define __autoreleasing
168 #endif
169 
170 #if __has_feature(objc_generics)
171 # define OF_HAVE_GENERICS
172 # define OF_GENERIC(...) <__VA_ARGS__>
173 #else
174 # define OF_GENERIC(...)
175 #endif
176 
177 #if __has_feature(nullability)
178 # define OF_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
179 # define OF_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
180 # define OF_NULLABLE_PROPERTY(...) (__VA_ARGS__, nullable)
181 # define OF_NULL_RESETTABLE_PROPERTY(...) (__VA_ARGS__, null_resettable)
182 #else
183 # define OF_ASSUME_NONNULL_BEGIN
184 # define OF_ASSUME_NONNULL_END
185 # define _Nonnull
186 # define _Nullable
187 # define _Null_unspecified
188 # define OF_NULLABLE_PROPERTY
189 # define OF_NULL_RESETTABLE_PROPERTY
190 # define nonnull
191 # define nullable
192 # define null_unspecified
193 #endif
194 
195 #if __has_feature(objc_kindof)
196 # define OF_KINDOF(cls) __kindof cls
197 #else
198 # define OF_KINDOF(cls) id
199 #endif
200 
201 #if defined(__clang__) || __GCC_VERSION__ >= 405
202 # define OF_UNREACHABLE __builtin_unreachable();
203 #else
204 # define OF_UNREACHABLE abort();
205 #endif
206 
207 #if defined(__clang__) || __GCC_VERSION__ >= 406
208 # define OF_SENTINEL __attribute__((__sentinel__))
209 # define OF_NO_RETURN __attribute__((__noreturn__))
210 #else
211 # define OF_SENTINEL
212 # define OF_NO_RETURN
213 #endif
214 
215 #if __has_attribute(__unavailable__)
216 # define OF_UNAVAILABLE __attribute__((__unavailable__))
217 #else
218 # define OF_UNAVAILABLE
219 #endif
220 
221 #if __has_attribute(__objc_requires_super__)
222 # define OF_REQUIRES_SUPER __attribute__((__objc_requires_super__))
223 #else
224 # define OF_REQUIRES_SUPER
225 #endif
226 
227 #if __has_attribute(__objc_root_class__)
228 # define OF_ROOT_CLASS __attribute__((__objc_root_class__))
229 #else
230 # define OF_ROOT_CLASS
231 #endif
232 
233 #if __has_attribute(__objc_subclassing_restricted__)
234 # define OF_SUBCLASSING_RESTRICTED \
235  __attribute__((__objc_subclassing_restricted__))
236 #else
237 # define OF_SUBCLASSING_RESTRICTED
238 #endif
239 
240 #if __has_attribute(__objc_method_family__)
241 # define OF_METHOD_FAMILY(f) __attribute__((__objc_method_family__(f)))
242 #else
243 # define OF_METHOD_FAMILY(f)
244 #endif
245 
246 #if __has_attribute(__objc_designated_initializer__)
247 # define OF_DESIGNATED_INITIALIZER \
248  __attribute__((__objc_designated_initializer__))
249 #else
250 # define OF_DESIGNATED_INITIALIZER
251 #endif
252 
253 #ifdef __GNUC__
254 # ifdef OF_X86_64
255 # define OF_X86_64_ASM
256 # endif
257 # ifdef OF_X86
258 # define OF_X86_ASM
259 # endif
260 # ifdef OF_POWERPC
261 # define OF_POWERPC_ASM
262 # endif
263 # ifdef OF_ARM64
264 # define OF_ARM64_ASM
265 # endif
266 # ifdef OF_ARM
267 # define OF_ARM_ASM
268 # endif
269 # ifdef OF_ARMV7
270 # define OF_ARMV7_ASM
271 # endif
272 # ifdef OF_ARMV6
273 # define OF_ARMV6_ASM
274 # endif
275 # ifdef OF_MIPS64
276 # define OF_MIPS64_ASM
277 # endif
278 # ifdef OF_MIPS
279 # define OF_MIPS_ASM
280 # endif
281 #endif
282 
283 #ifdef OF_APPLE_RUNTIME
284 # if defined(OF_X86_64) || defined(OF_X86) || defined(OF_ARM64) || \
285  defined(OF_ARM) || defined(OF_POWERPC)
286 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
287 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
288 # endif
289 #else
290 # if defined(OF_ELF)
291 # if defined(OF_X86_64) || defined(OF_X86) || \
292  defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \
293  defined(OF_MIPS)
294 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
295 # if __OBJFW_RUNTIME_ABI__ >= 800
296 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
297 # endif
298 # endif
299 # elif defined(OF_MACH_O)
300 # if defined(OF_X86_64)
301 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
302 # if __OBJFW_RUNTIME_ABI__ >= 800
303 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
304 # endif
305 # endif
306 # elif defined(OF_WINDOWS)
307 # if defined(OF_X86_64) || defined(OF_X86)
308 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
309 # if __OBJFW_RUNTIME_ABI__ >= 800
310 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
311 # endif
312 # endif
313 # endif
314 #endif
315 
316 #define OF_RETAIN_COUNT_MAX UINT_MAX
317 #define OF_NOT_FOUND SIZE_MAX
318 
319 #if !defined(OF_WINDOWS) && !defined(OF_MSDOS)
320 # define OF_PATH_DELIMITER '/'
321 # define OF_PATH_DELIMITER_STRING @"/"
322 # define OF_IS_PATH_DELIMITER(c) (c == '/')
323 #else
324 # define OF_PATH_DELIMITER '\\'
325 # define OF_PATH_DELIMITER_STRING @"\\"
326 # define OF_IS_PATH_DELIMITER(c) (c == '\\' || c == '/')
327 #endif
328 #define OF_PATH_CURRENT_DIRECTORY @"."
329 #define OF_PATH_PARENT_DIRECTORY @".."
330 
331 #define OF_ENSURE(cond) \
332  do { \
333  if (!(cond)) { \
334  fprintf(stderr, "Failed to ensure condition " \
335  "in " __FILE__ ":%d:\n" #cond "\n", \
336  __LINE__); \
337  abort(); \
338  } \
339  } while (0)
340 
341 #define OF_UNRECOGNIZED_SELECTOR of_method_not_found(self, _cmd);
342 #if __has_feature(objc_arc)
343 # define OF_INVALID_INIT_METHOD \
344  [self doesNotRecognizeSelector: _cmd]; \
345  \
346  abort();
347 #else
348 # define OF_INVALID_INIT_METHOD \
349  @try { \
350  [self doesNotRecognizeSelector: _cmd]; \
351  } @catch (id e) { \
352  [self release]; \
353  @throw e; \
354  } \
355  \
356  abort();
357 #endif
358 #ifdef __clang__
359 # define OF_DEALLOC_UNSUPPORTED \
360  [self doesNotRecognizeSelector: _cmd]; \
361  \
362  abort(); \
363  \
364  _Pragma("clang diagnostic push ignore \"-Wunreachable-code\""); \
365  [super dealloc]; /* Get rid of a stupid warning */ \
366  _Pragma("clang diagnostic pop");
367 #else
368 # define OF_DEALLOC_UNSUPPORTED \
369  [self doesNotRecognizeSelector: _cmd]; \
370  \
371  abort(); \
372  \
373  [super dealloc]; /* Get rid of a stupid warning */
374 #endif
375 
376 #define OF_PREPROCESSOR_CONCAT2(a, b) a##b
377 #define OF_PREPROCESSOR_CONCAT(a, b) OF_PREPROCESSOR_CONCAT2(a, b)
378 #define OF_CONSTRUCTOR(prio) \
379  static void __attribute__((__constructor__(prio))) \
380  OF_PREPROCESSOR_CONCAT(constructor, __LINE__)(void)
381 #define OF_DESTRUCTOR(prio) \
382  static void __attribute__((__destructor__(prio))) \
383  OF_PREPROCESSOR_CONCAT(destructor, __LINE__)(void)
384 
385 static OF_INLINE uint16_t OF_CONST_FUNC
386 OF_BSWAP16_CONST(uint16_t i)
387 {
388  return (i & UINT16_C(0xFF00)) >> 8 |
389  (i & UINT16_C(0x00FF)) << 8;
390 }
391 
392 static OF_INLINE uint32_t OF_CONST_FUNC
393 OF_BSWAP32_CONST(uint32_t i)
394 {
395  return (i & UINT32_C(0xFF000000)) >> 24 |
396  (i & UINT32_C(0x00FF0000)) >> 8 |
397  (i & UINT32_C(0x0000FF00)) << 8 |
398  (i & UINT32_C(0x000000FF)) << 24;
399 }
400 
401 static OF_INLINE uint64_t OF_CONST_FUNC
402 OF_BSWAP64_CONST(uint64_t i)
403 {
404  return (i & UINT64_C(0xFF00000000000000)) >> 56 |
405  (i & UINT64_C(0x00FF000000000000)) >> 40 |
406  (i & UINT64_C(0x0000FF0000000000)) >> 24 |
407  (i & UINT64_C(0x000000FF00000000)) >> 8 |
408  (i & UINT64_C(0x00000000FF000000)) << 8 |
409  (i & UINT64_C(0x0000000000FF0000)) << 24 |
410  (i & UINT64_C(0x000000000000FF00)) << 40 |
411  (i & UINT64_C(0x00000000000000FF)) << 56;
412 }
413 
414 static OF_INLINE uint16_t OF_CONST_FUNC
415 OF_BSWAP16_NONCONST(uint16_t i)
416 {
417 #if defined(OF_HAVE_BUILTIN_BSWAP16)
418  return __builtin_bswap16(i);
419 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
420  __asm__ (
421  "xchgb %h0, %b0"
422  : "=Q"(i)
423  : "0"(i)
424  );
425 #elif defined(OF_POWERPC_ASM)
426  __asm__ (
427  "lhbrx %0, 0, %1"
428  : "=r"(i)
429  : "r"(&i), "m"(i)
430  );
431 #elif defined(OF_ARMV6_ASM)
432  __asm__ (
433  "rev16 %0, %0"
434  : "=r"(i)
435  : "0"(i)
436  );
437 #else
438  i = (i & UINT16_C(0xFF00)) >> 8 |
439  (i & UINT16_C(0x00FF)) << 8;
440 #endif
441  return i;
442 }
443 
444 static OF_INLINE uint32_t OF_CONST_FUNC
445 OF_BSWAP32_NONCONST(uint32_t i)
446 {
447 #if defined(OF_HAVE_BUILTIN_BSWAP32)
448  return __builtin_bswap32(i);
449 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
450  __asm__ (
451  "bswap %0"
452  : "=q"(i)
453  : "0"(i)
454  );
455 #elif defined(OF_POWERPC_ASM)
456  __asm__ (
457  "lwbrx %0, 0, %1"
458  : "=r"(i)
459  : "r"(&i), "m"(i)
460  );
461 #elif defined(OF_ARMV6_ASM)
462  __asm__ (
463  "rev %0, %0"
464  : "=r"(i)
465  : "0"(i)
466  );
467 #else
468  i = (i & UINT32_C(0xFF000000)) >> 24 |
469  (i & UINT32_C(0x00FF0000)) >> 8 |
470  (i & UINT32_C(0x0000FF00)) << 8 |
471  (i & UINT32_C(0x000000FF)) << 24;
472 #endif
473  return i;
474 }
475 
476 static OF_INLINE uint64_t OF_CONST_FUNC
477 OF_BSWAP64_NONCONST(uint64_t i)
478 {
479 #if defined(OF_HAVE_BUILTIN_BSWAP64)
480  return __builtin_bswap64(i);
481 #elif defined(OF_X86_64_ASM)
482  __asm__ (
483  "bswap %0"
484  : "=r"(i)
485  : "0"(i)
486  );
487 #elif defined(OF_X86_ASM)
488  __asm__ (
489  "bswap %%eax\n\t"
490  "bswap %%edx\n\t"
491  "xchgl %%eax, %%edx"
492  : "=A"(i)
493  : "0"(i)
494  );
495 #else
496  i = (uint64_t)OF_BSWAP32_NONCONST((uint32_t)(i & 0xFFFFFFFF)) << 32 |
497  OF_BSWAP32_NONCONST((uint32_t)(i >> 32));
498 #endif
499  return i;
500 }
501 
502 #ifdef __GNUC__
503 # define OF_BSWAP16(i) \
504  (__builtin_constant_p(i) ? OF_BSWAP16_CONST(i) : OF_BSWAP16_NONCONST(i))
505 # define OF_BSWAP32(i) \
506  (__builtin_constant_p(i) ? OF_BSWAP32_CONST(i) : OF_BSWAP32_NONCONST(i))
507 # define OF_BSWAP64(i) \
508  (__builtin_constant_p(i) ? OF_BSWAP64_CONST(i) : OF_BSWAP64_NONCONST(i))
509 #else
510 # define OF_BSWAP16(i) OF_BSWAP16_CONST(i)
511 # define OF_BSWAP32(i) OF_BSWAP32_CONST(i)
512 # define OF_BSWAP64(i) OF_BSWAP64_CONST(i)
513 #endif
514 
515 static OF_INLINE float OF_CONST_FUNC
516 OF_BSWAP_FLOAT(float f)
517 {
518  union {
519  float f;
520  uint32_t i;
521  } u;
522 
523  u.f = f;
524  u.i = OF_BSWAP32(u.i);
525 
526  return u.f;
527 }
528 
529 static OF_INLINE double OF_CONST_FUNC
530 OF_BSWAP_DOUBLE(double d)
531 {
532  union {
533  double d;
534  uint64_t i;
535  } u;
536 
537  u.d = d;
538  u.i = OF_BSWAP64(u.i);
539 
540  return u.d;
541 }
542 
543 #ifdef OF_BIG_ENDIAN
544 # define OF_BSWAP16_IF_BE(i) OF_BSWAP16(i)
545 # define OF_BSWAP32_IF_BE(i) OF_BSWAP32(i)
546 # define OF_BSWAP64_IF_BE(i) OF_BSWAP64(i)
547 # define OF_BSWAP16_IF_LE(i) (i)
548 # define OF_BSWAP32_IF_LE(i) (i)
549 # define OF_BSWAP64_IF_LE(i) (i)
550 #else
551 # define OF_BSWAP16_IF_BE(i) (i)
552 # define OF_BSWAP32_IF_BE(i) (i)
553 # define OF_BSWAP64_IF_BE(i) (i)
554 # define OF_BSWAP16_IF_LE(i) OF_BSWAP16(i)
555 # define OF_BSWAP32_IF_LE(i) OF_BSWAP32(i)
556 # define OF_BSWAP64_IF_LE(i) OF_BSWAP64(i)
557 #endif
558 
559 #ifdef OF_FLOAT_BIG_ENDIAN
560 # define OF_BSWAP_FLOAT_IF_BE(i) OF_BSWAP_FLOAT(i)
561 # define OF_BSWAP_DOUBLE_IF_BE(i) OF_BSWAP_DOUBLE(i)
562 # define OF_BSWAP_FLOAT_IF_LE(i) (i)
563 # define OF_BSWAP_DOUBLE_IF_LE(i) (i)
564 #else
565 # define OF_BSWAP_FLOAT_IF_BE(i) (i)
566 # define OF_BSWAP_DOUBLE_IF_BE(i) (i)
567 # define OF_BSWAP_FLOAT_IF_LE(i) OF_BSWAP_FLOAT(i)
568 # define OF_BSWAP_DOUBLE_IF_LE(i) OF_BSWAP_DOUBLE(i)
569 #endif
570 
571 #define OF_ROL(value, bits) \
572  (((bits) % (sizeof(value) * 8)) > 0 \
573  ? ((value) << ((bits) % (sizeof(value) * 8))) | \
574  ((value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) \
575  : (value))
576 #define OF_ROR(value, bits) \
577  (((bits) % (sizeof(value) * 8)) > 0 \
578  ? ((value) >> ((bits) % (sizeof(value) * 8))) | \
579  ((value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) \
580  : (value))
581 
582 #define OF_ROUND_UP_POW2(pow2, value) (((value) + (pow2) - 1) & ~((pow2) - 1))
583 
584 #define OF_HASH_INIT(hash) hash = of_hash_seed;
585 #define OF_HASH_ADD(hash, byte) \
586  { \
587  hash += (uint8_t)(byte); \
588  hash += (hash << 10); \
589  hash ^= (hash >> 6); \
590  }
591 #define OF_HASH_FINALIZE(hash) \
592  { \
593  hash += (hash << 3); \
594  hash ^= (hash >> 11); \
595  hash += (hash << 15); \
596  }
597 #define OF_HASH_ADD_HASH(hash, other) \
598  { \
599  uint32_t otherCopy = other; \
600  OF_HASH_ADD(hash, (otherCopy >> 24) & 0xFF); \
601  OF_HASH_ADD(hash, (otherCopy >> 16) & 0xFF); \
602  OF_HASH_ADD(hash, (otherCopy >> 8) & 0xFF); \
603  OF_HASH_ADD(hash, otherCopy & 0xFF); \
604  }
605 
606 static OF_INLINE bool
607 of_bitset_isset(uint8_t *storage, size_t index)
608 {
609  return storage[index / 8] & (1 << (index % 8));
610 }
611 
612 static OF_INLINE void
613 of_bitset_set(uint8_t *storage, size_t index)
614 {
615  storage[index / 8] |= (1 << (index % 8));
616 }
617 
618 static OF_INLINE void
619 of_bitset_clear(uint8_t *storage, size_t index)
620 {
621  storage[index / 8] &= ~(1 << (index % 8));
622 }
623 
624 static OF_INLINE char *
625 of_strdup(const char *string)
626 {
627  char *copy;
628  size_t length = strlen(string);
629 
630  if ((copy = (char *)malloc(length + 1)) == NULL)
631  return NULL;
632 
633  memcpy(copy, string, length + 1);
634 
635  return copy;
636 }
637 
638 static OF_INLINE void
639 of_explicit_memset(void *buffer_, int character, size_t length)
640 {
641  volatile unsigned char *buffer = (volatile unsigned char *)buffer_;
642 
643  while (buffer < (unsigned char *)buffer_ + length)
644  *buffer++ = character;
645 }
646 
647 static OF_INLINE bool
648 of_ascii_isalpha(char c)
649 {
650  return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
651 }
652 
653 static OF_INLINE bool
654 of_ascii_isalnum(char c)
655 {
656  return (of_ascii_isalpha(c) || (c >= '0' && c <= '9'));
657 }
658 
659 static OF_INLINE bool
660 of_ascii_isspace(char c)
661 {
662  return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' ||
663  c == '\v');
664 }
665 
666 static OF_INLINE char
667 of_ascii_toupper(char c)
668 {
669  return (c >= 'a' && c <= 'z' ? 'A' + (c - 'a') : c);
670 }
671 
672 static OF_INLINE char
673 of_ascii_tolower(char c)
674 {
675  return (c >= 'A' && c <= 'Z' ? 'a' + (c - 'A') : c);
676 }