diff options
Diffstat (limited to 'ecb.h')
-rw-r--r-- | ecb.h | 319 |
1 files changed, 215 insertions, 104 deletions
@@ -30,7 +30,23 @@ #ifndef ECB_H #define ECB_H -#include <inttypes.h> +#ifdef _WIN32 + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; + #if __GNUC__ + typedef signed long long int64_t; + typedef unsigned long long uint64_t; + #else + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; + #endif +#else + #include <inttypes.h> +#endif /* many compilers define _GNUC_ to some versions but then only implement * what their idiot authors think are the "more important" extensions, @@ -40,182 +56,277 @@ * an issue with that they should have done it right in the first place. */ #ifndef ECB_GCC_VERSION -# if defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__llvm__) -# define ECB_GCC_VERSION(major,minor) 0 -# else -# define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) -# endif + #if !defined(__GNUC_MINOR__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__llvm__) || defined(__clang__) + #define ECB_GCC_VERSION(major,minor) 0 + #else + #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) + #endif #endif -#ifndef __cplusplus -# if __STDC_VERSION__ >= 199901L -# define ECB_INLINE static inline -typedef _Bool ecb_bool; -# else -# define ECB_INLINE static inline /* yeah! */ -typedef int ecb_bool; -# endif +#define ECB_C99 (__STDC_VERSION__ >= 199901L) + +#if __cplusplus + #define ecb_inline static inline +#elif ECB_GCC_VERSION(2,5) + #define ecb_inline static __inline__ +#elif ECB_C99 + #define ecb_inline static inline +#else + #define ecb_inline static +#endif + +#if ECB_GCC_VERSION(3,3) + #define ecb_restrict __restrict__ +#elif ECB_C99 + #define ecb_restrict restrict #else -# define ECB_INLINE static inline -typedef bool ecb_bool; + #define ecb_restrict #endif +typedef int ecb_bool; + #define ECB_CONCAT_(a, b) a ## b #define ECB_CONCAT(a, b) ECB_CONCAT_(a, b) #define ECB_STRINGIFY_(a) # a #define ECB_STRINGIFY(a) ECB_STRINGIFY_(a) -#define ECB_HEADER_INLINE ECB_INLINE +#define ecb_function_ ecb_inline #if ECB_GCC_VERSION(3,1) -# define ecb_attribute(attrlist) __attribute__(attrlist) -# define ecb_is_constant(expr) __builtin_constant_p (expr) -# define ecb_expect(expr,value) __builtin_expect ((expr),(value)) -# define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) + #define ecb_attribute(attrlist) __attribute__(attrlist) + #define ecb_is_constant(expr) __builtin_constant_p (expr) + #define ecb_expect(expr,value) __builtin_expect ((expr),(value)) + #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) #else -# define ecb_attribute(attrlist) -# define ecb_is_constant(expr) 0 -# define ecb_expect(expr,value) (expr) -# define ecb_prefetch(addr,rw,locality) + #define ecb_attribute(attrlist) + #define ecb_is_constant(expr) 0 + #define ecb_expect(expr,value) (expr) + #define ecb_prefetch(addr,rw,locality) #endif /* no emulation for ecb_decltype */ #if ECB_GCC_VERSION(4,5) -# define ecb_decltype(x) __decltype(x) + #define ecb_decltype(x) __decltype(x) #elif ECB_GCC_VERSION(3,0) -# define ecb_decltype(x) typeof(x) + #define ecb_decltype(x) __typeof(x) #endif -#define ecb_artificial ecb_attribute ((__artificial__)) /* 4.3 */ #define ecb_noinline ecb_attribute ((__noinline__)) #define ecb_noreturn ecb_attribute ((__noreturn__)) #define ecb_unused ecb_attribute ((__unused__)) #define ecb_const ecb_attribute ((__const__)) #define ecb_pure ecb_attribute ((__pure__)) -#define ecb_hot ecb_attribute ((__hot__)) /* 4.3 */ -#define ecb_cold ecb_attribute ((__cold__)) /* 4.3 */ -/* put into if's if you are very sure that the expression */ -/* is mostly true or mostly false. note that these return */ -/* booleans, not the expression. */ +#if ECB_GCC_VERSION(4,3) + #define ecb_artificial ecb_attribute ((__artificial__)) + #define ecb_hot ecb_attribute ((__hot__)) + #define ecb_cold ecb_attribute ((__cold__)) +#else + #define ecb_artificial + #define ecb_hot + #define ecb_cold +#endif + +/* put around conditional expressions if you are very sure that the */ +/* expression is mostly true or mostly false. note that these return */ +/* booleans, not the expression. */ #define ecb_expect_false(expr) ecb_expect (!!(expr), 0) #define ecb_expect_true(expr) ecb_expect (!!(expr), 1) +/* for compatibility to the rest of the world */ #define ecb_likely(expr) ecb_expect_true (expr) #define ecb_unlikely(expr) ecb_expect_false (expr) -/* try to tell the compiler that some condition is definitely true */ -#define ecb_assume(cond) do { if (!(cond)) ecb_unreachable (); } while (0) - /* count trailing zero bits and count # of one bits */ #if ECB_GCC_VERSION(3,4) -#define ecb_ctz32(x) __builtin_ctz (x) -#define ecb_popcount32(x) __builtin_popcount (x) + /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */ + #define ecb_ld32(x) (__builtin_clz (x) ^ 31) + #define ecb_ld64(x) (__builtin_clzll (x) ^ 63) + #define ecb_ctz32(x) __builtin_ctz (x) + #define ecb_ctz64(x) __builtin_ctzll (x) + #define ecb_popcount32(x) __builtin_popcount (x) + /* no popcountll */ #else -ECB_HEADER_INLINE int ecb_ctz32 (uint32_t x) ecb_const; -ECB_HEADER_INLINE int -ecb_ctz32 (uint32_t x) -{ - int r = 0; + ecb_function_ int ecb_ctz32 (uint32_t x) ecb_const; + ecb_function_ int + ecb_ctz32 (uint32_t x) + { + int r = 0; - x &= -x; /* this isolates the lowest bit */ + x &= ~x + 1; /* this isolates the lowest bit */ - if (x & 0xaaaaaaaa) r += 1; - if (x & 0xcccccccc) r += 2; - if (x & 0xf0f0f0f0) r += 4; - if (x & 0xff00ff00) r += 8; - if (x & 0xffff0000) r += 16; + if (x & 0xaaaaaaaa) r += 1; + if (x & 0xcccccccc) r += 2; + if (x & 0xf0f0f0f0) r += 4; + if (x & 0xff00ff00) r += 8; + if (x & 0xffff0000) r += 16; - return r; -} + return r; + } -ECB_HEADER_INLINE int ecb_popcount32 (uint32_t x) ecb_const; -ECB_HEADER_INLINE int -ecb_popcount32 (uint32_t x) -{ - x -= (x >> 1) & 0x55555555; - x = ((x >> 2) & 0x33333333) + (x & 0x33333333); - x = ((x >> 4) + x) & 0x0f0f0f0f; - x *= 0x01010101; + ecb_function_ int ecb_ctz64 (uint64_t x) ecb_const; + ecb_function_ int + ecb_ctz64 (uint64_t x) + { + int shift = x & 0xffffffffU ? 0 : 32; + return ecb_ctz (x >> shift) + shift; + } - return x >> 24; -} + ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const; + ecb_function_ int + ecb_popcount32 (uint32_t x) + { + x -= (x >> 1) & 0x55555555; + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + x = ((x >> 4) + x) & 0x0f0f0f0f; + x *= 0x01010101; + + return x >> 24; + } + + /* you have the choice beetween something with a table lookup, */ + /* something using lots of bit arithmetic and a simple loop */ + /* we went for the loop */ + ecb_function_ int ecb_ld32 (uint32_t x) ecb_const; + ecb_function_ int ecb_ld32 (uint32_t x) + { + int r = -1; + + do + { + x >>= 1; + ++r; + } + while (x); + + return r; + } + + ecb_function_ int ecb_ld64 (uint64_t x) ecb_const; + ecb_function_ int ecb_ld64 (uint64_t x) + { + int r = -1; + + do + { + x >>= 1; + ++r; + } + while (x); + + return r; + } #endif -#if ECB_GCC_VERSION(4,3) -# define ecb_bswap32(x) __builtin_bswap32 (x) -# define ecb_bswap16(x) (__builtin_bswap32(x) >> 16) -#else -ECB_HEADER_INLINE uint32_t ecb_bswap32 (uint32_t x) ecb_const; -ECB_HEADER_INLINE uint32_t -ecb_bswap32 (uint32_t x) +/* 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_popcount64 (uint64_t x) { - return (x >> 24) - | ((x >> 8) & 0x0000ff00) - | ((x << 8) & 0x00ff0000) - | (x << 24); + return ecb_popcount32 (x) + ecb_popcount32 (x >> 32); } -ECB_HEADER_INLINE uint32_t ecb_bswap16 (uint32_t x) ecb_const; -ECB_HEADER_INLINE uint32_t -ecb_bswap16 (uint32_t x) -{ - return ((x >> 8) & 0xff) - | ((x << 8) & 0x00ff0000) - | (x << 24); -} +#if ECB_GCC_VERSION(4,3) + #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_ uint32_t ecb_bswap16 (uint32_t x) ecb_const; + ecb_function_ uint32_t + ecb_bswap16 (uint32_t x) + { + return ((x >> 8) & 0xff) + | ((x << 8) & 0x00ff0000) + | (x << 24); + } + + ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const; + ecb_function_ uint32_t + ecb_bswap32 (uint32_t x) + { + return (x >> 24) + | ((x >> 8) & 0x0000ff00) + | ((x << 8) & 0x00ff0000) + | (x << 24); + } + + ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const; + ecb_function_ uint64_t + ecb_bswap64 (uint64_t x) + { + return (((uint64_t)ecb_bswap32 (x)) << 32) + | ecb_bswap32 (x >> 32); + } #endif #if ECB_GCC_VERSION(4,5) -# define ecb_unreachable() __builtin_unreachable () + #define ecb_unreachable() __builtin_unreachable () #else -/* this seems to work fine, but gcc always emits a warning for it :/ */ -ECB_HEADER_INLINE void ecb_unreachable (void) ecb_noreturn; -ECB_HEADER_INLINE void ecb_unreachable (void) { } + /* this seems to work fine, but gcc always emits a warning for it :/ */ + ecb_function_ void ecb_unreachable (void) ecb_noreturn; + ecb_function_ void ecb_unreachable (void) { } #endif -ECB_HEADER_INLINE unsigned char ecb_byteorder_helper (void) ecb_const; -ECB_HEADER_INLINE unsigned char +/* try to tell the compiler that some condition is definitely true */ +#define ecb_assume(cond) do { if (!(cond)) ecb_unreachable (); } while (0) + +ecb_function_ unsigned char ecb_byteorder_helper (void) ecb_const; +ecb_function_ unsigned char ecb_byteorder_helper (void) { const uint32_t u = 0x11223344; return *(unsigned char *)&u; } -ECB_HEADER_INLINE ecb_bool ecb_big_endian (void) ecb_const; -ECB_HEADER_INLINE ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }; -ECB_HEADER_INLINE ecb_bool ecb_little_endian (void) ecb_const; -ECB_HEADER_INLINE ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }; +ecb_function_ ecb_bool ecb_big_endian (void) ecb_const; +ecb_function_ ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; } +ecb_function_ ecb_bool ecb_little_endian (void) ecb_const; +ecb_function_ ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; } -#if ECB_GCC_VERSION(3,0) -# define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0)) +#if ECB_GCC_VERSION(3,0) || ECB_C99 + #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0)) #else -# define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n))) + #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n))) #endif #if ecb_cplusplus_does_not_suck -// does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) -template<typename T, int N> -static inline int ecb_array_length (const T (&arr)[N]) -{ - return N; -} + /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */ + template<typename T, int N> + static inline int ecb_array_length (const T (&arr)[N]) + { + return N; + } #else -#define ecb_array_length(name) (sizeof (name) / sizeof (name [0])) + #define ecb_array_length(name) (sizeof (name) / sizeof (name [0])) #endif -ECB_INLINE uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const; -ECB_INLINE uint32_t +ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const; +ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); } -ECB_INLINE uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const; -ECB_INLINE uint32_t +ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const; +ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); } +ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const; +ecb_inline uint64_t +ecb_rotr64 (uint64_t x, unsigned int count) +{ + return (x << (64 - count)) | (x >> count); +} + +ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const; +ecb_inline uint64_t +ecb_rotl64 (uint64_t x, unsigned int count) +{ + return (x >> (64 - count)) | (x << count); +} + #endif |