Artifact 3c8f4714cc0386061986ecee152c9f5976577fa89e7caf11368ee1298ad63d80:
- File
src/macros.h
— part of check-in
[96f946d7ad]
at
2024-05-09 10:21:24
on branch trunk
— Use unsigned long for bit sets
This should be more efficient on some architectures.
As a nice side effect, this is also what Linux does in some userspace
APIs, so after this change, these macros can be used for this as well
(and Linux interestingly does not provide similar macros in the
userspace headers). (user: js, size: 25972) [annotate] [blame] [check-ins using] [more...]
/* * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im> * * All rights reserved. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3.0 only, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * version 3.0 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3.0 along with this program. If not, see * <https://www.gnu.org/licenses/>. */ #ifndef OBJFW_MACROS_H #define OBJFW_MACROS_H #include "objfw-defs.h" #ifndef __STDC_LIMIT_MACROS # define __STDC_LIMIT_MACROS #endif #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS #endif #include <limits.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> /** @file */ #include "platform.h" #ifdef OF_OBJFW_RUNTIME # ifdef OF_COMPILING_OBJFW # include "ObjFWRT.h" # else # include <ObjFWRT/ObjFWRT.h> # endif #endif #ifdef OF_APPLE_RUNTIME # include <objc/objc.h> # include <objc/runtime.h> # include <objc/message.h> #endif #if defined(__GNUC__) # define restrict __restrict__ #elif __STDC_VERSION__ < 199901L # define restrict #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> # ifdef OF_AIX /* AIX has a bug where thread_local is defined to "Thread_local;". */ # undef thread_local # define thread_local _Thread_local # endif # else # define thread_local _Thread_local # endif #elif defined(OF_HAVE___THREAD) # define OF_HAVE_COMPILER_TLS # define thread_local __thread #endif /* * Do not use compiler TLS when targeting the iOS simulator, as the iOS 9 * simulator does not support it (fails at runtime). */ #if defined(OF_HAVE_COMPILER_TLS) && defined(OF_IOS) && defined(OF_X86) # undef OF_HAVE_COMPILER_TLS #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__)) # define OF_NO_RETURN_FUNC __attribute__((__noreturn__)) # define OF_WEAK_REF(sym) __attribute__((__weakref__(sym))) # define OF_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) #else # define OF_INLINE inline # define OF_LIKELY(cond) (cond) # define OF_UNLIKELY(cond) (cond) # define OF_CONST_FUNC # define OF_NO_RETURN_FUNC # define OF_WEAK_REF(sym) # define OF_VISIBILITY_HIDDEN #endif #if __STDC_VERSION__ >= 201112L # define OF_ALIGN(size) _Alignas(size) # define OF_ALIGNOF(type) _Alignof(type) # define OF_ALIGNAS(type) _Alignas(type) #else # define OF_ALIGN(size) __attribute__((__aligned__(size))) # define OF_ALIGNOF(type) __alignof__(type) # define OF_ALIGNAS(type) OF_ALIGN(OF_ALIGNOF(type)) #endif #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 /* * We use SSE inline assembly on AMD64 and x86, so it must never be smaller * than 16. */ #if (defined(OF_AMD64) || defined(OF_X86)) && OF_BIGGEST_ALIGNMENT < 16 # undef OF_BIGGEST_ALIGNMENT # define OF_BIGGEST_ALIGNMENT 16 #endif #define OF_PREPROCESSOR_CONCAT2(a, b) a##b #define OF_PREPROCESSOR_CONCAT(a, b) OF_PREPROCESSOR_CONCAT2(a, b) #if __OBJFW_RUNTIME_ABI__ || (defined(OF_APPLE_RUNTIME) && defined(__OBJC2__)) # define OF_HAVE_NONFRAGILE_IVARS #endif #ifdef OF_HAVE_NONFRAGILE_IVARS # define OF_RESERVE_IVARS(cls, num) #else # define OF_RESERVE_IVARS(cls, num) \ @private \ void *OF_PREPROCESSOR_CONCAT(_reserved_, cls)[num]; #endif #ifdef __GNUC__ # define OF_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) #else # define OF_GCC_VERSION 0 #endif #define OF_STRINGIFY(s) OF_STRINGIFY2(s) #define OF_STRINGIFY2(s) #s #ifndef __has_feature # define __has_feature(x) 0 #endif #ifndef __has_attribute # define __has_attribute(x) 0 #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 !__has_feature(objc_instancetype) # define instancetype id #endif #if __has_feature(blocks) # define OF_HAVE_BLOCKS #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 /* * undef them first, as new Clang versions have these as built-in defines even * when ARC is disabled. */ # undef __unsafe_unretained # undef __bridge # undef __autoreleasing # define __unsafe_unretained # define __bridge # define __autoreleasing #endif #if __has_feature(objc_generics) # define OF_HAVE_GENERICS # define OF_GENERIC(...) <__VA_ARGS__> #else # define OF_GENERIC(...) #endif #if __has_feature(nullability) # define OF_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") # define OF_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") # define OF_NULLABLE_PROPERTY(...) (__VA_ARGS__, nullable) # define OF_NULL_RESETTABLE_PROPERTY(...) (__VA_ARGS__, null_resettable) #else # define OF_ASSUME_NONNULL_BEGIN # define OF_ASSUME_NONNULL_END # define _Nonnull # define _Nullable # define _Null_unspecified # define OF_NULLABLE_PROPERTY # define OF_NULL_RESETTABLE_PROPERTY # define nonnull # define nullable # define null_unspecified #endif #if __has_feature(objc_kindof) # define OF_KINDOF(class_) __kindof class_ #else # define OF_KINDOF(class_) id #endif #if __has_feature(objc_class_property) # define OF_HAVE_CLASS_PROPERTIES #endif #if defined(__clang__) || OF_GCC_VERSION >= 405 # define OF_UNREACHABLE __builtin_unreachable(); #else # define OF_UNREACHABLE abort(); #endif #if defined(__clang__) || OF_GCC_VERSION >= 406 # define OF_SENTINEL __attribute__((__sentinel__)) # define OF_NO_RETURN __attribute__((__noreturn__)) #else # define OF_SENTINEL # define OF_NO_RETURN #endif #ifdef __clang__ # define OF_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #else # define OF_WARN_UNUSED_RESULT #endif #if __has_attribute(__unavailable__) # define OF_UNAVAILABLE __attribute__((__unavailable__)) #else # define OF_UNAVAILABLE #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 #if __has_attribute(__objc_subclassing_restricted__) # define OF_SUBCLASSING_RESTRICTED \ __attribute__((__objc_subclassing_restricted__)) #else # define OF_SUBCLASSING_RESTRICTED #endif #if __has_attribute(__objc_method_family__) # define OF_METHOD_FAMILY(f) __attribute__((__objc_method_family__(f))) #else # define OF_METHOD_FAMILY(f) #endif #if __has_attribute(__objc_designated_initializer__) # define OF_DESIGNATED_INITIALIZER \ __attribute__((__objc_designated_initializer__)) #else # define OF_DESIGNATED_INITIALIZER #endif #if defined(__clang__) || OF_GCC_VERSION >= 405 # define OF_DEPRECATED(project, major, minor, msg) \ __attribute__((__deprecated__("Deprecated in " #project " " \ #major "." #minor ": " msg))) #elif defined(__GNUC__) # define OF_DEPRECATED(project, major, minor, msg) \ __attribute__((__deprecated__)) #else # define OF_DEPRECATED(project, major, minor, msg) #endif #if __has_attribute(__objc_boxable__) # define OF_BOXABLE __attribute__((__objc_boxable__)) #else # define OF_BOXABLE #endif #if __has_attribute(__swift_name__) # define OF_SWIFT_NAME(name) __attribute__((__swift_name__(name))) #else # define OF_SWIFT_NAME(name) #endif #if __has_attribute(__objc_direct__) && defined(OF_APPLE_RUNTIME) # define OF_DIRECT __attribute__((__objc_direct__)) #else # define OF_DIRECT #endif #if __has_attribute(__objc_direct_members__) && defined(OF_APPLE_RUNTIME) # define OF_DIRECT_MEMBERS __attribute__((__objc_direct_members__)) #else # define OF_DIRECT_MEMBERS #endif #ifdef OF_APPLE_RUNTIME # if defined(OF_AMD64) || defined(OF_X86) || defined(OF_ARM64) || \ defined(OF_ARM) || defined(OF_POWERPC) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif #else # if defined(OF_ELF) # if defined(OF_AMD64) || defined(OF_X86) || \ defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \ defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif # elif defined(OF_MACH_O) # if defined(OF_AMD64) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif # elif defined(OF_WINDOWS) # if defined(OF_AMD64) || defined(OF_X86) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif # endif #endif #define OFMaxRetainCount UINT_MAX #ifdef OBJC_COMPILING_RUNTIME # define OFEnsure(cond) \ do { \ if OF_UNLIKELY (!(cond)) \ objc_error("ObjFWRT @ " __FILE__ ":" \ OF_STRINGIFY(__LINE__), \ "Failed to ensure condition:\n" #cond); \ } while(0) #else @class OFConstantString; # ifdef __cplusplus extern "C" { # endif extern void OFLog(OFConstantString *_Nonnull, ...); # ifdef __cplusplus } # endif # define OFEnsure(cond) \ do { \ if OF_UNLIKELY (!(cond)) { \ OFLog(@"Failed to ensure condition in " \ @__FILE__ ":%d: " @#cond, __LINE__); \ abort(); \ } \ } while (0) #endif #ifndef NDEBUG # define OFAssert(...) OFEnsure(__VA_ARGS__) #else # define OFAssert(...) #endif #define OF_UNRECOGNIZED_SELECTOR OFMethodNotFound(self, _cmd); #if __has_feature(objc_arc) # define OF_INVALID_INIT_METHOD OFMethodNotFound(self, _cmd); #else # define OF_INVALID_INIT_METHOD \ @try { \ OFMethodNotFound(self, _cmd); \ } @catch (id e) { \ [self release]; \ @throw e; \ } \ \ abort(); #endif #ifdef __clang__ # define OF_DEALLOC_UNSUPPORTED \ [self doesNotRecognizeSelector: _cmd]; \ \ abort(); \ \ _Pragma("clang diagnostic push"); \ _Pragma("clang diagnostic ignored \"-Wunreachable-code\""); \ [super dealloc]; /* Get rid of a stupid warning */ \ _Pragma("clang diagnostic pop"); #else # define OF_DEALLOC_UNSUPPORTED \ [self doesNotRecognizeSelector: _cmd]; \ \ abort(); \ \ [super dealloc]; /* Get rid of a stupid warning */ #endif #define OF_SINGLETON_METHODS \ - (instancetype)autorelease \ { \ return self; \ } \ \ - (instancetype)retain \ { \ return self; \ } \ \ - (void)release \ { \ } \ \ - (unsigned int)retainCount \ { \ return OFMaxRetainCount; \ } \ \ - (void)dealloc \ { \ OF_DEALLOC_UNSUPPORTED \ } #define OF_CONSTRUCTOR(prio) \ static void __attribute__((__constructor__(prio))) \ OF_PREPROCESSOR_CONCAT(constructor, __LINE__)(void) #define OF_DESTRUCTOR(prio) \ static void __attribute__((__destructor__(prio))) \ OF_PREPROCESSOR_CONCAT(destructor, __LINE__)(void) static OF_INLINE uint16_t OF_CONST_FUNC _OFByteSwap16Const(uint16_t i) { return (i & UINT16_C(0xFF00)) >> 8 | (i & UINT16_C(0x00FF)) << 8; } static OF_INLINE uint32_t OF_CONST_FUNC _OFByteSwap32Const(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 _OFByteSwap64Const(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 _OFByteSwap16NonConst(uint16_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP16) return __builtin_bswap16(i); #elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) __asm__ ( "xchg{b} { %h0, %b0 | %b0, %h0 }" : "=Q" (i) : "0" (i) ); #elif defined(OF_POWERPC) && defined(__GNUC__) __asm__ ( "lhbrx %0, 0, %1" : "=r" (i) : "r" (&i), "m" (i) ); #elif defined(OF_ARMV6) && defined(__GNUC__) __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 _OFByteSwap32NonConst(uint32_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP32) return __builtin_bswap32(i); #elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) __asm__ ( "bswap %0" : "=q" (i) : "0" (i) ); #elif defined(OF_POWERPC) && defined(__GNUC__) __asm__ ( "lwbrx %0, 0, %1" : "=r" (i) : "r" (&i), "m" (i) ); #elif defined(OF_ARMV6) && defined(__GNUC__) __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 _OFByteSwap64NonConst(uint64_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP64) return __builtin_bswap64(i); #elif defined(OF_AMD64) && defined(__GNUC__) __asm__ ( "bswap %0" : "=r" (i) : "0" (i) ); #elif defined(OF_X86) && defined(__GNUC__) __asm__ ( "bswap {%%}eax\n\t" "bswap {%%}edx\n\t" "xchg{l} { %%eax, %%edx | edx, eax }" : "=A" (i) : "0" (i) ); #else i = (uint64_t)_OFByteSwap32NonConst( (uint32_t)(i & UINT32_C(0xFFFFFFFF))) << 32 | _OFByteSwap32NonConst((uint32_t)(i >> 32)); #endif return i; } #if defined(__GNUC__) || defined(DOXYGEN) /** * @brief Byte swaps the specified 16 bit integer. * * @param i The integer to byte swap * @return The byte swapped integer */ # define OFByteSwap16(i) \ (__builtin_constant_p(i) ? _OFByteSwap16Const(i) : _OFByteSwap16NonConst(i)) /** * @brief Byte swaps the specified 32 bit integer. * * @param i The integer to byte swap * @return The byte swapped integer */ # define OFByteSwap32(i) \ (__builtin_constant_p(i) ? _OFByteSwap32Const(i) : _OFByteSwap32NonConst(i)) /** * @brief Byte swaps the specified 64 bit integer. * * @param i The integer to byte swap * @return The byte swapped integer */ # define OFByteSwap64(i) \ (__builtin_constant_p(i) ? _OFByteSwap64Const(i) : _OFByteSwap64NonConst(i)) #else # define OFByteSwap16(i) _OFByteSwap16Const(i) # define OFByteSwap32(i) _OFByteSwap32Const(i) # define OFByteSwap64(i) _OFByteSwap64Const(i) #endif /** * @brief Bit-converts the specified float to a uint32_t. * * @param f The float to bit-convert * @return The float bit-converted to a uint32_t */ static OF_INLINE uint32_t OF_CONST_FUNC OFBitConvertFloatToUInt32(float f) { uint32_t ret; memcpy(&ret, &f, 4); return ret; } /** * @brief Bit-converts the specified uint32_t to a float. * * @param uInt32 The uint32_t to bit-convert * @return The uint32_t bit-converted to a float */ static OF_INLINE float OF_CONST_FUNC OFBitConvertUInt32ToFloat(uint32_t uInt32) { float ret; memcpy(&ret, &uInt32, 4); return ret; } /** * @brief Bit-converts the specified double to a uint64_t. * * @param d The double to bit-convert * @return The double bit-converted to a uint64_t */ static OF_INLINE uint64_t OF_CONST_FUNC OFBitConvertDoubleToUInt64(double d) { uint64_t ret; memcpy(&ret, &d, 8); return ret; } /** * @brief Bit-converts the specified uint64_t to a double. * * @param uInt64 The uint64_t to bit-convert * @return The uint64_t bit-converted to a double */ static OF_INLINE double OF_CONST_FUNC OFBitConvertUInt64ToDouble(uint64_t uInt64) { double ret; memcpy(&ret, &uInt64, 8); return ret; } /** * @brief Byte swaps the specified float. * * @param f The float to byte swap * @return The byte swapped float */ static OF_INLINE float OF_CONST_FUNC OFByteSwapFloat(float f) { return OFBitConvertUInt32ToFloat(OFByteSwap32( OFBitConvertFloatToUInt32(f))); } /** * @brief Byte swaps the specified double. * * @param d The double to byte swap * @return The byte swapped double */ static OF_INLINE double OF_CONST_FUNC OFByteSwapDouble(double d) { return OFBitConvertUInt64ToDouble(OFByteSwap64( OFBitConvertDoubleToUInt64(d))); } #if defined(OF_BIG_ENDIAN) || defined(DOXYGEN) /** * @brief Converts the specified 16 bit integer from big endian to native * endian. * * @param i The 16 bit integer to convert * @return The 16 bit integer converted to native endian */ # define OFFromBigEndian16(i) (i) /** * @brief Converts the specified 32 bit integer from big endian to native * endian. * * @param i The 32 bit integer to convert * @return The 32 bit integer converted to native endian */ # define OFFromBigEndian32(i) (i) /** * @brief Converts the specified 64 bit integer from big endian to native * endian. * * @param i The 64 bit integer to convert * @return The 64 bit integer converted to native endian */ # define OFFromBigEndian64(i) (i) /** * @brief Converts the specified 16 bit integer from little endian to native * endian. * * @param i The 16 bit integer to convert * @return The 16 bit integer converted to native endian */ # define OFFromLittleEndian16(i) OFByteSwap16(i) /** * @brief Converts the specified 32 bit integer from little endian to native * endian. * * @param i The 32 bit integer to convert * @return The 32 bit integer converted to native endian */ # define OFFromLittleEndian32(i) OFByteSwap32(i) /** * @brief Converts the specified 64 bit integer from little endian to native * endian. * * @param i The 64 bit integer to convert * @return The 64 bit integer converted to native endian */ # define OFFromLittleEndian64(i) OFByteSwap64(i) /** * @brief Converts the specified 16 bit integer from native endian to big * endian. * * @param i The 16 bit integer to convert * @return The 16 bit integer converted to big endian */ # define OFToBigEndian16(i) (i) /** * @brief Converts the specified 32 bit integer from native endian to big * endian. * * @param i The 32 bit integer to convert * @return The 32 bit integer converted to big endian */ # define OFToBigEndian32(i) (i) /** * @brief Converts the specified 64 bit integer from native endian to big * endian. * * @param i The 64 bit integer to convert * @return The 64 bit integer converted to big endian */ # define OFToBigEndian64(i) (i) /** * @brief Converts the specified 16 bit integer from native endian to little * endian. * * @param i The 16 bit integer to convert * @return The 16 bit integer converted to little endian */ # define OFToLittleEndian16(i) OFByteSwap16(i) /** * @brief Converts the specified 32 bit integer from native endian to little * endian. * * @param i The 32 bit integer to convert * @return The 32 bit integer converted to little endian */ # define OFToLittleEndian32(i) OFByteSwap32(i) /** * @brief Converts the specified 64 bit integer from native endian to little * endian. * * @param i The 64 bit integer to convert * @return The 64 bit integer converted to little endian */ # define OFToLittleEndian64(i) OFByteSwap64(i) #else # define OFFromBigEndian16(i) OFByteSwap16(i) # define OFFromBigEndian32(i) OFByteSwap32(i) # define OFFromBigEndian64(i) OFByteSwap64(i) # define OFFromLittleEndian16(i) (i) # define OFFromLittleEndian32(i) (i) # define OFFromLittleEndian64(i) (i) # define OFToBigEndian16(i) OFByteSwap16(i) # define OFToBigEndian32(i) OFByteSwap32(i) # define OFToBigEndian64(i) OFByteSwap64(i) # define OFToLittleEndian16(i) (i) # define OFToLittleEndian32(i) (i) # define OFToLittleEndian64(i) (i) #endif #if defined(OF_FLOAT_BIG_ENDIAN) || defined(DOXYGEN) /** * @brief Converts the specified float from big endian to native endian. * * @param f The float to convert * @return The float converted to native endian */ # define OFFromBigEndianFloat(f) (f) /** * @brief Converts the specified double from big endian to native endian. * * @param d The double to convert * @return The double converted to native endian */ # define OFFromBigEndianDouble(d) (d) /** * @brief Converts the specified float from little endian to native endian. * * @param f The float to convert * @return The float converted to native endian */ # define OFFromLittleEndianFloat(f) OFByteSwapFloat(f) /** * @brief Converts the specified double from little endian to native endian. * * @param d The double to convert * @return The double converted to native endian */ # define OFFromLittleEndianDouble(d) OFByteSwapDouble(d) /** * @brief Converts the specified float from native endian to big endian. * * @param f The float to convert * @return The float converted to big endian */ # define OFToBigEndianFloat(f) (f) /** * @brief Converts the specified double from native endian to big endian. * * @param d The double to convert * @return The double converted to big endian */ # define OFToBigEndianDouble(d) (d) /** * @brief Converts the specified float from native endian to little endian. * * @param f The float to convert * @return The float converted to little endian */ # define OFToLittleEndianFloat(f) OFByteSwapFloat(f) /** * @brief Converts the specified double from native endian to little endian. * * @param d The double to convert * @return The double converted to little endian */ # define OFToLittleEndianDouble(d) OFByteSwapDouble(d) #else # define OFFromBigEndianFloat(f) OFByteSwapFloat(f) # define OFFromBigEndianDouble(d) OFByteSwapDouble(d) # define OFFromLittleEndianFloat(f) (f) # define OFFromLittleEndianDouble(d) (d) # define OFToBigEndianFloat(f) OFByteSwapFloat(f) # define OFToBigEndianDouble(d) OFByteSwapDouble(d) # define OFToLittleEndianFloat(f) (f) # define OFToLittleEndianDouble(d) (d) #endif /** * @brief Rotates the specified value left by the specified amount of bits. * * @param value The value to rotate * @param bits The number of bits to rotate left the value by * @return The value rotated left by the specified amount of bits */ #define OFRotateLeft(value, bits) \ (((bits) % (sizeof(value) * 8)) > 0 \ ? ((value) << ((bits) % (sizeof(value) * 8))) | \ ((value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) \ : (value)) /** * @brief Rotates the specified value right by the specified amount of bits. * * @param value The value to rotate * @param bits The number of bits to rotate right the value by * @return The value rotated right by the specified amount of bits */ #define OFRotateRight(value, bits) \ (((bits) % (sizeof(value) * 8)) > 0 \ ? ((value) >> ((bits) % (sizeof(value) * 8))) | \ ((value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) \ : (value)) /** * @brief Rounds up the specified value to the specified power of two. * * @param pow2 The power of 2 to round up to * @param value The value to round up to the specified power of two * @return The specified value rounded up to the specified power of two */ #define OFRoundUpToPowerOf2(pow2, value) \ (((value) + (pow2) - 1) & ~((pow2) - 1)) #define OF_ULONG_BIT (sizeof(unsigned long) * CHAR_BIT) static OF_INLINE bool OFBitSetIsSet(unsigned long *_Nonnull storage, size_t idx) { return storage[idx / OF_ULONG_BIT] & (1ul << (idx % OF_ULONG_BIT)); } static OF_INLINE void OFBitSetSet(unsigned long *_Nonnull storage, size_t idx) { storage[idx / OF_ULONG_BIT] |= (1ul << (idx % OF_ULONG_BIT)); } static OF_INLINE void OFBitSetClear(unsigned long *_Nonnull storage, size_t idx) { storage[idx / OF_ULONG_BIT] &= ~(1ul << (idx % OF_ULONG_BIT)); } static OF_INLINE void OFZeroMemory(void *_Nonnull buffer_, size_t length) { volatile unsigned char *buffer = (volatile unsigned char *)buffer_; while (buffer < (unsigned char *)buffer_ + length) *buffer++ = '\0'; } static OF_INLINE bool OFASCIIIsAlpha(char c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); } static OF_INLINE bool OFASCIIIsDigit(char c) { return (c >= '0' && c <= '9'); } static OF_INLINE bool OFASCIIIsAlnum(char c) { return (OFASCIIIsAlpha(c) || OFASCIIIsDigit(c)); } static OF_INLINE bool OFASCIIIsSpace(char c) { return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'); } static OF_INLINE char OFASCIIToUpper(char c) { return (c >= 'a' && c <= 'z' ? 'A' + (c - 'a') : c); } static OF_INLINE char OFASCIIToLower(char c) { return (c >= 'A' && c <= 'Z' ? 'a' + (c - 'A') : c); } #endif