mirror of
https://github.com/esphome/esphome.git
synced 2026-01-09 19:50:49 -07:00
[core] Add format_hex_to helper for zero-allocation hex formatting (#12670)
This commit is contained in:
@@ -49,7 +49,8 @@ void OneWireBus::search() {
|
||||
break;
|
||||
auto *address8 = reinterpret_cast<uint8_t *>(&address);
|
||||
if (crc8(address8, 7) != address8[7]) {
|
||||
ESP_LOGW(TAG, "Dallas device 0x%s has invalid CRC.", format_hex(address).c_str());
|
||||
char hex_buf[17];
|
||||
ESP_LOGW(TAG, "Dallas device 0x%s has invalid CRC.", format_hex_to(hex_buf, address));
|
||||
} else {
|
||||
this->devices_.push_back(address);
|
||||
}
|
||||
@@ -82,8 +83,9 @@ void OneWireBus::dump_devices_(const char *tag) {
|
||||
ESP_LOGW(tag, " Found no devices!");
|
||||
} else {
|
||||
ESP_LOGCONFIG(tag, " Found devices:");
|
||||
char hex_buf[17]; // uint64_t = 16 hex chars + null
|
||||
for (auto &address : this->devices_) {
|
||||
ESP_LOGCONFIG(tag, " 0x%s (%s)", format_hex(address).c_str(), LOG_STR_ARG(get_model_str(address & 0xff)));
|
||||
ESP_LOGCONFIG(tag, " 0x%s (%s)", format_hex_to(hex_buf, address), LOG_STR_ARG(get_model_str(address & 0xff)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,7 +527,9 @@ void SX126x::dump_config() {
|
||||
this->spreading_factor_, cr, this->preamble_size_);
|
||||
}
|
||||
if (!this->sync_value_.empty()) {
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s", format_hex(this->sync_value_).c_str());
|
||||
char hex_buf[17]; // 8 bytes max = 16 hex chars + null
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s",
|
||||
format_hex_to(hex_buf, this->sync_value_.data(), this->sync_value_.size()));
|
||||
}
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Configuring SX126x failed");
|
||||
|
||||
@@ -476,7 +476,9 @@ void SX127x::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Payload Length: %" PRIu32, this->payload_length_);
|
||||
}
|
||||
if (!this->sync_value_.empty()) {
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s", format_hex(this->sync_value_).c_str());
|
||||
char hex_buf[17]; // 8 bytes max = 16 hex chars + null
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s",
|
||||
format_hex_to(hex_buf, this->sync_value_.data(), this->sync_value_.size()));
|
||||
}
|
||||
if (this->preamble_size_ > 0 || this->preamble_detect_ > 0) {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
|
||||
@@ -297,6 +297,19 @@ std::string format_hex(const uint8_t *data, size_t length) {
|
||||
}
|
||||
std::string format_hex(const std::vector<uint8_t> &data) { return format_hex(data.data(), data.size()); }
|
||||
|
||||
char *format_hex_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length) {
|
||||
size_t max_bytes = (buffer_size - 1) / 2;
|
||||
if (length > max_bytes) {
|
||||
length = max_bytes;
|
||||
}
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
buffer[2 * i] = format_hex_char(data[i] >> 4);
|
||||
buffer[2 * i + 1] = format_hex_char(data[i] & 0x0F);
|
||||
}
|
||||
buffer[length * 2] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Shared implementation for uint8_t and string hex formatting
|
||||
static std::string format_hex_pretty_uint8(const uint8_t *data, size_t length, char separator, bool show_length) {
|
||||
if (data == nullptr || length == 0)
|
||||
|
||||
@@ -730,6 +730,24 @@ inline void format_mac_addr_lower_no_sep(const uint8_t *mac, char *output) {
|
||||
output[12] = '\0';
|
||||
}
|
||||
|
||||
/// Format byte array as lowercase hex to buffer (base implementation).
|
||||
char *format_hex_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length);
|
||||
|
||||
/// Format byte array as lowercase hex to buffer. Automatically deduces buffer size.
|
||||
/// Truncates output if data exceeds buffer capacity. Returns pointer to buffer.
|
||||
template<size_t N> inline char *format_hex_to(char (&buffer)[N], const uint8_t *data, size_t length) {
|
||||
static_assert(N >= 3, "Buffer must hold at least one hex byte (3 chars)");
|
||||
return format_hex_to(buffer, N, data, length);
|
||||
}
|
||||
|
||||
/// Format an unsigned integer in lowercased hex to buffer, starting with the most significant byte.
|
||||
template<size_t N, typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0>
|
||||
inline char *format_hex_to(char (&buffer)[N], T val) {
|
||||
static_assert(N >= sizeof(T) * 2 + 1, "Buffer too small for type");
|
||||
val = convert_big_endian(val);
|
||||
return format_hex_to(buffer, reinterpret_cast<const uint8_t *>(&val), sizeof(T));
|
||||
}
|
||||
|
||||
/// Format the six-byte array \p mac into a MAC address.
|
||||
std::string format_mac_address_pretty(const uint8_t mac[6]);
|
||||
/// Format the byte array \p data of length \p len in lowercased hex.
|
||||
|
||||
Reference in New Issue
Block a user