Motion Master
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <bit>
5#include <charconv>
6#include <chrono>
7#include <condition_variable>
8#include <cstdint>
9#include <cstring>
10#include <fstream>
11#include <iostream>
12#include <iterator>
13#include <map>
14#include <memory>
15#include <mutex>
16#include <optional>
17#include <queue>
18#include <set>
19#include <sstream>
20#include <string>
21#include <string_view>
22#include <thread>
23#include <type_traits>
24#include <typeindex>
25#include <unordered_map>
26#include <utility>
27#include <variant>
28#include <vector>
29
30#include <nlohmann/json.hpp>
31
32namespace mm::core::util {
33
52template <typename T>
53T parseHex(const std::string& s) {
54 static_assert(std::is_unsigned<T>::value,
55 "parseHex only supports unsigned integer types");
56
57 // Use the appropriate std::stoul or std::stoull depending on size
58 if constexpr (sizeof(T) <= sizeof(uint64_t)) {
59 // Use std::stoul
60 return static_cast<T>(std::stoul(s, nullptr, 16));
61 } else {
62 // Use std::stoull for larger types like uint64_t
63 return static_cast<T>(std::stoull(s, nullptr, 16));
64 }
65}
66
77enum class Endianness { LITTLE, BIG };
78
102template <typename T>
103T toInteger(const std::vector<std::uint8_t>& data, std::size_t offset = 0,
105 // Ensure T is an integral type
106 static_assert(std::is_integral<T>::value, "T must be an integral type");
107
108 // Use unsigned type for accumulation to avoid sign extension issues
109 using U = typename std::make_unsigned<T>::type;
110 U value = 0;
111
112 // Check if offset is within bounds
113 // If offset is greater than the size of data, return 0
114 std::size_t remaining = (data.size() > offset) ? (data.size() - offset) : 0;
115 std::size_t byteCount = (sizeof(T) < remaining) ? sizeof(T) : remaining;
116
117 if (endian == Endianness::LITTLE) {
118 for (std::size_t i = 0; i < byteCount; ++i) {
119 value |= static_cast<U>(data[offset + i]) << (8 * i);
120 }
121 } else {
122 for (std::size_t i = 0; i < byteCount; ++i) {
123 value |= static_cast<U>(data[offset + i]) << (8 * (sizeof(T) - 1 - i));
124 }
125 }
126
127 return static_cast<T>(value);
128}
129
137std::vector<std::vector<uint8_t>> splitIntoParts(
138 const std::vector<uint8_t>& input, size_t partSize);
139
158std::vector<uint8_t> zipData(const std::string& filename,
159 const std::vector<uint8_t>& data);
160
177std::unordered_map<std::string, std::vector<uint8_t>> unzipData(
178 const std::vector<uint8_t>& data);
179
196template <typename T>
197bool stringViewToNumber(std::string_view sv, T& result) {
198 static_assert(std::is_arithmetic_v<T>, "T must be an arithmetic type");
199
200 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
201 return ec == std::errc();
202}
203
219template <typename T>
220std::vector<uint8_t> toBytes(T value, bool bigEndian = false) {
221 static_assert(std::is_trivially_copyable<T>::value,
222 "T must be trivially copyable");
223
224 std::vector<uint8_t> bytes(sizeof(T));
225 std::memcpy(bytes.data(), &value, sizeof(T));
226
227 if (bigEndian) {
228 std::reverse(bytes.begin(), bytes.end());
229 }
230
231 return bytes;
232}
233
254template <typename T>
255T fromBytes(const std::vector<uint8_t>& bytes, bool bigEndian = false) {
256 static_assert(std::is_trivially_copyable<T>::value,
257 "T must be trivially copyable");
258
259 if (bytes.size() != sizeof(T)) {
260 throw std::invalid_argument(
261 "Byte vector size does not match target type size");
262 }
263
264 std::vector<uint8_t> temp = bytes;
265
266 if (bigEndian) {
267 std::reverse(temp.begin(), temp.end());
268 }
269
270 T value;
271 std::memcpy(&value, temp.data(), sizeof(T));
272 return value;
273}
274
289inline std::string makeParameterId(int index, int subindex) {
290 std::stringstream oss;
291 // Format index and subindex into "0xINDEX:SUBINDEX"
292 oss << "0x" << std::setw(4) << std::setfill('0') << std::hex << std::uppercase
293 << index << ":" << std::setw(2) << std::setfill('0') << std::hex
294 << std::uppercase << subindex;
295
296 return oss.str();
297}
298
310inline std::string toHex(const std::vector<uint8_t>& data) {
311 std::ostringstream oss;
312 oss << std::uppercase; // Ensure hex letters are uppercase
313 for (size_t i = 0; i < data.size(); ++i) {
314 oss << "0x" << std::hex << std::setw(2) << std::setfill('0')
315 << static_cast<int>(data[i]);
316 if (i != data.size() - 1) {
317 oss << " ";
318 }
319 }
320 return oss.str();
321}
322
336template <typename T>
337inline std::string toHex(T value) {
338 static_assert(std::is_integral<T>::value, "toHex requires an integer type");
339 constexpr size_t hexWidth = sizeof(T) * 2;
340
341 std::ostringstream oss;
342 oss << "0x" << std::hex << std::uppercase << std::setw(hexWidth)
343 << std::setfill('0') << static_cast<uint64_t>(value);
344 return oss.str();
345}
346
358std::vector<uint8_t> readBinaryFile(const std::string& filename);
359
368std::string readTextFile(const std::string& filename);
369
382std::string joinStrings(const std::vector<std::string>& list,
383 const std::string& delimiter);
384
399std::string formatMacAddress(const std::string& originalMacAddress);
400
410std::string extractIpAddress(const std::string& socketAddress);
411
423uint16_t extractPort(const std::string& socketAddress);
424
432inline bool endsWith(const std::string& str, const std::string& suffix) {
433 return str.size() >= suffix.size() &&
434 std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
435}
436
444inline size_t countStringsStartingWith(const std::vector<std::string>& strings,
445 const std::string& prefix) {
446 return std::count_if(
447 strings.begin(), strings.end(), [&](const std::string& s) {
448 return s.rfind(prefix, 0) == 0; // checks if s starts with prefix
449 });
450}
451
463inline std::vector<std::string> split(const std::string& input,
464 char delimiter) {
465 std::vector<std::string> result;
466 std::istringstream stream(input);
467 std::string token;
468
469 while (std::getline(stream, token, delimiter)) {
470 result.push_back(token);
471 }
472
473 return result;
474}
475
485inline int64_t currentTimeMillis() {
486 // Get current time point from system clock
487 auto now = std::chrono::system_clock::now();
488
489 // Convert to duration since epoch in milliseconds
490 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
491 now.time_since_epoch());
492
493 // Return the count as an integer (int64_t)
494 return duration.count();
495}
496
508template <typename T>
509inline constexpr T linearScale(T value, T inMin, T inMax, T outMin, T outMax) {
510 static_assert(std::is_arithmetic<T>::value,
511 "linearScale requires a numeric type");
512 return outMin + (value - inMin) * (outMax - outMin) / (inMax - inMin);
513}
514
515} // namespace mm::core::util
516
527namespace std {
528template <>
529struct hash<std::pair<uint16_t, uint8_t>> {
540 size_t operator()(const std::pair<uint16_t, uint8_t>& p) const {
541 return hash<uint16_t>()(p.first) ^ (hash<uint8_t>()(p.second) << 1);
542 }
543};
544
545} // namespace std
uint8_t * value
Definition co_dictionary.h:9
uint16_t index
Definition co_dictionary.h:0
Definition util.cc:15
std::string joinStrings(const std::vector< std::string > &list, const std::string &delimiter)
Joins a list of strings into a single string with a delimiter.
Definition util.cc:156
bool stringViewToNumber(std::string_view sv, T &result)
Converts a string_view to a numeric type.
Definition util.h:197
std::vector< std::vector< uint8_t > > splitIntoParts(const std::vector< uint8_t > &input, size_t partSize)
Splits a byte vector into parts of a specified maximum size.
Definition util.cc:17
int64_t currentTimeMillis()
Gets the current system time in milliseconds since the Unix epoch.
Definition util.h:485
std::vector< uint8_t > zipData(const std::string &filename, const std::vector< uint8_t > &data)
Compresses a block of data into a ZIP archive containing a single file.
Definition util.cc:35
Endianness
Specifies the byte order used when converting a byte sequence to an integer.
Definition util.h:77
@ LITTLE
Definition util.h:77
@ BIG
Definition util.h:77
size_t countStringsStartingWith(const std::vector< std::string > &strings, const std::string &prefix)
Count how many strings in the list start with the given prefix.
Definition util.h:444
T parseHex(const std::string &s)
Parses a hexadecimal string into an unsigned integer of type T.
Definition util.h:53
std::string readTextFile(const std::string &filePath)
Reads the entire content of a text file into a std::string.
Definition util.cc:142
bool endsWith(const std::string &str, const std::string &suffix)
Checks whether a string ends with the given suffix.
Definition util.h:432
std::vector< std::string > split(const std::string &input, char delimiter)
Splits a string into substrings based on a delimiter character.
Definition util.h:463
std::string extractIpAddress(const std::string &socketAddress)
Extracts the IP address from a socket address string.
Definition util.cc:195
constexpr T linearScale(T value, T inMin, T inMax, T outMin, T outMax)
Definition util.h:509
T fromBytes(const std::vector< uint8_t > &bytes, bool bigEndian=false)
Reconstructs a value of type T from a byte vector.
Definition util.h:255
std::string toHex(const std::vector< uint8_t > &data)
Converts a vector of bytes to a space-separated hexadecimal string.
Definition util.h:310
std::string formatMacAddress(const std::string &originalMacAddress)
Formats a MAC address string to ensure each component is two digits and uppercase.
Definition util.cc:171
uint16_t extractPort(const std::string &socketAddress)
Extracts the port number from a socket address string.
Definition util.cc:203
std::string makeParameterId(int index, int subindex)
Formats the given index and subindex into a parameter identifier string.
Definition util.h:289
std::unordered_map< std::string, std::vector< uint8_t > > unzipData(const std::vector< uint8_t > &data)
Unzips a ZIP archive from an in-memory byte buffer.
Definition util.cc:70
T toInteger(const std::vector< std::uint8_t > &data, std::size_t offset=0, Endianness endian=Endianness::LITTLE)
Converts a byte sequence to an integer of type T with optional offset and endianness.
Definition util.h:103
std::vector< uint8_t > readBinaryFile(const std::string &filePath)
Reads the entire contents of a binary file into a byte vector.
Definition util.cc:129
std::vector< uint8_t > toBytes(T value, bool bigEndian=false)
Converts a trivially copyable value to a byte vector.
Definition util.h:220
Specialization of std::hash for std::pair<uint16_t, uint8_t>.
Definition util.h:527
size_t operator()(const std::pair< uint16_t, uint8_t > &p) const
Computes a hash for a given std::pair<uint16_t, uint8_t>.
Definition util.h:540