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.

92 lines
2.1 KiB

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2022 Ivan Polyakov */
#include "query.h"
#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int rpd_query_parse(rpd_keyval *dest, const char *src)
{
int len = count_char_entries(src, '=');
if (!len) {
dest->items = NULL;
dest->capacity = 0;
dest->size = 0;
return 0;
}
char *query = rpd_strdup(src);
if (!query)
return 1;
dest->items = realloc(dest->items, sizeof(rpd_keyval_item *) * len);
if (!dest->items)
return 2;
dest->capacity = len;
char *tokens = query, *p = query;
int i = 0;
while ((p = rpd_strsep(&tokens, "&\n")) && i < len) {
char *param, *val;
if (*p == '=')
continue;
param = strtok(p, "=");
val = strtok(NULL, "=");
if (param) {
dest->items[i].key = rpd_strdup(param);
dest->items[i].val = val ? rpd_strdup(val) : NULL;
i++;
}
}
dest->size = i;
dest->capacity = i;
free(query);
return 0;
}
char *rpd_query_str(const rpd_keyval *query)
{
size_t len = 0;
rpd_keyval_item *item;
for (int i = 0; i < query->size; i++) {
item = &query->items[i];
if (!item->key || !item->val)
continue;
len += strlen(item->key) + strlen(item->val);
}
/* len + number of key-val delimeters + terminating char */
size_t size = len + (query->size - 1) + 1;
if (size <= 0)
return NULL;
char *buff = (char *) malloc(sizeof(char) * size);
if (!buff)
return NULL;
buff[size - 1] = '\0';
size_t offset = 0;
for (int i = 0; i < query->size; i++) {
item = &query->items[i];
if (!item->key || !item->val)
continue;
offset += sprintf(buff + offset, "%s=%s", item->key, item->val);
if (i + 1 < query->size) {
buff[offset] = '&';
offset++;
}
}
if (buff[offset - 1] == '&') {
buff[offset - 1] = '\0';
}
return buff;
}