• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for byte-ordering encoding.
32  */
33 
34 #ifndef ENCODING_HPP_
35 #define ENCODING_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #ifndef BYTE_ORDER_BIG_ENDIAN
40 #if defined(WORDS_BIGENDIAN) || \
41     defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
42 #define BYTE_ORDER_BIG_ENDIAN 1
43 #else
44 #define BYTE_ORDER_BIG_ENDIAN 0
45 #endif
46 #endif
47 
48 #include <limits.h>
49 #include <stdint.h>
50 
51 namespace ot {
52 namespace Encoding {
53 
Swap16(uint16_t v)54 inline uint16_t Swap16(uint16_t v)
55 {
56     return (((v & 0x00ffU) << 8) & 0xff00) | (((v & 0xff00U) >> 8) & 0x00ff);
57 }
58 
Swap32(uint32_t v)59 inline uint32_t Swap32(uint32_t v)
60 {
61     return ((v & static_cast<uint32_t>(0x000000ffUL)) << 24) | ((v & static_cast<uint32_t>(0x0000ff00UL)) << 8) |
62            ((v & static_cast<uint32_t>(0x00ff0000UL)) >> 8) | ((v & static_cast<uint32_t>(0xff000000UL)) >> 24);
63 }
64 
Swap64(uint64_t v)65 inline uint64_t Swap64(uint64_t v)
66 {
67     return ((v & static_cast<uint64_t>(0x00000000000000ffULL)) << 56) |
68            ((v & static_cast<uint64_t>(0x000000000000ff00ULL)) << 40) |
69            ((v & static_cast<uint64_t>(0x0000000000ff0000ULL)) << 24) |
70            ((v & static_cast<uint64_t>(0x00000000ff000000ULL)) << 8) |
71            ((v & static_cast<uint64_t>(0x000000ff00000000ULL)) >> 8) |
72            ((v & static_cast<uint64_t>(0x0000ff0000000000ULL)) >> 24) |
73            ((v & static_cast<uint64_t>(0x00ff000000000000ULL)) >> 40) |
74            ((v & static_cast<uint64_t>(0xff00000000000000ULL)) >> 56);
75 }
76 
Reverse32(uint32_t v)77 inline uint32_t Reverse32(uint32_t v)
78 {
79     v = ((v & 0x55555555) << 1) | ((v & 0xaaaaaaaa) >> 1);
80     v = ((v & 0x33333333) << 2) | ((v & 0xcccccccc) >> 2);
81     v = ((v & 0x0f0f0f0f) << 4) | ((v & 0xf0f0f0f0) >> 4);
82     v = ((v & 0x00ff00ff) << 8) | ((v & 0xff00ff00) >> 8);
83     v = ((v & 0x0000ffff) << 16) | ((v & 0xffff0000) >> 16);
84 
85     return v;
86 }
87 
88 #define BitVectorBytes(x) static_cast<uint8_t>(((x) + (CHAR_BIT - 1)) / CHAR_BIT)
89 
90 namespace BigEndian {
91 
92 #if BYTE_ORDER_BIG_ENDIAN
93 
HostSwap16(uint16_t v)94 inline uint16_t HostSwap16(uint16_t v)
95 {
96     return v;
97 }
HostSwap32(uint32_t v)98 inline uint32_t HostSwap32(uint32_t v)
99 {
100     return v;
101 }
HostSwap64(uint64_t v)102 inline uint64_t HostSwap64(uint64_t v)
103 {
104     return v;
105 }
106 
107 #else /* BYTE_ORDER_LITTLE_ENDIAN */
108 
109 inline uint16_t HostSwap16(uint16_t v)
110 {
111     return Swap16(v);
112 }
113 inline uint32_t HostSwap32(uint32_t v)
114 {
115     return Swap32(v);
116 }
117 inline uint64_t HostSwap64(uint64_t v)
118 {
119     return Swap64(v);
120 }
121 
122 #endif // LITTLE_ENDIAN
123 
124 /**
125  * This template function performs host swap on a given unsigned integer value assuming big-endian encoding.
126  *
127  * @tparam  UintType   The unsigned int type.
128  *
129  * @param   aValue     The value to host swap.
130  *
131  * @returns The host swapped value.
132  *
133  */
134 template <typename UintType> UintType HostSwap(UintType aValue);
135 
HostSwap(uint8_t aValue)136 template <> inline uint8_t HostSwap(uint8_t aValue)
137 {
138     return aValue;
139 }
HostSwap(uint16_t aValue)140 template <> inline uint16_t HostSwap(uint16_t aValue)
141 {
142     return HostSwap16(aValue);
143 }
HostSwap(uint32_t aValue)144 template <> inline uint32_t HostSwap(uint32_t aValue)
145 {
146     return HostSwap32(aValue);
147 }
HostSwap(uint64_t aValue)148 template <> inline uint64_t HostSwap(uint64_t aValue)
149 {
150     return HostSwap64(aValue);
151 }
152 
153 /**
154  * This function reads a `uint16_t` value from a given buffer assuming big-endian encoding.
155  *
156  * @param[in] aBuffer   Pointer to buffer to read from.
157  *
158  * @returns The `uint16_t` value read from buffer.
159  *
160  */
ReadUint16(const uint8_t * aBuffer)161 inline uint16_t ReadUint16(const uint8_t *aBuffer)
162 {
163     return static_cast<uint16_t>((aBuffer[0] << 8) | aBuffer[1]);
164 }
165 
166 /**
167  * This function reads a `uint32_t` value from a given buffer assuming big-endian encoding.
168  *
169  * @param[in] aBuffer   Pointer to buffer to read from.
170  *
171  * @returns The `uint32_t` value read from buffer.
172  *
173  */
ReadUint32(const uint8_t * aBuffer)174 inline uint32_t ReadUint32(const uint8_t *aBuffer)
175 {
176     return ((static_cast<uint32_t>(aBuffer[0]) << 24) | (static_cast<uint32_t>(aBuffer[1]) << 16) |
177             (static_cast<uint32_t>(aBuffer[2]) << 8) | (static_cast<uint32_t>(aBuffer[3]) << 0));
178 }
179 
180 /**
181  * This function reads a 24-bit integer value from a given buffer assuming big-endian encoding.
182  *
183  * @param[in] aBuffer   Pointer to buffer to read from.
184  *
185  * @returns The value read from buffer.
186  *
187  */
ReadUint24(const uint8_t * aBuffer)188 inline uint32_t ReadUint24(const uint8_t *aBuffer)
189 {
190     return ((static_cast<uint32_t>(aBuffer[0]) << 16) | (static_cast<uint32_t>(aBuffer[1]) << 8) |
191             (static_cast<uint32_t>(aBuffer[2]) << 0));
192 }
193 
194 /**
195  * This function reads a `uint64_t` value from a given buffer assuming big-endian encoding.
196  *
197  * @param[in] aBuffer   Pointer to buffer to read from.
198  *
199  * @returns The `uint64_t` value read from buffer.
200  *
201  */
ReadUint64(const uint8_t * aBuffer)202 inline uint64_t ReadUint64(const uint8_t *aBuffer)
203 {
204     return ((static_cast<uint64_t>(aBuffer[0]) << 56) | (static_cast<uint64_t>(aBuffer[1]) << 48) |
205             (static_cast<uint64_t>(aBuffer[2]) << 40) | (static_cast<uint64_t>(aBuffer[3]) << 32) |
206             (static_cast<uint64_t>(aBuffer[4]) << 24) | (static_cast<uint64_t>(aBuffer[5]) << 16) |
207             (static_cast<uint64_t>(aBuffer[6]) << 8) | (static_cast<uint64_t>(aBuffer[7]) << 0));
208 }
209 
210 /**
211  * This function writes a `uint16_t` value to a given buffer using big-endian encoding.
212  *
213  * @param[in]  aValue    The value to write to buffer.
214  * @param[out] aBuffer   Pointer to buffer where the value will be written.
215  *
216  */
WriteUint16(uint16_t aValue,uint8_t * aBuffer)217 inline void WriteUint16(uint16_t aValue, uint8_t *aBuffer)
218 {
219     aBuffer[0] = (aValue >> 8) & 0xff;
220     aBuffer[1] = (aValue >> 0) & 0xff;
221 }
222 
223 /**
224  * This function writes a 24-bit integer value to a given buffer using big-endian encoding.
225  *
226  * @param[in]  aValue    The value to write to buffer.
227  * @param[out] aBuffer   Pointer to buffer where the value will be written.
228  *
229  */
WriteUint24(uint32_t aValue,uint8_t * aBuffer)230 inline void WriteUint24(uint32_t aValue, uint8_t *aBuffer)
231 {
232     aBuffer[0] = (aValue >> 16) & 0xff;
233     aBuffer[1] = (aValue >> 8) & 0xff;
234     aBuffer[2] = (aValue >> 0) & 0xff;
235 }
236 
237 /**
238  * This function writes a `uint32_t` value to a given buffer using big-endian encoding.
239  *
240  * @param[in]  aValue    The value to write to buffer.
241  * @param[out] aBuffer   Pointer to buffer where the value will be written.
242  *
243  */
WriteUint32(uint32_t aValue,uint8_t * aBuffer)244 inline void WriteUint32(uint32_t aValue, uint8_t *aBuffer)
245 {
246     aBuffer[0] = (aValue >> 24) & 0xff;
247     aBuffer[1] = (aValue >> 16) & 0xff;
248     aBuffer[2] = (aValue >> 8) & 0xff;
249     aBuffer[3] = (aValue >> 0) & 0xff;
250 }
251 
252 /**
253  * This function writes a `uint64_t` value to a given buffer using big-endian encoding.
254  *
255  * @param[in]  aValue    The value to write to buffer.
256  * @param[out] aBuffer   Pointer to buffer where the value will be written.
257  *
258  */
WriteUint64(uint64_t aValue,uint8_t * aBuffer)259 inline void WriteUint64(uint64_t aValue, uint8_t *aBuffer)
260 {
261     aBuffer[0] = (aValue >> 56) & 0xff;
262     aBuffer[1] = (aValue >> 48) & 0xff;
263     aBuffer[2] = (aValue >> 40) & 0xff;
264     aBuffer[3] = (aValue >> 32) & 0xff;
265     aBuffer[4] = (aValue >> 24) & 0xff;
266     aBuffer[5] = (aValue >> 16) & 0xff;
267     aBuffer[6] = (aValue >> 8) & 0xff;
268     aBuffer[7] = (aValue >> 0) & 0xff;
269 }
270 
271 } // namespace BigEndian
272 
273 namespace LittleEndian {
274 
275 #if BYTE_ORDER_BIG_ENDIAN
276 
HostSwap16(uint16_t v)277 inline uint16_t HostSwap16(uint16_t v)
278 {
279     return Swap16(v);
280 }
HostSwap32(uint32_t v)281 inline uint32_t HostSwap32(uint32_t v)
282 {
283     return Swap32(v);
284 }
HostSwap64(uint64_t v)285 inline uint64_t HostSwap64(uint64_t v)
286 {
287     return Swap64(v);
288 }
289 
290 #else /* BYTE_ORDER_LITTLE_ENDIAN */
291 
292 inline uint16_t HostSwap16(uint16_t v)
293 {
294     return v;
295 }
296 inline uint32_t HostSwap32(uint32_t v)
297 {
298     return v;
299 }
300 inline uint64_t HostSwap64(uint64_t v)
301 {
302     return v;
303 }
304 
305 #endif
306 
307 /**
308  * This template function performs host swap on a given unsigned integer value assuming little-endian encoding.
309  *
310  * @tparam  UintType   The unsigned int type.
311  *
312  * @param   aValue     The value to host swap.
313  *
314  * @returns The host swapped value.
315  *
316  */
317 template <typename UintType> UintType HostSwap(UintType aValue);
318 
HostSwap(uint8_t aValue)319 template <> inline uint8_t HostSwap(uint8_t aValue)
320 {
321     return aValue;
322 }
HostSwap(uint16_t aValue)323 template <> inline uint16_t HostSwap(uint16_t aValue)
324 {
325     return HostSwap16(aValue);
326 }
HostSwap(uint32_t aValue)327 template <> inline uint32_t HostSwap(uint32_t aValue)
328 {
329     return HostSwap32(aValue);
330 }
HostSwap(uint64_t aValue)331 template <> inline uint64_t HostSwap(uint64_t aValue)
332 {
333     return HostSwap64(aValue);
334 }
335 
336 /**
337  * This function reads a `uint16_t` value from a given buffer assuming little-endian encoding.
338  *
339  * @param[in] aBuffer   Pointer to buffer to read from.
340  *
341  * @returns The `uint16_t` value read from buffer.
342  *
343  */
ReadUint16(const uint8_t * aBuffer)344 inline uint16_t ReadUint16(const uint8_t *aBuffer)
345 {
346     return static_cast<uint16_t>(aBuffer[0] | (aBuffer[1] << 8));
347 }
348 
349 /**
350  * This function reads a 24-bit integer value from a given buffer assuming little-endian encoding.
351  *
352  * @param[in] aBuffer   Pointer to buffer to read from.
353  *
354  * @returns The value read from buffer.
355  *
356  */
ReadUint24(const uint8_t * aBuffer)357 inline uint32_t ReadUint24(const uint8_t *aBuffer)
358 {
359     return ((static_cast<uint32_t>(aBuffer[0]) << 0) | (static_cast<uint32_t>(aBuffer[1]) << 8) |
360             (static_cast<uint32_t>(aBuffer[2]) << 16));
361 }
362 
363 /**
364  * This function reads a `uint32_t` value from a given buffer assuming little-endian encoding.
365  *
366  * @param[in] aBuffer   Pointer to buffer to read from.
367  *
368  * @returns The `uint32_t` value read from buffer.
369  *
370  */
ReadUint32(const uint8_t * aBuffer)371 inline uint32_t ReadUint32(const uint8_t *aBuffer)
372 {
373     return ((static_cast<uint32_t>(aBuffer[0]) << 0) | (static_cast<uint32_t>(aBuffer[1]) << 8) |
374             (static_cast<uint32_t>(aBuffer[2]) << 16) | (static_cast<uint32_t>(aBuffer[3]) << 24));
375 }
376 
377 /**
378  * This function reads a `uint64_t` value from a given buffer assuming little-endian encoding.
379  *
380  * @param[in] aBuffer   Pointer to buffer to read from.
381  *
382  * @returns The `uint64_t` value read from buffer.
383  *
384  */
ReadUint64(const uint8_t * aBuffer)385 inline uint64_t ReadUint64(const uint8_t *aBuffer)
386 {
387     return ((static_cast<uint64_t>(aBuffer[0]) << 0) | (static_cast<uint64_t>(aBuffer[1]) << 8) |
388             (static_cast<uint64_t>(aBuffer[2]) << 16) | (static_cast<uint64_t>(aBuffer[3]) << 24) |
389             (static_cast<uint64_t>(aBuffer[4]) << 32) | (static_cast<uint64_t>(aBuffer[5]) << 40) |
390             (static_cast<uint64_t>(aBuffer[6]) << 48) | (static_cast<uint64_t>(aBuffer[7]) << 56));
391 }
392 
393 /**
394  * This function writes a `uint16_t` value to a given buffer using little-endian encoding.
395  *
396  * @param[in]  aValue    The value to write to buffer.
397  * @param[out] aBuffer   Pointer to buffer where the value will be written.
398  *
399  */
WriteUint16(uint16_t aValue,uint8_t * aBuffer)400 inline void WriteUint16(uint16_t aValue, uint8_t *aBuffer)
401 {
402     aBuffer[0] = (aValue >> 0) & 0xff;
403     aBuffer[1] = (aValue >> 8) & 0xff;
404 }
405 
406 /**
407  * This function writes a 24-bit integer value to a given buffer using little-endian encoding.
408  *
409  * @param[in]  aValue   The value to write to buffer.
410  * @param[out] aBuffer  Pointer to buffer where the value will be written.
411  *
412  */
WriteUint24(uint32_t aValue,uint8_t * aBuffer)413 inline void WriteUint24(uint32_t aValue, uint8_t *aBuffer)
414 {
415     aBuffer[0] = (aValue >> 0) & 0xff;
416     aBuffer[1] = (aValue >> 8) & 0xff;
417     aBuffer[2] = (aValue >> 16) & 0xff;
418 }
419 
420 /**
421  * This function writes a `uint32_t` value to a given buffer using little-endian encoding.
422  *
423  * @param[in]  aValue   The value to write to buffer.
424  * @param[out] aBuffer  Pointer to buffer where the value will be written.
425  *
426  */
WriteUint32(uint32_t aValue,uint8_t * aBuffer)427 inline void WriteUint32(uint32_t aValue, uint8_t *aBuffer)
428 {
429     aBuffer[0] = (aValue >> 0) & 0xff;
430     aBuffer[1] = (aValue >> 8) & 0xff;
431     aBuffer[2] = (aValue >> 16) & 0xff;
432     aBuffer[3] = (aValue >> 24) & 0xff;
433 }
434 
435 /**
436  * This function writes a `uint64_t` value to a given buffer using little-endian encoding.
437  *
438  * @param[in]  aValue   The value to write to buffer.
439  * @param[out] aBuffer  Pointer to buffer where the value will be written.
440  *
441  */
WriteUint64(uint64_t aValue,uint8_t * aBuffer)442 inline void WriteUint64(uint64_t aValue, uint8_t *aBuffer)
443 {
444     aBuffer[0] = (aValue >> 0) & 0xff;
445     aBuffer[1] = (aValue >> 8) & 0xff;
446     aBuffer[2] = (aValue >> 16) & 0xff;
447     aBuffer[3] = (aValue >> 24) & 0xff;
448     aBuffer[4] = (aValue >> 32) & 0xff;
449     aBuffer[5] = (aValue >> 40) & 0xff;
450     aBuffer[6] = (aValue >> 48) & 0xff;
451     aBuffer[7] = (aValue >> 56) & 0xff;
452 }
453 
454 } // namespace LittleEndian
455 } // namespace Encoding
456 } // namespace ot
457 
458 #endif // ENCODING_HPP_
459