commit 53d4fc03a514f94f3957ce475b6dee9771093faf
parent e8129215852034a143fdd6a5bed5e50353afbf64
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Thu, 10 Oct 2024 13:24:00 +0000
endian: Add example for binary data exchange
Diffstat:
A | src/endian.cpp | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 99 insertions(+), 0 deletions(-)
diff --git a/src/endian.cpp b/src/endian.cpp
@@ -0,0 +1,99 @@
+#include <cstddef>
+#include <print>
+#include <type_traits>
+
+template<typename T>
+T load_little(std::byte const (&p)[sizeof(T)])
+{
+ using U = std::make_unsigned_t<T>;
+ U accum = 0;
+ for (unsigned i = 0; i < sizeof(T); ++i)
+ accum |= std::to_integer<U>(p[i]) << (i * 8u);
+ return accum;
+}
+
+template<typename T>
+T load_big(std::byte const (&p)[sizeof(T)])
+{
+ using U = std::make_unsigned_t<T>;
+ U accum = 0;
+ for (unsigned i = 0; i < sizeof(T); ++i)
+ accum |= std::to_integer<U>(p[i]) << ((sizeof(T) - i - 1u) * 8u);
+ return accum;
+}
+
+template<typename T>
+void store_little(T v, std::byte (&p)[sizeof(T)])
+{
+ std::make_unsigned_t<T> u = v;
+ for (unsigned i = 0; i < sizeof(T); ++i)
+ p[i] = std::byte{static_cast<unsigned char>(u >> (i * 8u))};
+}
+
+template<typename T>
+void store_big(T v, std::byte (&p)[sizeof(T)])
+{
+ std::make_unsigned_t<T> u = v;
+ for (unsigned i = 0; i < sizeof(T); ++i)
+ p[i] = std::byte{static_cast<unsigned char>(u >> ((sizeof(T) - i - 1u) * 8u))};
+}
+
+template <typename T>
+struct little_endian
+{
+ little_endian(T v) { store_little(v, bytes); }
+
+ operator T() const { return load_little<T>(bytes); }
+private:
+ std::byte bytes[sizeof(T)];
+};
+
+template <typename T>
+struct big_endian
+{
+ big_endian(T v)
+ {
+ store_big(v, bytes);
+ }
+
+ operator T() const {
+ return load_big<T>(bytes);
+ }
+private:
+ std::byte bytes[sizeof(T)];
+};
+
+std::byte buf[100];
+
+
+struct data
+{
+ int a;
+ unsigned short b;
+
+ struct network_rep
+ {
+ network_rep(data const& d) : b{d.b}, a{d.a} {}
+ operator data() const { return data{a, b}; }
+ private:
+ little_endian<decltype(data::b)> b;
+ big_endian<decltype(data::a)> a;
+ };
+ static_assert(sizeof(network_rep) == 6);
+ static_assert(alignof(network_rep) == 1);
+};
+
+int main(int, char* argv[])
+{
+ unsigned char buf[] = {1,2,3,4,5,6,0};
+
+ argv[0][2] = -1;
+ data d = *reinterpret_cast<data::network_rep*>(argv[0]);
+ std::println("{}", argv[0]);
+ std::println("{:08x} {:04x}", (unsigned)d.a, d.b);
+ std::println("{} {}", d.a, d.b);
+ *reinterpret_cast<data::network_rep*>(buf) = d;
+ for (auto b : buf)
+ std::print("{:02x} ", b);
+ std::println("\n{}", (char*)buf);
+}