So many changes. Broken.
[invirt/third/libt4.git] / include / endian.h
1 #ifndef endian_h
2 #define endian_h
3
4 #include <cinttypes>
5 #include <arpa/inet.h>
6
7 constexpr union { uint32_t i; uint8_t is_little_endian; } endianness{1};
8
9 inline uint8_t hton(uint8_t t) { return t; }
10 inline int8_t hton(int8_t t) { return t; }
11 inline uint16_t hton(uint16_t t) { return htons(t); }
12 inline int16_t hton(int16_t t) { return (int16_t)htons((uint16_t)t); }
13 inline uint32_t hton(uint32_t t) { return htonl(t); }
14 inline int32_t hton(int32_t t) { return (int32_t)htonl((uint32_t)t); }
15 inline uint64_t hton(uint64_t t) {
16     if (!endianness.is_little_endian)
17         return t;
18     return (uint64_t)htonl((uint32_t)(t >> 32)) | ((uint64_t)htonl((uint32_t)t) << 32);
19 }
20 inline int64_t hton(int64_t t) { return (int64_t)hton((uint64_t)t); }
21
22 template <class T> inline T ntoh(T t) { return hton(t); }
23
24 template <class... Args, size_t... Indices>
25 inline tuple<typename std::remove_reference<Args>::type...>
26 tuple_hton_imp(tuple<Args...> && t, std::index_sequence<Indices...>) {
27     return tuple<
28         typename std::remove_reference<Args>::type...
29     >(hton(std::get<Indices>(t))...);
30 }
31
32 template <class... Args>
33 inline tuple<typename std::remove_reference<Args>::type...>
34 hton(tuple<Args...> && t) {
35     return tuple_hton_imp(std::forward<tuple<Args...>>(t), std::index_sequence_for<Args...>{});
36 }
37
38 template <class T> inline typename
39 enable_if<is_tuple_convertible<T>::value, T>::type
40 hton(T && t) {
41     T result;
42     result._tuple_() = hton(t._tuple_());
43     return result;
44 }
45
46 #endif