]> mj.ucw.cz Git - libucw.git/blob - lib/unaligned.h
Don't forget to increase run counter.
[libucw.git] / lib / 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(byte *p) { return *(u16 *)p; }
17 static inline u32 get_u32_be(byte *p) { return *(u32 *)p; }
18 static inline u64 get_u64_be(byte *p) { return *(u64 *)p; }
19 static inline void put_u16_be(byte *p, uns x) { *(u16 *)p = x; }
20 static inline void put_u32_be(byte *p, u32 x) { *(u32 *)p = x; }
21 static inline void put_u64_be(byte *p, u64 x) { *(u64 *)p = x; }
22 #else
23 static inline uns get_u16_be(byte *p)
24 {
25   return (p[0] << 8) | p[1];
26 }
27 static inline u32 get_u32_be(byte *p)
28 {
29   return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
30 }
31 static inline u64 get_u64_be(byte *p)
32 {
33   return ((u64) get_u32_be(p) << 32) | get_u32_be(p+4);
34 }
35 static inline void put_u16_be(byte *p, uns x)
36 {
37   p[0] = x >> 8;
38   p[1] = x;
39 }
40 static inline void put_u32_be(byte *p, u32 x)
41 {
42   p[0] = x >> 24;
43   p[1] = x >> 16;
44   p[2] = x >> 8;
45   p[3] = x;
46 }
47 static inline void put_u64_be(byte *p, u64 x)
48 {
49   put_u32_be(p, x >> 32);
50   put_u32_be(p+4, x);
51 }
52 #endif
53
54 /* Little-endian format */
55
56 #if defined(CPU_ALLOW_UNALIGNED) && !defined(CPU_BIG_ENDIAN)
57 static inline uns get_u16_le(byte *p) { return *(u16 *)p; }
58 static inline u32 get_u32_le(byte *p) { return *(u32 *)p; }
59 static inline u64 get_u64_le(byte *p) { return *(u64 *)p; }
60 static inline void put_u16_le(byte *p, uns x) { *(u16 *)p = x; }
61 static inline void put_u32_le(byte *p, u32 x) { *(u32 *)p = x; }
62 static inline void put_u64_le(byte *p, u64 x) { *(u64 *)p = x; }
63 #else
64 static inline uns get_u16_le(byte *p)
65 {
66   return p[0] | (p[1] << 8);
67 }
68 static inline u32 get_u32_le(byte *p)
69 {
70   return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
71 }
72 static inline u64 get_u64_le(byte *p)
73 {
74   return get_u32_le(p) | ((u64) get_u32_le(p+4) << 32);
75 }
76 static inline void put_u16_le(byte *p, uns x)
77 {
78   p[0] = x;
79   p[1] = x >> 8;
80 }
81 static inline void put_u32_le(byte *p, u32 x)
82 {
83   p[0] = x;
84   p[1] = x >> 8;
85   p[2] = x >> 16;
86   p[3] = x >> 24;
87 }
88 static inline void put_u64_le(byte *p, u64 x)
89 {
90   put_u32_le(p, x);
91   put_u32_le(p+4, x >> 32);
92 }
93 #endif
94
95 static inline u64 get_u40_be(byte *p)
96 {
97   return ((u64)p[0] << 32) | get_u32_be(p+1);
98 }
99
100 static inline void put_u40_be(byte *p, u64 x)
101 {
102   p[0] = x >> 32;
103   put_u32_be(p+1, x);
104 }
105
106 static inline u64 get_u40_le(byte *p)
107 {
108   return get_u32_le(p) | ((u64) p[4] << 32);
109 }
110
111 static inline void put_u40_le(byte *p, u64 x)
112 {
113   put_u32_le(p, x);
114   p[4] = x >> 32;
115 }
116
117 /* The native format */
118
119 #ifdef CPU_BIG_ENDIAN
120
121 static inline uns get_u16(byte *p) { return get_u16_be(p); }
122 static inline u32 get_u32(byte *p) { return get_u32_be(p); }
123 static inline u64 get_u64(byte *p) { return get_u64_be(p); }
124 static inline u64 get_u40(byte *p) { return get_u40_be(p); }
125 static inline void put_u16(byte *p, uns x) { return put_u16_be(p, x); }
126 static inline void put_u32(byte *p, u32 x) { return put_u32_be(p, x); }
127 static inline void put_u64(byte *p, u64 x) { return put_u64_be(p, x); }
128 static inline void put_u40(byte *p, u64 x) { return put_u40_be(p, x); }
129
130 #else
131
132 static inline uns get_u16(byte *p) { return get_u16_le(p); }
133 static inline u32 get_u32(byte *p) { return get_u32_le(p); }
134 static inline u64 get_u64(byte *p) { return get_u64_le(p); }
135 static inline u64 get_u40(byte *p) { return get_u40_le(p); }
136 static inline void put_u16(byte *p, uns x) { return put_u16_le(p, x); }
137 static inline void put_u32(byte *p, u32 x) { return put_u32_le(p, x); }
138 static inline void put_u64(byte *p, u64 x) { return put_u64_le(p, x); }
139 static inline void put_u40(byte *p, u64 x) { return put_u40_le(p, x); }
140
141 #endif
142
143 /* Just for completeness */
144
145 static inline uns get_u8(byte *p) { return *p; }
146 static inline void put_u8(byte *p, uns x) { *p = x; }
147
148 /* Backward compatibility macros */
149
150 #define GET_U8(p) get_u8((byte*)(p))
151 #define GET_U16(p) get_u16((byte*)(p))
152 #define GET_U32(p) get_u32((byte*)(p))
153 #define GET_U64(p) get_u64((byte*)(p))
154 #define GET_U40(p) get_u40((byte*)(p))
155
156 #define PUT_U8(p,x) put_u8((byte*)(p),x);
157 #define PUT_U16(p,x) put_u16((byte*)(p),x)
158 #define PUT_U32(p,x) put_u32((byte*)p,x)
159 #define PUT_U64(p,x) put_u64((byte*)p,x)
160 #define PUT_U40(p,x) put_u40((byte*)p,x)
161
162 #endif