blob: c616d68540ee8b4407d82c0235d9d98601c66869 [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 Silverman5bf41dc2014-04-21 18:31:45 -070035#ifdef __clang__
36// Apparently the macros use "register", and clang doesn't like that.
37#define register
38#endif
Brian Silvermanca20b6b2014-03-19 17:52:33 -070039static inline uint64_t _be64toh(uint64_t in) { return be64toh(in); }
40static inline uint64_t _htobe64(uint64_t in) { return htobe64(in); }
41static inline uint32_t _be32toh(uint32_t in) { return be32toh(in); }
42static inline uint32_t _htobe32(uint32_t in) { return htobe32(in); }
43static inline uint16_t _be16toh(uint16_t in) { return be16toh(in); }
44static inline uint16_t _htobe16(uint16_t in) { return htobe16(in); }
Brian Silverman5bf41dc2014-04-21 18:31:45 -070045#ifdef __clang__
46#undef register
47#endif
brians343bc112013-02-10 01:53:46 +000048
49template<int bytes, typename T> class do_ntoh {
50 public:
51 static inline T apply(T net);
52 static inline void copy(const char *in, T &net);
53};
54template<typename T> class do_ntoh<1, T> {
55 public:
56 static inline T apply(T net) { return net; }
57 static inline void copy(const char *in, T *host) { host[0] = in[0]; }
58};
59template<typename T> class do_ntoh<2, T> {
60 public:
61 static inline T apply(T net) { return memcpier<uint16_t, T, _be16toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070062 static inline void copy(const char *in, T *host) {
63 copier<uint16_t, _be16toh>(in, host);
64 }
brians343bc112013-02-10 01:53:46 +000065};
66template<typename T> class do_ntoh<4, T> {
67 public:
68 static inline T apply(T net) { return memcpier<uint32_t, T, _be32toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070069 static inline void copy(const char *in, T *host) {
70 copier<uint32_t, _be32toh>(in, host);
71 }
brians343bc112013-02-10 01:53:46 +000072};
73template<typename T> class do_ntoh<8, T> {
74 public:
75 static inline T apply(T net) { return memcpier<uint64_t, T, _be64toh>(net); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -070076 static inline void copy(const char *in, T *host) {
77 copier<uint64_t, _be64toh>(in, host);
78 }
brians343bc112013-02-10 01:53:46 +000079};
Brian Silvermanca20b6b2014-03-19 17:52:33 -070080
81template <size_t Size>
82struct do_ntoh_int {
83 static inline void copy(const char *in, char *host);
84};
85template <>
86struct do_ntoh_int<1> {
87 static inline void copy(const char *in, char *host) { host[0] = in[0]; }
88};
89template <>
90struct do_ntoh_int<2> {
91 static inline void copy(const char *in, char *host) {
92 copier<uint16_t, _be16toh>(in, host);
93 }
94};
95template <>
96struct do_ntoh_int<4> {
97 static inline void copy(const char *in, char *host) {
98 copier<uint32_t, _be32toh>(in, host);
99 }
100};
101template <>
102struct do_ntoh_int<8> {
103 static inline void copy(const char *in, char *host) {
104 copier<uint64_t, _be64toh>(in, host);
105 }
106};
107
brians343bc112013-02-10 01:53:46 +0000108template<int bytes, typename T> class do_hton {
109 public:
110 static inline T apply(T host);
111 static inline void copy(const T *host, char *out);
112};
113template<typename T> class do_hton<1, T> {
114 public:
115 static inline T apply(T host) { return host; }
116 static inline void copy(const T *host, char *out) { out[0] = host[0]; }
117};
118template<typename T> class do_hton<2, T> {
119 public:
120 static inline T apply(T host) { return memcpier<uint16_t, T, _htobe16>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700121 static inline void copy(const T *host, char *out) {
122 copier<uint16_t, _htobe16>(host, out);
123 }
brians343bc112013-02-10 01:53:46 +0000124};
125template<typename T> class do_hton<4, T> {
126 public:
127 static inline T apply(T host) { return memcpier<uint32_t, T, _htobe32>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700128 static inline void copy(const T *host, char *out) {
129 copier<uint32_t, _htobe32>(host, out);
130 }
brians343bc112013-02-10 01:53:46 +0000131};
132template<typename T> class do_hton<8, T> {
133 public:
134 static inline T apply(T host) { return memcpier<uint64_t, T, _htobe64>(host); }
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700135 static inline void copy(const T *host, char *out) {
136 copier<uint64_t, _htobe64>(host, out);
137 }
brians343bc112013-02-10 01:53:46 +0000138};
139
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700140template <size_t Size>
141struct do_hton_int {
142 static inline void copy(const char *host, char *out);
143};
144template <>
145struct do_hton_int<1> {
146 static inline void copy(const char *host, char *out) { out[0] = host[0]; }
147};
148template <>
149struct do_hton_int<2> {
150 static inline void copy(const char *host, char *out) {
151 copier<uint16_t, _htobe16>(host, out);
152 }
153};
154template <>
155struct do_hton_int<4> {
156 static inline void copy(const char *host, char *out) {
157 copier<uint32_t, _htobe32>(host, out);
158 }
159};
160template <>
161struct do_hton_int<8> {
162 static inline void copy(const char *host, char *out) {
163 copier<uint64_t, _htobe64>(host, out);
164 }
165};
166
167} // namespace
brians343bc112013-02-10 01:53:46 +0000168
169// Converts T from network to host byte order.
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700170template <typename T>
171static inline T ntoh(T net) {
brians343bc112013-02-10 01:53:46 +0000172 return do_ntoh<sizeof(net), T>::apply(net);
brians343bc112013-02-10 01:53:46 +0000173}
174// Converts T from host to network byte order.
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700175template <typename T>
176static inline T hton(T host) {
brians343bc112013-02-10 01:53:46 +0000177 return do_hton<sizeof(host), T>::apply(host);
brians343bc112013-02-10 01:53:46 +0000178}
179
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700180template <typename T>
181static inline void to_host(const char *input, T *host) {
brians343bc112013-02-10 01:53:46 +0000182 do_ntoh<sizeof(*host), T>::copy(input, host);
brians343bc112013-02-10 01:53:46 +0000183}
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700184template <typename T>
185static inline void to_network(const T *host, char *output) {
brians343bc112013-02-10 01:53:46 +0000186 do_hton<sizeof(*host), T>::copy(host, output);
Brian Silvermanca20b6b2014-03-19 17:52:33 -0700187}
188
189template <size_t Size>
190static inline void to_host(const char *input, char *host) {
191 do_ntoh_int<Size>::copy(input, host);
192}
193template <size_t Size>
194static inline void to_network(const char *host, char *output) {
195 do_hton_int<Size>::copy(host, output);
brians343bc112013-02-10 01:53:46 +0000196}
197
198} // namespace aos
199
200#endif