QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
LittleEndian.h
Go to the documentation of this file.
1#pragma once
2
3#include <bit>
4#include <concepts>
5#include <cstddef>
6#include <cstdint>
7#include <limits>
8#include <optional>
9#include <span>
10#include <type_traits>
11
12namespace LittleEndian {
13
14template <typename T>
15concept Scalar = ((std::integral<T> && !std::same_as<std::remove_cv_t<T>, bool>) || std::floating_point<T>) &&
16 (sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
17
18template <Scalar T>
19using Bits = std::conditional_t<
20 sizeof(T) == 1, uint8_t,
21 std::conditional_t<sizeof(T) == 2, uint16_t, std::conditional_t<sizeof(T) == 4, uint32_t, uint64_t>>>;
22
24template <Scalar T>
25[[nodiscard]] constexpr std::optional<T> read(std::span<const uint8_t> bytes, std::size_t offset = 0)
26{
27 static_assert(!std::floating_point<T> || std::numeric_limits<T>::is_iec559);
28 if (offset > bytes.size() || sizeof(T) > bytes.size() - offset) {
29 return std::nullopt;
30 }
31
32 uint64_t bits = 0;
33 for (std::size_t i = 0; i < sizeof(T); ++i) {
34 bits |= uint64_t{bytes[offset + i]} << (8 * i);
35 }
36 return std::bit_cast<T>(static_cast<Bits<T>>(bits));
37}
38
40template <Scalar T>
41[[nodiscard]] constexpr bool write(std::span<uint8_t> bytes, std::size_t offset, T value)
42{
43 static_assert(!std::floating_point<T> || std::numeric_limits<T>::is_iec559);
44 if (offset > bytes.size() || sizeof(T) > bytes.size() - offset) {
45 return false;
46 }
47
48 const auto bits = std::bit_cast<Bits<T>>(value);
49 for (std::size_t i = 0; i < sizeof(T); ++i) {
50 bytes[offset + i] = static_cast<uint8_t>(bits >> (8 * i));
51 }
52 return true;
53}
54
55} // namespace LittleEndian
constexpr std::optional< T > read(std::span< const uint8_t > bytes, std::size_t offset=0)
Decode an unaligned little-endian scalar, returning nullopt when its bytes are unavailable.
std::conditional_t< sizeof(T)==1, uint8_t, std::conditional_t< sizeof(T)==2, uint16_t, std::conditional_t< sizeof(T)==4, uint32_t, uint64_t > > > Bits
constexpr bool write(std::span< uint8_t > bytes, std::size_t offset, T value)
Encode an unaligned little-endian scalar. Insufficient space leaves the destination unchanged.