Files
Leo-ElixirLights/components/nvsUtils/src/nvsIo.cpp
T
2025-01-01 21:15:01 +01:00

168 lines
4.6 KiB
C++

/**
* @file nvsIo.cpp
* @author Gustice
* @brief Read-Write access to specific NVS partition
*
* @copyright Copyright (c) 2024
*/
#include "nvsIo.hpp"
#include "esp_err.h"
#include "esp_log.h"
#include <cstring>
#include <memory>
static const char *TAG = "NVS";
static esp_err_t storeBlob(nvs_handle_t nvs, const char *key, const char *str_values) {
uint8_t value;
size_t str_len = strlen(str_values);
size_t blob_len = str_len / 2;
if (str_len % 2) {
ESP_LOGE(TAG, "Blob data must contain even number of characters");
return ESP_ERR_NVS_TYPE_MISMATCH;
}
char *blob = (char *)malloc(blob_len);
if (blob == NULL) {
return ESP_ERR_NO_MEM;
}
for (int i = 0, j = 0; i < str_len; i++) {
char ch = str_values[i];
if (ch >= '0' && ch <= '9') {
value = ch - '0';
} else if (ch >= 'A' && ch <= 'F') {
value = ch - 'A' + 10;
} else if (ch >= 'a' && ch <= 'f') {
value = ch - 'a' + 10;
} else {
ESP_LOGE(TAG, "Blob data contain invalid character");
free(blob);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
if (i & 1) {
blob[j++] += value;
} else {
blob[j] = value << 4;
}
}
esp_err_t err = nvs_set_blob(nvs, key, blob, blob_len);
free(blob);
if (err == ESP_OK) {
err = nvs_commit(nvs);
}
return err;
}
template <>
esp_err_t NvsIo::setValueByStr<int8_t>(const char *key, const char *strValue) {
int32_t value = strtol(strValue, NULL, 0);
if (value < INT8_MIN || value > INT8_MAX || errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setInt8(key, (int8_t)value);
}
template <>
esp_err_t NvsIo::setValueByStr<uint8_t>(const char *key, const char *strValue) {
uint32_t value = strtoul(strValue, NULL, 0);
if (value > UINT8_MAX || errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setUint8(key, (uint8_t)value);
}
template <>
esp_err_t NvsIo::setValueByStr<int16_t>(const char *key, const char *strValue) {
int32_t value = strtol(strValue, NULL, 0);
if (value < INT16_MIN || value > INT16_MAX || errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setInt16(key, (int16_t)value);
}
template <>
esp_err_t NvsIo::setValueByStr<uint16_t>(const char *key, const char *strValue) {
uint32_t value = strtoul(strValue, NULL, 0);
if (value > UINT16_MAX || errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setUint16(key, (uint16_t)value);
}
template <>
esp_err_t NvsIo::setValueByStr<int32_t>(const char *key, const char *strValue) {
int32_t value = strtol(strValue, NULL, 0);
if (errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setInt32(key, value);
}
template <>
esp_err_t NvsIo::setValueByStr<uint32_t>(const char *key, const char *strValue) {
uint32_t value = strtoul(strValue, NULL, 0);
if (errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setUint32(key, value);
}
template <>
esp_err_t NvsIo::setValueByStr<int64_t>(const char *key, const char *strValue) {
int64_t value = strtoll(strValue, NULL, 0);
if (errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setInt64(key, value);
}
template <>
esp_err_t NvsIo::setValueByStr<uint64_t>(const char *key, const char *strValue) {
uint64_t value = strtoull(strValue, NULL, 0);
if (errno == ERANGE) {
throw CoreException(ErrMsg_TooLong);
}
return setUint64(key, value);
}
esp_err_t NvsIo::setString(const char *key, const char *strValue) {
return nvs_set_str(_nvs, key, strValue);
}
esp_err_t NvsIo::setBlob(const char *key, const char *strValue) {
return storeBlob(_nvs, key, strValue);
}
std::optional<std::string> NvsIo::getString(const char *key) {
size_t len;
if (nvs_get_str(_nvs, key, NULL, &len) != ESP_OK) {
return {std::nullopt};
}
auto str = std::make_unique<char[]>(len);
if ((nvs_get_str(_nvs, key, str.get(), &len)) != ESP_OK) {
return {std::nullopt};
}
return {str.get()};
}
std::optional<std::vector<char>> NvsIo::getBlob(const char *key) {
size_t len;
if (nvs_get_blob(_nvs, key, NULL, &len) != ESP_OK) {
return {std::nullopt};
}
auto blob = std::make_unique<char[]>(len);
if (nvs_get_blob(_nvs, key, blob.get(), &len) != ESP_OK) {
return {std::nullopt};
}
std::vector<char> vec;
vec.reserve(len);
vec.insert(vec.end(), blob.get(), blob.get() + len);
return {vec};
}