examples

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

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:
Asrc/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); +}