mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-15 16:48:22 -04:00
Add trimwhitespace(), keyval sorting and alloc to misc functions
- features required by the LastFM module
This commit is contained in:
parent
d5efc2dcb3
commit
21cf3ab7d3
109
src/misc.c
109
src/misc.c
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -258,12 +259,33 @@ safe_hextou64(const char *str, uint64_t *val)
|
|||||||
|
|
||||||
|
|
||||||
/* Key/value functions */
|
/* Key/value functions */
|
||||||
|
struct keyval *
|
||||||
|
keyval_alloc(void)
|
||||||
|
{
|
||||||
|
struct keyval *kv;
|
||||||
|
|
||||||
|
kv = (struct keyval *)malloc(sizeof(struct keyval));
|
||||||
|
if (!kv)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_MISC, "Out of memory for keyval alloc\n");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(kv, 0, sizeof(struct keyval));
|
||||||
|
|
||||||
|
return kv;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
keyval_add_size(struct keyval *kv, const char *name, const char *value, size_t size)
|
keyval_add_size(struct keyval *kv, const char *name, const char *value, size_t size)
|
||||||
{
|
{
|
||||||
struct onekeyval *okv;
|
struct onekeyval *okv;
|
||||||
const char *val;
|
const char *val;
|
||||||
|
|
||||||
|
if (!kv)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Check for duplicate key names */
|
/* Check for duplicate key names */
|
||||||
val = keyval_get(kv, name);
|
val = keyval_get(kv, name);
|
||||||
if (val)
|
if (val)
|
||||||
@ -330,6 +352,9 @@ keyval_remove(struct keyval *kv, const char *name)
|
|||||||
struct onekeyval *okv;
|
struct onekeyval *okv;
|
||||||
struct onekeyval *pokv;
|
struct onekeyval *pokv;
|
||||||
|
|
||||||
|
if (!kv)
|
||||||
|
return;
|
||||||
|
|
||||||
for (pokv = NULL, okv = kv->head; okv; pokv = okv, okv = okv->next)
|
for (pokv = NULL, okv = kv->head; okv; pokv = okv, okv = okv->next)
|
||||||
{
|
{
|
||||||
if (strcasecmp(okv->name, name) == 0)
|
if (strcasecmp(okv->name, name) == 0)
|
||||||
@ -358,6 +383,9 @@ keyval_get(struct keyval *kv, const char *name)
|
|||||||
{
|
{
|
||||||
struct onekeyval *okv;
|
struct onekeyval *okv;
|
||||||
|
|
||||||
|
if (!kv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (okv = kv->head; okv; okv = okv->next)
|
for (okv = kv->head; okv; okv = okv->next)
|
||||||
{
|
{
|
||||||
if (strcasecmp(okv->name, name) == 0)
|
if (strcasecmp(okv->name, name) == 0)
|
||||||
@ -373,6 +401,9 @@ keyval_clear(struct keyval *kv)
|
|||||||
struct onekeyval *hokv;
|
struct onekeyval *hokv;
|
||||||
struct onekeyval *okv;
|
struct onekeyval *okv;
|
||||||
|
|
||||||
|
if (!kv)
|
||||||
|
return;
|
||||||
|
|
||||||
hokv = kv->head;
|
hokv = kv->head;
|
||||||
|
|
||||||
for (okv = hokv; hokv; okv = hokv)
|
for (okv = hokv; hokv; okv = hokv)
|
||||||
@ -388,6 +419,47 @@ keyval_clear(struct keyval *kv)
|
|||||||
kv->tail = NULL;
|
kv->tail = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
keyval_sort(struct keyval *kv)
|
||||||
|
{
|
||||||
|
struct onekeyval *head;
|
||||||
|
struct onekeyval *okv;
|
||||||
|
struct onekeyval *sokv;
|
||||||
|
|
||||||
|
if (!kv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
head = kv->head;
|
||||||
|
for (okv = kv->head; okv; okv = okv->next)
|
||||||
|
{
|
||||||
|
okv->sort = NULL;
|
||||||
|
for (sokv = kv->head; sokv; sokv = sokv->next)
|
||||||
|
{
|
||||||
|
// We try to find a name which is greater than okv->name
|
||||||
|
// but less than our current candidate (okv->sort->name)
|
||||||
|
if ( (strcmp(sokv->name, okv->name) > 0) &&
|
||||||
|
((okv->sort == NULL) || (strcmp(sokv->name, okv->sort->name) < 0)) )
|
||||||
|
okv->sort = sokv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find smallest name, which will be the new head
|
||||||
|
if (strcmp(okv->name, head->name) < 0)
|
||||||
|
head = okv;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((okv = kv->head))
|
||||||
|
{
|
||||||
|
kv->head = okv->next;
|
||||||
|
okv->next = okv->sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv->head = head;
|
||||||
|
for (okv = kv->head; okv; okv = okv->next)
|
||||||
|
kv->tail = okv;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_MISC, "Keyval sorted. New head: %s. New tail: %s.\n", kv->head->name, kv->tail->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
m_realpath(const char *pathname)
|
m_realpath(const char *pathname)
|
||||||
@ -445,6 +517,43 @@ unicode_fixup_string(char *str)
|
|||||||
return (char *)ret;
|
return (char *)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
trimwhitespace(const char *str)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
char *start;
|
||||||
|
char *out;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Find the beginning
|
||||||
|
while (isspace(*str))
|
||||||
|
str++;
|
||||||
|
|
||||||
|
if (*str == 0) // All spaces?
|
||||||
|
return strdup("");
|
||||||
|
|
||||||
|
// Make copy, because we will need to insert a null terminator
|
||||||
|
start = strdup(str);
|
||||||
|
if (!start)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Find the end
|
||||||
|
ptr = start + strlen(start) - 1;
|
||||||
|
while (ptr > start && isspace(*ptr))
|
||||||
|
ptr--;
|
||||||
|
|
||||||
|
// Insert null terminator
|
||||||
|
*(ptr+1) = 0;
|
||||||
|
|
||||||
|
out = strdup(start);
|
||||||
|
|
||||||
|
free(start);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
djb_hash(void *data, size_t len)
|
djb_hash(void *data, size_t len)
|
||||||
{
|
{
|
||||||
|
10
src/misc.h
10
src/misc.h
@ -12,6 +12,7 @@ struct onekeyval {
|
|||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
struct onekeyval *next;
|
struct onekeyval *next;
|
||||||
|
struct onekeyval *sort;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct keyval {
|
struct keyval {
|
||||||
@ -40,6 +41,9 @@ safe_hextou64(const char *str, uint64_t *val);
|
|||||||
|
|
||||||
|
|
||||||
/* Key/value functions */
|
/* Key/value functions */
|
||||||
|
struct keyval *
|
||||||
|
keyval_alloc(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
keyval_add(struct keyval *kv, const char *name, const char *value);
|
keyval_add(struct keyval *kv, const char *name, const char *value);
|
||||||
|
|
||||||
@ -55,6 +59,9 @@ keyval_get(struct keyval *kv, const char *name);
|
|||||||
void
|
void
|
||||||
keyval_clear(struct keyval *kv);
|
keyval_clear(struct keyval *kv);
|
||||||
|
|
||||||
|
void
|
||||||
|
keyval_sort(struct keyval *kv);
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
m_realpath(const char *pathname);
|
m_realpath(const char *pathname);
|
||||||
@ -62,6 +69,9 @@ m_realpath(const char *pathname);
|
|||||||
char *
|
char *
|
||||||
unicode_fixup_string(char *str);
|
unicode_fixup_string(char *str);
|
||||||
|
|
||||||
|
char *
|
||||||
|
trimwhitespace(const char *str);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
djb_hash(void *data, size_t len);
|
djb_hash(void *data, size_t len);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user