esp32 firmware for a toaster reflow oven WIP!!!!!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
reflower/components/httpd_utils/src/session_kvmap.c

181 lines
4.5 KiB

//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <rom/queue.h>
#include <malloc.h>
#include <assert.h>
#include <esp_log.h>
#include <esp_err.h>
#include <string.h>
#include "httpd_utils/session_kvmap.h"
static const char *TAG = "sess_kvmap";
// this struct is opaque, a stub like this is sufficient for the head pointer.
struct sess_kv_entry;
/** Session head structure, dynamically allocated */
SLIST_HEAD(sess_kv_map, sess_kv_entry);
struct sess_kv_entry {
SLIST_ENTRY(sess_kv_entry) link;
char key[SESS_KVMAP_KEY_LEN];
void *value;
sess_kv_free_func_t free_fn;
};
struct sess_kv_map *sess_kv_map_alloc(void)
{
ESP_LOGD(TAG, "kv store alloc");
struct sess_kv_map *map = malloc(sizeof(struct sess_kv_map));
assert(map);
SLIST_INIT(map);
return map;
}
void sess_kv_map_free(void *head_v)
{
struct sess_kv_map* head = head_v;
ESP_LOGD(TAG, "kv store free");
assert(head);
struct sess_kv_entry *item, *tmp;
SLIST_FOREACH_SAFE(item, head, link, tmp) {
if (item->free_fn) {
item->free_fn(item->value);
free(item);
}
}
free(head);
}
void * sess_kv_map_get(struct sess_kv_map *head, const char *key)
{
assert(head);
assert(key);
ESP_LOGD(TAG, "kv store get %s", key);
struct sess_kv_entry *item;
SLIST_FOREACH(item, head, link) {
if (0==strcmp(item->key, key)) {
ESP_LOGD(TAG, "got ok");
return item->value;
}
}
ESP_LOGD(TAG, "not found in store");
return NULL;
}
void * sess_kv_map_take(struct sess_kv_map *head, const char *key)
{
assert(head);
assert(key);
ESP_LOGD(TAG, "kv store take %s", key);
struct sess_kv_entry *item;
SLIST_FOREACH(item, head, link) {
if (0==strcmp(item->key, key)) {
item->key[0] = 0;
item->free_fn = NULL;
ESP_LOGD(TAG, "taken ok");
return item->value;
}
}
ESP_LOGD(TAG, "not found in store");
return NULL;
}
esp_err_t sess_kv_map_remove(struct sess_kv_map *head, const char *key)
{
assert(head);
assert(key);
ESP_LOGD(TAG, "kv store remove %s", key);
struct sess_kv_entry *item;
SLIST_FOREACH(item, head, link) {
if (0==strcmp(item->key, key)) {
if (item->free_fn) {
item->free_fn(item->value);
}
item->key[0] = 0;
item->value = NULL;
item->free_fn = NULL;
return ESP_OK;
}
}
ESP_LOGD(TAG, "couldn't remove, not found: %s", key);
return ESP_ERR_NOT_FOUND;
}
esp_err_t sess_kv_map_set(struct sess_kv_map *head, const char *key, void *value, sess_kv_free_func_t free_fn)
{
assert(head);
assert(key);
ESP_LOGD(TAG, "kv set value for key %s", key);
size_t key_len = strlen(key);
if (key_len > SESS_KVMAP_KEY_LEN-1) {
ESP_LOGE(TAG, "Key too long: %s", key);
// discard illegal key
return ESP_FAIL;
}
if (key_len == 0) {
ESP_LOGE(TAG, "Key too short: \"%s\"", key);
// discard illegal key
return ESP_FAIL;
}
struct sess_kv_entry *item = NULL;
struct sess_kv_entry *empty_item = NULL; // found item with no content
SLIST_FOREACH(item, head, link) {
ESP_LOGD(TAG, "test item with key %s, ptr %p > %p", item->key, item, item->link.sle_next);
if (0 == item->key[0]) {
ESP_LOGD(TAG, "found an empty slot");
empty_item = item;
}
else if (0==strcmp(item->key, key)) {
ESP_LOGD(TAG, "old value replaced");
if (item->free_fn) {
item->free_fn(item->value);
}
item->value = value;
item->free_fn = free_fn;
return ESP_OK;
} else {
ESP_LOGD(TAG, "skip this one");
}
}
struct sess_kv_entry *new_item = NULL;
// insert new or reuse an empty item
if (empty_item) {
new_item = empty_item;
ESP_LOGD(TAG, "empty item reused (%p)", new_item);
} else {
ESP_LOGD(TAG, "alloc new item");
// key not found, add a new entry.
new_item = malloc(sizeof(struct sess_kv_entry));
if (!new_item) {
ESP_LOGE(TAG, "New entry alloc failed");
return ESP_ERR_NO_MEM;
}
}
strcpy(new_item->key, key);
new_item->free_fn = free_fn;
new_item->value = value;
if (!empty_item) {
ESP_LOGD(TAG, "insert new item into list");
// this item was malloc'd
SLIST_INSERT_HEAD(head, new_item, link);
}
return ESP_OK;
}