examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

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 }