Enhance NVSStorageHandler with filtering capabilities and update constructor to accept namespace

This commit is contained in:
GW_MC
2026-01-19 12:55:12 +08:00
parent 01c36669cf
commit 18ac21e257
4 changed files with 164 additions and 12 deletions

View File

@@ -2,6 +2,9 @@
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
typedef bool(*FilterFunc)(const char* const& key);
typedef void (*KeyValueProcessor)(void* arg, const char* const& key, const char* const& value);
class KVStorageHandler {
public:
virtual ~KVStorageHandler() = default;
@@ -9,12 +12,15 @@ public:
virtual void init(const EventGroupHandle_t& system_event_group) = 0;
// Store a key-value pair
virtual void put(const char*& key, const char*& value) = 0;
virtual void put(const char* const& key, const char* const& value) = 0;
// Retrieve a value by key, returns nullptr if key not found
// The caller is responsible for freeing the returned memory
virtual char* get(const char*& key) const = 0;
virtual char* get(const char* const& key) const = 0;
virtual esp_err_t process_all(KeyValueProcessor processor, void* arg) const = 0;
virtual esp_err_t process_filtered(const char* const& key_prefix, KeyValueProcessor processor, void* arg) const = 0;
virtual esp_err_t process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const = 0;
// Delete a key-value pair
virtual void remove(const char*& key) = 0;
virtual void remove(const char* const& key) = 0;
};

View File

