mirror of
https://github.com/esphome/esphome.git
synced 2025-09-02 11:22:24 +01:00
[mapping] Use custom allocator (#9972)
This commit is contained in:
@@ -10,7 +10,8 @@ from esphome.loader import get_component
|
|||||||
CODEOWNERS = ["@clydebarrow"]
|
CODEOWNERS = ["@clydebarrow"]
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
|
||||||
map_ = cg.std_ns.class_("map")
|
mapping_ns = cg.esphome_ns.namespace("mapping")
|
||||||
|
mapping_class = mapping_ns.class_("Mapping")
|
||||||
|
|
||||||
CONF_ENTRIES = "entries"
|
CONF_ENTRIES = "entries"
|
||||||
CONF_CLASS = "class"
|
CONF_CLASS = "class"
|
||||||
@@ -29,7 +30,11 @@ class IndexType:
|
|||||||
|
|
||||||
INDEX_TYPES = {
|
INDEX_TYPES = {
|
||||||
"int": IndexType(cv.int_, cg.int_, int),
|
"int": IndexType(cv.int_, cg.int_, int),
|
||||||
"string": IndexType(cv.string, cg.std_string, str),
|
"string": IndexType(
|
||||||
|
cv.string,
|
||||||
|
cg.std_string,
|
||||||
|
str,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,7 +52,7 @@ def to_schema(value):
|
|||||||
|
|
||||||
BASE_SCHEMA = cv.Schema(
|
BASE_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.declare_id(map_),
|
cv.Required(CONF_ID): cv.declare_id(mapping_class),
|
||||||
cv.Required(CONF_FROM): cv.one_of(*INDEX_TYPES, lower=True),
|
cv.Required(CONF_FROM): cv.one_of(*INDEX_TYPES, lower=True),
|
||||||
cv.Required(CONF_TO): cv.string,
|
cv.Required(CONF_TO): cv.string,
|
||||||
},
|
},
|
||||||
@@ -123,12 +128,15 @@ async def to_code(config):
|
|||||||
if list(entries.values())[0].op != ".":
|
if list(entries.values())[0].op != ".":
|
||||||
value_type = value_type.operator("ptr")
|
value_type = value_type.operator("ptr")
|
||||||
varid = config[CONF_ID]
|
varid = config[CONF_ID]
|
||||||
varid.type = map_.template(index_type, value_type)
|
varid.type = mapping_class.template(
|
||||||
|
index_type,
|
||||||
|
value_type,
|
||||||
|
)
|
||||||
var = MockObj(varid, ".")
|
var = MockObj(varid, ".")
|
||||||
decl = VariableDeclarationExpression(varid.type, "", varid)
|
decl = VariableDeclarationExpression(varid.type, "", varid)
|
||||||
add_global(decl)
|
add_global(decl)
|
||||||
CORE.register_variable(varid, var)
|
CORE.register_variable(varid, var)
|
||||||
|
|
||||||
for key, value in entries.items():
|
for key, value in entries.items():
|
||||||
cg.add(var.insert((key, value)))
|
cg.add(var.set(key, value))
|
||||||
return var
|
return var
|
||||||
|
69
esphome/components/mapping/mapping.h
Normal file
69
esphome/components/mapping/mapping.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace esphome::mapping {
|
||||||
|
|
||||||
|
using alloc_string_t = std::basic_string<char, std::char_traits<char>, RAMAllocator<char>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Mapping class with custom allocator.
|
||||||
|
* Additionally, when std::string is used as key or value, it will be replaced with a custom string type
|
||||||
|
* that uses RAMAllocator.
|
||||||
|
* @tparam K The type of the key in the mapping.
|
||||||
|
* @tparam V The type of the value in the mapping. Should be a basic type or pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char *const TAG = "mapping";
|
||||||
|
|
||||||
|
template<typename K, typename V> class Mapping {
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
Mapping() = default;
|
||||||
|
|
||||||
|
using key_t = const std::conditional_t<std::is_same_v<K, std::string>,
|
||||||
|
alloc_string_t, // if K is std::string, custom string type
|
||||||
|
K>;
|
||||||
|
using value_t = std::conditional_t<std::is_same_v<V, std::string>,
|
||||||
|
alloc_string_t, // if V is std::string, custom string type
|
||||||
|
V>;
|
||||||
|
|
||||||
|
void set(const K &key, const V &value) { this->map_[key_t{key}] = value; }
|
||||||
|
|
||||||
|
V get(const K &key) const {
|
||||||
|
auto it = this->map_.find(key_t{key});
|
||||||
|
if (it != this->map_.end()) {
|
||||||
|
return V{it->second};
|
||||||
|
}
|
||||||
|
if constexpr (std::is_pointer_v<K>) {
|
||||||
|
esph_log_e(TAG, "Key '%p' not found in mapping", key);
|
||||||
|
} else if constexpr (std::is_same_v<K, std::string>) {
|
||||||
|
esph_log_e(TAG, "Key '%s' not found in mapping", key.c_str());
|
||||||
|
} else {
|
||||||
|
esph_log_e(TAG, "Key '%s' not found in mapping", to_string(key).c_str());
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// index map overload
|
||||||
|
V operator[](K key) { return this->get(key); }
|
||||||
|
|
||||||
|
// convenience function for strings to get a C-style string
|
||||||
|
template<typename T = V, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
|
||||||
|
const char *operator[](K key) const {
|
||||||
|
auto it = this->map_.find(key_t{key});
|
||||||
|
if (it != this->map_.end()) {
|
||||||
|
return it->second.c_str(); // safe since value remains in map
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::map<key_t, value_t, std::less<key_t>, RAMAllocator<std::pair<key_t, value_t>>> map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace esphome::mapping
|
1
tests/components/mapping/.gitattributes
vendored
Normal file
1
tests/components/mapping/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.ttf -text
|
@@ -50,6 +50,14 @@ mapping:
|
|||||||
red: red_id
|
red: red_id
|
||||||
blue: blue_id
|
blue: blue_id
|
||||||
green: green_id
|
green: green_id
|
||||||
|
- id: string_map_2
|
||||||
|
from: string
|
||||||
|
to: string
|
||||||
|
entries:
|
||||||
|
one: "one"
|
||||||
|
two: "two"
|
||||||
|
three: "three"
|
||||||
|
seventy-seven: "seventy-seven"
|
||||||
|
|
||||||
color:
|
color:
|
||||||
- id: red_id
|
- id: red_id
|
||||||
@@ -65,7 +73,14 @@ color:
|
|||||||
green: 0.0
|
green: 0.0
|
||||||
blue: 1.0
|
blue: 1.0
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: "$component_dir/helvetica.ttf"
|
||||||
|
id: font_id
|
||||||
|
size: 20
|
||||||
|
|
||||||
display:
|
display:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.image(0, 0, id(weather_map)[0]);
|
std::string value = id(int_map)[2];
|
||||||
it.image(0, 100, id(weather_map)[1]);
|
it.print(0, 0, id(font_id), TextAlign::TOP_LEFT, value.c_str());
|
||||||
|
it.image(0, 0, id(weather_map)["clear-night"]);
|
||||||
|
it.image(0, 100, id(weather_map)["sunny"]);
|
||||||
|
BIN
tests/components/mapping/helvetica.ttf
Normal file
BIN
tests/components/mapping/helvetica.ttf
Normal file
Binary file not shown.
@@ -4,14 +4,14 @@ spi:
|
|||||||
mosi_pin: 17
|
mosi_pin: 17
|
||||||
miso_pin: 15
|
miso_pin: 15
|
||||||
|
|
||||||
display:
|
|
||||||
- platform: ili9xxx
|
|
||||||
id: main_lcd
|
|
||||||
model: ili9342
|
|
||||||
cs_pin: 12
|
|
||||||
dc_pin: 13
|
|
||||||
reset_pin: 21
|
|
||||||
invert_colors: false
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
|
||||||
|
display:
|
||||||
|
platform: ili9xxx
|
||||||
|
id: main_lcd
|
||||||
|
model: ili9342
|
||||||
|
cs_pin: 12
|
||||||
|
dc_pin: 13
|
||||||
|
reset_pin: 21
|
||||||
|
invert_colors: false
|
||||||
|
@@ -5,13 +5,13 @@ spi:
|
|||||||
miso_pin: 5
|
miso_pin: 5
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
platform: ili9xxx
|
||||||
id: main_lcd
|
id: main_lcd
|
||||||
model: ili9342
|
model: ili9342
|
||||||
cs_pin: 8
|
cs_pin: 8
|
||||||
dc_pin: 9
|
dc_pin: 9
|
||||||
reset_pin: 10
|
reset_pin: 10
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
@@ -5,13 +5,13 @@ spi:
|
|||||||
miso_pin: 5
|
miso_pin: 5
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
platform: ili9xxx
|
||||||
id: main_lcd
|
id: main_lcd
|
||||||
model: ili9342
|
model: ili9342
|
||||||
cs_pin: 8
|
cs_pin: 8
|
||||||
dc_pin: 9
|
dc_pin: 9
|
||||||
reset_pin: 10
|
reset_pin: 10
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
@@ -5,13 +5,13 @@ spi:
|
|||||||
miso_pin: 15
|
miso_pin: 15
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
platform: ili9xxx
|
||||||
id: main_lcd
|
id: main_lcd
|
||||||
model: ili9342
|
model: ili9342
|
||||||
cs_pin: 12
|
cs_pin: 12
|
||||||
dc_pin: 13
|
dc_pin: 13
|
||||||
reset_pin: 21
|
reset_pin: 21
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
@@ -5,13 +5,13 @@ spi:
|
|||||||
miso_pin: 12
|
miso_pin: 12
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
platform: ili9xxx
|
||||||
id: main_lcd
|
id: main_lcd
|
||||||
model: ili9342
|
model: ili9342
|
||||||
cs_pin: 5
|
cs_pin: 5
|
||||||
dc_pin: 15
|
dc_pin: 15
|
||||||
reset_pin: 16
|
reset_pin: 16
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
display:
|
display:
|
||||||
- platform: sdl
|
platform: sdl
|
||||||
id: sdl_display
|
id: sdl_display
|
||||||
update_interval: 1s
|
update_interval: 1s
|
||||||
auto_clear_enabled: false
|
auto_clear_enabled: false
|
||||||
show_test_card: true
|
show_test_card: true
|
||||||
dimensions:
|
dimensions:
|
||||||
width: 450
|
width: 450
|
||||||
height: 600
|
height: 600
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
@@ -5,13 +5,13 @@ spi:
|
|||||||
miso_pin: 4
|
miso_pin: 4
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
platform: ili9xxx
|
||||||
id: main_lcd
|
id: main_lcd
|
||||||
model: ili9342
|
model: ili9342
|
||||||
cs_pin: 20
|
cs_pin: 20
|
||||||
dc_pin: 21
|
dc_pin: 21
|
||||||
reset_pin: 22
|
reset_pin: 22
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
map: !include common.yaml
|
map: !include common.yaml
|
||||||
|
Reference in New Issue
Block a user