mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 02:02:51 +00:00
Fold dev's ProgmemStringRef struct into the class and share the progmem short string body
This commit is contained in:
@@ -410,7 +410,7 @@ class ProtoEncode {
|
||||
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint8_t tag, const StringRef &ref) {
|
||||
#ifdef USE_ESP8266
|
||||
// memcpy_P reads RAM too, so RAM strings share the progmem copy
|
||||
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
|
||||
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
|
||||
#else
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
@@ -424,7 +424,6 @@ class ProtoEncode {
|
||||
#endif
|
||||
}
|
||||
/// encode_short_string_force for a string that may be in flash (PROGMEM).
|
||||
#ifdef USE_ESP8266
|
||||
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
@@ -436,12 +435,6 @@ class ProtoEncode {
|
||||
progmem_memcpy(pos + 2, ref.progmem_ptr(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
}
|
||||
#else
|
||||
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
|
||||
return encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ref.ram_ref());
|
||||
}
|
||||
#endif
|
||||
/// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field.
|
||||
[[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, uint32_t value) {
|
||||
|
||||
+10
-19
@@ -190,24 +190,6 @@ inline bool operator!=(const StringRef &lhs, const __FlashStringHelper *rhs) { r
|
||||
|
||||
inline bool operator!=(const __FlashStringHelper *lhs, const StringRef &rhs) { return !(rhs == lhs); }
|
||||
|
||||
/// Codegen use only: a flash string literal with its byte length, compared without a runtime strlen.
|
||||
struct ProgmemStringRef {
|
||||
PGM_P str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
inline bool operator==(const std::string &lhs, ProgmemStringRef rhs) {
|
||||
return lhs.size() == rhs.len && (rhs.len == 0 || memcmp_P(lhs.data(), rhs.str, rhs.len) == 0);
|
||||
}
|
||||
|
||||
inline bool operator!=(const std::string &lhs, ProgmemStringRef rhs) { return !(lhs == rhs); }
|
||||
|
||||
inline bool operator==(const StringRef &lhs, ProgmemStringRef rhs) {
|
||||
// A StringRef may be {nullptr, 0}, and memcmp_P with a null pointer is undefined even for 0 bytes
|
||||
return lhs.size() == rhs.len && (rhs.len == 0 || memcmp_P(lhs.c_str(), rhs.str, rhs.len) == 0);
|
||||
}
|
||||
|
||||
inline bool operator!=(const StringRef &lhs, ProgmemStringRef rhs) { return !(lhs == rhs); }
|
||||
#endif // USE_ESP8266
|
||||
|
||||
inline bool operator<(const StringRef &lhs, const StringRef &rhs) {
|
||||
@@ -271,7 +253,9 @@ class ProgmemStringRef {
|
||||
|
||||
bool equals(const StringRef &other) const {
|
||||
#ifdef USE_ESP8266
|
||||
return other.size() == this->ref_.size() && memcmp_P(other.c_str(), this->ref_.c_str(), other.size()) == 0;
|
||||
// A StringRef may be {nullptr, 0}, and memcmp_P with a null pointer is undefined even for 0 bytes
|
||||
return other.size() == this->ref_.size() &&
|
||||
(other.empty() || memcmp_P(other.c_str(), this->ref_.c_str(), other.size()) == 0);
|
||||
#else
|
||||
return other == this->ref_;
|
||||
#endif
|
||||
@@ -293,6 +277,13 @@ class ProgmemStringRef {
|
||||
StringRef ref_;
|
||||
};
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
inline bool operator==(const StringRef &lhs, const ProgmemStringRef &rhs) { return rhs.equals(lhs); }
|
||||
inline bool operator!=(const StringRef &lhs, const ProgmemStringRef &rhs) { return !rhs.equals(lhs); }
|
||||
inline bool operator==(const std::string &lhs, const ProgmemStringRef &rhs) { return rhs.equals(StringRef(lhs)); }
|
||||
inline bool operator!=(const std::string &lhs, const ProgmemStringRef &rhs) { return !rhs.equals(StringRef(lhs)); }
|
||||
#endif
|
||||
|
||||
// String conversion functions for ADL compatibility (allows stoi(x) where x is StringRef)
|
||||
// Must be in esphome namespace for ADL to find them. Uses strtol/strtod directly to avoid heap allocation.
|
||||
namespace internal {
|
||||
|
||||
@@ -1158,6 +1158,11 @@ class PointerToBufferTypeBase(TypeInfo):
|
||||
"""Get the wire type for this field."""
|
||||
return WireType.LENGTH_DELIMITED # Uses wire type 2
|
||||
|
||||
@property
|
||||
def progmem(self) -> bool:
|
||||
"""Whether the data is in flash, so encode and dump copy it with progmem_memcpy."""
|
||||
return get_field_opt(self._field, pb.progmem, False)
|
||||
|
||||
def get_estimated_size(self) -> int:
|
||||
# field ID + length varint + typical data (assume small for pointer fields)
|
||||
return self.calculate_field_id_size() + 2 + 16
|
||||
@@ -1171,11 +1176,6 @@ class PointerToBytesBufferType(PointerToBufferTypeBase):
|
||||
reference_type = "const uint8_t*"
|
||||
const_reference_type = "const uint8_t*"
|
||||
|
||||
@property
|
||||
def progmem(self) -> bool:
|
||||
"""Whether the data is in flash, so encode and dump copy it with progmem_memcpy."""
|
||||
return get_field_opt(self._field, pb.progmem, False)
|
||||
|
||||
@property
|
||||
def public_content(self) -> list[str]:
|
||||
# Use uint16_t for length - max packet size is well below 65535
|
||||
@@ -1253,11 +1253,6 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
|
||||
one zero fill. Any encode path that copies unconditionally must check this."""
|
||||
return not self._needs_decode and not self.force
|
||||
|
||||
@property
|
||||
def progmem(self) -> bool:
|
||||
"""Whether the string is in flash, so encode and dump copy it with progmem_memcpy."""
|
||||
return get_field_opt(self._field, pb.progmem, False)
|
||||
|
||||
@property
|
||||
def public_content(self) -> list[str]:
|
||||
if self.progmem:
|
||||
|
||||
Reference in New Issue
Block a user