[esp32_ble] Avoid string allocation when setting BLE device name (#12579)
This commit is contained in:
@@ -256,8 +256,11 @@ bool ESP32BLE::ble_setup_() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// BLE device names are limited to 20 characters
|
||||
// Buffer: 20 chars + null terminator
|
||||
constexpr size_t ble_name_max_len = 21;
|
||||
char name_buffer[ble_name_max_len];
|
||||
const char *device_name;
|
||||
std::string name_with_suffix;
|
||||
|
||||
if (this->name_ != nullptr) {
|
||||
if (App.is_name_add_mac_suffix_enabled()) {
|
||||
@@ -268,23 +271,28 @@ bool ESP32BLE::ble_setup_() {
|
||||
char mac_addr[mac_address_len];
|
||||
get_mac_address_into_buffer(mac_addr);
|
||||
const char *mac_suffix_ptr = mac_addr + mac_address_suffix_len;
|
||||
name_with_suffix =
|
||||
make_name_with_suffix(this->name_, strlen(this->name_), '-', mac_suffix_ptr, mac_address_suffix_len);
|
||||
device_name = name_with_suffix.c_str();
|
||||
make_name_with_suffix_to(name_buffer, sizeof(name_buffer), this->name_, strlen(this->name_), '-', mac_suffix_ptr,
|
||||
mac_address_suffix_len);
|
||||
device_name = name_buffer;
|
||||
} else {
|
||||
device_name = this->name_;
|
||||
}
|
||||
} else {
|
||||
name_with_suffix = App.get_name();
|
||||
if (name_with_suffix.length() > 20) {
|
||||
const std::string &app_name = App.get_name();
|
||||
size_t name_len = app_name.length();
|
||||
if (name_len > 20) {
|
||||
if (App.is_name_add_mac_suffix_enabled()) {
|
||||
// Keep first 13 chars and last 7 chars (MAC suffix), remove middle
|
||||
name_with_suffix.erase(13, name_with_suffix.length() - 20);
|
||||
memcpy(name_buffer, app_name.c_str(), 13);
|
||||
memcpy(name_buffer + 13, app_name.c_str() + name_len - 7, 7);
|
||||
} else {
|
||||
name_with_suffix.resize(20);
|
||||
memcpy(name_buffer, app_name.c_str(), 20);
|
||||
}
|
||||
name_buffer[20] = '\0';
|
||||
} else {
|
||||
memcpy(name_buffer, app_name.c_str(), name_len + 1); // Include null terminator
|
||||
}
|
||||
device_name = name_with_suffix.c_str();
|
||||
device_name = name_buffer;
|
||||
}
|
||||
|
||||
err = esp_ble_gap_set_device_name(device_name);
|
||||
|
||||
@@ -244,17 +244,16 @@ std::string str_sprintf(const char *fmt, ...) {
|
||||
// Maximum size for name with suffix: 120 (max friendly name) + 1 (separator) + 6 (MAC suffix) + 1 (null term)
|
||||
static constexpr size_t MAX_NAME_WITH_SUFFIX_SIZE = 128;
|
||||
|
||||
std::string make_name_with_suffix(const char *name, size_t name_len, char sep, const char *suffix_ptr,
|
||||
size_t suffix_len) {
|
||||
char buffer[MAX_NAME_WITH_SUFFIX_SIZE];
|
||||
size_t make_name_with_suffix_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, char sep,
|
||||
const char *suffix_ptr, size_t suffix_len) {
|
||||
size_t total_len = name_len + 1 + suffix_len;
|
||||
|
||||
// Silently truncate if needed: prioritize keeping the full suffix
|
||||
if (total_len >= MAX_NAME_WITH_SUFFIX_SIZE) {
|
||||
// NOTE: This calculation could underflow if suffix_len >= MAX_NAME_WITH_SUFFIX_SIZE - 2,
|
||||
if (total_len >= buffer_size) {
|
||||
// NOTE: This calculation could underflow if suffix_len >= buffer_size - 2,
|
||||
// but this is safe because this helper is only called with small suffixes:
|
||||
// MAC suffixes (6-12 bytes), ".local" (5 bytes), etc.
|
||||
name_len = MAX_NAME_WITH_SUFFIX_SIZE - suffix_len - 2; // -2 for separator and null terminator
|
||||
name_len = buffer_size - suffix_len - 2; // -2 for separator and null terminator
|
||||
total_len = name_len + 1 + suffix_len;
|
||||
}
|
||||
|
||||
@@ -262,7 +261,14 @@ std::string make_name_with_suffix(const char *name, size_t name_len, char sep, c
|
||||
buffer[name_len] = sep;
|
||||
memcpy(buffer + name_len + 1, suffix_ptr, suffix_len);
|
||||
buffer[total_len] = '\0';
|
||||
return std::string(buffer, total_len);
|
||||
return total_len;
|
||||
}
|
||||
|
||||
std::string make_name_with_suffix(const char *name, size_t name_len, char sep, const char *suffix_ptr,
|
||||
size_t suffix_len) {
|
||||
char buffer[MAX_NAME_WITH_SUFFIX_SIZE];
|
||||
size_t len = make_name_with_suffix_to(buffer, sizeof(buffer), name, name_len, sep, suffix_ptr, suffix_len);
|
||||
return std::string(buffer, len);
|
||||
}
|
||||
|
||||
std::string make_name_with_suffix(const std::string &name, char sep, const char *suffix_ptr, size_t suffix_len) {
|
||||
|
||||
@@ -549,6 +549,18 @@ std::string make_name_with_suffix(const std::string &name, char sep, const char
|
||||
std::string make_name_with_suffix(const char *name, size_t name_len, char sep, const char *suffix_ptr,
|
||||
size_t suffix_len);
|
||||
|
||||
/// Zero-allocation version: format name + separator + suffix directly into buffer.
|
||||
/// @param buffer Output buffer (must have space for result + null terminator)
|
||||
/// @param buffer_size Size of the output buffer
|
||||
/// @param name The base name string
|
||||
/// @param name_len Length of the name
|
||||
/// @param sep Single character separator
|
||||
/// @param suffix_ptr Pointer to the suffix characters
|
||||
/// @param suffix_len Length of the suffix
|
||||
/// @return Length written (excluding null terminator)
|
||||
size_t make_name_with_suffix_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, char sep,
|
||||
const char *suffix_ptr, size_t suffix_len);
|
||||
|
||||
///@}
|
||||
|
||||
/// @name Parsing & formatting
|
||||
|
||||
Reference in New Issue
Block a user