Remove leading null from blobs and EMPTY_REF from getters

- Blobs now start directly with first string (no wasted \0 prefix)
- Lookup functions handle index 0 by pointing to trailing null of blob
- get_*_ref() simplified: just calls lookup, no separate empty check
- Removes EMPTY_REF constant and per-getter branch
This commit is contained in:
J. Nick Koston
2026-02-20 23:09:30 -06:00
parent 22e9c30af1
commit 6100d1c1d7
2 changed files with 21 additions and 22 deletions
+5 -15
View File
@@ -50,23 +50,16 @@ __attribute__((weak)) const char *entity_device_class_lookup(uint16_t) { return
__attribute__((weak)) const char *entity_uom_lookup(uint16_t) { return ""; }
__attribute__((weak)) const char *entity_icon_lookup(uint16_t) { return ""; }
static constexpr auto EMPTY_REF = StringRef::from_lit("");
// Entity device class (from packed index)
StringRef EntityBase::get_device_class_ref() const {
uint16_t idx = (this->entity_string_packed_ >> ENTITY_STR_DC_SHIFT) & ENTITY_STR_DC_MASK;
if (idx == 0)
return EMPTY_REF;
return StringRef(entity_device_class_lookup(idx));
return StringRef(
entity_device_class_lookup((this->entity_string_packed_ >> ENTITY_STR_DC_SHIFT) & ENTITY_STR_DC_MASK));
}
std::string EntityBase::get_device_class() const { return std::string(this->get_device_class_ref().c_str()); }
// Entity unit of measurement (from packed index)
StringRef EntityBase::get_unit_of_measurement_ref() const {
uint16_t idx = (this->entity_string_packed_ >> ENTITY_STR_UOM_SHIFT) & ENTITY_STR_UOM_MASK;
if (idx == 0)
return EMPTY_REF;
return StringRef(entity_uom_lookup(idx));
return StringRef(entity_uom_lookup((this->entity_string_packed_ >> ENTITY_STR_UOM_SHIFT) & ENTITY_STR_UOM_MASK));
}
std::string EntityBase::get_unit_of_measurement() const {
return std::string(this->get_unit_of_measurement_ref().c_str());
@@ -75,12 +68,9 @@ std::string EntityBase::get_unit_of_measurement() const {
// Entity icon (from packed index)
StringRef EntityBase::get_icon_ref() const {
#ifdef USE_ENTITY_ICON
uint16_t idx = (this->entity_string_packed_ >> ENTITY_STR_ICON_SHIFT) & ENTITY_STR_ICON_MASK;
if (idx == 0)
return EMPTY_REF;
return StringRef(entity_icon_lookup(idx));
return StringRef(entity_icon_lookup((this->entity_string_packed_ >> ENTITY_STR_ICON_SHIFT) & ENTITY_STR_ICON_MASK));
#else
return EMPTY_REF;
return StringRef(entity_icon_lookup(0));
#endif
}
std::string EntityBase::get_icon() const { return std::string(this->get_icon_ref().c_str()); }
+16 -7
View File
@@ -84,13 +84,14 @@ def _generate_blob_and_offsets(
) -> tuple[bytes, list[int]]:
"""Build a packed blob and offset list from a string dict.
Returns (blob_bytes, offsets) where offsets[0] points to "" (empty)
and offsets[i] points to the i-th string.
Returns (blob_bytes, offsets) where offsets are 1-based (matching the
1-based indices returned by _register_string). Index 0 means "not set"
and is handled by the caller before reaching the lookup function.
"""
# Sort by assigned index to ensure deterministic output
sorted_strings = sorted(strings.items(), key=lambda x: x[1])
blob = bytearray(b"\x00") # Index 0 = offset 0 = empty string
offsets = [0] # offset for index 0 (empty string)
blob = bytearray()
offsets = []
for s, _idx in sorted_strings:
offsets.append(len(blob))
blob.extend(s.encode("utf-8"))
@@ -104,7 +105,11 @@ def _generate_category_code(
lookup_fn: str,
strings: dict[str, int],
) -> str:
"""Generate C++ code for one string category (blob + offsets + lookup)."""
"""Generate C++ code for one string category (blob + offsets + lookup).
Index 0 means "not set" and is handled by get_*_ref() before calling
the lookup function. The lookup uses 1-based indexing directly.
"""
if not strings:
return ""
@@ -116,12 +121,16 @@ def _generate_category_code(
blob_escaped = cpp_string_escape(blob_bytes)
offsets_str = ", ".join(str(o) for o in offsets)
# The blob's last byte is always '\0' (null terminator of last string).
# Point there for index 0 ("not set") and out-of-range to return "".
empty_offset = len(blob_bytes) - 1
return (
f"static const char {blob_var}[] = {blob_escaped};\n"
f"static const {offset_type} {offsets_var}[] PROGMEM = {{{offsets_str}}};\n"
f"const char *{lookup_fn}(uint16_t index) {{\n"
f" if (index >= {count}) return {blob_var};\n"
f" return &{blob_var}[{read_fn}(&{offsets_var}[index])];\n"
f" if (index == 0 || index > {count}) return &{blob_var}[{empty_offset}];\n"
f" return &{blob_var}[{read_fn}(&{offsets_var}[index - 1])];\n"
f"}}\n"
)