--- libecb/ecb.h 2014/10/14 22:14:32 1.140 +++ libecb/ecb.h 2015/02/20 14:02:39 1.156 @@ -1,7 +1,7 @@ /* * libecb - http://software.schmorp.de/pkg/libecb * - * Copyright (©) 2009-2014 Marc Alexander Lehmann + * Copyright (©) 2009-2015 Marc Alexander Lehmann * Copyright (©) 2011 Emanuele Giaquinta * All rights reserved. * @@ -42,7 +42,7 @@ #define ECB_H /* 16 bits major, 16 bits minor */ -#define ECB_VERSION 0x00010003 +#define ECB_VERSION 0x00010004 #ifdef _WIN32 typedef signed char int8_t; @@ -100,14 +100,14 @@ #define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor))) -#if __clang__ && defined(__has_builtin) - #define ECB_CLANG_BUILTIN(x) __has_builtin(x) +#if __clang__ && defined __has_builtin + #define ECB_CLANG_BUILTIN(x) __has_builtin (x) #else #define ECB_CLANG_BUILTIN(x) 0 #endif -#if __clang__ && defined(__has_extension) - #define ECB_CLANG_EXTENSION(x) __has_extension(x) +#if __clang__ && defined __has_extension + #define ECB_CLANG_EXTENSION(x) __has_extension (x) #else #define ECB_CLANG_EXTENSION(x) 0 #endif @@ -280,7 +280,7 @@ /*****************************************************************************/ -#if __cplusplus +#if ECB_CPP #define ecb_inline static inline #elif ECB_GCC_VERSION(2,5) #define ecb_inline static __inline__ @@ -304,11 +304,12 @@ #define ECB_CONCAT(a, b) ECB_CONCAT_(a, b) #define ECB_STRINGIFY_(a) # a #define ECB_STRINGIFY(a) ECB_STRINGIFY_(a) +#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr)) #define ecb_function_ ecb_inline #if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8) - #define ecb_attribute(attrlist) __attribute__(attrlist) + #define ecb_attribute(attrlist) __attribute__ (attrlist) #else #define ecb_attribute(attrlist) #endif @@ -336,26 +337,46 @@ #endif /* no emulation for ecb_decltype */ -#if ECB_GCC_VERSION(4,5) - #define ecb_decltype(x) __decltype(x) -#elif ECB_GCC_VERSION(3,0) - #define ecb_decltype(x) __typeof(x) +#if ECB_CPP11 + // older implementations might have problems with decltype(x)::type, work around it + template struct ecb_decltype_t { typedef T type; }; + #define ecb_decltype(x) ecb_decltype_t::type +#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8) + #define ecb_decltype(x) __typeof__ (x) #endif #if _MSC_VER >= 1300 - #define ecb_deprecated __declspec(deprecated) + #define ecb_deprecated __declspec (deprecated) #else #define ecb_deprecated ecb_attribute ((__deprecated__)) #endif -#define ecb_noinline ecb_attribute ((__noinline__)) +#if __MSC_VER >= 1500 + #define ecb_deprecated_message(msg) __declspec (deprecated (msg)) +#elif ECB_GCC_VERSION(4,5) + #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg)) +#else + #define ecb_deprecated_message(msg) ecb_deprecated +#endif + +#if _MSC_VER >= 1400 + #define ecb_noinline __declspec (noinline) +#else + #define ecb_noinline ecb_attribute ((__noinline__)) +#endif + #define ecb_unused ecb_attribute ((__unused__)) #define ecb_const ecb_attribute ((__const__)) #define ecb_pure ecb_attribute ((__pure__)) -/* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx __declspec(noreturn) */ -#if ECB_C11 +#if ECB_C11 || __IBMC_NORETURN + /* http://pic.dhe.ibm.com/infocenter/compbg/v121v141/topic/com.ibm.xlcpp121.bg.doc/language_ref/noreturn.html */ #define ecb_noreturn _Noreturn +#elif ECB_CPP11 + #define ecb_noreturn [[noreturn]] +#elif _MSC_VER >= 1200 + /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */ + #define ecb_noreturn __declspec (noreturn) #else #define ecb_noreturn ecb_attribute ((__noreturn__)) #endif @@ -392,8 +413,8 @@ #define ecb_popcount32(x) __builtin_popcount (x) /* no popcountll */ #else - ecb_function_ int ecb_ctz32 (uint32_t x) ecb_const; - ecb_function_ int + ecb_function_ ecb_const int ecb_ctz32 (uint32_t x); + ecb_function_ ecb_const int ecb_ctz32 (uint32_t x) { int r = 0; @@ -417,16 +438,16 @@ return r; } - ecb_function_ int ecb_ctz64 (uint64_t x) ecb_const; - ecb_function_ int + ecb_function_ ecb_const int ecb_ctz64 (uint64_t x); + ecb_function_ ecb_const int ecb_ctz64 (uint64_t x) { int shift = x & 0xffffffffU ? 0 : 32; return ecb_ctz32 (x >> shift) + shift; } - ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const; - ecb_function_ int + ecb_function_ ecb_const int ecb_popcount32 (uint32_t x); + ecb_function_ ecb_const int ecb_popcount32 (uint32_t x) { x -= (x >> 1) & 0x55555555; @@ -437,8 +458,8 @@ return x >> 24; } - ecb_function_ int ecb_ld32 (uint32_t x) ecb_const; - ecb_function_ int ecb_ld32 (uint32_t x) + ecb_function_ ecb_const int ecb_ld32 (uint32_t x); + ecb_function_ ecb_const int ecb_ld32 (uint32_t x) { int r = 0; @@ -451,8 +472,8 @@ return r; } - ecb_function_ int ecb_ld64 (uint64_t x) ecb_const; - ecb_function_ int ecb_ld64 (uint64_t x) + ecb_function_ ecb_const int ecb_ld64 (uint64_t x); + ecb_function_ ecb_const int ecb_ld64 (uint64_t x) { int r = 0; @@ -462,20 +483,20 @@ } #endif -ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) ecb_const; -ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); } -ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) ecb_const; -ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); } +ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x); +ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); } +ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x); +ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); } -ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) ecb_const; -ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) +ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x); +ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x) { return ( (x * 0x0802U & 0x22110U) - | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16; + | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16; } -ecb_function_ uint16_t ecb_bitrev16 (uint16_t x) ecb_const; -ecb_function_ uint16_t ecb_bitrev16 (uint16_t x) +ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x); +ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x) { x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1); x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2); @@ -485,8 +506,8 @@ return x; } -ecb_function_ uint32_t ecb_bitrev32 (uint32_t x) ecb_const; -ecb_function_ uint32_t ecb_bitrev32 (uint32_t x) +ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x); +ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x) { x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1); x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2); @@ -499,52 +520,52 @@ /* popcount64 is only available on 64 bit cpus as gcc builtin */ /* so for this version we are lazy */ -ecb_function_ int ecb_popcount64 (uint64_t x) ecb_const; -ecb_function_ int +ecb_function_ ecb_const int ecb_popcount64 (uint64_t x); +ecb_function_ ecb_const int ecb_popcount64 (uint64_t x) { return ecb_popcount32 (x) + ecb_popcount32 (x >> 32); } -ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) ecb_const; -ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) ecb_const; -ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) ecb_const; -ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) ecb_const; -ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const; -ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const; -ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const; -ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const; - -ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); } -ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); } -ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); } -ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); } -ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); } -ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); } -ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); } -ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); } +ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count); +ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count); +ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count); +ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count); +ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count); +ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count); +ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count); +ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count); + +ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); } +ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); } +ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); } +ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); } +ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); } +ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); } +ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); } +ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); } #if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64)) #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16) #define ecb_bswap32(x) __builtin_bswap32 (x) #define ecb_bswap64(x) __builtin_bswap64 (x) #else - ecb_function_ uint16_t ecb_bswap16 (uint16_t x) ecb_const; - ecb_function_ uint16_t + ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x); + ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x) { return ecb_rotl16 (x, 8); } - ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const; - ecb_function_ uint32_t + ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x); + ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x) { return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16); } - ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const; - ecb_function_ uint64_t + ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x); + ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x) { return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32); @@ -555,15 +576,15 @@ #define ecb_unreachable() __builtin_unreachable () #else /* this seems to work fine, but gcc always emits a warning for it :/ */ - ecb_inline void ecb_unreachable (void) ecb_noreturn; - ecb_inline void ecb_unreachable (void) { } + ecb_inline ecb_noreturn void ecb_unreachable (void); + ecb_inline ecb_noreturn void ecb_unreachable (void) { } #endif /* try to tell the compiler that some condition is definitely true */ #define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0 -ecb_inline unsigned char ecb_byteorder_helper (void) ecb_const; -ecb_inline unsigned char +ecb_inline ecb_const unsigned char ecb_byteorder_helper (void); +ecb_inline ecb_const unsigned char ecb_byteorder_helper (void) { /* the union code still generates code under pressure in gcc, */ @@ -588,10 +609,10 @@ #endif } -ecb_inline ecb_bool ecb_big_endian (void) ecb_const; -ecb_inline ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; } -ecb_inline ecb_bool ecb_little_endian (void) ecb_const; -ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; } +ecb_inline ecb_const ecb_bool ecb_big_endian (void); +ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; } +ecb_inline ecb_const ecb_bool ecb_little_endian (void); +ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; } #if ECB_GCC_VERSION(3,0) || ECB_C99 #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0)) @@ -599,7 +620,7 @@ #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n))) #endif -#if __cplusplus +#if ECB_CPP template static inline T ecb_div_rd (T val, T div) { @@ -669,17 +690,23 @@ #define ECB_NAN ECB_INFINITY #endif + #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L + #define ecb_ldexpf(x,e) ldexpf ((x), (e)) + #else + #define ecb_ldexpf(x,e) (float) ldexp ((x), (e)) + #endif + /* converts an ieee half/binary16 to a float */ - ecb_function_ float ecb_binary16_to_float (uint16_t x) ecb_const; - ecb_function_ float + ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x); + ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x) { int e = (x >> 10) & 0x1f; int m = x & 0x3ff; float r; - if (!e ) r = ldexpf (m , -24); - else if (e != 31) r = ldexpf (m + 0x400, e - 25); + if (!e ) r = ecb_ldexpf (m , -24); + else if (e != 31) r = ecb_ldexpf (m + 0x400, e - 25); else if (m ) r = ECB_NAN; else r = ECB_INFINITY; @@ -687,8 +714,8 @@ } /* convert a float to ieee single/binary32 */ - ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const; - ecb_function_ uint32_t + ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x); + ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x) { uint32_t r; @@ -727,8 +754,8 @@ } /* converts an ieee single/binary32 to a float */ - ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const; - ecb_function_ float + ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x); + ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x) { float r; @@ -748,7 +775,7 @@ e = 1; /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */ - r = ldexpf (x * (0.5f / 0x800000U), e - 126); + r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126); r = neg ? -r : r; #endif @@ -757,8 +784,8 @@ } /* convert a double to ieee double/binary64 */ - ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const; - ecb_function_ uint64_t + ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x); + ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x) { uint64_t r; @@ -797,8 +824,8 @@ } /* converts an ieee double/binary64 to a double */ - ecb_function_ double ecb_binary64_to_double (uint64_t x) ecb_const; - ecb_function_ double + ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x); + ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x) { double r;