byteorder.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 RenĂ© Kijewski
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser
5  * General Public License v2.1. See the file LICENSE in the top level
6  * directory for more details.
7  */
8 
19 #ifndef BYTEORDER_H
20 #define BYTEORDER_H
21 
22 #include <string.h>
23 #include <stdint.h>
24 #include "unaligned.h"
25 
26 #if defined(__MACH__)
27 # include "clang_compat.h"
28 #endif
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /* ******************************* INTERFACE ******************************* */
35 
41 typedef union __attribute__((packed)) {
42  uint16_t u16;
43  uint8_t u8[2];
44 } le_uint16_t;
45 
51 typedef union __attribute__((packed)) {
52  uint32_t u32;
53  uint8_t u8[4];
54  uint16_t u16[2];
55  le_uint16_t l16[2];
56 } le_uint32_t;
57 
63 typedef union __attribute__((packed)) {
64  uint64_t u64;
65  uint8_t u8[8];
66  uint16_t u16[4];
67  uint32_t u32[2];
68  le_uint16_t l16[4];
69  le_uint32_t l32[2];
70 } le_uint64_t;
71 
77 typedef union __attribute__((packed)) {
78  uint16_t u16;
79  uint8_t u8[2];
80 } be_uint16_t;
81 
87 typedef union __attribute__((packed)) {
88  uint32_t u32;
89  uint8_t u8[4];
90  uint16_t u16[2];
91  be_uint16_t b16[2];
92 } be_uint32_t;
93 
99 typedef union __attribute__((packed)) {
100  uint64_t u64;
101  uint8_t u8[8];
102  uint16_t u16[4];
103  uint32_t u32[2];
104  be_uint16_t b16[4];
105  be_uint32_t b32[2];
106 } be_uint64_t;
107 
112 
117 
122 
128 static inline uint16_t byteorder_ltohs(le_uint16_t v);
129 
135 static inline uint32_t byteorder_ltohl(le_uint32_t v);
136 
142 static inline uint64_t byteorder_ltohll(le_uint64_t v);
143 
149 static inline be_uint16_t byteorder_ltobs(le_uint16_t v);
150 
156 static inline be_uint32_t byteorder_ltobl(le_uint32_t v);
157 
163 static inline be_uint64_t byteorder_ltobll(le_uint64_t v);
164 
170 static inline le_uint16_t byteorder_btols(be_uint16_t v);
171 
177 static inline le_uint32_t byteorder_btoll(be_uint32_t v);
178 
184 static inline le_uint64_t byteorder_btolll(be_uint64_t v);
185 
191 static inline le_uint16_t byteorder_htols(uint16_t v);
192 
198 static inline le_uint32_t byteorder_htoll(uint32_t v);
199 
205 static inline le_uint64_t byteorder_htolll(uint64_t v);
206 
212 static inline network_uint16_t byteorder_htons(uint16_t v);
213 
219 static inline network_uint32_t byteorder_htonl(uint32_t v);
220 
226 static inline network_uint64_t byteorder_htonll(uint64_t v);
227 
233 static inline uint16_t byteorder_ntohs(network_uint16_t v);
234 
240 static inline uint32_t byteorder_ntohl(network_uint32_t v);
241 
247 static inline uint64_t byteorder_ntohll(network_uint64_t v);
248 
254 static inline uint16_t byteorder_swaps(uint16_t v);
255 
261 static inline uint32_t byteorder_swapl(uint32_t v);
262 
268 static inline uint64_t byteorder_swapll(uint64_t v);
269 
281 static inline uint16_t byteorder_bebuftohs(const uint8_t *buf);
282 
294 static inline uint32_t byteorder_bebuftohl(const uint8_t *buf);
295 
307 static inline uint64_t byteorder_bebuftohll(const uint8_t *buf);
308 
319 static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val);
320 
331 static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val);
332 
343 static inline void byteorder_htobebufll(uint8_t *buf, uint64_t val);
344 
351 static inline uint16_t htons(uint16_t v);
352 
359 static inline uint32_t htonl(uint32_t v);
360 
367 static inline uint64_t htonll(uint64_t v);
368 
375 static inline uint16_t ntohs(uint16_t v);
376 
383 static inline uint32_t ntohl(uint32_t v);
384 
391 static inline uint64_t ntohll(uint64_t v);
392 
393 /* **************************** IMPLEMENTATION ***************************** */
394 
395 #ifdef HAVE_NO_BUILTIN_BSWAP16
396 static inline unsigned short __builtin_bswap16(unsigned short a)
397 {
398  return (a << 8) | (a >> 8);
399 }
400 #endif
401 
402 static inline uint16_t byteorder_swaps(uint16_t v)
403 {
404 #ifndef MODULE_MSP430_COMMON
405  return __builtin_bswap16(v);
406 #else
407  network_uint16_t result = { v };
408  uint8_t tmp = result.u8[0];
409  result.u8[0] = result.u8[1];
410  result.u8[1] = tmp;
411  return result.u16;
412 #endif
413 }
414 
415 static inline uint32_t byteorder_swapl(uint32_t v)
416 {
417  return __builtin_bswap32(v);
418 }
419 
420 static inline uint64_t byteorder_swapll(uint64_t v)
421 {
422  return __builtin_bswap64(v);
423 }
424 
428 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
429 # define _byteorder_swap_le(V, T) (V)
430 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
431 # define _byteorder_swap_le(V, T) (byteorder_swap ## T((V)))
432 #else
433 # error "Byte order is neither little nor big!"
434 #endif
435 
436 static inline uint16_t byteorder_ltohs(le_uint16_t v)
437 {
438  return _byteorder_swap_le(v.u16, s);
439 }
440 
441 static inline uint32_t byteorder_ltohl(le_uint32_t v)
442 {
443  return _byteorder_swap_le(v.u32, l);
444 }
445 
446 static inline uint64_t byteorder_ltohll(le_uint64_t v)
447 {
448  return _byteorder_swap_le(v.u64, ll);
449 }
450 
452 {
453  be_uint16_t result = { byteorder_swaps(v.u16) };
454 
455  return result;
456 }
457 
459 {
460  be_uint32_t result = { byteorder_swapl(v.u32) };
461 
462  return result;
463 }
464 
466 {
467  be_uint64_t result = { byteorder_swapll(v.u64) };
468 
469  return result;
470 }
471 
473 {
474  le_uint16_t result = { byteorder_swaps(v.u16) };
475 
476  return result;
477 }
478 
480 {
481  le_uint32_t result = { byteorder_swapl(v.u32) };
482 
483  return result;
484 }
485 
487 {
488  le_uint64_t result = { byteorder_swapll(v.u64) };
489 
490  return result;
491 }
492 
493 static inline le_uint16_t byteorder_htols(uint16_t v)
494 {
495  le_uint16_t result = { _byteorder_swap_le(v, s) };
496 
497  return result;
498 }
499 
500 static inline le_uint32_t byteorder_htoll(uint32_t v)
501 {
502  le_uint32_t result = { _byteorder_swap_le(v, l) };
503 
504  return result;
505 }
506 
507 static inline le_uint64_t byteorder_htolll(uint64_t v)
508 {
509  le_uint64_t result = { _byteorder_swap_le(v, ll) };
510 
511  return result;
512 }
513 
517 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
518 # define _byteorder_swap(V, T) (byteorder_swap ## T((V)))
519 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
520 # define _byteorder_swap(V, T) (V)
521 #else
522 # error "Byte order is neither little nor big!"
523 #endif
524 
525 static inline network_uint16_t byteorder_htons(uint16_t v)
526 {
527  network_uint16_t result = { _byteorder_swap(v, s) };
528 
529  return result;
530 }
531 
532 static inline network_uint32_t byteorder_htonl(uint32_t v)
533 {
534  network_uint32_t result = { _byteorder_swap(v, l) };
535 
536  return result;
537 }
538 
539 static inline network_uint64_t byteorder_htonll(uint64_t v)
540 {
541  network_uint64_t result = { _byteorder_swap(v, ll) };
542 
543  return result;
544 }
545 
546 static inline uint16_t byteorder_ntohs(network_uint16_t v)
547 {
548  return _byteorder_swap(v.u16, s);
549 }
550 
551 static inline uint32_t byteorder_ntohl(network_uint32_t v)
552 {
553  return _byteorder_swap(v.u32, l);
554 }
555 
556 static inline uint64_t byteorder_ntohll(network_uint64_t v)
557 {
558  return _byteorder_swap(v.u64, ll);
559 }
560 
561 static inline uint16_t htons(uint16_t v)
562 {
563  return byteorder_htons(v).u16;
564 }
565 
566 static inline uint32_t htonl(uint32_t v)
567 {
568  return byteorder_htonl(v).u32;
569 }
570 
571 static inline uint64_t htonll(uint64_t v)
572 {
573  return byteorder_htonll(v).u64;
574 }
575 
576 static inline uint16_t ntohs(uint16_t v)
577 {
578  network_uint16_t input = { v };
579 
580  return byteorder_ntohs(input);
581 }
582 
583 static inline uint32_t ntohl(uint32_t v)
584 {
585  network_uint32_t input = { v };
586 
587  return byteorder_ntohl(input);
588 }
589 
590 static inline uint64_t ntohll(uint64_t v)
591 {
592  network_uint64_t input = { v };
593 
594  return byteorder_ntohll(input);
595 }
596 
597 static inline uint16_t byteorder_bebuftohs(const uint8_t *buf)
598 {
599 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
600  return (uint16_t)((buf[0] << 8) | (buf[1] << 0));
601 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
602  /* big endian to big endian conversion is easy, but buffer might be
603  * unaligned */
604  return unaligned_get_u16(buf);
605 #endif
606 }
607 
608 static inline uint32_t byteorder_bebuftohl(const uint8_t *buf)
609 {
610 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
611  return (((uint32_t) buf[0] << 24)
612  | ((uint32_t) buf[1] << 16)
613  | ((uint32_t) buf[2] << 8)
614  | ((uint32_t) buf[3] << 0));
615 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
616  /* big endian to big endian conversion is easy, but buffer might be
617  * unaligned */
618  return unaligned_get_u32(buf);
619 #endif
620 }
621 
622 static inline uint64_t byteorder_bebuftohll(const uint8_t *buf)
623 {
624 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
625  return (((uint64_t) buf[0] << 56)
626  | ((uint64_t) buf[1] << 48)
627  | ((uint64_t) buf[2] << 40)
628  | ((uint64_t) buf[3] << 32)
629  | ((uint64_t) buf[4] << 24)
630  | ((uint64_t) buf[5] << 16)
631  | ((uint64_t) buf[6] << 8)
632  | ((uint64_t) buf[7] << 0));
633 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
634  /* big endian to big endian conversion is easy, but buffer might be
635  * unaligned */
636  return unaligned_get_u64(buf);
637 #endif
638 }
639 
640 static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val)
641 {
642 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
643  buf[0] = (uint8_t)(val >> 8);
644  buf[1] = (uint8_t)(val >> 0);
645 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
646  /* big endian to big endian conversion is easy, but buffer might be
647  * unaligned */
648  memcpy(buf, &val, sizeof(val));
649 #endif
650 }
651 
652 static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val)
653 {
654 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
655  buf[0] = (uint8_t)(val >> 24);
656  buf[1] = (uint8_t)(val >> 16);
657  buf[2] = (uint8_t)(val >> 8);
658  buf[3] = (uint8_t)(val >> 0);
659 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
660  /* big endian to big endian conversion is easy, but buffer might be
661  * unaligned */
662  memcpy(buf, &val, sizeof(val));
663 #endif
664 }
665 
666 static inline void byteorder_htobebufll(uint8_t *buf, uint64_t val)
667 {
668 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
669  buf[0] = (uint8_t)(val >> 56);
670  buf[1] = (uint8_t)(val >> 48);
671  buf[2] = (uint8_t)(val >> 40);
672  buf[3] = (uint8_t)(val >> 32);
673  buf[4] = (uint8_t)(val >> 24);
674  buf[5] = (uint8_t)(val >> 16);
675  buf[6] = (uint8_t)(val >> 8);
676  buf[7] = (uint8_t)(val >> 0);
677 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
678  /* big endian to big endian conversion is easy, but buffer might be
679  * unaligned */
680  memcpy(buf, &val, sizeof(val));
681 #endif
682 }
683 
684 static inline uint16_t byteorder_lebuftohs(const uint8_t *buf)
685 {
686 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
687  /* little endian to little endian conversion is easy, but buffer might be
688  * unaligned */
689  return unaligned_get_u16(buf);
690 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
691  return (uint16_t)((buf[0] << 8) | (buf[1] << 0));
692 #endif
693 }
694 
695 static inline uint32_t byteorder_lebuftohl(const uint8_t *buf)
696 {
697 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
698  /* little endian to little endian conversion is easy, but buffer might be
699  * unaligned */
700  return unaligned_get_u32(buf);
701 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
702  return (((uint32_t) buf[0] << 24)
703  | ((uint32_t) buf[1] << 16)
704  | ((uint32_t) buf[2] << 8)
705  | ((uint32_t) buf[3] << 0));
706 #endif
707 }
708 
709 static inline uint64_t byteorder_lebuftohll(const uint8_t *buf)
710 {
711 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
712  /* little endian to little endian conversion is easy, but buffer might be
713  * unaligned */
714  return unaligned_get_u64(buf);
715 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
716  return (((uint64_t) buf[0] << 56)
717  | ((uint64_t) buf[1] << 48)
718  | ((uint64_t) buf[2] << 40)
719  | ((uint64_t) buf[3] << 32)
720  | ((uint64_t) buf[4] << 24)
721  | ((uint64_t) buf[5] << 16)
722  | ((uint64_t) buf[6] << 8)
723  | ((uint64_t) buf[7] << 0));
724 #endif
725 }
726 
727 static inline void byteorder_htolebufs(uint8_t *buf, uint16_t val)
728 {
729 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
730  /* little endian to little endian conversion is easy, but buffer might be
731  * unaligned */
732  memcpy(buf, &val, sizeof(val));
733 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
734  buf[0] = (uint8_t)(val >> 8);
735  buf[1] = (uint8_t)(val >> 0);
736 #endif
737 }
738 
739 static inline void byteorder_htolebufl(uint8_t *buf, uint32_t val)
740 {
741 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
742  /* little endian to little endian conversion is easy, but buffer might be
743  * unaligned */
744  memcpy(buf, &val, sizeof(val));
745 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
746  buf[0] = (uint8_t)(val >> 24);
747  buf[1] = (uint8_t)(val >> 16);
748  buf[2] = (uint8_t)(val >> 8);
749  buf[3] = (uint8_t)(val >> 0);
750 #endif
751 }
752 
753 static inline void byteorder_htolebufll(uint8_t *buf, uint64_t val)
754 {
755 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
756  /* little endian to little endian conversion is easy, but buffer might be
757  * unaligned */
758  memcpy(buf, &val, sizeof(val));
759 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
760  buf[0] = (uint8_t)(val >> 56);
761  buf[1] = (uint8_t)(val >> 48);
762  buf[2] = (uint8_t)(val >> 40);
763  buf[3] = (uint8_t)(val >> 32);
764  buf[4] = (uint8_t)(val >> 24);
765  buf[5] = (uint8_t)(val >> 16);
766  buf[6] = (uint8_t)(val >> 8);
767  buf[7] = (uint8_t)(val >> 0);
768 #endif
769 }
770 
771 #ifdef __cplusplus
772 }
773 #endif
774 
775 #endif /* BYTEORDER_H */
be_uint32_t network_uint32_t
A 32 bit integer in network byte order.
Definition: byteorder.h:116
static uint64_t ntohll(uint64_t v)
Convert from network byte order to host byte order, 64 bit.
Definition: byteorder.h:590
static uint32_t byteorder_ntohl(network_uint32_t v)
Convert from network byte order to host byte order, 32 bit.
Definition: byteorder.h:551
static uint16_t ntohs(uint16_t v)
Convert from network byte order to host byte order, 16 bit.
Definition: byteorder.h:576
static void byteorder_htobebufs(uint8_t *buf, uint16_t val)
Write a host byte order encoded unsigned integer as big endian encoded value into a buffer,...
Definition: byteorder.h:640
static uint16_t byteorder_ltohs(le_uint16_t v)
Convert from little endian to host byte order, 16 bit.
Definition: byteorder.h:436
static uint64_t byteorder_ltohll(le_uint64_t v)
Convert from little endian to host byte order, 64 bit.
Definition: byteorder.h:446
static le_uint64_t byteorder_btolll(be_uint64_t v)
Convert from big endian to little endian, 64 bit.
Definition: byteorder.h:486
static uint64_t byteorder_swapll(uint64_t v)
Swap byte order, 64 bit.
Definition: byteorder.h:420
static be_uint32_t byteorder_ltobl(le_uint32_t v)
Convert from little endian to big endian, 32 bit.
Definition: byteorder.h:458
static network_uint64_t byteorder_htonll(uint64_t v)
Convert from host byte order to network byte order, 64 bit.
Definition: byteorder.h:539
static uint64_t byteorder_ntohll(network_uint64_t v)
Convert from network byte order to host byte order, 64 bit.
Definition: byteorder.h:556
static uint64_t byteorder_bebuftohll(const uint8_t *buf)
Read a big endian encoded unsigned integer from a buffer into host byte order encoded variable,...
Definition: byteorder.h:622
static uint32_t byteorder_ltohl(le_uint32_t v)
Convert from little endian to host byte order, 32 bit.
Definition: byteorder.h:441
be_uint16_t network_uint16_t
A 16 bit integer in network byte order.
Definition: byteorder.h:111
static void byteorder_htobebufll(uint8_t *buf, uint64_t val)
Write a host byte order encoded unsigned integer as big endian encoded value into a buffer,...
Definition: byteorder.h:666
static network_uint16_t byteorder_htons(uint16_t v)
Convert from host byte order to network byte order, 16 bit.
Definition: byteorder.h:525
static uint64_t htonll(uint64_t v)
Convert from host byte order to network byte order, 64 bit.
Definition: byteorder.h:571
static be_uint16_t byteorder_ltobs(le_uint16_t v)
Convert from little endian to big endian, 16 bit.
Definition: byteorder.h:451
static uint16_t byteorder_ntohs(network_uint16_t v)
Convert from network byte order to host byte order, 16 bit.
Definition: byteorder.h:546
static uint32_t htonl(uint32_t v)
Convert from host byte order to network byte order, 32 bit.
Definition: byteorder.h:566
static uint16_t byteorder_bebuftohs(const uint8_t *buf)
Read a big endian encoded unsigned integer from a buffer into host byte order encoded variable,...
Definition: byteorder.h:597
static le_uint64_t byteorder_htolll(uint64_t v)
Convert from host byte order to little endian, 64 bit.
Definition: byteorder.h:507
static le_uint32_t byteorder_btoll(be_uint32_t v)
Convert from big endian to little endian, 32 bit.
Definition: byteorder.h:479
static le_uint16_t byteorder_btols(be_uint16_t v)
Convert from big endian to little endian, 16 bit.
Definition: byteorder.h:472
static uint16_t byteorder_swaps(uint16_t v)
Swap byte order, 16 bit.
Definition: byteorder.h:402
static le_uint16_t byteorder_htols(uint16_t v)
Convert from host byte order to little endian, 16 bit.
Definition: byteorder.h:493
static void byteorder_htobebufl(uint8_t *buf, uint32_t val)
Write a host byte order encoded unsigned integer as big endian encoded value into a buffer,...
Definition: byteorder.h:652
static be_uint64_t byteorder_ltobll(le_uint64_t v)
Convert from little endian to big endian, 64 bit.
Definition: byteorder.h:465
static uint32_t byteorder_swapl(uint32_t v)
Swap byte order, 32 bit.
Definition: byteorder.h:415
be_uint64_t network_uint64_t
A 64 bit integer in network byte order.
Definition: byteorder.h:121
static le_uint32_t byteorder_htoll(uint32_t v)
Convert from host byte order to little endian, 32 bit.
Definition: byteorder.h:500
static uint32_t ntohl(uint32_t v)
Convert from network byte order to host byte order, 32 bit.
Definition: byteorder.h:583
static uint32_t byteorder_bebuftohl(const uint8_t *buf)
Read a big endian encoded unsigned integer from a buffer into host byte order encoded variable,...
Definition: byteorder.h:608
static network_uint32_t byteorder_htonl(uint32_t v)
Convert from host byte order to network byte order, 32 bit.
Definition: byteorder.h:532
#define _byteorder_swap_le(V, T)
Swaps the byteorder according to the endianness (host -> le)
Definition: byteorder.h:429
#define _byteorder_swap(V, T)
Swaps the byteorder according to the endianness (host -> BE)
Definition: byteorder.h:518
static uint16_t htons(uint16_t v)
Convert from host byte order to network byte order, 16 bit.
Definition: byteorder.h:561
static uint16_t unaligned_get_u16(const void *ptr)
Get uint16_t from possibly unaligned pointer.
Definition: unaligned.h:68
static uint64_t unaligned_get_u64(const void *ptr)
Get uint64_t from possibly unaligned pointer.
Definition: unaligned.h:94
static uint32_t unaligned_get_u32(const void *ptr)
Get uint32_t from possibly unaligned pointer.
Definition: unaligned.h:81
Unaligned but safe memory access functions.
A 16 bit integer in big endian aka network byte order.
Definition: byteorder.h:77
uint8_t u8[2]
8 bit representation
Definition: byteorder.h:79
uint16_t u16
16 bit representation
Definition: byteorder.h:78
A 32 bit integer in big endian aka network byte order.
Definition: byteorder.h:87
uint32_t u32
32 bit representation
Definition: byteorder.h:88
A 64 bit integer in big endian aka network byte order.
Definition: byteorder.h:99
uint64_t u64
64 bit representation
Definition: byteorder.h:100
A 16 bit integer in little endian.
Definition: byteorder.h:41
uint16_t u16
16 bit representation
Definition: byteorder.h:42
A 32 bit integer in little endian.
Definition: byteorder.h:51
uint32_t u32
32 bit representation
Definition: byteorder.h:52
A 64 bit integer in little endian.
Definition: byteorder.h:63
uint64_t u64
64 bit representation
Definition: byteorder.h:64