blob: fb65685ef41b1692740a7149cd3aeaf76177ae68 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_COMMON_BYTEORDER_H_
2#define AOS_COMMON_BYTEORDER_H_
3
4#ifndef __VXWORKS__
5#include <endian.h> // endian(3)
6#endif
Brian Silvermanf665d692013-02-17 22:11:39 -08007#include <string.h>
brians343bc112013-02-10 01:53:46 +00008
9// Contains functions for converting between host and network byte order for
10// things other than 16/32 bit integers (those are provided by byteorder(3)).
11// Also gives a nice templated interface to these functions.
12
13namespace aos {
brians343bc112013-02-10 01:53:46 +000014namespace {
15
Brian Silvermanca20b6b2014-03-19 17:52:33 -070016template <typename int_type, int_type (*function)(int_type)>
17static inline void copier(const void *in, void *out) {
brians343bc112013-02-10 01:53:46 +000018 // Have confirmed by looking at the assembly code that this generates the same
19 // code as the (undefined by the c++ standard) way of using a union to do it.
20 // (which is pretty efficient)
21 int_type temp;
Brian Silvermanca20b6b2014-03-19 17:52:33 -070022 memcpy(&temp, in, sizeof(int_type));
brians343bc112013-02-10 01:53:46 +000023 temp = function(temp);
Brian Silvermanca20b6b2014-03-19 17:52:33 -070024 memcpy(out, &temp, sizeof(int_type));
brians343bc112013-02-10 01:53:46 +000025}
Brian Silvermanca20b6b2014-03-19 17:52:33 -070026template <typename int_type, typename T, int_type (*function)(int_type)>
27static inline T memcpier(T in) {
28 copier<int_type, function>(&in, &in);
brians343bc112013-02-10 01:53:46 +000029 return in;
30}
31
Brian Silvermanca20b6b2014-03-19 17:52:33 -070032// Needed because be64toh etc are macros (not that the manpage says
33// anything...).
brians343bc112013-02-10 01:53:46 +000034// These are used instead of ntohs etc because gcc didn't inline those.
Brian Silvermanca20b6b2014-03-19 17:52:33 -070035static inline uint64_t _be64toh(uint64_t in) { return be64toh(in); }
36static inline uint64_t _htobe64(uint64_t in) { return htobe64(in); }
37static inline uint32_t _be32toh(uint32_t in) { return be32toh(in); }
38static inline uint32_t _htobe32(uint32_t in) { return htobe32(in); }
39static inline uint16_t _be16toh(uint16_t in) { return be16toh(in); }
40static inline uint16_t _htobe16(uint16_t in) { return htobe16(in); }
brians343bc112013-02-10 01:53:46 +000041
42template<int bytes, typename T> class do_ntoh {
43 public:
44 static inline T apply(T net);
45 static inline void copy(const char *in, T &net);
46};
47template<typename T> class do_ntoh<1, T> {
48 public:
49 static inline T apply(T net) { return net; }
50 static inline void copy(const char *in, T *host) { host[0] = in[0]; }
51};
52template<typename T> class do_ntoh<2, T> {
53 public:
54 static inline T apply(T net) { return memcpier<uint16_t, T, _be16toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070055 static inline void copy(const char *in, T *host) {
56 copier<uint16_t, _be16toh>(in, host);
57 }
brians343bc112013-02-10 01:53:46 +000058};
59template<typename T> class do_ntoh<4, T> {
60 public:
61 static inline T apply(T net) { return memcpier<uint32_t, T, _be32toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070062 static inline void copy(const char *in, T *host) {
63 copier<uint32_t, _be32toh>(in, host);
64 }
brians343bc112013-02-10 01:53:46 +000065};
66template<typename T> class do_ntoh<8, T> {
67 public:
68 static inline T apply(T net) { return memcpier<uint64_t, T, _be64toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070069 static inline void copy(const char *in, T *host) {
70 copier<uint64_t, _be64toh>(in, host);
71 }
brians343bc112013-02-10 01:53:46 +000072};
Brian Silvermanca20b6b2014-03-19 17:52:33 -070073
74template <size_t Size>
75struct do_ntoh_int {
76 static inline void copy(const char *in, char *host);
77};
78template <>
79struct do_ntoh_int<1> {
80 static inline void copy(const char *in, char *host) { host[0] = in[0]; }
81};
82template <>
83struct do_ntoh_int<2> {
84 static inline void copy(const char *in, char *host) {
85 copier<uint16_t, _be16toh>(in, host);
86 }
87};
88template <>
89struct do_ntoh_int<4> {
90 static inline void copy(const char *in, char *host) {
91 copier<uint32_t, _be32toh>(in, host);
92 }
93};
94template <>
95struct do_ntoh_int<8> {
96 static inline void copy(const char *in, char *host) {
97 copier<uint64_t, _be64toh>(in, host);
98 }
99};
100
brians343bc112013-02-10 01:53:46 +0000101template<int bytes, typename T> class do_hton {
102 public:
103 static inline T apply(T host);
104 static inline void copy(const T *host, char *out);
105};
106template<typename T> class do_hton<1, T> {
107 public:
108 static inline T apply(T host) { return host; }
109 static inline void copy(const T *host, char *out) { out[0] = host[0]; }
110};
111template<typename T> class do_hton<2, T> {
112 public:
113 static inline T apply(T host) { return memcpier<uint16_t, T, _htobe16>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700114 static inline void copy(const T *host, char *out) {
115 copier<uint16_t, _htobe16>(host, out);
116 }
brians343bc112013-02-10 01:53:46 +0000117};
118template<typename T> class do_hton<4, T> {
119 public:
120 static inline T apply(T host) { return memcpier<uint32_t, T, _htobe32>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700121 static inline void copy(const T *host, char *out) {
122 copier<uint32_t, _htobe32>(host, out);
123 }
brians343bc112013-02-10 01:53:46 +0000124};
125template<typename T> class do_hton<8, T> {
126 public:
127 static inline T apply(T host) { return memcpier<uint64_t, T, _htobe64>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700128 static inline void copy(const T *host, char *out) {
129 copier<uint64_t, _htobe64>(host, out);
130 }
brians343bc112013-02-10 01:53:46 +0000131};
132
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700133template <size_t Size>
134struct do_hton_int {
135 static inline void copy(const char *host, char *out);
136};
137template <>
138struct do_hton_int<1> {
139 static inline void copy(const char *host, char *out) { out[0] = host[0]; }
140};
141template <>
142struct do_hton_int<2> {
143 static inline void copy(const char *host, char *out) {
144 copier<uint16_t, _htobe16>(host, out);
145 }
146};
147template <>
148struct do_hton_int<4> {
149 static inline void copy(const char *host, char *out) {
150 copier<uint32_t, _htobe32>(host, out);
151 }
152};
153template <>
154struct do_hton_int<8> {
155 static inline void copy(const char *host, char *out) {
156 copier<uint64_t, _htobe64>(host, out);
157 }
158};
159
160} // namespace
brians343bc112013-02-10 01:53:46 +0000161
162// Converts T from network to host byte order.
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700163template <typename T>
164static inline T ntoh(T net) {
brians343bc112013-02-10 01:53:46 +0000165 return do_ntoh<sizeof(net), T>::apply(net);
brians343bc112013-02-10 01:53:46 +0000166}
167// Converts T from host to network byte order.
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700168template <typename T>
169static inline T hton(T host) {
brians343bc112013-02-10 01:53:46 +0000170 return do_hton<sizeof(host), T>::apply(host);
brians343bc112013-02-10 01:53:46 +0000171}
172
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700173template <typename T>
174static inline void to_host(const char *input, T *host) {
brians343bc112013-02-10 01:53:46 +0000175 do_ntoh<sizeof(*host), T>::copy(input, host);
brians343bc112013-02-10 01:53:46 +0000176}
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700177template <typename T>
178static inline void to_network(const T *host, char *output) {
brians343bc112013-02-10 01:53:46 +0000179 do_hton<sizeof(*host), T>::copy(host, output);
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700180}
181
182template <size_t Size>
183static inline void to_host(const char *input, char *host) {
184 do_ntoh_int<Size>::copy(input, host);
185}
186template <size_t Size>
187static inline void to_network(const char *host, char *output) {
188 do_hton_int<Size>::copy(host, output);
brians343bc112013-02-10 01:53:46 +0000189}
190
191} // namespace aos
192
193#endif