save memory by moving allowReset and nvsName into vtable

This commit is contained in:
2022-04-20 17:42:31 +02:00
parent 50d24f0d25
commit 2ec9d89594
4 changed files with 43 additions and 54 deletions

View File

@@ -16,21 +16,21 @@ namespace espconfig {
using ConfigConstraintReturnType = ConfigStatusReturnType; using ConfigConstraintReturnType = ConfigStatusReturnType;
template<typename T> template<typename T>
class ConfigWrapper final : public ConfigWrapperInterface class ConfigWrapper : public ConfigWrapperInterface
{ {
CPP_DISABLE_COPY_MOVE(ConfigWrapper) CPP_DISABLE_COPY_MOVE(ConfigWrapper)
public:
using DefaultValueCallbackRef = T(&)(); using DefaultValueCallbackRef = T(&)();
using DefaultValueCallbackPtr = T(*)(); using DefaultValueCallbackPtr = T(*)();
public:
using value_t = typename std::conditional<std::is_same<T, std::string>::value, const T &, T>::type; using value_t = typename std::conditional<std::is_same<T, std::string>::value, const T &, T>::type;
using ConstraintCallback = ConfigConstraintReturnType(*)(value_t); using ConstraintCallback = ConfigConstraintReturnType(*)(value_t);
ConfigWrapper(const T &defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); ConfigWrapper(const T &defaultValue, ConstraintCallback constraintCallback);
ConfigWrapper(T &&defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); ConfigWrapper(T &&defaultValue, ConstraintCallback constraintCallback);
ConfigWrapper(const ConfigWrapper<T> &factoryConfig, ConstraintCallback constraintCallback, const char *nvsName); ConfigWrapper(const ConfigWrapper<T> &factoryConfig, ConstraintCallback constraintCallback);
ConfigWrapper(const DefaultValueCallbackRef &defaultCallback, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); ConfigWrapper(const DefaultValueCallbackRef &defaultCallback, ConstraintCallback constraintCallback);
~ConfigWrapper() override; ~ConfigWrapper() override;
ConfigStatusReturnType write(nvs_handle_t nvsHandle, value_t value); ConfigStatusReturnType write(nvs_handle_t nvsHandle, value_t value);

View File

@@ -19,10 +19,11 @@
#define INSTANTIATE_CONFIGWRAPPER_TEMPLATES(TYPE) \ #define INSTANTIATE_CONFIGWRAPPER_TEMPLATES(TYPE) \
namespace espconfig { \ namespace espconfig { \
template ConfigWrapper<TYPE>::ConfigWrapper(const TYPE &defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); \ template ConfigWrapper<TYPE>::ConfigWrapper(const TYPE &defaultValue, ConstraintCallback constraintCallback); \
template ConfigWrapper<TYPE>::ConfigWrapper(TYPE &&defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); \ template ConfigWrapper<TYPE>::ConfigWrapper(TYPE &&defaultValue, ConstraintCallback constraintCallback); \
template ConfigWrapper<TYPE>::ConfigWrapper(const ConfigWrapper<TYPE> &factoryConfig, ConstraintCallback constraintCallback, const char *nvsName); \ template ConfigWrapper<TYPE>::ConfigWrapper(const ConfigWrapper<TYPE> &factoryConfig, ConstraintCallback constraintCallback); \
template ConfigWrapper<TYPE>::ConfigWrapper(DefaultValueCallbackRef &defaultCallback, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName); \ template ConfigWrapper<TYPE>::ConfigWrapper(DefaultValueCallbackRef &defaultCallback, ConstraintCallback constraintCallback); \
template ConfigWrapper<TYPE>::~ConfigWrapper(); \
template ConfigStatusReturnType ConfigWrapper<TYPE>::write(nvs_handle_t nvsHandle, value_t value); \ template ConfigStatusReturnType ConfigWrapper<TYPE>::write(nvs_handle_t nvsHandle, value_t value); \
template<> const char *ConfigWrapper<TYPE>::type() const { return #TYPE; } \ template<> const char *ConfigWrapper<TYPE>::type() const { return #TYPE; } \
template std::string ConfigWrapper<TYPE>::valueAsString() const; \ template std::string ConfigWrapper<TYPE>::valueAsString() const; \
@@ -41,8 +42,7 @@ constexpr const char * const TAG = "CONFIG";
} // namespace } // namespace
template<typename T> template<typename T>
ConfigWrapper<T>::ConfigWrapper(const T &defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName) : ConfigWrapper<T>::ConfigWrapper(const T &defaultValue, ConstraintCallback constraintCallback) :
ConfigWrapperInterface{allowReset, nvsName},
m_defaultType{DefaultByValue}, m_defaultType{DefaultByValue},
m_defaultValue{defaultValue}, m_defaultValue{defaultValue},
m_constraintCallback{constraintCallback} m_constraintCallback{constraintCallback}
@@ -50,8 +50,7 @@ ConfigWrapper<T>::ConfigWrapper(const T &defaultValue, AllowReset allowReset, Co
} }
template<typename T> template<typename T>
ConfigWrapper<T>::ConfigWrapper(T &&defaultValue, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName) : ConfigWrapper<T>::ConfigWrapper(T &&defaultValue, ConstraintCallback constraintCallback) :
ConfigWrapperInterface{allowReset, nvsName},
m_defaultType{DefaultByValue}, m_defaultType{DefaultByValue},
m_defaultValue{std::move(defaultValue)}, m_defaultValue{std::move(defaultValue)},
m_constraintCallback{constraintCallback} m_constraintCallback{constraintCallback}
@@ -59,8 +58,7 @@ ConfigWrapper<T>::ConfigWrapper(T &&defaultValue, AllowReset allowReset, Constra
} }
template<typename T> template<typename T>
ConfigWrapper<T>::ConfigWrapper(const ConfigWrapper<T> &factoryConfig, ConstraintCallback constraintCallback, const char *nvsName) : ConfigWrapper<T>::ConfigWrapper(const ConfigWrapper<T> &factoryConfig, ConstraintCallback constraintCallback) :
ConfigWrapperInterface{AllowReset::DoReset, nvsName},
m_defaultType{DefaultByFactoryConfig}, m_defaultType{DefaultByFactoryConfig},
m_factoryConfig{&factoryConfig}, m_factoryConfig{&factoryConfig},
m_constraintCallback{constraintCallback} m_constraintCallback{constraintCallback}
@@ -68,8 +66,7 @@ ConfigWrapper<T>::ConfigWrapper(const ConfigWrapper<T> &factoryConfig, Constrain
} }
template<typename T> template<typename T>
ConfigWrapper<T>::ConfigWrapper(const DefaultValueCallbackRef &defaultCallback, AllowReset allowReset, ConstraintCallback constraintCallback, const char *nvsName) : ConfigWrapper<T>::ConfigWrapper(const DefaultValueCallbackRef &defaultCallback, ConstraintCallback constraintCallback) :
ConfigWrapperInterface{allowReset, nvsName},
m_defaultType{DefaultByCallback}, m_defaultType{DefaultByCallback},
m_defaultCallback{&defaultCallback}, m_defaultCallback{&defaultCallback},
m_constraintCallback{constraintCallback} m_constraintCallback{constraintCallback}
@@ -92,14 +89,14 @@ ConfigStatusReturnType ConfigWrapper<T>::write(nvs_handle_t nvsHandle, value_t v
{ {
CONFIGWRAPPER_TOSTRING_USINGS CONFIGWRAPPER_TOSTRING_USINGS
ESP_LOGD(TAG, "%s %s", m_nvsName, toString(value).c_str()); ESP_LOGD(TAG, "%s %s", nvsName(), toString(value).c_str());
if (!m_loaded) if (!m_loaded)
ESP_LOGE(TAG, "%s has not been loaded yet!", m_nvsName); ESP_LOGE(TAG, "%s has not been loaded yet!", nvsName());
if (const auto result = checkValue(value); !result) if (const auto result = checkValue(value); !result)
{ {
ESP_LOGW(TAG, "%s cannot be set to %s: constraint not met: %s", m_nvsName, toString(value).c_str(), result.error().c_str()); ESP_LOGW(TAG, "%s cannot be set to %s: constraint not met: %s", nvsName(), toString(value).c_str(), result.error().c_str());
return result; return result;
} }
@@ -144,17 +141,17 @@ T ConfigWrapper<T>::defaultValue() const
template<typename T> template<typename T>
ConfigStatusReturnType ConfigWrapper<T>::loadFromFlash(nvs_handle_t nvsHandle) ConfigStatusReturnType ConfigWrapper<T>::loadFromFlash(nvs_handle_t nvsHandle)
{ {
//ESP_LOGD(TAG, "%s", m_nvsName); //ESP_LOGD(TAG, "%s", nvsName());
const auto result = nvs_get(nvsHandle, m_nvsName, &m_value); const auto result = nvs_get(nvsHandle, nvsName(), &m_value);
ESP_LOG_LEVEL_LOCAL((cpputils::is_in(result, ESP_OK, ESP_ERR_NVS_NOT_FOUND) ? ESP_LOG_DEBUG : ESP_LOG_ERROR), TAG, "%s nvs_get() returned: %s", m_nvsName, esp_err_to_name(result)); ESP_LOG_LEVEL_LOCAL((cpputils::is_in(result, ESP_OK, ESP_ERR_NVS_NOT_FOUND) ? ESP_LOG_DEBUG : ESP_LOG_ERROR), TAG, "%s nvs_get() returned: %s", nvsName(), esp_err_to_name(result));
if (result == ESP_OK) if (result == ESP_OK)
{ {
if (const auto result = checkValue(m_value); !result) if (const auto result = checkValue(m_value); !result)
{ {
ESP_LOGE(TAG, "%s constraint not met for value in flash: %s", m_nvsName, result.error().c_str()); ESP_LOGE(TAG, "%s constraint not met for value in flash: %s", nvsName(), result.error().c_str());
return forceReset(nvsHandle); return forceReset(nvsHandle);
} }
@@ -168,7 +165,7 @@ ConfigStatusReturnType ConfigWrapper<T>::loadFromFlash(nvs_handle_t nvsHandle)
m_touched = false; m_touched = false;
m_value = defaultValue(); m_value = defaultValue();
if (const auto result = checkValue(m_value); !result) if (const auto result = checkValue(m_value); !result)
ESP_LOGE(TAG, "%s constraint not met for value from default: %s", m_nvsName, result.error().c_str()); ESP_LOGE(TAG, "%s constraint not met for value from default: %s", nvsName(), result.error().c_str());
return {}; return {};
} }
@@ -181,9 +178,9 @@ ConfigStatusReturnType ConfigWrapper<T>::loadFromFlash(nvs_handle_t nvsHandle)
template<typename T> template<typename T>
ConfigStatusReturnType ConfigWrapper<T>::reset(nvs_handle_t nvsHandle) ConfigStatusReturnType ConfigWrapper<T>::reset(nvs_handle_t nvsHandle)
{ {
ESP_LOGD(TAG, "%s", m_nvsName); ESP_LOGD(TAG, "%s", nvsName());
if (!m_allowReset) if (!allowReset())
return {}; return {};
return forceReset(nvsHandle); return forceReset(nvsHandle);
@@ -192,16 +189,16 @@ ConfigStatusReturnType ConfigWrapper<T>::reset(nvs_handle_t nvsHandle)
template<typename T> template<typename T>
ConfigStatusReturnType ConfigWrapper<T>::forceReset(nvs_handle_t nvsHandle) ConfigStatusReturnType ConfigWrapper<T>::forceReset(nvs_handle_t nvsHandle)
{ {
ESP_LOGD(TAG, "%s", m_nvsName); ESP_LOGD(TAG, "%s", nvsName());
auto result = nvs_erase_key(nvsHandle, m_nvsName); auto result = nvs_erase_key(nvsHandle, nvsName());
ESP_LOG_LEVEL_LOCAL((cpputils::is_in(result, ESP_OK, ESP_ERR_NVS_NOT_FOUND) ? ESP_LOG_DEBUG : ESP_LOG_ERROR), TAG, "%s nvs_erase_key() returned: %s", m_nvsName, esp_err_to_name(result)); ESP_LOG_LEVEL_LOCAL((cpputils::is_in(result, ESP_OK, ESP_ERR_NVS_NOT_FOUND) ? ESP_LOG_DEBUG : ESP_LOG_ERROR), TAG, "%s nvs_erase_key() returned: %s", nvsName(), esp_err_to_name(result));
if (result == ESP_ERR_NVS_NOT_FOUND) if (result == ESP_ERR_NVS_NOT_FOUND)
{ {
if (m_touched) if (m_touched)
ESP_LOGE(TAG, "%s for touched and not found?!", m_nvsName); ESP_LOGE(TAG, "%s for touched and not found?!", nvsName());
result = ESP_OK; result = ESP_OK;
} }
@@ -233,11 +230,11 @@ ConfigStatusReturnType ConfigWrapper<T>::writeToFlash(nvs_handle_t nvsHandle, va
{ {
CONFIGWRAPPER_TOSTRING_USINGS CONFIGWRAPPER_TOSTRING_USINGS
ESP_LOGD(TAG, "%s %s", m_nvsName, toString(value).c_str()); ESP_LOGD(TAG, "%s %s", nvsName(), toString(value).c_str());
const auto result = nvs_set(nvsHandle, m_nvsName, value); const auto result = nvs_set(nvsHandle, nvsName(), value);
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "%s %s nvs_set() returned %s", m_nvsName, toString(value).c_str(), esp_err_to_name(result)); ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), TAG, "%s %s nvs_set() returned %s", nvsName(), toString(value).c_str(), esp_err_to_name(result));
m_value = value; m_value = value;
m_touched = true; m_touched = true;

View File

@@ -16,16 +16,13 @@ namespace {
constexpr const char * const TAG = "CONFIG"; constexpr const char * const TAG = "CONFIG";
} // namespace } // namespace
ConfigWrapperInterface::ConfigWrapperInterface(AllowReset allowReset, const char *nvsName) : //ConfigWrapperInterface::ConfigWrapperInterface(AllowReset allowReset) :
m_allowReset{allowReset == AllowReset::DoReset}, // m_allowReset{allowReset == AllowReset::DoReset}
m_nvsName{nvsName} //{
{ // const auto length = std::strlen(nvsName());
{ // if (length >= NVS_KEY_NAME_MAX_SIZE)
const auto length = std::strlen(nvsName); // ESP_LOGE(TAG, "invalid nvs key %s (too long %zd)", nvsName(), length);
if (length >= NVS_KEY_NAME_MAX_SIZE) // assert(length < NVS_KEY_NAME_MAX_SIZE);
ESP_LOGE(TAG, "invalid nvs key %s (too long %zd)", nvsName, length); //}
assert(length < NVS_KEY_NAME_MAX_SIZE);
}
}
} // namespace espconfig } // namespace espconfig

View File

@@ -13,9 +13,6 @@
#include "cppmacros.h" #include "cppmacros.h"
namespace espconfig { namespace espconfig {
enum class AllowReset { NoReset, DoReset };
constexpr auto NoReset = AllowReset::NoReset;
constexpr auto DoReset = AllowReset::DoReset;
using ConfigStatusReturnType = tl::expected<void, std::string>; using ConfigStatusReturnType = tl::expected<void, std::string>;
@@ -24,7 +21,7 @@ class ConfigWrapperInterface
CPP_DISABLE_COPY_MOVE(ConfigWrapperInterface) CPP_DISABLE_COPY_MOVE(ConfigWrapperInterface)
public: public:
ConfigWrapperInterface(AllowReset allowReset, const char *nvsName); ConfigWrapperInterface() = default;
virtual ~ConfigWrapperInterface() = default; virtual ~ConfigWrapperInterface() = default;
virtual const char *type() const = 0; virtual const char *type() const = 0;
@@ -36,14 +33,12 @@ public:
virtual ConfigStatusReturnType reset(nvs_handle_t nvsHandle) = 0; virtual ConfigStatusReturnType reset(nvs_handle_t nvsHandle) = 0;
virtual ConfigStatusReturnType forceReset(nvs_handle_t nvsHandle) = 0; virtual ConfigStatusReturnType forceReset(nvs_handle_t nvsHandle) = 0;
bool allowReset() const { return m_allowReset; } virtual bool allowReset() const = 0;
const char *nvsName() const { return m_nvsName; } virtual const char *nvsName() const = 0;
bool touched() const { return m_touched; } bool touched() const { return m_touched; }
bool loaded() const { return m_loaded; } bool loaded() const { return m_loaded; }
protected: protected:
const bool m_allowReset;
const char * const m_nvsName;
bool m_touched{}; bool m_touched{};
bool m_loaded{}; bool m_loaded{};
}; };