xref: /aosp_15_r20/external/sg3_utils/include/sg_unaligned.h (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1*44704f69SBart Van Assche #ifndef SG_UNALIGNED_H
2*44704f69SBart Van Assche #define SG_UNALIGNED_H
3*44704f69SBart Van Assche 
4*44704f69SBart Van Assche /*
5*44704f69SBart Van Assche  * Copyright (c) 2014-2018 Douglas Gilbert.
6*44704f69SBart Van Assche  * All rights reserved.
7*44704f69SBart Van Assche  * Use of this source code is governed by a BSD-style
8*44704f69SBart Van Assche  * license that can be found in the BSD_LICENSE file.
9*44704f69SBart Van Assche  *
10*44704f69SBart Van Assche  * SPDX-License-Identifier: BSD-2-Clause
11*44704f69SBart Van Assche  */
12*44704f69SBart Van Assche 
13*44704f69SBart Van Assche #include <stdbool.h>
14*44704f69SBart Van Assche #include <stdint.h>     /* for uint8_t and friends */
15*44704f69SBart Van Assche #include <string.h>     /* for memcpy */
16*44704f69SBart Van Assche 
17*44704f69SBart Van Assche #ifdef __cplusplus
18*44704f69SBart Van Assche extern "C" {
19*44704f69SBart Van Assche #endif
20*44704f69SBart Van Assche 
21*44704f69SBart Van Assche /* These inline functions convert integers (always unsigned) to byte streams
22*44704f69SBart Van Assche  * and vice versa. They have two goals:
23*44704f69SBart Van Assche  *   - change the byte ordering of integers between host order and big
24*44704f69SBart Van Assche  *     endian ("_be") or little endian ("_le")
25*44704f69SBart Van Assche  *   - copy the big or little endian byte stream so it complies with any
26*44704f69SBart Van Assche  *     alignment that host integers require
27*44704f69SBart Van Assche  *
28*44704f69SBart Van Assche  * Host integer to given endian byte stream is a "_put_" function taking
29*44704f69SBart Van Assche  * two arguments (integer and pointer to byte stream) returning void.
30*44704f69SBart Van Assche  * Given endian byte stream to host integer is a "_get_" function that takes
31*44704f69SBart Van Assche  * one argument and returns an integer of appropriate size (uint32_t for 24
32*44704f69SBart Van Assche  * bit operations, uint64_t for 48 bit operations).
33*44704f69SBart Van Assche  *
34*44704f69SBart Van Assche  * Big endian byte format "on the wire" is the default used by SCSI
35*44704f69SBart Van Assche  * standards (www.t10.org). Big endian is also the network byte order.
36*44704f69SBart Van Assche  * Little endian is used by ATA, PCI and NVMe.
37*44704f69SBart Van Assche  */
38*44704f69SBart Van Assche 
39*44704f69SBart Van Assche /* The generic form of these routines was borrowed from the Linux kernel,
40*44704f69SBart Van Assche  * via mhvtl. There is a specialised version of the main functions for
41*44704f69SBart Van Assche  * little endian or big endian provided that not-quite-standard defines for
42*44704f69SBart Van Assche  * endianness are available from the compiler and the <byteswap.h> header
43*44704f69SBart Van Assche  * (a GNU extension) has been detected by ./configure . To force the
44*44704f69SBart Van Assche  * generic version, use './configure --disable-fast-lebe ' . */
45*44704f69SBart Van Assche 
46*44704f69SBart Van Assche /* Note: Assumes that the source and destination locations do not overlap.
47*44704f69SBart Van Assche  * An example of overlapping source and destination:
48*44704f69SBart Van Assche  *     sg_put_unaligned_le64(j, ((uint8_t *)&j) + 1);
49*44704f69SBart Van Assche  * Best not to do things like that.
50*44704f69SBart Van Assche  */
51*44704f69SBart Van Assche 
52*44704f69SBart Van Assche 
53*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
54*44704f69SBart Van Assche #include "config.h"     /* need this to see if HAVE_BYTESWAP_H */
55*44704f69SBart Van Assche #endif
56*44704f69SBart Van Assche 
57*44704f69SBart Van Assche #undef GOT_UNALIGNED_SPECIALS   /* just in case */
58*44704f69SBart Van Assche 
59*44704f69SBart Van Assche #if defined(__BYTE_ORDER__) && defined(HAVE_BYTESWAP_H) && \
60*44704f69SBart Van Assche     ! defined(IGNORE_FAST_LEBE)
61*44704f69SBart Van Assche 
62*44704f69SBart Van Assche #if defined(__LITTLE_ENDIAN__) || (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
63*44704f69SBart Van Assche 
64*44704f69SBart Van Assche #define GOT_UNALIGNED_SPECIALS 1
65*44704f69SBart Van Assche 
66*44704f69SBart Van Assche #include <byteswap.h>           /* for bswap_16(), bswap_32() and bswap_64() */
67*44704f69SBart Van Assche 
68*44704f69SBart Van Assche // #warning ">>>>>> Doing Little endian special unaligneds"
69*44704f69SBart Van Assche 
sg_get_unaligned_be16(const void * p)70*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_be16(const void *p)
71*44704f69SBart Van Assche {
72*44704f69SBart Van Assche         uint16_t u;
73*44704f69SBart Van Assche 
74*44704f69SBart Van Assche         memcpy(&u, p, 2);
75*44704f69SBart Van Assche         return bswap_16(u);
76*44704f69SBart Van Assche }
77*44704f69SBart Van Assche 
sg_get_unaligned_be32(const void * p)78*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_be32(const void *p)
79*44704f69SBart Van Assche {
80*44704f69SBart Van Assche         uint32_t u;
81*44704f69SBart Van Assche 
82*44704f69SBart Van Assche         memcpy(&u, p, 4);
83*44704f69SBart Van Assche         return bswap_32(u);
84*44704f69SBart Van Assche }
85*44704f69SBart Van Assche 
sg_get_unaligned_be64(const void * p)86*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_be64(const void *p)
87*44704f69SBart Van Assche {
88*44704f69SBart Van Assche         uint64_t u;
89*44704f69SBart Van Assche 
90*44704f69SBart Van Assche         memcpy(&u, p, 8);
91*44704f69SBart Van Assche         return bswap_64(u);
92*44704f69SBart Van Assche }
93*44704f69SBart Van Assche 
sg_put_unaligned_be16(uint16_t val,void * p)94*44704f69SBart Van Assche static inline void sg_put_unaligned_be16(uint16_t val, void *p)
95*44704f69SBart Van Assche {
96*44704f69SBart Van Assche         uint16_t u = bswap_16(val);
97*44704f69SBart Van Assche 
98*44704f69SBart Van Assche         memcpy(p, &u, 2);
99*44704f69SBart Van Assche }
100*44704f69SBart Van Assche 
sg_put_unaligned_be32(uint32_t val,void * p)101*44704f69SBart Van Assche static inline void sg_put_unaligned_be32(uint32_t val, void *p)
102*44704f69SBart Van Assche {
103*44704f69SBart Van Assche         uint32_t u = bswap_32(val);
104*44704f69SBart Van Assche 
105*44704f69SBart Van Assche         memcpy(p, &u, 4);
106*44704f69SBart Van Assche }
107*44704f69SBart Van Assche 
sg_put_unaligned_be64(uint64_t val,void * p)108*44704f69SBart Van Assche static inline void sg_put_unaligned_be64(uint64_t val, void *p)
109*44704f69SBart Van Assche {
110*44704f69SBart Van Assche         uint64_t u = bswap_64(val);
111*44704f69SBart Van Assche 
112*44704f69SBart Van Assche         memcpy(p, &u, 8);
113*44704f69SBart Van Assche }
114*44704f69SBart Van Assche 
sg_get_unaligned_le16(const void * p)115*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_le16(const void *p)
116*44704f69SBart Van Assche {
117*44704f69SBart Van Assche         uint16_t u;
118*44704f69SBart Van Assche 
119*44704f69SBart Van Assche         memcpy(&u, p, 2);
120*44704f69SBart Van Assche         return u;
121*44704f69SBart Van Assche }
122*44704f69SBart Van Assche 
sg_get_unaligned_le32(const void * p)123*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_le32(const void *p)
124*44704f69SBart Van Assche {
125*44704f69SBart Van Assche         uint32_t u;
126*44704f69SBart Van Assche 
127*44704f69SBart Van Assche         memcpy(&u, p, 4);
128*44704f69SBart Van Assche         return u;
129*44704f69SBart Van Assche }
130*44704f69SBart Van Assche 
sg_get_unaligned_le64(const void * p)131*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_le64(const void *p)
132*44704f69SBart Van Assche {
133*44704f69SBart Van Assche         uint64_t u;
134*44704f69SBart Van Assche 
135*44704f69SBart Van Assche         memcpy(&u, p, 8);
136*44704f69SBart Van Assche         return u;
137*44704f69SBart Van Assche }
138*44704f69SBart Van Assche 
sg_put_unaligned_le16(uint16_t val,void * p)139*44704f69SBart Van Assche static inline void sg_put_unaligned_le16(uint16_t val, void *p)
140*44704f69SBart Van Assche {
141*44704f69SBart Van Assche         memcpy(p, &val, 2);
142*44704f69SBart Van Assche }
143*44704f69SBart Van Assche 
sg_put_unaligned_le32(uint32_t val,void * p)144*44704f69SBart Van Assche static inline void sg_put_unaligned_le32(uint32_t val, void *p)
145*44704f69SBart Van Assche {
146*44704f69SBart Van Assche         memcpy(p, &val, 4);
147*44704f69SBart Van Assche }
148*44704f69SBart Van Assche 
sg_put_unaligned_le64(uint64_t val,void * p)149*44704f69SBart Van Assche static inline void sg_put_unaligned_le64(uint64_t val, void *p)
150*44704f69SBart Van Assche {
151*44704f69SBart Van Assche         memcpy(p, &val, 8);
152*44704f69SBart Van Assche }
153*44704f69SBart Van Assche 
154*44704f69SBart Van Assche #elif defined(__BIG_ENDIAN__) || (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
155*44704f69SBart Van Assche 
156*44704f69SBart Van Assche #define GOT_UNALIGNED_SPECIALS 1
157*44704f69SBart Van Assche 
158*44704f69SBart Van Assche #include <byteswap.h>
159*44704f69SBart Van Assche 
160*44704f69SBart Van Assche // #warning ">>>>>> Doing BIG endian special unaligneds"
161*44704f69SBart Van Assche 
162*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_le16(const void *p)
163*44704f69SBart Van Assche {
164*44704f69SBart Van Assche         uint16_t u;
165*44704f69SBart Van Assche 
166*44704f69SBart Van Assche         memcpy(&u, p, 2);
167*44704f69SBart Van Assche         return bswap_16(u);
168*44704f69SBart Van Assche }
169*44704f69SBart Van Assche 
170*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_le32(const void *p)
171*44704f69SBart Van Assche {
172*44704f69SBart Van Assche         uint32_t u;
173*44704f69SBart Van Assche 
174*44704f69SBart Van Assche         memcpy(&u, p, 4);
175*44704f69SBart Van Assche         return bswap_32(u);
176*44704f69SBart Van Assche }
177*44704f69SBart Van Assche 
178*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_le64(const void *p)
179*44704f69SBart Van Assche {
180*44704f69SBart Van Assche         uint64_t u;
181*44704f69SBart Van Assche 
182*44704f69SBart Van Assche         memcpy(&u, p, 8);
183*44704f69SBart Van Assche         return bswap_64(u);
184*44704f69SBart Van Assche }
185*44704f69SBart Van Assche 
186*44704f69SBart Van Assche static inline void sg_put_unaligned_le16(uint16_t val, void *p)
187*44704f69SBart Van Assche {
188*44704f69SBart Van Assche         uint16_t u = bswap_16(val);
189*44704f69SBart Van Assche 
190*44704f69SBart Van Assche         memcpy(p, &u, 2);
191*44704f69SBart Van Assche }
192*44704f69SBart Van Assche 
193*44704f69SBart Van Assche static inline void sg_put_unaligned_le32(uint32_t val, void *p)
194*44704f69SBart Van Assche {
195*44704f69SBart Van Assche         uint32_t u = bswap_32(val);
196*44704f69SBart Van Assche 
197*44704f69SBart Van Assche         memcpy(p, &u, 4);
198*44704f69SBart Van Assche }
199*44704f69SBart Van Assche 
200*44704f69SBart Van Assche static inline void sg_put_unaligned_le64(uint64_t val, void *p)
201*44704f69SBart Van Assche {
202*44704f69SBart Van Assche         uint64_t u = bswap_64(val);
203*44704f69SBart Van Assche 
204*44704f69SBart Van Assche         memcpy(p, &u, 8);
205*44704f69SBart Van Assche }
206*44704f69SBart Van Assche 
207*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_be16(const void *p)
208*44704f69SBart Van Assche {
209*44704f69SBart Van Assche         uint16_t u;
210*44704f69SBart Van Assche 
211*44704f69SBart Van Assche         memcpy(&u, p, 2);
212*44704f69SBart Van Assche         return u;
213*44704f69SBart Van Assche }
214*44704f69SBart Van Assche 
215*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_be32(const void *p)
216*44704f69SBart Van Assche {
217*44704f69SBart Van Assche         uint32_t u;
218*44704f69SBart Van Assche 
219*44704f69SBart Van Assche         memcpy(&u, p, 4);
220*44704f69SBart Van Assche         return u;
221*44704f69SBart Van Assche }
222*44704f69SBart Van Assche 
223*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_be64(const void *p)
224*44704f69SBart Van Assche {
225*44704f69SBart Van Assche         uint64_t u;
226*44704f69SBart Van Assche 
227*44704f69SBart Van Assche         memcpy(&u, p, 8);
228*44704f69SBart Van Assche         return u;
229*44704f69SBart Van Assche }
230*44704f69SBart Van Assche 
231*44704f69SBart Van Assche static inline void sg_put_unaligned_be16(uint16_t val, void *p)
232*44704f69SBart Van Assche {
233*44704f69SBart Van Assche         memcpy(p, &val, 2);
234*44704f69SBart Van Assche }
235*44704f69SBart Van Assche 
236*44704f69SBart Van Assche static inline void sg_put_unaligned_be32(uint32_t val, void *p)
237*44704f69SBart Van Assche {
238*44704f69SBart Van Assche         memcpy(p, &val, 4);
239*44704f69SBart Van Assche }
240*44704f69SBart Van Assche 
241*44704f69SBart Van Assche static inline void sg_put_unaligned_be64(uint64_t val, void *p)
242*44704f69SBart Van Assche {
243*44704f69SBart Van Assche         memcpy(p, &val, 8);
244*44704f69SBart Van Assche }
245*44704f69SBart Van Assche 
246*44704f69SBart Van Assche #endif          /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  */
247*44704f69SBart Van Assche #endif          /* #if defined __BYTE_ORDER__ && defined <byteswap.h> &&
248*44704f69SBart Van Assche                  *     ! defined IGNORE_FAST_LEBE */
249*44704f69SBart Van Assche 
250*44704f69SBart Van Assche 
251*44704f69SBart Van Assche #ifndef GOT_UNALIGNED_SPECIALS
252*44704f69SBart Van Assche 
253*44704f69SBart Van Assche /* Now we have no tricks left, so use the only way this can be done
254*44704f69SBart Van Assche  * correctly in C safely: lots of shifts. */
255*44704f69SBart Van Assche 
256*44704f69SBart Van Assche // #warning ">>>>>> Doing GENERIC unaligneds"
257*44704f69SBart Van Assche 
sg_get_unaligned_be16(const void * p)258*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_be16(const void *p)
259*44704f69SBart Van Assche {
260*44704f69SBart Van Assche         return ((const uint8_t *)p)[0] << 8 | ((const uint8_t *)p)[1];
261*44704f69SBart Van Assche }
262*44704f69SBart Van Assche 
sg_get_unaligned_be32(const void * p)263*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_be32(const void *p)
264*44704f69SBart Van Assche {
265*44704f69SBart Van Assche         return ((const uint8_t *)p)[0] << 24 | ((const uint8_t *)p)[1] << 16 |
266*44704f69SBart Van Assche                 ((const uint8_t *)p)[2] << 8 | ((const uint8_t *)p)[3];
267*44704f69SBart Van Assche }
268*44704f69SBart Van Assche 
sg_get_unaligned_be64(const void * p)269*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_be64(const void *p)
270*44704f69SBart Van Assche {
271*44704f69SBart Van Assche         return (uint64_t)sg_get_unaligned_be32(p) << 32 |
272*44704f69SBart Van Assche                sg_get_unaligned_be32((const uint8_t *)p + 4);
273*44704f69SBart Van Assche }
274*44704f69SBart Van Assche 
sg_put_unaligned_be16(uint16_t val,void * p)275*44704f69SBart Van Assche static inline void sg_put_unaligned_be16(uint16_t val, void *p)
276*44704f69SBart Van Assche {
277*44704f69SBart Van Assche         ((uint8_t *)p)[0] = (uint8_t)(val >> 8);
278*44704f69SBart Van Assche         ((uint8_t *)p)[1] = (uint8_t)val;
279*44704f69SBart Van Assche }
280*44704f69SBart Van Assche 
sg_put_unaligned_be32(uint32_t val,void * p)281*44704f69SBart Van Assche static inline void sg_put_unaligned_be32(uint32_t val, void *p)
282*44704f69SBart Van Assche {
283*44704f69SBart Van Assche         sg_put_unaligned_be16(val >> 16, p);
284*44704f69SBart Van Assche         sg_put_unaligned_be16(val, (uint8_t *)p + 2);
285*44704f69SBart Van Assche }
286*44704f69SBart Van Assche 
sg_put_unaligned_be64(uint64_t val,void * p)287*44704f69SBart Van Assche static inline void sg_put_unaligned_be64(uint64_t val, void *p)
288*44704f69SBart Van Assche {
289*44704f69SBart Van Assche         sg_put_unaligned_be32(val >> 32, p);
290*44704f69SBart Van Assche         sg_put_unaligned_be32(val, (uint8_t *)p + 4);
291*44704f69SBart Van Assche }
292*44704f69SBart Van Assche 
293*44704f69SBart Van Assche 
sg_get_unaligned_le16(const void * p)294*44704f69SBart Van Assche static inline uint16_t sg_get_unaligned_le16(const void *p)
295*44704f69SBart Van Assche {
296*44704f69SBart Van Assche         return ((const uint8_t *)p)[1] << 8 | ((const uint8_t *)p)[0];
297*44704f69SBart Van Assche }
298*44704f69SBart Van Assche 
sg_get_unaligned_le32(const void * p)299*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_le32(const void *p)
300*44704f69SBart Van Assche {
301*44704f69SBart Van Assche         return ((const uint8_t *)p)[3] << 24 | ((const uint8_t *)p)[2] << 16 |
302*44704f69SBart Van Assche                 ((const uint8_t *)p)[1] << 8 | ((const uint8_t *)p)[0];
303*44704f69SBart Van Assche }
304*44704f69SBart Van Assche 
sg_get_unaligned_le64(const void * p)305*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_le64(const void *p)
306*44704f69SBart Van Assche {
307*44704f69SBart Van Assche         return (uint64_t)sg_get_unaligned_le32((const uint8_t *)p + 4) << 32 |
308*44704f69SBart Van Assche                sg_get_unaligned_le32(p);
309*44704f69SBart Van Assche }
310*44704f69SBart Van Assche 
sg_put_unaligned_le16(uint16_t val,void * p)311*44704f69SBart Van Assche static inline void sg_put_unaligned_le16(uint16_t val, void *p)
312*44704f69SBart Van Assche {
313*44704f69SBart Van Assche         ((uint8_t *)p)[0] = val & 0xff;
314*44704f69SBart Van Assche         ((uint8_t *)p)[1] = val >> 8;
315*44704f69SBart Van Assche }
316*44704f69SBart Van Assche 
sg_put_unaligned_le32(uint32_t val,void * p)317*44704f69SBart Van Assche static inline void sg_put_unaligned_le32(uint32_t val, void *p)
318*44704f69SBart Van Assche {
319*44704f69SBart Van Assche         sg_put_unaligned_le16(val >> 16, (uint8_t *)p + 2);
320*44704f69SBart Van Assche         sg_put_unaligned_le16(val, p);
321*44704f69SBart Van Assche }
322*44704f69SBart Van Assche 
sg_put_unaligned_le64(uint64_t val,void * p)323*44704f69SBart Van Assche static inline void sg_put_unaligned_le64(uint64_t val, void *p)
324*44704f69SBart Van Assche {
325*44704f69SBart Van Assche         sg_put_unaligned_le32(val >> 32, (uint8_t *)p + 4);
326*44704f69SBart Van Assche         sg_put_unaligned_le32(val, p);
327*44704f69SBart Van Assche }
328*44704f69SBart Van Assche 
329*44704f69SBart Van Assche #endif          /* #ifndef GOT_UNALIGNED_SPECIALS */
330*44704f69SBart Van Assche 
331*44704f69SBart Van Assche /* Following are lesser used conversions that don't have specializations
332*44704f69SBart Van Assche  * for endianness; big endian first. In summary these are the 24, 48 bit and
333*44704f69SBart Van Assche  * given-length conversions plus the "nz" conditional put conversions. */
334*44704f69SBart Van Assche 
335*44704f69SBart Van Assche /* Now big endian, get 24+48 then put 24+48 */
sg_get_unaligned_be24(const void * p)336*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_be24(const void *p)
337*44704f69SBart Van Assche {
338*44704f69SBart Van Assche         return ((const uint8_t *)p)[0] << 16 | ((const uint8_t *)p)[1] << 8 |
339*44704f69SBart Van Assche                ((const uint8_t *)p)[2];
340*44704f69SBart Van Assche }
341*44704f69SBart Van Assche 
342*44704f69SBart Van Assche /* Assume 48 bit value placed in uint64_t */
sg_get_unaligned_be48(const void * p)343*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_be48(const void *p)
344*44704f69SBart Van Assche {
345*44704f69SBart Van Assche         return (uint64_t)sg_get_unaligned_be16(p) << 32 |
346*44704f69SBart Van Assche                sg_get_unaligned_be32((const uint8_t *)p + 2);
347*44704f69SBart Van Assche }
348*44704f69SBart Van Assche 
349*44704f69SBart Van Assche /* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than
350*44704f69SBart Van Assche  * 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is
351*44704f69SBart Van Assche  * an 8 byte unsigned integer. */
sg_get_unaligned_be(int num_bytes,const void * p)352*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_be(int num_bytes, const void *p)
353*44704f69SBart Van Assche {
354*44704f69SBart Van Assche         if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t)))
355*44704f69SBart Van Assche                 return 0;
356*44704f69SBart Van Assche         else {
357*44704f69SBart Van Assche                 const uint8_t * xp = (const uint8_t *)p;
358*44704f69SBart Van Assche                 uint64_t res = *xp;
359*44704f69SBart Van Assche 
360*44704f69SBart Van Assche                 for (++xp; num_bytes > 1; ++xp, --num_bytes)
361*44704f69SBart Van Assche                         res = (res << 8) | *xp;
362*44704f69SBart Van Assche                 return res;
363*44704f69SBart Van Assche         }
364*44704f69SBart Van Assche }
365*44704f69SBart Van Assche 
sg_put_unaligned_be24(uint32_t val,void * p)366*44704f69SBart Van Assche static inline void sg_put_unaligned_be24(uint32_t val, void *p)
367*44704f69SBart Van Assche {
368*44704f69SBart Van Assche         ((uint8_t *)p)[0] = (val >> 16) & 0xff;
369*44704f69SBart Van Assche         ((uint8_t *)p)[1] = (val >> 8) & 0xff;
370*44704f69SBart Van Assche         ((uint8_t *)p)[2] = val & 0xff;
371*44704f69SBart Van Assche }
372*44704f69SBart Van Assche 
373*44704f69SBart Van Assche /* Assume 48 bit value placed in uint64_t */
sg_put_unaligned_be48(uint64_t val,void * p)374*44704f69SBart Van Assche static inline void sg_put_unaligned_be48(uint64_t val, void *p)
375*44704f69SBart Van Assche {
376*44704f69SBart Van Assche         sg_put_unaligned_be16(val >> 32, p);
377*44704f69SBart Van Assche         sg_put_unaligned_be32(val, (uint8_t *)p + 2);
378*44704f69SBart Van Assche }
379*44704f69SBart Van Assche 
380*44704f69SBart Van Assche /* Now little endian, get 24+48 then put 24+48 */
sg_get_unaligned_le24(const void * p)381*44704f69SBart Van Assche static inline uint32_t sg_get_unaligned_le24(const void *p)
382*44704f69SBart Van Assche {
383*44704f69SBart Van Assche         return (uint32_t)sg_get_unaligned_le16(p) |
384*44704f69SBart Van Assche                ((const uint8_t *)p)[2] << 16;
385*44704f69SBart Van Assche }
386*44704f69SBart Van Assche 
387*44704f69SBart Van Assche /* Assume 48 bit value placed in uint64_t */
sg_get_unaligned_le48(const void * p)388*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_le48(const void *p)
389*44704f69SBart Van Assche {
390*44704f69SBart Van Assche         return (uint64_t)sg_get_unaligned_le16((const uint8_t *)p + 4) << 32 |
391*44704f69SBart Van Assche                sg_get_unaligned_le32(p);
392*44704f69SBart Van Assche }
393*44704f69SBart Van Assche 
sg_put_unaligned_le24(uint32_t val,void * p)394*44704f69SBart Van Assche static inline void sg_put_unaligned_le24(uint32_t val, void *p)
395*44704f69SBart Van Assche {
396*44704f69SBart Van Assche         ((uint8_t *)p)[2] = (val >> 16) & 0xff;
397*44704f69SBart Van Assche         ((uint8_t *)p)[1] = (val >> 8) & 0xff;
398*44704f69SBart Van Assche         ((uint8_t *)p)[0] = val & 0xff;
399*44704f69SBart Van Assche }
400*44704f69SBart Van Assche 
401*44704f69SBart Van Assche /* Assume 48 bit value placed in uint64_t */
sg_put_unaligned_le48(uint64_t val,void * p)402*44704f69SBart Van Assche static inline void sg_put_unaligned_le48(uint64_t val, void *p)
403*44704f69SBart Van Assche {
404*44704f69SBart Van Assche         ((uint8_t *)p)[5] = (val >> 40) & 0xff;
405*44704f69SBart Van Assche         ((uint8_t *)p)[4] = (val >> 32) & 0xff;
406*44704f69SBart Van Assche         ((uint8_t *)p)[3] = (val >> 24) & 0xff;
407*44704f69SBart Van Assche         ((uint8_t *)p)[2] = (val >> 16) & 0xff;
408*44704f69SBart Van Assche         ((uint8_t *)p)[1] = (val >> 8) & 0xff;
409*44704f69SBart Van Assche         ((uint8_t *)p)[0] = val & 0xff;
410*44704f69SBart Van Assche }
411*44704f69SBart Van Assche 
412*44704f69SBart Van Assche /* Returns 0 if 'num_bytes' is less than or equal to 0 or greater than
413*44704f69SBart Van Assche  * 8 (i.e. sizeof(uint64_t)). Else returns result in uint64_t which is
414*44704f69SBart Van Assche  * an 8 byte unsigned integer. */
sg_get_unaligned_le(int num_bytes,const void * p)415*44704f69SBart Van Assche static inline uint64_t sg_get_unaligned_le(int num_bytes, const void *p)
416*44704f69SBart Van Assche {
417*44704f69SBart Van Assche         if ((num_bytes <= 0) || (num_bytes > (int)sizeof(uint64_t)))
418*44704f69SBart Van Assche                 return 0;
419*44704f69SBart Van Assche         else {
420*44704f69SBart Van Assche                 const uint8_t * xp = (const uint8_t *)p + (num_bytes - 1);
421*44704f69SBart Van Assche                 uint64_t res = *xp;
422*44704f69SBart Van Assche 
423*44704f69SBart Van Assche                 for (--xp; num_bytes > 1; --xp, --num_bytes)
424*44704f69SBart Van Assche                         res = (res << 8) | *xp;
425*44704f69SBart Van Assche                 return res;
426*44704f69SBart Van Assche         }
427*44704f69SBart Van Assche }
428*44704f69SBart Van Assche 
429*44704f69SBart Van Assche /* Since cdb and parameter blocks are often memset to zero before these
430*44704f69SBart Van Assche  * unaligned function partially fill them, then check for a val of zero
431*44704f69SBart Van Assche  * and ignore if it is with these variants. First big endian, then little */
sg_nz_put_unaligned_be16(uint16_t val,void * p)432*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_be16(uint16_t val, void *p)
433*44704f69SBart Van Assche {
434*44704f69SBart Van Assche         if (val)
435*44704f69SBart Van Assche                 sg_put_unaligned_be16(val, p);
436*44704f69SBart Van Assche }
437*44704f69SBart Van Assche 
sg_nz_put_unaligned_be24(uint32_t val,void * p)438*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_be24(uint32_t val, void *p)
439*44704f69SBart Van Assche {
440*44704f69SBart Van Assche         if (val) {
441*44704f69SBart Van Assche                 ((uint8_t *)p)[0] = (val >> 16) & 0xff;
442*44704f69SBart Van Assche                 ((uint8_t *)p)[1] = (val >> 8) & 0xff;
443*44704f69SBart Van Assche                 ((uint8_t *)p)[2] = val & 0xff;
444*44704f69SBart Van Assche         }
445*44704f69SBart Van Assche }
446*44704f69SBart Van Assche 
sg_nz_put_unaligned_be32(uint32_t val,void * p)447*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_be32(uint32_t val, void *p)
448*44704f69SBart Van Assche {
449*44704f69SBart Van Assche         if (val)
450*44704f69SBart Van Assche                 sg_put_unaligned_be32(val, p);
451*44704f69SBart Van Assche }
452*44704f69SBart Van Assche 
sg_nz_put_unaligned_be64(uint64_t val,void * p)453*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_be64(uint64_t val, void *p)
454*44704f69SBart Van Assche {
455*44704f69SBart Van Assche         if (val)
456*44704f69SBart Van Assche             sg_put_unaligned_be64(val, p);
457*44704f69SBart Van Assche }
458*44704f69SBart Van Assche 
sg_nz_put_unaligned_le16(uint16_t val,void * p)459*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_le16(uint16_t val, void *p)
460*44704f69SBart Van Assche {
461*44704f69SBart Van Assche         if (val)
462*44704f69SBart Van Assche                 sg_put_unaligned_le16(val, p);
463*44704f69SBart Van Assche }
464*44704f69SBart Van Assche 
sg_nz_put_unaligned_le24(uint32_t val,void * p)465*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_le24(uint32_t val, void *p)
466*44704f69SBart Van Assche {
467*44704f69SBart Van Assche         if (val) {
468*44704f69SBart Van Assche                 ((uint8_t *)p)[2] = (val >> 16) & 0xff;
469*44704f69SBart Van Assche                 ((uint8_t *)p)[1] = (val >> 8) & 0xff;
470*44704f69SBart Van Assche                 ((uint8_t *)p)[0] = val & 0xff;
471*44704f69SBart Van Assche         }
472*44704f69SBart Van Assche }
473*44704f69SBart Van Assche 
sg_nz_put_unaligned_le32(uint32_t val,void * p)474*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_le32(uint32_t val, void *p)
475*44704f69SBart Van Assche {
476*44704f69SBart Van Assche         if (val)
477*44704f69SBart Van Assche                 sg_put_unaligned_le32(val, p);
478*44704f69SBart Van Assche }
479*44704f69SBart Van Assche 
sg_nz_put_unaligned_le64(uint64_t val,void * p)480*44704f69SBart Van Assche static inline void sg_nz_put_unaligned_le64(uint64_t val, void *p)
481*44704f69SBart Van Assche {
482*44704f69SBart Van Assche         if (val)
483*44704f69SBart Van Assche             sg_put_unaligned_le64(val, p);
484*44704f69SBart Van Assche }
485*44704f69SBart Van Assche 
486*44704f69SBart Van Assche 
487*44704f69SBart Van Assche #ifdef __cplusplus
488*44704f69SBart Van Assche }
489*44704f69SBart Van Assche #endif
490*44704f69SBart Van Assche 
491*44704f69SBart Van Assche #endif /* SG_UNALIGNED_H */
492