Lots more clean-ups
[invirt/third/libt4.git] / endian.h
1 #ifndef endian_h
2 #define endian_h
3
4 #include <cinttypes>
5
6 constexpr union { uint32_t i; uint8_t is_little_endian; } endianness{1};
7
8 inline uint8_t hton(uint8_t t) { return t; }
9 inline int8_t hton(int8_t t) { return t; }
10 inline uint16_t hton(uint16_t t) { return htons(t); }
11 inline int16_t hton(int16_t t) { return (int16_t)htons((uint16_t)t); }
12 inline uint32_t hton(uint32_t t) { return htonl(t); }
13 inline int32_t hton(int32_t t) { return (int32_t)htonl((uint32_t)t); }
14 inline uint64_t hton(uint64_t t) {
15     if (!endianness.is_little_endian)
16         return t;
17     return (uint64_t)htonl((uint32_t)(t >> 32)) | ((uint64_t)htonl((uint32_t)t) << 32);
18 }
19 inline int64_t hton(int64_t t) { return (int64_t)hton((uint64_t)t); }
20
21 template <class T> inline T ntoh(T t) { return hton(t); }
22
23 template <class... Args, size_t... Indices> inline tuple<typename remove_reference<Args>::type...>
24 tuple_hton_imp(tuple<Args...> && t, tuple_indices<Indices...>) {
25     return tuple<typename remove_reference<Args>::type...>(hton(get<Indices>(t))...);
26 }
27
28 template <class... Args> inline tuple<typename remove_reference<Args>::type...>
29 hton(tuple<Args...> && t) {
30     using Indices = typename make_tuple_indices<sizeof...(Args)>::type;
31     return tuple_hton_imp(forward<tuple<Args...>>(t), Indices());
32 }
33
34 #define ENDIAN_SWAPPABLE(_c_) \
35 inline _c_ hton(_c_ && t) { \
36     _c_ result; \
37     result._tuple_() = hton(t._tuple_()); \
38     return result; \
39 }
40
41 #endif