X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Funaligned.h;h=62a6643da4f0315829b8c8004be4520545b2357b;hb=ed4e86de76d1c3bfb685207fe00078950f67355a;hp=a3908b0a9e31747ddfa197aee0aaff9b05accfe7;hpb=f484eae8dd0221b738f885f6ee1eaf6130dbe676;p=libucw.git diff --git a/lib/unaligned.h b/lib/unaligned.h index a3908b0a..62a6643d 100644 --- a/lib/unaligned.h +++ b/lib/unaligned.h @@ -1,44 +1,174 @@ /* - * Sherlock Library -- Fast Access to Unaligned Data + * UCW Library -- Fast Access to Unaligned Data * - * (c) 1997--2001 Martin Mares + * (c) 1997--2007 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. */ -#ifndef _SHERLOCK_UNALIGNED_H -#define _SHERLOCK_UNALIGNED_H - -#ifdef CPU_ALLOW_UNALIGNED -#define GET_U16(p) (*((u16 *)(p))) -#define GET_U32(p) (*((u32 *)(p))) -#define GET_U32_16(p) (*((u32 *)(p))) -#define GET_U64(p) (*((u64 *)(p))) -#define PUT_U16(p,x) *((u16 *)(p)) = (x) -#define PUT_U32(p,x) *((u32 *)(p)) = (x) -#define PUT_U64(p,x) *((u64 *)(p)) = (x) -#else -#define GET_U64(p) ({ u64 _x; memcpy(&_x, p, 8); _x; }) -#define PUT_U64(p,x) do { u64 _x=x; memcpy(p, &_x, 8); } while(0) -#ifdef CPU_BIG_ENDIAN -#define GET_U16(p) (((p)[0] << 8) | (p)[1]) -#define GET_U32(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3]) -#define PUT_U16(p,x) (void)(((p)[0] = ((x) >> 8)), (((p)[1]) = (x))) -#define PUT_U32(p,x) (void)(((p)[0] = ((x) >> 24)), (((p)[1]) = ((x) >> 16)), (((p)[2]) = ((x) >> 8)), (((p)[3]) = (x))) +#ifndef _UCW_UNALIGNED_H +#define _UCW_UNALIGNED_H + +/* Big endian format */ + +#if defined(CPU_ALLOW_UNALIGNED) && defined(CPU_BIG_ENDIAN) +static inline uns get_u16_be(const void *p) { return *(u16 *)p; } +static inline u32 get_u32_be(const void *p) { return *(u32 *)p; } +static inline u64 get_u64_be(const void *p) { return *(u64 *)p; } +static inline void put_u16_be(void *p, uns x) { *(u16 *)p = x; } +static inline void put_u32_be(void *p, u32 x) { *(u32 *)p = x; } +static inline void put_u64_be(void *p, u64 x) { *(u64 *)p = x; } #else -#define GET_U16(p) (((p)[1] << 8) | (p)[0]) -#define GET_U32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0]) -#define PUT_U16(p,x) (void)(((p)[1] = ((x) >> 8)), (((p)[0]) = (x))) -#define PUT_U32(p,x) (void)(((p)[3] = ((x) >> 24)), (((p)[2]) = ((x) >> 16)), (((p)[1]) = ((x) >> 8)), (((p)[0]) = (x))) +static inline uns get_u16_be(const void *p) +{ + const byte *c = p; + return (c[0] << 8) | c[1]; +} +static inline u32 get_u32_be(const void *p) +{ + const byte *c = p; + return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +static inline u64 get_u64_be(const void *p) +{ + return ((u64) get_u32_be(p) << 32) | get_u32_be((const byte *)p+4); +} +static inline void put_u16_be(void *p, uns x) +{ + byte *c = p; + c[0] = x >> 8; + c[1] = x; +} +static inline void put_u32_be(void *p, u32 x) +{ + byte *c = p; + c[0] = x >> 24; + c[1] = x >> 16; + c[2] = x >> 8; + c[3] = x; +} +static inline void put_u64_be(void *p, u64 x) +{ + put_u32_be(p, x >> 32); + put_u32_be((byte *)p+4, x); +} #endif + +/* Little-endian format */ + +#if defined(CPU_ALLOW_UNALIGNED) && !defined(CPU_BIG_ENDIAN) +static inline uns get_u16_le(const void *p) { return *(u16 *)p; } +static inline u32 get_u32_le(const void *p) { return *(u32 *)p; } +static inline u64 get_u64_le(const void *p) { return *(u64 *)p; } +static inline void put_u16_le(void *p, uns x) { *(u16 *)p = x; } +static inline void put_u32_le(void *p, u32 x) { *(u32 *)p = x; } +static inline void put_u64_le(void *p, u64 x) { *(u64 *)p = x; } +#else +static inline uns get_u16_le(const void *p) +{ + const byte *c = p; + return c[0] | (c[1] << 8); +} +static inline u32 get_u32_le(const void *p) +{ + const byte *c = p; + return c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); +} +static inline u64 get_u64_le(const void *p) +{ + return get_u32_le(p) | ((u64) get_u32_le((const byte *)p+4) << 32); +} +static inline void put_u16_le(void *p, uns x) +{ + byte *c = p; + c[0] = x; + c[1] = x >> 8; +} +static inline void put_u32_le(void *p, u32 x) +{ + byte *c = p; + c[0] = x; + c[1] = x >> 8; + c[2] = x >> 16; + c[3] = x >> 24; +} +static inline void put_u64_le(void *p, u64 x) +{ + put_u32_le(p, x); + put_u32_le((byte *)p+4, x >> 32); +} #endif -#define GET_U32_BE16(p) (((p)[0] << 16) | (p)[1]) +static inline u64 get_u40_be(const void *p) +{ + const byte *c = p; + return ((u64)c[0] << 32) | get_u32_be(c+1); +} + +static inline void put_u40_be(void *p, u64 x) +{ + byte *c = p; + c[0] = x >> 32; + put_u32_be(c+1, x); +} + +static inline u64 get_u40_le(const void *p) +{ + const byte *c = p; + return get_u32_le(c) | ((u64) c[4] << 32); +} + +static inline void put_u40_le(void *p, u64 x) +{ + byte *c = p; + put_u32_le(c, x); + c[4] = x >> 32; +} + +/* The native format */ #ifdef CPU_BIG_ENDIAN -#define GET_U40(p) (((u64) (p)[0] << 32) | GET_U32((p)+1)) -#define PUT_U40(p,x) do { (p)[0] = ((x) >> 32); PUT_U32(((p)+1), x); } while(0) + +static inline uns get_u16(const void *p) { return get_u16_be(p); } +static inline u32 get_u32(const void *p) { return get_u32_be(p); } +static inline u64 get_u64(const void *p) { return get_u64_be(p); } +static inline u64 get_u40(const void *p) { return get_u40_be(p); } +static inline void put_u16(void *p, uns x) { return put_u16_be(p, x); } +static inline void put_u32(void *p, u32 x) { return put_u32_be(p, x); } +static inline void put_u64(void *p, u64 x) { return put_u64_be(p, x); } +static inline void put_u40(void *p, u64 x) { return put_u40_be(p, x); } + #else -#define GET_U40(p) (((u64) (p)[4] << 32) | GET_U32(p)) -#define PUT_U40(p,x) do { (p)[4] = ((x) >> 32); PUT_U32(p, x); } while(0) + +static inline uns get_u16(const void *p) { return get_u16_le(p); } +static inline u32 get_u32(const void *p) { return get_u32_le(p); } +static inline u64 get_u64(const void *p) { return get_u64_le(p); } +static inline u64 get_u40(const void *p) { return get_u40_le(p); } +static inline void put_u16(void *p, uns x) { return put_u16_le(p, x); } +static inline void put_u32(void *p, u32 x) { return put_u32_le(p, x); } +static inline void put_u64(void *p, u64 x) { return put_u64_le(p, x); } +static inline void put_u40(void *p, u64 x) { return put_u40_le(p, x); } + #endif +/* Just for completeness */ + +static inline uns get_u8(const void *p) { return *(const byte *)p; } +static inline void put_u8(void *p, uns x) { *(byte *)p = x; } + +/* Backward compatibility macros */ + +#define GET_U8(p) get_u8(p) +#define GET_U16(p) get_u16(p) +#define GET_U32(p) get_u32(p) +#define GET_U64(p) get_u64(p) +#define GET_U40(p) get_u40(p) + +#define PUT_U8(p,x) put_u8(p,x); +#define PUT_U16(p,x) put_u16(p,x) +#define PUT_U32(p,x) put_u32(p,x) +#define PUT_U64(p,x) put_u64(p,x) +#define PUT_U40(p,x) put_u40(p,x) + #endif