C and C++ web framework. http://rapida.vilor.one/docs
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.

134 lines
2.9 KiB

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2022 Ivan Polyakov */
#include "keyval.h"
#include "utils.h"
#include <stdlib.h>
#include <string.h>
/*!
* \brief Reallocate key-value storage with new capacity.
*
* \param keyval Key-value storage.
* \param capacity New capacity.
*
* \return Status code.
*/
static int rpd_keyval_realloc(rpd_keyval *keyval, int capacity);
int rpd_keyval_init(rpd_keyval *keyval, int capacity)
{
keyval->size = keyval->capacity = 0;
keyval->unique = 1;
if (capacity == 0) {
keyval->items = NULL;
return 0;
}
keyval->items = (rpd_keyval_item *) malloc(sizeof(rpd_keyval_item) * capacity);
if (!keyval->items) {
return 1;
}
keyval->capacity = capacity;
return 0;
}
int rpd_keyval_insert(rpd_keyval *keyval, const char *key, const char *value)
{
if (!key || !value)
return 1;
if (keyval->size == keyval->capacity) {
int tmp = keyval->capacity == 0 ? 10 : keyval->capacity * 2;
if ((tmp = rpd_keyval_realloc(keyval, tmp)))
return tmp;
}
rpd_keyval_item *item = rpd_keyval_find(keyval, key);
if (item && keyval->unique) {
free(item->key);
item->key = NULL;
if (item->val) {
free(item->val);
item->val = NULL;
}
} else {
item = &keyval->items[keyval->size];
keyval->size++;
}
item->key = rpd_strdup(key);
item->val = rpd_strdup(value);
return item->key && item->val ? 0 : 2;
}
rpd_keyval_item *rpd_keyval_find(const rpd_keyval *keyval, const char *key)
{
int i = 0;
while (i < keyval->size) {
if (!strcmp(keyval->items[i].key, key)) {
return keyval->items + i;
}
i++;
}
return NULL;
}
rpd_keyval_item **rpd_keyval_findall(const rpd_keyval *keyval, const char *key)
{
int i = 0, n = 0;
rpd_keyval_item **items = NULL;
while (i < keyval->size) {
if (!strcmp(keyval->items[i].key, key)) {
n++;
}
i++;
}
if (!n)
return NULL;
items = malloc(sizeof(rpd_keyval_item *) * (n + 1));
if (!items)
return NULL;
items[n] = NULL;
i = 0, n = 0;
while (i < keyval->size) {
if (!strcmp(keyval->items[i].key, key)) {
items[n] = keyval->items + i;
n++;
}
i++;
}
return items;
}
void rpd_keyval_cleanup(rpd_keyval *keyval)
{
if (keyval->items) {
int i = 0;
while (i < keyval->size) {
rpd_keyval_item *item = keyval->items + i;
free(item->key);
if (item->val) {
free(item->val);
}
i++;
}
}
keyval->size = 0;
}
static int rpd_keyval_realloc(rpd_keyval *keyval, int capacity)
{
keyval->items = realloc(keyval->items, sizeof(rpd_keyval_item) * capacity);
if (!keyval->items) {
return 1;
}
keyval->capacity = capacity;
return 0;
}