Motion Master 6.0.0-alpha.86
Next-generation motion control software
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <bit>
6#include <charconv>
7#include <cstddef>
8#include <cstdint>
9#include <format>
10#include <optional>
11#include <span>
12#include <string>
13#include <string_view>
14#include <type_traits>
15#include <vector>
16
17namespace mm::core {
18
31inline bool isUrlSafeId(std::string_view s) {
32 constexpr std::size_t kMaxLength = 64;
33 if (s.empty() || s.size() > kMaxLength) {
34 return false;
35 }
36 return std::all_of(s.begin(), s.end(), [](const char c) {
37 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' ||
38 c == '_' || c == '-';
39 });
40}
41
52template <typename T>
53std::optional<T> parseHexOrDec(std::string_view s) {
54 T value{};
55 std::from_chars_result r;
56 if (s.size() >= 2 && (s[0] == '0' || s[0] == '#') && (s[1] == 'x' || s[1] == 'X')) {
57 r = std::from_chars(s.data() + 2, s.data() + s.size(), value, 16);
58 } else {
59 r = std::from_chars(s.data(), s.data() + s.size(), value);
60 }
61 if (r.ec != std::errc{} || r.ptr != s.data() + s.size()) { // NOLINT(whitespace/braces)
62 return std::nullopt;
63 }
64 return value;
65}
66
75inline std::string toHex(std::span<const uint8_t> bytes, std::string_view separator = {}) {
76 std::string out;
77 out.reserve(bytes.size() * (2 + separator.size()));
78 for (std::size_t i = 0; i < bytes.size(); ++i) {
79 if (i != 0) {
80 out += separator;
81 }
82 out += std::format("{:02X}", bytes[i]);
83 }
84 return out;
85}
86
100inline std::optional<std::vector<uint8_t>> fromHex(std::string_view hex) {
101 if (hex.size() % 2 != 0) {
102 return std::nullopt;
103 }
104 const auto digit = [](char c) -> int {
105 if (c >= '0' && c <= '9') {
106 return c - '0';
107 }
108 if (c >= 'a' && c <= 'f') {
109 return c - 'a' + 10;
110 }
111 if (c >= 'A' && c <= 'F') {
112 return c - 'A' + 10;
113 }
114 return -1;
115 };
116 std::vector<uint8_t> out;
117 out.reserve(hex.size() / 2);
118 for (std::size_t i = 0; i < hex.size(); i += 2) {
119 const int hi = digit(hex[i]);
120 const int lo = digit(hex[i + 1]);
121 if (hi < 0 || lo < 0) {
122 return std::nullopt;
123 }
124 out.push_back(static_cast<uint8_t>((hi << 4) | lo));
125 }
126 return out;
127}
128
142template <typename T>
143std::array<uint8_t, sizeof(T)> toBytes(T value, std::endian order = std::endian::little) {
144 static_assert(std::is_integral_v<T>, "toBytes is for integral types");
145 using U = std::make_unsigned_t<T>;
146 const auto u = static_cast<U>(value);
147 std::array<uint8_t, sizeof(T)> out{};
148 for (std::size_t i = 0; i < sizeof(T); ++i) {
149 const std::size_t byte = (order == std::endian::little) ? i : (sizeof(T) - 1 - i);
150 out[byte] = static_cast<uint8_t>((u >> (8 * i)) & 0xFFu);
151 }
152 return out;
153}
154
166template <typename T>
167T fromBytes(std::span<const uint8_t> bytes, std::endian order = std::endian::little) {
168 static_assert(std::is_integral_v<T>, "fromBytes is for integral types");
169 using U = std::make_unsigned_t<T>;
170 U v = 0;
171 const std::size_t n = std::min(sizeof(T), bytes.size());
172 for (std::size_t i = 0; i < n; ++i) {
173 const std::size_t shift = (order == std::endian::little) ? (8 * i) : (8 * (n - 1 - i));
174 v |= static_cast<U>(bytes[i]) << shift;
175 }
176 return static_cast<T>(v);
177}
178
179} // namespace mm::core
Definition http_server.h:25
std::optional< std::vector< uint8_t > > fromHex(std::string_view hex)
Decodes a continuous hexadecimal string into bytes — the inverse of toHex.
Definition util.h:100
std::optional< T > parseHexOrDec(std::string_view s)
Parses an unsigned integer from a string in decimal or hexadecimal notation.
Definition util.h:53
std::array< uint8_t, sizeof(T)> toBytes(T value, std::endian order=std::endian::little)
Encodes an integer into a fixed-width byte array in the given byte order.
Definition util.h:143
bool isUrlSafeId(std::string_view s)
Whether s is a valid URL-safe identifier usable as a path segment and pub/sub topic.
Definition util.h:31
std::string toHex(std::span< const uint8_t > bytes, std::string_view separator={})
Formats bytes as uppercase hexadecimal.
Definition util.h:75
T fromBytes(std::span< const uint8_t > bytes, std::endian order=std::endian::little)
Decodes an integer from a raw byte buffer interpreted in the given byte order.
Definition util.h:167