byteorder: Provide a fallback for le32toh/htole32()
[strongswan.git] / src / libstrongswan / utils / utils / byteorder.h
1 /*
2 * Copyright (C) 2008-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 /**
18 * @defgroup byteorder_i byteorder
19 * @{ @ingroup utils_i
20 */
21
22 #ifndef BYTEORDER_H_
23 #define BYTEORDER_H_
24
25 /**
26 * Architecture independent bitfield definition helpers (at least with GCC).
27 *
28 * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
29 * BITFIELD2(u_int8_t,
30 * low: 4,
31 * high: 4,
32 * ) flags;
33 * The member defined first placed at bit 0.
34 */
35 #if BYTE_ORDER == LITTLE_ENDIAN
36 #define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
37 #define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
38 #define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
39 #define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
40 #elif BYTE_ORDER == BIG_ENDIAN
41 #define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
42 #define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
43 #define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
44 #define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
45 #endif
46
47 /**
48 * Write a 16-bit host order value in network order to an unaligned address.
49 *
50 * @param host host order 16-bit value
51 * @param network unaligned address to write network order value to
52 */
53 static inline void htoun16(void *network, u_int16_t host)
54 {
55 char *unaligned = (char*)network;
56
57 host = htons(host);
58 memcpy(unaligned, &host, sizeof(host));
59 }
60
61 /**
62 * Write a 32-bit host order value in network order to an unaligned address.
63 *
64 * @param host host order 32-bit value
65 * @param network unaligned address to write network order value to
66 */
67 static inline void htoun32(void *network, u_int32_t host)
68 {
69 char *unaligned = (char*)network;
70
71 host = htonl(host);
72 memcpy((char*)unaligned, &host, sizeof(host));
73 }
74
75 /**
76 * Write a 64-bit host order value in network order to an unaligned address.
77 *
78 * @param host host order 64-bit value
79 * @param network unaligned address to write network order value to
80 */
81 static inline void htoun64(void *network, u_int64_t host)
82 {
83 char *unaligned = (char*)network;
84
85 #ifdef be64toh
86 host = htobe64(host);
87 memcpy((char*)unaligned, &host, sizeof(host));
88 #else
89 u_int32_t high_part, low_part;
90
91 high_part = host >> 32;
92 high_part = htonl(high_part);
93 low_part = host & 0xFFFFFFFFLL;
94 low_part = htonl(low_part);
95
96 memcpy(unaligned, &high_part, sizeof(high_part));
97 unaligned += sizeof(high_part);
98 memcpy(unaligned, &low_part, sizeof(low_part));
99 #endif
100 }
101
102 /**
103 * Read a 16-bit value in network order from an unaligned address to host order.
104 *
105 * @param network unaligned address to read network order value from
106 * @return host order value
107 */
108 static inline u_int16_t untoh16(void *network)
109 {
110 char *unaligned = (char*)network;
111 u_int16_t tmp;
112
113 memcpy(&tmp, unaligned, sizeof(tmp));
114 return ntohs(tmp);
115 }
116
117 /**
118 * Read a 32-bit value in network order from an unaligned address to host order.
119 *
120 * @param network unaligned address to read network order value from
121 * @return host order value
122 */
123 static inline u_int32_t untoh32(void *network)
124 {
125 char *unaligned = (char*)network;
126 u_int32_t tmp;
127
128 memcpy(&tmp, unaligned, sizeof(tmp));
129 return ntohl(tmp);
130 }
131
132 /**
133 * Read a 64-bit value in network order from an unaligned address to host order.
134 *
135 * @param network unaligned address to read network order value from
136 * @return host order value
137 */
138 static inline u_int64_t untoh64(void *network)
139 {
140 char *unaligned = (char*)network;
141
142 #ifdef be64toh
143 u_int64_t tmp;
144
145 memcpy(&tmp, unaligned, sizeof(tmp));
146 return be64toh(tmp);
147 #else
148 u_int32_t high_part, low_part;
149
150 memcpy(&high_part, unaligned, sizeof(high_part));
151 unaligned += sizeof(high_part);
152 memcpy(&low_part, unaligned, sizeof(low_part));
153
154 high_part = ntohl(high_part);
155 low_part = ntohl(low_part);
156
157 return (((u_int64_t)high_part) << 32) + low_part;
158 #endif
159 }
160
161 #ifndef le32toh
162 # if BYTE_ORDER == BIG_ENDIAN
163 # define le32toh(x) __builtin_bswap32(x)
164 # define htole32(x) __builtin_bswap32(x)
165 # else
166 # define le32toh(x) (x)
167 # define htole32(x) (x)
168 # endif
169 #endif
170
171 #ifndef le64toh
172 # if BYTE_ORDER == BIG_ENDIAN
173 # define le64toh(x) __builtin_bswap64(x)
174 # define htole64(x) __builtin_bswap64(x)
175 # else
176 # define le64toh(x) (x)
177 # define htole64(x) (x)
178 # endif
179 #endif
180
181 /**
182 * Read a 32-bit value in little-endian order from unaligned address.
183 *
184 * @param network unaligned address to read little endian value from
185 * @return host order value
186 */
187 static inline u_int32_t uletoh32(void *p)
188 {
189 u_int32_t ret;
190
191 memcpy(&ret, p, sizeof(ret));
192 ret = le32toh(ret);
193 return ret;
194 }
195
196 /**
197 * Write a 32-bit value in little-endian to an unaligned address.
198 *
199 * @param host host order 32-bit value
200 * @param network unaligned address to write little endian value to
201 */
202 static inline void htoule32(void *p, u_int32_t v)
203 {
204 v = htole32(v);
205 memcpy(p, &v, sizeof(v));
206 }
207
208 #endif /** BYTEORDER_H_ @} */