mirror of
https://github.com/esphome/esphome.git
synced 2026-09-08 22:08:49 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2e8320f0 | ||
|
|
49ef5f9ad6 | ||
|
|
707f3f4749 |
@@ -298,15 +298,33 @@ constexpr uint32_t VARINT_MAX_2_BYTE = 1 << 14; // 16384
|
|||||||
class ProtoEncode {
|
class ProtoEncode {
|
||||||
public:
|
public:
|
||||||
/// Write a multi-byte varint directly through a pos pointer.
|
/// Write a multi-byte varint directly through a pos pointer.
|
||||||
|
/// Unrolled based on the compile-time max varint length for T
|
||||||
|
/// (5 bytes for uint32_t, 10 bytes for uint64_t). The explicit unroll gives
|
||||||
|
/// the compiler straight-line code with early exits instead of a
|
||||||
|
/// data-dependent back-edge branch, which measurably speeds up BLE raw
|
||||||
|
/// advertisement MAC encoding (always 7-byte varints) among other hot paths.
|
||||||
|
///
|
||||||
|
/// Takes/returns pos by value so this function can remain out-of-line without
|
||||||
|
/// forcing the caller to spill pos to memory on every byte write. Callers
|
||||||
|
/// (which are ALWAYS_INLINE) should assign the returned pos back to their
|
||||||
|
/// local. Code size win vs. inlining the whole unroll at every call site.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline void encode_varint_raw_loop(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, T value) {
|
static uint8_t *encode_varint_raw_loop(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, T value) {
|
||||||
do {
|
constexpr int MAX_VARINT_BYTES = (sizeof(T) * 8 + 6) / 7; // 5 for u32, 10 for u64
|
||||||
|
#pragma GCC unroll 10
|
||||||
|
for (int i = 0; i < MAX_VARINT_BYTES - 1; i++) {
|
||||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 1);
|
PROTO_ENCODE_CHECK_BOUNDS(pos, 1);
|
||||||
*pos++ = static_cast<uint8_t>(value | 0x80);
|
*pos++ = static_cast<uint8_t>(value) | 0x80;
|
||||||
value >>= 7;
|
value >>= 7;
|
||||||
} while (value > 0x7F);
|
if (value <= 0x7F) {
|
||||||
|
PROTO_ENCODE_CHECK_BOUNDS(pos, 1);
|
||||||
|
*pos++ = static_cast<uint8_t>(value);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 1);
|
PROTO_ENCODE_CHECK_BOUNDS(pos, 1);
|
||||||
*pos++ = static_cast<uint8_t>(value);
|
*pos++ = static_cast<uint8_t>(value);
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
||||||
uint32_t value) {
|
uint32_t value) {
|
||||||
@@ -315,7 +333,7 @@ class ProtoEncode {
|
|||||||
*pos++ = static_cast<uint8_t>(value);
|
*pos++ = static_cast<uint8_t>(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
pos = encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
||||||
}
|
}
|
||||||
/// Encode a varint that is expected to be 1-2 bytes (e.g. zigzag RSSI, small lengths).
|
/// Encode a varint that is expected to be 1-2 bytes (e.g. zigzag RSSI, small lengths).
|
||||||
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_short(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_short(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
||||||
@@ -331,7 +349,7 @@ class ProtoEncode {
|
|||||||
*pos++ = static_cast<uint8_t>(value >> 7);
|
*pos++ = static_cast<uint8_t>(value >> 7);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
pos = encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
||||||
}
|
}
|
||||||
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
||||||
uint64_t value) {
|
uint64_t value) {
|
||||||
@@ -340,7 +358,7 @@ class ProtoEncode {
|
|||||||
*pos++ = static_cast<uint8_t>(value);
|
*pos++ = static_cast<uint8_t>(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
pos = encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value);
|
||||||
}
|
}
|
||||||
static inline void ESPHOME_ALWAYS_INLINE encode_field_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
static inline void ESPHOME_ALWAYS_INLINE encode_field_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM,
|
||||||
uint32_t field_id, uint32_t type) {
|
uint32_t field_id, uint32_t type) {
|
||||||
@@ -402,7 +420,7 @@ class ProtoEncode {
|
|||||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 1 + len);
|
PROTO_ENCODE_CHECK_BOUNDS(pos, 1 + len);
|
||||||
*pos++ = static_cast<uint8_t>(len);
|
*pos++ = static_cast<uint8_t>(len);
|
||||||
} else {
|
} else {
|
||||||
encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, len);
|
pos = encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, len);
|
||||||
PROTO_ENCODE_CHECK_BOUNDS(pos, len);
|
PROTO_ENCODE_CHECK_BOUNDS(pos, len);
|
||||||
}
|
}
|
||||||
std::memcpy(pos, string, len);
|
std::memcpy(pos, string, len);
|
||||||
|
|||||||
Reference in New Issue
Block a user