ympd/src/list.c

207 lines
5.2 KiB
C

/* myMPD
(c) 2018-2019 Juergen Mang <mail@jcgames.de>
This project's homepage is: https://github.com/jcorporation/mympd
This linked list implementation is based on: https://github.com/joshkunz/ashuffle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
#include "list.h"
int list_init(struct list *l) {
l->length = 0;
l->list = NULL;
return 0;
}
int list_get_value(const struct list *l, const char *data) {
int value = -1;
struct node *current = l->list;
while (current != NULL) {
if (strcmp(current->data, data) == 0) {
value = current->value;
break;
}
current = current->next;
}
return value;
}
struct node *list_node_at(const struct list *l, unsigned index) {
/* if there's no data in the list, fail */
if (l->list == NULL) { return NULL; }
struct node * current = l->list;
for (; index > 0; index--) {
if (current->next == NULL) { return NULL; }
current = current->next;
}
return current;
}
int list_swap_item(struct node *n1, struct node *n2) {
if (n1 == n2)
return 1;
if (n1 == NULL || n2 == NULL)
return 1;
int value = n2->value;
char *data = n2->data;
n2->value = n1->value;
n2->data = n1->data;
n1->value = value;
n1->data = data;
return 0;
}
int list_shuffle(struct list *l) {
int pos;
int n = 0;
if (l->length < 2)
return 1;
// srand((unsigned int)time(NULL));
struct node *current = l->list;
while (current != NULL) {
pos = rand() / (RAND_MAX / (l->length - n + 1) + 1);
list_swap_item(current, list_node_at(l, pos));
n++;
current = current->next;
}
return 0;
}
int list_sort_by_value(struct list *l, bool order) {
int swapped;
struct node *ptr1;
struct node *lptr = NULL;
if (l->list == NULL)
return 1;
do {
swapped = 0;
ptr1 = l->list;
while (ptr1->next != lptr) {
if (order == true && ptr1->value > ptr1->next->value) {
list_swap_item(ptr1, ptr1->next);
swapped = 1;
}
else if (order == false && ptr1->value < ptr1->next->value) {
list_swap_item(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
return 0;
}
int list_replace(struct list *l, int pos, const char *data, int value) {
int i = 0;
struct node *current = l->list;
while (current->next != NULL) {
if (i == pos)
break;
current = current->next;
i++;
}
current->value = value;
current->data = realloc(current->data, strlen(data) + 1);
if (current->data)
strcpy(current->data, data);
return 0;
}
int list_push(struct list *l, const char *data, int value) {
struct node *n = malloc(sizeof(struct node));
n->value = value;
n->data = strdup(data);
n->next = NULL;
struct node **next = &l->list;
while (*next != NULL) {
next = &(*next)->next;
}
*next = n;
l->length++;
return 0;
}
int list_insert(struct list *l, const char *data, int value) {
struct node *n = malloc(sizeof(struct node));
n->value = value;
n->data = strdup(data);
n->next = l->list;
l->list = n;
l->length++;
return 0;
}
struct node *list_node_extract(struct list *l, unsigned idx) {
if (l->list == NULL) { return NULL; }
struct node *current = l->list, **previous = &l->list;
for (; idx > 0; idx--) {
if (current->next == NULL)
return NULL;
previous = &current->next;
current = current->next;
}
/* set the previous node's 'next' value to the current
* nodes next value */
*previous = current->next;
/* null out this node's next value since it's not part of
* a list anymore */
current->next = NULL;
l->length--;
return current;
}
int list_shift(struct list *l, unsigned idx) {
struct node * extracted = list_node_extract(l, idx);
if (extracted == NULL)
return -1;
free(extracted->data);
free(extracted);
return 0;
}
int list_free(struct list *l) {
struct node *current = l->list, *tmp = NULL;
while (current != NULL) {
free(current->data);
tmp = current;
current = current->next;
free(tmp);
}
list_init(l);
return 0;
}