spandsp  3.0.0
unaligned.h
Go to the documentation of this file.
1 /*
2  * SpanDSP - a series of DSP components for telephony
3  *
4  * unaligned.h - Cross platform unaligned data access
5  *
6  * Written by Steve Underwood <steveu@coppice.org>
7  *
8  * Copyright (C) 2006, 2022 Steve Underwood
9  *
10  * All rights reserved.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2, as
14  * published by the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 /*! \file */
27 
28 #if !defined(_SPANDSP_UNALIGNED_H_)
29 #define _SPANDSP_UNALIGNED_H_
30 
31 #if defined(__cplusplus)
32 extern "C"
33 {
34 #endif
35 
36 #if defined(_MSC_VER)
37 #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
38 
39 PACK(struct __dealign_uint16 { uint16_t datum; };)
40 PACK(struct __dealign_uint32 { uint32_t datum; };)
41 PACK(struct __dealign_uint64 { uint64_t datum; };)
42 #endif
43 
44 #if defined(__GNUC__) || defined(__clang__)
45 struct __dealign_uint16 { uint16_t datum; } __attribute__((packed));
46 struct __dealign_uint32 { uint32_t datum; } __attribute__((packed));
47 struct __dealign_uint64 { uint64_t datum; } __attribute__((packed));
48 #endif
49 
50 #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
51 /* If we just tell GCC what's going on, we can trust it to behave optimally */
52 static __inline__ uint64_t get_unaligned_uint64(const void *p)
53 {
54  const struct __dealign_uint64 *pp = (const struct __dealign_uint64 *) p;
55 
56  return pp->datum;
57 }
58 /*- End of function --------------------------------------------------------*/
59 
60 static __inline__ void put_unaligned_uint64(void *p, uint32_t datum)
61 {
62  struct __dealign_uint64 *pp = (struct __dealign_uint64 *) p;
63 
64  pp->datum = datum;
65 }
66 /*- End of function --------------------------------------------------------*/
67 
68 static __inline__ uint64_t get_net_unaligned_uint64(const void *p)
69 {
70  const struct __dealign_uint64 *pp = (const struct __dealign_uint64 *) p;
71 
72 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
73  return pp->datum;
74 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
75  return __builtin_bswap64(pp->datum);
76 #endif
77 }
78 /*- End of function --------------------------------------------------------*/
79 
80 static __inline__ void put_net_unaligned_uint64(void *p, uint64_t datum)
81 {
82  struct __dealign_uint64 *pp = (struct __dealign_uint64 *) p;
83 
84 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
85  pp->datum = datum;
86 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
87  pp->datum = __builtin_bswap64(datum);
88 #endif
89 }
90 /*- End of function --------------------------------------------------------*/
91 
92 static __inline__ uint32_t get_unaligned_uint32(const void *p)
93 {
94  const struct __dealign_uint32 *pp = (const struct __dealign_uint32 *) p;
95 
96  return pp->datum;
97 }
98 /*- End of function --------------------------------------------------------*/
99 
100 static __inline__ void put_unaligned_uint32(void *p, uint32_t datum)
101 {
102  struct __dealign_uint32 *pp = (struct __dealign_uint32 *) p;
103 
104  pp->datum = datum;
105 }
106 /*- End of function --------------------------------------------------------*/
107 
108 static __inline__ uint32_t get_net_unaligned_uint32(const void *p)
109 {
110  const struct __dealign_uint32 *pp = (const struct __dealign_uint32 *) p;
111 
112 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
113  return pp->datum;
114 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
115  return __builtin_bswap32(pp->datum);
116 #endif
117 }
118 /*- End of function --------------------------------------------------------*/
119 
120 static __inline__ void put_net_unaligned_uint32(void *p, uint32_t datum)
121 {
122  struct __dealign_uint32 *pp = (struct __dealign_uint32 *) p;
123 
124 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
125  pp->datum = datum;
126 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
127  pp->datum = __builtin_bswap32(datum);
128 #endif
129 }
130 /*- End of function --------------------------------------------------------*/
131 
132 static __inline__ uint16_t get_unaligned_uint16(const void *p)
133 {
134  const struct __dealign_uint16 *pp = (const struct __dealign_uint16 *) p;
135 
136  return pp->datum;
137 }
138 /*- End of function --------------------------------------------------------*/
139 
140 static __inline__ void put_unaligned_uint16(void *p, uint16_t datum)
141 {
142  struct __dealign_uint16 *pp = (struct __dealign_uint16 *) p;
143 
144  pp->datum = datum;
145 }
146 /*- End of function --------------------------------------------------------*/
147 
148 static __inline__ uint16_t get_net_unaligned_uint16(const void *p)
149 {
150  const struct __dealign_uint16 *pp = (const struct __dealign_uint16 *) p;
151 
152 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
153  return pp->datum;
154 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
155  return __builtin_bswap16(pp->datum);
156 #endif
157 }
158 /*- End of function --------------------------------------------------------*/
159 
160 static __inline__ void put_net_unaligned_uint16(void *p, uint16_t datum)
161 {
162  struct __dealign_uint16 *pp = (struct __dealign_uint16 *) p;
163 
164 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
165  pp->datum = datum;
166 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
167  pp->datum = __builtin_bswap16(datum);
168 #endif
169 }
170 /*- End of function --------------------------------------------------------*/
171 
172 #elif defined(SOLARIS) && defined(__sparc__)
173 
174 static __inline__ uint64_t get_unaligned_uint64(const void *p)
175 {
176  const uint8_t *cp = p;
177 
178  return (cp[0] << 56) | (cp[1] << 48) | (cp[2] << 40) | (cp[3] << 32) | (cp[4] << 24) | (cp[5] << 16) | (cp[6] << 8) | cp[7];
179 }
180 /*- End of function --------------------------------------------------------*/
181 
182 static __inline__ void put_unaligned_uint64(void *p, uint64_t datum)
183 {
184  const uint8_t *cp = p;
185 
186  cp[0] = datum >> 56;
187  cp[1] = datum >> 48;
188  cp[2] = datum >> 40;
189  cp[3] = datum >> 32;
190  cp[4] = datum >> 24;
191  cp[5] = datum >> 16;
192  cp[6] = datum >> 8;
193  cp[7] = datum;
194 }
195 /*- End of function --------------------------------------------------------*/
196 
197 static __inline__ uint32_t get_unaligned_uint32(const void *p)
198 {
199  const uint8_t *cp = p;
200 
201  return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
202 }
203 /*- End of function --------------------------------------------------------*/
204 
205 static __inline__ void put_unaligned_uint32(void *p, uint32_t datum)
206 {
207  const uint8_t *cp = p;
208 
209  cp[0] = datum >> 24;
210  cp[1] = datum >> 16;
211  cp[2] = datum >> 8;
212  cp[3] = datum;
213 }
214 /*- End of function --------------------------------------------------------*/
215 
216 static __inline__ uint16_t get_unaligned_uint16(const void *p)
217 {
218  const uint8_t *cp = p;
219 
220  return (cp[0] << 8) | cp[1];
221 }
222 /*- End of function --------------------------------------------------------*/
223 
224 static __inline__ void put_unaligned_uint16(void *p, uint16_t datum)
225 {
226  uint8_t *cp = p;
227 
228  cp[0] = datum >> 8;
229  cp[1] = datum;
230 }
231 /*- End of function --------------------------------------------------------*/
232 
233 #else
234 
235 /* The generic case. Assume we can handle direct load/store. */
236 #define get_unaligned_uint64(p) (*((uint64_t *) (p)))
237 #define put_unaligned_uint64(p,d) do { uint64_t *__P = (p); *__P = d; } while(0)
238 #define get_net_unaligned_uint64(p) (*((uint64_t *) (p)))
239 #define put_net_unaligned_uint64(p,d) do { uint64_t *__P = (p); *__P = d; } while(0)
240 #define get_unaligned_uint32(p) (*((uint32_t *) (p)))
241 #define put_unaligned_uint32(p,d) do { uint32_t *__P = (p); *__P = d; } while(0)
242 #define get_net_unaligned_uint32(p) (*((uint32_t *) (p)))
243 #define put_net_unaligned_uint32(p,d) do { uint32_t *__P = (p); *__P = d; } while(0)
244 #define get_unaligned_uint16(p) (*((uint16_t *) (p)))
245 #define put_unaligned_uint16(p,d) do { uint16_t *__P = (p); *__P = d; } while(0)
246 #define get_net_unaligned_uint16(p) (*((uint16_t *) (p)))
247 #define put_net_unaligned_uint16(p,d) do { uint16_t *__P = (p); *__P = d; } while(0)
248 #endif
249 
250 #if defined(__cplusplus)
251 }
252 #endif
253 
254 #endif
255 /*- End of file ------------------------------------------------------------*/