I'm trying to improve my double linked list API.
int ll_create(linked_list_p list, void (*print_data)(uint8_t)) {
if (list == NULL) {
list = calloc(1, sizeof(linked_list_p));
return 0;
}
return -1;
}
int ll_destroy(linked_list_p list) {
if (list == NULL) {
return -1;
}
linked_list_node_p node_ptr = list->tail;
for(int i = list->size-1; i > 0; i--) {
if (node_ptr->next) {
free(node_ptr->next);
node_ptr->next = NULL;
}
node_ptr = node_ptr->previous;
if (node_ptr->next->previous) {
node_ptr->next->previous = NULL;
}
free(node_ptr->next);
node_ptr->next = NULL;
}
free(list->head);
list->head = NULL;
list->size = 0;
return 0;
}
int ll_get(linked_list_p list, uint32_t index, uint8_t *data){
if (list == NULL) {
return -1;
}
if (index >= list->size) {
return -1;
}
linked_list_node_p node_ptr = list->head;
for (int i = 0; i < index; i++){
if (node_ptr == NULL) {
return -1;
}
node_ptr = node_ptr->next;
}
*data = node_ptr->data.data;
return 0;
}
int ll_remove(linked_list_p list, uint32_t index) {
if (list == NULL) {
return -1;
}
if (index > list->size-1) {
return -1;
}
linked_list_node_p node_to_delete;
if (index == 0) {
node_to_delete = list->head;
list->head = list->head->next;
free(list->head->previous);
list->head->previous = NULL;
free(node_to_delete->next);
node_to_delete->next = NULL;
node_to_delete = NULL;
free(node_to_delete);
list->size --;
return 0;
}
if (index == list->size-1) {
node_to_delete = list->tail;
list->tail = list->tail->previous;
free(list->tail->next);
list->tail->next = NULL;
free(node_to_delete->previous);
node_to_delete->previous = NULL;
free(node_to_delete);
node_to_delete = NULL;
list->size --;
return 0;
}
linked_list_node_p node_ptr = list->head;
for (int i = 0; i < index-1; i++) {
node_ptr = node_ptr->next;
}
node_to_delete = node_ptr->next;
node_ptr->next->next->previous = node_ptr;
node_ptr->next = node_ptr->next->next;
node_to_delete->next = NULL;
node_to_delete->previous = NULL;
free(node_to_delete->next);
free(node_to_delete->previous);
list->size--;
return 0;
}
This is the main : I've tried to test it myself but not sure if its the right way to do it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linked_list.h"
static void print_data(uint8_t data){
printf("%d", data);
}
int main(int argc, char *argv[]){
static linked_list_t list;
ll_create(&list, print_data);
ll_add_first(&list, 2);
ll_insert(&list, 13, 0);
ll_remove(&list, 32);
ll_add_last(&list, 3);
ll_add_last(&list, 4);
ll_print(&list);
ll_destroy(&list);
ll_print(&list);
ll_add_last(&list, 5);
ll_add_last(&list, 6);
ll_add_first(&list, 7);
ll_print(&list);
ll_print_backward(&list);
ll_insert(&list, 8, 4);
printf("list size : %ld\n", list.size);
ll_insert(&list, 8, list.size);
ll_print(&list);
//TODO use every API functions
// ll_get
uint8_t get_data = 0;
ll_get(&list, 95, &get_data);
printf("got data : %d\n\n", get_data);
// ll_remove
ll_remove(&list, 5);
ll_print(&list);
// ll_insert
ll_insert(&list, 10, 2);
ll_print(&list);
// ll_contains
uint8_t data_to_find = 96;
printf("The data %d is in the list : %s", data_to_find, ll_contains(&list, data_to_find) ? "true\n" : "false\n");
data_to_find = 10;
printf("The data %d is in the list : %s", data_to_find, ll_contains(&list, data_to_find) ? "true\n" : "false\n");
printf("\n");
// ll_first_index
data_to_find = 10;
printf("The data %d is at node [%d]\n", data_to_find, ll_first_index(&list, data_to_find));
data_to_find = 96;
printf("The data %d is at node [%d]\n", data_to_find, ll_first_index(&list, data_to_find));
// ll_indexes
ll_add_last(&list, 25);
ll_add_first(&list, 25);
ll_insert(&list, 25, list.size);
ll_print(&list);
uint32_t *indexes = NULL;
uint32_t indexes_size = 0;
if (ll_indexes(&list, 25, &indexes, &indexes_size) == 0) {
for (int i = 0; i < indexes_size; i++) {
printf("%d ", indexes[i]);
}
printf("\n");
}
free(indexes);
if (ll_indexes(&list, 6, &indexes, &indexes_size) == 0) {
for (int i = 0; i < indexes_size; i++) {
printf("%d ", indexes[i]);
}
printf("\n");
}
free(indexes);
if (ll_indexes(&list, 7, &indexes, &indexes_size) == 0) {
for (int i = 0; i < indexes_size; i++) {
printf("%d ", indexes[i]);
}
printf("\n");
}
free(indexes);
ll_destroy(&list);
ll_destroy(&list);
return 0;
}
This is the header file structs and typedef
/**
* No modification required here
*/
typedef struct data_s{
uint8_t data;
} data_t;
/**
* To be implemented : double linked list
*/
struct linked_list_s;
struct linked_list_node_s;
typedef struct linked_list_s linked_list_t;
typedef linked_list_t *linked_list_p;
typedef struct linked_list_node_s linked_list_node_t;
typedef linked_list_node_t *linked_list_node_p;
struct linked_list_node_s{
linked_list_node_p next;
linked_list_node_p previous;
data_t data;
};
struct linked_list_s{
linked_list_node_p head;
linked_list_node_p tail;
size_t size;
void (*print_data)(uint8_t);
};
Why does the ll_create function have a memory leak? In the main, the list was created without nodes. Thus if we call this function, we won't enter the if statement. So how will this have a memory leak?