@@ -1,6 +1,11 @@
#include "common/constants.h"
#include "io/nvs_handler.h"
#include "nvs_flash.h"
#include "string.h"
NVSStorageHandler::NVSStorageHandler(
const char* name_space
) : name_space(name_space) { }
NVSStorageHandler::~NVSStorageHandler() {
if (this->nvsHandle != 0) {
@@ -17,7 +22,7 @@ void NVSStorageHandler::init(const EventGroupHandle_t& system_event_group) {
}
ESP_ERROR_CHECK(err);
err = nvs_open("storage", NVS_READWRITE, &this->nvsHandle);
err = nvs_open(this->name_space, NVS_READWRITE, &this->nvsHandle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
} else {
@@ -26,7 +31,7 @@ void NVSStorageHandler::init(const EventGroupHandle_t& system_event_group) {
}
}
void NVSStorageHandler::put(const char*& key, const char*& value) {
void NVSStorageHandler::put(const char* const& key, const char* const& value) {
if (this->nvsHandle == 0) {
printf("NVS handle is not initialized.\n");
return;
@@ -41,7 +46,7 @@ void NVSStorageHandler::put(const char*& key, const char*& value) {
}
}
char* NVSStorageHandler::get(const char*& key) const {
char* NVSStorageHandler::get(const char* const& key) const {
if (this->nvsHandle == 0) {
printf("NVS handle is not initialized.\n");
return nullptr;
@@ -68,7 +73,102 @@ char* NVSStorageHandler::get(const char*& key) const {
return value;
}
void NVSStorageHandler::remove(const char*& key) {
NVSIteratorGuard NVSStorageHandler::create_iterator() const {
nvs_iterator_t it = nullptr;
esp_err_t err = nvs_entry_find(NVS_DEFAULT_PART_NAME, this->name_space, NVS_TYPE_ANY, &it);
if (err != ESP_OK) {
printf("Error (%s) creating NVS iterator!\n", esp_err_to_name(err));
return NVSIteratorGuard(nullptr, err);
}
return NVSIteratorGuard(it, ESP_OK);
}
esp_err_t NVSStorageHandler::process_all(KeyValueProcessor processor, void* arg) const {
NVSIteratorGuard iterator_guard = this->create_iterator();
if (!iterator_guard.is_valid()) {
return iterator_guard.get_error();
}
const nvs_iterator_t& it = iterator_guard.get_iterator();
for (; it != NULL; iterator_guard.advance_iter()) {
nvs_entry_info_t info;
esp_err_t err = nvs_entry_info(it, &info);
if (err != ESP_OK) {
printf("Error (%s) getting NVS entry info!\n", esp_err_to_name(err));
return err;
}
nvs_handle_t temp_handle;
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle for reading!\n", esp_err_to_name(err));
return err;
}
// call the processor with the key and value
processor(arg, info.key, this->get(info.key));
}
return ESP_OK;
}
esp_err_t NVSStorageHandler::process_filtered(const char* const& key_prefix, KeyValueProcessor processor, void* arg) const {
NVSIteratorGuard iterator_guard = this->create_iterator();
if (!iterator_guard.is_valid()) {
return iterator_guard.get_error();
}
const nvs_iterator_t& it = iterator_guard.get_iterator();
for (; it != NULL; iterator_guard.advance_iter()) {
nvs_entry_info_t info;
esp_err_t err = nvs_entry_info(it, &info);
if (err != ESP_OK) {
printf("Error (%s) getting NVS entry info!\n", esp_err_to_name(err));
return err;
}
// check if the key matches the prefix
if (strncmp(info.key, key_prefix, strlen(key_prefix)) == 0) {
nvs_handle_t temp_handle;
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle for reading!\n", esp_err_to_name(err));
return err;
}
// call the processor with the key and value
processor(arg, info.key, this->get(info.key));
}
}
return ESP_OK;
}
esp_err_t NVSStorageHandler::process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const {
NVSIteratorGuard iterator_guard = this->create_iterator();
if (!iterator_guard.is_valid()) {
return iterator_guard.get_error();
}
const nvs_iterator_t& it = iterator_guard.get_iterator();
for (; it != NULL; iterator_guard.advance_iter()) {
nvs_entry_info_t info;
esp_err_t err = nvs_entry_info(it, &info);
if (err != ESP_OK) {
printf("Error (%s) getting NVS entry info!\n", esp_err_to_name(err));
return err;
}
// check if the key matches the filter function
if (filter_func(info.key)) {
nvs_handle_t temp_handle;
err = nvs_open(this->name_space, NVS_READONLY, &temp_handle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle for reading!\n", esp_err_to_name(err));
return err;
}
// call the processor with the key and value
processor(arg, info.key, this->get(info.key));
}
}
return ESP_OK;
}
void NVSStorageHandler::remove(const char* const& key) {
if (this->nvsHandle == 0) {
printf("NVS handle is not initialized.\n");
return;

View File

@@ -5,17 +5,61 @@
class NVSStorageHandler : public KVStorageHandler {
public:
NVSStorageHandler() = default;
NVSStorageHandler(
const char* name_space
);
~NVSStorageHandler() override;
void init(const EventGroupHandle_t& system_event_group) override;
void put(const char*& key, const char*& value) override;
void put(const char* const& key, const char* const& value) override;
char* get(const char*& key) const override;
char* get(const char* const& key) const override;
esp_err_t process_all(KeyValueProcessor processor, void* arg) const override;
esp_err_t process_filtered(const char* const& key_prefix, KeyValueProcessor processor, void* arg) const override;
esp_err_t process_filtered(FilterFunc filter_func, KeyValueProcessor processor, void* arg) const override;
void remove(const char*& key) override;
void remove(const char* const& key) override;
private:
NVSIteratorGuard create_iterator() const;
nvs_handle_t nvsHandle = 0;
const char* name_space;
};
struct NVSIteratorGuard {
public:
~NVSIteratorGuard() {
if (iterator) {
nvs_release_iterator(iterator);
}
}
const nvs_iterator_t const& get_iterator() const {
return iterator;
}
void advance_iter() {
if (iterator) {
// advance the iterator and update the internal state
esp_err_t err = nvs_entry_next(&iterator);
if (err != ESP_OK) {
error = err;
iterator = nullptr;
}
}
}
esp_err_t get_error() const {
return error;
}
bool is_valid() const {
return iterator != nullptr && error == ESP_OK;
}
friend class NVSStorageHandler;
private:
NVSIteratorGuard(nvs_iterator_t it
, esp_err_t err
) : iterator(it), error(err) { }
nvs_iterator_t iterator;
esp_err_t error;
};