Sélectionner une révision Git
-
ultrakatiz a rédigéultrakatiz a rédigé
uri.c 3,85 Kio
#define _POSIX_C_SOURCE 200809L
#include <common/common.h>
#include <lektor/uri.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
static inline char *
__prefix(char *str, struct lkt_uri *ret)
{
char *val;
size_t len;
if (!str || !ret)
return NULL;
/* The minimal uri is id://1 which is a 6 characters long */
if ((len = strlen(str)) <= 5)
return NULL;
if (STR_NMATCH(str, "id", 2)) {
ret->type = uri_id;
val = str + 2;
} else if (STR_NMATCH(str, "playlist", 8)) {
ret->type = uri_playlist;
val = str + 3;
} else if (STR_NMATCH(str, "type", 4)) {
ret->type = uri_type;
val = str + 4;
} else if (STR_NMATCH(str, "author", 6)) {
ret->type = uri_author;
val = str + 6;
} else if (STR_NMATCH(str, "category", 8)) {
ret->type = uri_category;
val = str + 8;
} else if (STR_NMATCH(str, "lang", 4)) {
ret->type = uri_language;
val = str + 4;
} else if (STR_NMATCH(str, "query", 5)) {
ret->type = uri_query;
val = str + 5;
} else
return NULL;
/* No place for the '://' separator */
if (len - (val - str) < 3)
return NULL;
val += 3;
ret->value = val;
return val;
}
bool
lkt_uri_from(struct lkt_uri *ret, char *const str)
{
if (NULL == __prefix(str, ret))
return false;
if (ret->type == uri_id) {
errno = 0;
ret->id = strtol(ret->value, NULL, 10); /* Override */
if (errno != 0)
return false;
}
ret->_allocated = false;
return true;
}
bool
lkt_uri_from_list(struct lkt_uri *ret, char **list)
{
int i;
if (!list || !list[0])
return false;
if (!list[1])
return lkt_uri_from(ret, list[0]);
if (NULL == __prefix(list[0], ret))
return false;
/* Nothing after the separator */
if ('\0' == * (char *) ret->value)
return false;
char *buffer = (char *) malloc(sizeof(char) * (strlen(ret->value) + 1));
if (NULL == buffer)
return false;
strcpy(buffer, ret->value);
for (i = 1; list[i]; ++i) {
char *new = realloc(buffer, strlen(buffer) + 1 + strlen(list[i]) + 1);
if (NULL == new) {
free(buffer);
return false;
}
buffer = new;
strcat(buffer, " ");
strcat(buffer, list[i]);
}
ret->value = buffer;
ret->_allocated = true;
return true;
}
void
lkt_uri_free(struct lkt_uri *ret)
{
if (NULL == ret)
return;
if (ret->_allocated)
free(ret->value);
}
/* Support a subrange of URIs. */
static inline int
__lkt_to_str(struct lkt_uri *uri, char *ret, size_t len)
{
switch (uri->type) {
case uri_id:
safe_snprintf(ret, len, "id=%s", (char *) uri->value);
break;
case uri_type:
safe_snprintf(ret, len, "type=%s", (char *) uri->value);
break;
case uri_author:
safe_snprintf(ret, len, "author=%s", (char *) uri->value);
break;
case uri_category:
safe_snprintf(ret, len, "cat=%s", (char *) uri->value);
break;
case uri_query:
safe_snprintf(ret, len, "search=%s", (char *) uri->value);
break;
default:
LOG_WARN("URI", "type %d may not be supported by kurisu, "
"generate an error", uri->type);
return 1;
}
ret[len - 1] = '\0';
return 0;
}
int
lkt_uri_to_url(struct lkt_uri *uri, const char *base_url, char *ret, size_t len)
{
RETURN_UNLESS(uri && base_url && ret && len > 0, "Invalid argument", 1);
/* Craft URL */
memset(ret, 0, len);
memcpy(ret, base_url, sizeof(char) * strlen(base_url));
strncat(ret, "?", len - 1);
/* The query */
size_t init_len = strlen(ret);
return __lkt_to_str(uri, ret + init_len, len - init_len);
}