ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
mapping.h
Go to the documentation of this file.
1#pragma once
2
4#include "esphome/core/log.h"
5#include <cinttypes>
6#include <map>
7#include <string>
8
9namespace esphome::mapping {
10
11using alloc_string_t = std::basic_string<char, std::char_traits<char>, RAMAllocator<char>>;
12
22static const char *const TAG = "mapping";
23
24template<typename K, typename V> class Mapping {
25 public:
26 // Constructor
27 Mapping() = default;
28
29 using key_t = const std::conditional_t<std::is_same_v<K, std::string>,
30 alloc_string_t, // if K is std::string, custom string type
31 K>;
32 using value_t = std::conditional_t<std::is_same_v<V, std::string>,
33 alloc_string_t, // if V is std::string, custom string type
34 V>;
35
36 void set(const K &key, const V &value) { this->map_[key_t{key}] = value; }
37
38 V get(const K &key) const {
39 auto it = this->map_.find(key_t{key});
40 if (it != this->map_.end()) {
41 return V{it->second};
42 }
43 if (this->default_value_.has_value()) {
44 return this->default_value_.value();
45 }
46 if constexpr (std::is_pointer_v<K>) {
47 esph_log_e(TAG, "Key '%p' not found in mapping", key);
48 } else if constexpr (std::is_same_v<K, std::string>) {
49 esph_log_e(TAG, "Key '%s' not found in mapping", key.c_str());
50 } else if constexpr (std::is_integral_v<K>) {
51 char buf[24]; // enough for 64-bit integer
52 if constexpr (std::is_unsigned_v<K>) {
53 buf_append_printf(buf, sizeof(buf), 0, "%" PRIu64, static_cast<uint64_t>(key));
54 } else {
55 buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, static_cast<int64_t>(key));
56 }
57 esph_log_e(TAG, "Key '%s' not found in mapping", buf);
58 } else {
59 // All supported key types are handled above - this should never be reached
60 static_assert(sizeof(K) == 0, "Unsupported key type for Mapping error logging");
61 }
62 return {};
63 }
64
65 // index map overload
66 V operator[](K key) { return this->get(key); }
67
68 // convenience function for strings to get a C-style string
69 template<typename T = V, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
70 const char *operator[](K key) const {
71 auto it = this->map_.find(key_t{key});
72 if (it != this->map_.end()) {
73 return it->second.c_str(); // safe since value remains in map
74 }
75 if (this->default_value_.has_value()) {
76 return this->default_value_.value();
77 }
78 return "";
79 }
80
81 void set_default_value(const V &default_value) { this->default_value_ = default_value; }
82
83 protected:
84 std::map<key_t, value_t, std::less<key_t>, RAMAllocator<std::pair<key_t, value_t>>> map_;
85 std::optional<V> default_value_{};
86};
87
88} // namespace esphome::mapping
An STL allocator that uses SPI or internal RAM.
Definition helpers.h:2053
const char * operator[](K key) const
Definition mapping.h:70
void set(const K &key, const V &value)
Definition mapping.h:36
std::conditional_t< std::is_same_v< V, std::string >, alloc_string_t, V > value_t
Definition mapping.h:32
const std::conditional_t< std::is_same_v< K, std::string >, alloc_string_t, K > key_t
Definition mapping.h:29
V get(const K &key) const
Definition mapping.h:38
std::optional< V > default_value_
Definition mapping.h:85
std::map< key_t, value_t, std::less< key_t >, RAMAllocator< std::pair< key_t, value_t > > > map_
Definition mapping.h:84
void set_default_value(const V &default_value)
Definition mapping.h:81
std::basic_string< char, std::char_traits< char >, RAMAllocator< char > > alloc_string_t
Definition mapping.h:11