]> mj.ucw.cz Git - libucw.git/blobdiff - lib/unaligned.h
Merge with git+ssh://git.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / lib / unaligned.h
index a3908b0a9e31747ddfa197aee0aaff9b05accfe7..62a6643da4f0315829b8c8004be4520545b2357b 100644 (file)
 /*
- *     Sherlock Library -- Fast Access to Unaligned Data
+ *     UCW Library -- Fast Access to Unaligned Data
  *
- *     (c) 1997--2001 Martin Mares <mj@ucw.cz>
+ *     (c) 1997--2007 Martin Mares <mj@ucw.cz>
+ *
+ *     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