endian.cpp (2287B)
1 #include <cstddef> 2 #include <print> 3 #include <type_traits> 4 5 template<typename T> 6 T load_little(std::byte const (&p)[sizeof(T)]) 7 { 8 using U = std::make_unsigned_t<T>; 9 U accum = 0; 10 for (unsigned i = 0; i < sizeof(T); ++i) 11 accum |= std::to_integer<U>(p[i]) << (i * 8u); 12 return accum; 13 } 14 15 template<typename T> 16 T load_big(std::byte const (&p)[sizeof(T)]) 17 { 18 using U = std::make_unsigned_t<T>; 19 U accum = 0; 20 for (unsigned i = 0; i < sizeof(T); ++i) 21 accum |= std::to_integer<U>(p[i]) << ((sizeof(T) - i - 1u) * 8u); 22 return accum; 23 } 24 25 template<typename T> 26 void store_little(T v, std::byte (&p)[sizeof(T)]) 27 { 28 std::make_unsigned_t<T> u = v; 29 for (unsigned i = 0; i < sizeof(T); ++i) 30 p[i] = std::byte{static_cast<unsigned char>(u >> (i * 8u))}; 31 } 32 33 template<typename T> 34 void store_big(T v, std::byte (&p)[sizeof(T)]) 35 { 36 std::make_unsigned_t<T> u = v; 37 for (unsigned i = 0; i < sizeof(T); ++i) 38 p[i] = std::byte{static_cast<unsigned char>(u >> ((sizeof(T) - i - 1u) * 8u))}; 39 } 40 41 template <typename T> 42 struct little_endian 43 { 44 little_endian(T v) { store_little(v, bytes); } 45 46 operator T() const { return load_little<T>(bytes); } 47 private: 48 std::byte bytes[sizeof(T)]; 49 }; 50 51 template <typename T> 52 struct big_endian 53 { 54 big_endian(T v) 55 { 56 store_big(v, bytes); 57 } 58 59 operator T() const { 60 return load_big<T>(bytes); 61 } 62 private: 63 std::byte bytes[sizeof(T)]; 64 }; 65 66 std::byte buf[100]; 67 68 69 struct data 70 { 71 int a; 72 unsigned short b; 73 74 struct network_rep 75 { 76 network_rep(data const& d) : b{d.b}, a{d.a} {} 77 operator data() const { return data{a, b}; } 78 private: 79 little_endian<decltype(data::b)> b; 80 big_endian<decltype(data::a)> a; 81 }; 82 static_assert(sizeof(network_rep) == 6); 83 static_assert(alignof(network_rep) == 1); 84 }; 85 86 int main(int, char* argv[]) 87 { 88 unsigned char buf[] = {1,2,3,4,5,6,0}; 89 90 argv[0][2] = -1; 91 data d = *reinterpret_cast<data::network_rep*>(argv[0]); 92 std::println("{}", argv[0]); 93 std::println("{:08x} {:04x}", (unsigned)d.a, d.b); 94 std::println("{} {}", d.a, d.b); 95 *reinterpret_cast<data::network_rep*>(buf) = d; 96 for (auto b : buf) 97 std::print("{:02x} ", b); 98 std::println("\n{}", (char*)buf); 99 }