From 75c8d2235b4acd40ca83cf81374cbdc91f419d37 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 16 Feb 2021 17:37:00 +0100 Subject: [PATCH] util/ByteOrder: add classes PackedBE16, PackedLE16, PackedLE32 --- src/util/ByteOrder.hxx | 148 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/src/util/ByteOrder.hxx b/src/util/ByteOrder.hxx index 48222854e..7ffde15bb 100644 --- a/src/util/ByteOrder.hxx +++ b/src/util/ByteOrder.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2015 Max Kellermann , + * Copyright 2011-2021 Max Kellermann , * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -254,4 +254,150 @@ FromLE16S(uint16_t value) noexcept return static_cast(FromLE16(value)); } +/** + * A packed big-endian 16 bit integer. + */ +class PackedBE16 { + uint8_t hi, lo; + +public: + PackedBE16() = default; + + constexpr PackedBE16(uint16_t src) noexcept + :hi(uint8_t(src >> 8)), + lo(uint8_t(src)) {} + + /** + * Construct an instance from an integer which is already + * big-endian. + */ + static constexpr auto FromBE(uint16_t src) noexcept { + union { + uint16_t in; + PackedBE16 out; + } u{src}; + return u.out; + } + + constexpr operator uint16_t() const noexcept { + return (uint16_t(hi) << 8) | uint16_t(lo); + } + + /** + * Reads the raw, big-endian value. + */ + constexpr uint16_t raw() const noexcept { + uint16_t x = *this; + if (IsLittleEndian()) + x = ByteSwap16(x); + return x; + } +}; + +static_assert(sizeof(PackedBE16) == sizeof(uint16_t), "Wrong size"); +static_assert(alignof(PackedBE16) == 1, "Wrong alignment"); + +/** + * A packed little-endian 16 bit integer. + */ +class PackedLE16 { + uint8_t lo, hi; + +public: + PackedLE16() = default; + + constexpr PackedLE16(uint16_t src) noexcept + :lo(uint8_t(src)), + hi(uint8_t(src >> 8)) {} + + /** + * Construct an instance from an integer which is already + * little-endian. + */ + static constexpr auto FromLE(uint16_t src) noexcept { + union { + uint16_t in; + PackedLE16 out; + } u{src}; + return u.out; + } + + constexpr operator uint16_t() const noexcept { + return (uint16_t(hi) << 8) | uint16_t(lo); + } + + PackedLE16 &operator=(uint16_t new_value) noexcept { + lo = uint8_t(new_value); + hi = uint8_t(new_value >> 8); + return *this; + } + + /** + * Reads the raw, little-endian value. + */ + constexpr uint16_t raw() const noexcept { + uint16_t x = *this; + if (IsBigEndian()) + x = ByteSwap16(x); + return x; + } +}; + +static_assert(sizeof(PackedLE16) == sizeof(uint16_t), "Wrong size"); +static_assert(alignof(PackedLE16) == 1, "Wrong alignment"); + +/** + * A packed little-endian 32 bit integer. + */ +class PackedLE32 { + uint8_t a, b, c, d; + +public: + PackedLE32() = default; + + constexpr PackedLE32(uint32_t src) noexcept + :a(uint8_t(src)), + b(uint8_t(src >> 8)), + c(uint8_t(src >> 16)), + d(uint8_t(src >> 24)) {} + + /** + * Construct an instance from an integer which is already + * little-endian. + */ + static constexpr auto FromLE(uint32_t src) noexcept { + union { + uint32_t in; + PackedLE32 out; + } u{src}; + return u.out; + } + + constexpr operator uint32_t() const noexcept { + return uint32_t(a) | (uint32_t(b) << 8) | + (uint32_t(c) << 16) | (uint32_t(d) << 24); + } + + PackedLE32 &operator=(uint32_t new_value) noexcept { + a = uint8_t(new_value); + b = uint8_t(new_value >> 8); + c = uint8_t(new_value >> 16); + d = uint8_t(new_value >> 24); + return *this; + } + + /** + * Reads the raw, little-endian value. + */ + constexpr uint32_t raw() const noexcept { + uint32_t x = *this; + if (IsBigEndian()) + x = ByteSwap32(x); + return x; + } +}; + +static_assert(sizeof(PackedLE32) == sizeof(uint32_t), "Wrong size"); +static_assert(alignof(PackedLE32) == 1, "Wrong alignment"); + #endif