mirror of
https://github.com/esphome/esphome.git
synced 2025-09-12 16:22:22 +01:00
Introduce hex parsing & formatting helper functions (#2882)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
@@ -45,8 +46,6 @@ std::string to_string(unsigned long long val); // NOLINT
|
||||
std::string to_string(float val);
|
||||
std::string to_string(double val);
|
||||
std::string to_string(long double val);
|
||||
optional<int> parse_hex(const std::string &str, size_t start, size_t length);
|
||||
optional<int> parse_hex(char chr);
|
||||
|
||||
/// Compare string a to string b (ignoring case) and return whether they are equal.
|
||||
bool str_equals_case_insensitive(const std::string &a, const std::string &b);
|
||||
@@ -186,10 +185,6 @@ enum ParseOnOffState {
|
||||
|
||||
ParseOnOffState parse_on_off(const char *str, const char *on = nullptr, const char *off = nullptr);
|
||||
|
||||
// Encode raw data to a human-readable string (for debugging)
|
||||
std::string hexencode(const uint8_t *data, uint32_t len);
|
||||
template<typename T> std::string hexencode(const T &data) { return hexencode(data.data(), data.size()); }
|
||||
|
||||
// https://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer/7858971#7858971
|
||||
template<int...> struct seq {}; // NOLINT
|
||||
template<int N, int... S> struct gens : gens<N - 1, N - 1, S...> {}; // NOLINT
|
||||
@@ -408,6 +403,77 @@ optional<T> parse_number(const std::string &str) {
|
||||
return parse_number<T>(str.c_str());
|
||||
}
|
||||
|
||||
/** Parse bytes from a hex-encoded string into a byte array.
|
||||
*
|
||||
* When \p len is less than \p 2*count, the result is written to the back of \p data (i.e. this function treats \p str
|
||||
* as if it were padded with zeros at the front).
|
||||
*
|
||||
* @param str String to read from.
|
||||
* @param len Length of \p str (excluding optional null-terminator), is a limit on the number of characters parsed.
|
||||
* @param data Byte array to write to.
|
||||
* @param count Length of \p data.
|
||||
* @return The number of characters parsed from \p str.
|
||||
*/
|
||||
size_t parse_hex(const char *str, size_t len, uint8_t *data, size_t count);
|
||||
/// Parse \p count bytes from the hex-encoded string \p str of at least \p 2*count characters into array \p data.
|
||||
inline bool parse_hex(const char *str, uint8_t *data, size_t count) {
|
||||
return parse_hex(str, strlen(str), data, count) == 2 * count;
|
||||
}
|
||||
/// Parse \p count bytes from the hex-encoded string \p str of at least \p 2*count characters into array \p data.
|
||||
inline bool parse_hex(const std::string &str, uint8_t *data, size_t count) {
|
||||
return parse_hex(str.c_str(), str.length(), data, count) == 2 * count;
|
||||
}
|
||||
/// Parse \p count bytes from the hex-encoded string \p str of at least \p 2*count characters into vector \p data.
|
||||
inline bool parse_hex(const char *str, std::vector<uint8_t> &data, size_t count) {
|
||||
data.resize(count);
|
||||
return parse_hex(str, strlen(str), data.data(), count) == 2 * count;
|
||||
}
|
||||
/// Parse \p count bytes from the hex-encoded string \p str of at least \p 2*count characters into vector \p data.
|
||||
inline bool parse_hex(const std::string &str, std::vector<uint8_t> &data, size_t count) {
|
||||
data.resize(count);
|
||||
return parse_hex(str.c_str(), str.length(), data.data(), count) == 2 * count;
|
||||
}
|
||||
/** Parse a hex-encoded string into an unsigned integer.
|
||||
*
|
||||
* @param str String to read from, starting with the most significant byte.
|
||||
* @param len Length of \p str (excluding optional null-terminator), is a limit on the number of characters parsed.
|
||||
*/
|
||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0>
|
||||
optional<T> parse_hex(const char *str, size_t len) {
|
||||
T val = 0;
|
||||
if (len > 2 * sizeof(T) || parse_hex(str, len, reinterpret_cast<uint8_t *>(&val), sizeof(T)) == 0)
|
||||
return {};
|
||||
return convert_big_endian(val);
|
||||
}
|
||||
/// Parse a hex-encoded null-terminated string (starting with the most significant byte) into an unsigned integer.
|
||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> optional<T> parse_hex(const char *str) {
|
||||
return parse_hex<T>(str, strlen(str));
|
||||
}
|
||||
/// Parse a hex-encoded null-terminated string (starting with the most significant byte) into an unsigned integer.
|
||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> optional<T> parse_hex(const std::string &str) {
|
||||
return parse_hex<T>(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
/// Format the byte array \p data of length \p len in lowercased hex.
|
||||
std::string format_hex(const uint8_t *data, size_t length);
|
||||
/// Format the vector \p data in lowercased hex.
|
||||
std::string format_hex(std::vector<uint8_t> data);
|
||||
/// Format an unsigned integer in lowercased hex, starting with the most significant byte.
|
||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::string format_hex(T val) {
|
||||
val = convert_big_endian(val);
|
||||
return format_hex(reinterpret_cast<uint8_t *>(&val), sizeof(T));
|
||||
}
|
||||
|
||||
/// Format the byte array \p data of length \p len in pretty-printed, human-readable hex.
|
||||
std::string format_hex_pretty(const uint8_t *data, size_t length);
|
||||
/// Format the vector \p data in pretty-printed, human-readable hex.
|
||||
std::string format_hex_pretty(std::vector<uint8_t> data);
|
||||
/// Format an unsigned integer in pretty-printed, human-readable hex, starting with the most significant byte.
|
||||
template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> std::string format_hex_pretty(T val) {
|
||||
val = convert_big_endian(val);
|
||||
return format_hex_pretty(reinterpret_cast<uint8_t *>(&val), sizeof(T));
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
/// @name Number manipulation
|
||||
@@ -420,4 +486,18 @@ template<typename T, typename U> T remap(U value, U min, U max, T min_out, T max
|
||||
|
||||
///@}
|
||||
|
||||
/// @name Deprecated functions
|
||||
///@{
|
||||
|
||||
ESPDEPRECATED("hexencode() is deprecated, use format_hex_pretty() instead.", "2022.1")
|
||||
inline std::string hexencode(const uint8_t *data, uint32_t len) { return format_hex_pretty(data, len); }
|
||||
|
||||
template<typename T>
|
||||
ESPDEPRECATED("hexencode() is deprecated, use format_hex_pretty() instead.", "2022.1")
|
||||
std::string hexencode(const T &data) {
|
||||
return hexencode(data.data(), data.size());
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
} // namespace esphome
|
||||
|
Reference in New Issue
Block a user