]> mj.ucw.cz Git - libucw.git/blob - ucw/unaligned.h
libucw: Implemented Loging.Stream.FileDesc.
[libucw.git] / ucw / unaligned.h
1 /*
2  *      UCW Library -- Fast Access to Unaligned Data
3  *
4  *      (c) 1997--2007 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef _UCW_UNALIGNED_H
11 #define _UCW_UNALIGNED_H
12
13 /* Big endian format */
14
15 #if defined(CPU_ALLOW_UNALIGNED) && defined(CPU_BIG_ENDIAN)
16 static inline uns get_u16_be(const void *p) { return *(u16 *)p; } /** Read 16-bit integer value from an unaligned sequence of 2 bytes (big-endian version). **/
17 static inline u32 get_u32_be(const void *p) { return *(u32 *)p; } /** Read 32-bit integer value from an unaligned sequence of 4 bytes (big-endian version). **/
18 static inline u64 get_u64_be(const void *p) { return *(u64 *)p; } /** Read 64-bit integer value from an unaligned sequence of 8 bytes (big-endian version). **/
19 static inline void put_u16_be(void *p, uns x) { *(u16 *)p = x; } /** Write 16-bit integer value to an unaligned sequence of 2 bytes (big-endian version). **/
20 static inline void put_u32_be(void *p, u32 x) { *(u32 *)p = x; } /** Write 32-bit integer value to an unaligned sequence of 4 bytes (big-endian version). **/
21 static inline void put_u64_be(void *p, u64 x) { *(u64 *)p = x; } /** Write 64-bit integer value to an unaligned sequence of 8 bytes (big-endian version). **/
22 #else
23 static inline uns get_u16_be(const void *p)
24 {
25   const byte *c = (const byte *)p;
26   return (c[0] << 8) | c[1];
27 }
28 static inline u32 get_u32_be(const void *p)
29 {
30   const byte *c = (const byte *)p;
31   return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
32 }
33 static inline u64 get_u64_be(const void *p)
34 {
35   return ((u64) get_u32_be(p) << 32) | get_u32_be((const byte *)p+4);
36 }
37 static inline void put_u16_be(void *p, uns x)
38 {
39   byte *c = (byte *)p;
40   c[0] = x >> 8;
41   c[1] = x;
42 }
43 static inline void put_u32_be(void *p, u32 x)
44 {
45   byte *c = (byte *)p;
46   c[0] = x >> 24;
47   c[1] = x >> 16;
48   c[2] = x >> 8;
49   c[3] = x;
50 }
51 static inline void put_u64_be(void *p, u64 x)
52 {
53   put_u32_be(p, x >> 32);
54   put_u32_be((byte *)p+4, x);
55 }
56 #endif
57
58 static inline u64 get_u40_be(const void *p) /** Read 40-bit integer value from an unaligned sequence of 5 bytes (big-endian version). **/
59 {
60   const byte *c = (const byte *)p;
61   return ((u64)c[0] << 32) | get_u32_be(c+1);
62 }
63
64 static inline void put_u40_be(void *p, u64 x)
65 {
66   byte *c = (byte *)p;
67   c[0] = x >> 32;
68   put_u32_be(c+1, x);
69 }
70
71 /* Little-endian format */
72
73 #if defined(CPU_ALLOW_UNALIGNED) && !defined(CPU_BIG_ENDIAN)
74 static inline uns get_u16_le(const void *p) { return *(u16 *)p; } /** Read 16-bit integer value from an unaligned sequence of 2 bytes (little-endian version). **/
75 static inline u32 get_u32_le(const void *p) { return *(u32 *)p; } /** Read 32-bit integer value from an unaligned sequence of 4 bytes (little-endian version). **/
76 static inline u64 get_u64_le(const void *p) { return *(u64 *)p; } /** Read 64-bit integer value from an unaligned sequence of 8 bytes (little-endian version). **/
77 static inline void put_u16_le(void *p, uns x) { *(u16 *)p = x; } /** Write 16-bit integer value to an unaligned sequence of 2 bytes (little-endian version). **/
78 static inline void put_u32_le(void *p, u32 x) { *(u32 *)p = x; } /** Write 32-bit integer value to an unaligned sequence of 4 bytes (little-endian version). **/
79 static inline void put_u64_le(void *p, u64 x) { *(u64 *)p = x; } /** Write 64-bit integer value to an unaligned sequence of 8 bytes (little-endian version). **/
80 #else
81 static inline uns get_u16_le(const void *p)
82 {
83   const byte *c = p;
84   return c[0] | (c[1] << 8);
85 }
86 static inline u32 get_u32_le(const void *p)
87 {
88   const byte *c = p;
89   return c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
90 }
91 static inline u64 get_u64_le(const void *p)
92 {
93   return get_u32_le(p) | ((u64) get_u32_le((const byte *)p+4) << 32);
94 }
95 static inline void put_u16_le(void *p, uns x)
96 {
97   byte *c = p;
98   c[0] = x;
99   c[1] = x >> 8;
100 }
101 static inline void put_u32_le(void *p, u32 x)
102 {
103   byte *c = p;
104   c[0] = x;
105   c[1] = x >> 8;
106   c[2] = x >> 16;
107   c[3] = x >> 24;
108 }
109 static inline void put_u64_le(void *p, u64 x)
110 {
111   put_u32_le(p, x);
112   put_u32_le((byte *)p+4, x >> 32);
113 }
114 #endif
115
116 static inline u64 get_u40_le(const void *p) /** Read 40-bit integer value from an unaligned sequence of 5 bytes (little-endian version). **/
117 {
118   const byte *c = (const byte *)p;
119   return get_u32_le(c) | ((u64) c[4] << 32);
120 }
121
122 static inline void put_u40_le(void *p, u64 x)
123 {
124   byte *c = (byte *)p;
125   put_u32_le(c, x);
126   c[4] = x >> 32;
127 }
128
129 /* The native format */
130
131 #ifdef CPU_BIG_ENDIAN
132
133 static inline uns get_u16(const void *p) { return get_u16_be(p); } /** Read 16-bit integer value from an unaligned sequence of 2 bytes (native byte-order). **/
134 static inline u32 get_u32(const void *p) { return get_u32_be(p); } /** Read 32-bit integer value from an unaligned sequence of 4 bytes (native byte-order). **/
135 static inline u64 get_u64(const void *p) { return get_u64_be(p); } /** Read 64-bit integer value from an unaligned sequence of 8 bytes (native byte-order). **/
136 static inline u64 get_u40(const void *p) { return get_u40_be(p); } /** Read 40-bit integer value from an unaligned sequence of 5 bytes (native byte-order). **/
137 static inline void put_u16(void *p, uns x) { return put_u16_be(p, x); } /** Write 16-bit integer value to an unaligned sequence of 2 bytes (native byte-order). **/
138 static inline void put_u32(void *p, u32 x) { return put_u32_be(p, x); } /** Write 32-bit integer value to an unaligned sequence of 4 bytes (native byte-order). **/
139 static inline void put_u64(void *p, u64 x) { return put_u64_be(p, x); } /** Write 64-bit integer value to an unaligned sequence of 8 bytes (native byte-order). **/
140 static inline void put_u40(void *p, u64 x) { return put_u40_be(p, x); } /** Write 40-bit integer value to an unaligned sequence of 5 bytes (native byte-order). **/
141
142 #else
143
144 static inline uns get_u16(const void *p) { return get_u16_le(p); }
145 static inline u32 get_u32(const void *p) { return get_u32_le(p); }
146 static inline u64 get_u64(const void *p) { return get_u64_le(p); }
147 static inline u64 get_u40(const void *p) { return get_u40_le(p); }
148 static inline void put_u16(void *p, uns x) { return put_u16_le(p, x); }
149 static inline void put_u32(void *p, u32 x) { return put_u32_le(p, x); }
150 static inline void put_u64(void *p, u64 x) { return put_u64_le(p, x); }
151 static inline void put_u40(void *p, u64 x) { return put_u40_le(p, x); }
152
153 #endif
154
155 /* Just for completeness */
156
157 static inline uns get_u8(const void *p) { return *(const byte *)p; } /** Read 8-bit integer value. **/
158 static inline void put_u8(void *p, uns x) { *(byte *)p = x; } /** Write 8-bit integer value. **/
159
160 /* Backward compatibility macros */
161
162 #define GET_U8(p) get_u8(p)
163 #define GET_U16(p) get_u16(p)
164 #define GET_U32(p) get_u32(p)
165 #define GET_U64(p) get_u64(p)
166 #define GET_U40(p) get_u40(p)
167
168 #define PUT_U8(p,x) put_u8(p,x);
169 #define PUT_U16(p,x) put_u16(p,x)
170 #define PUT_U32(p,x) put_u32(p,x)
171 #define PUT_U64(p,x) put_u64(p,x)
172 #define PUT_U40(p,x) put_u40(p,x)
173
174 #endif