Codebase list massdns / 2e893220-3b6e-42c7-8ec6-604da13b89e5/main list.h
2e893220-3b6e-42c7-8ec6-604da13b89e5/main

Tree @2e893220-3b6e-42c7-8ec6-604da13b89e5/main (Download .tar.gz)

list.h @2e893220-3b6e-42c7-8ec6-604da13b89e5/mainraw · history · blame

#ifndef INC_LIST
#define INC_LIST

#include "buffers.h"
#include "security.h"
#include <stdbool.h>

#define single_list_foreach(list, element) for (single_list_element_t *(element) = (list).first; (element) != NULL; (element) = (element)->next)
#define single_list_ref_foreach(list, element) for (single_list_element_t *(element) = (list)->first; (element) != NULL; (element) = (element)->next)
#define single_list_foreach_free(list, element) for (single_list_element_t *(element) = (list).first; (element) != NULL; (element) = single_list_free_and_next(element))
#define single_list_ref_foreach_free(list, element) for (single_list_element_t *(element) = (list)->first; (element) != NULL; (element) = single_list_free_and_next(element))

#define double_list_foreach_free(list, element) for (double_list_element_t *(element) = (list).first; (element) != NULL; (element) = double_list_free_and_next(element))

typedef struct single_list_element
{
    void *data;
    struct single_list_element *next;
} single_list_element_t;

typedef struct
{
    size_t count;
    single_list_element_t *first;
    single_list_element_t *last;
} single_list_t;

typedef struct double_list_element
{
    void *data;
    struct double_list_element *previous;
    struct double_list_element *next;
} double_list_element_t;

typedef struct
{
    size_t count;
    double_list_element_t *first;
    double_list_element_t *last;
} double_list_t;

size_t single_list_count(single_list_t* list)
{
    return list->count;
}

bool single_list_iterate(single_list_t *list, bool (*f)(void *, void *), void *param)
{
    single_list_element_t* element = list->first;
    while (element != NULL)
    {
        single_list_element_t *next = element->next;
        if(!f(element->data, param))
        {
            return false;
        }
        element = next;
    }
    return true;
}

bool single_list_iterate_free(single_list_t *list, bool (*f)(void *, void *), void *param)
{
    single_list_element_t* element = list->first;
    while (element != NULL)
    {
        single_list_element_t *next = element->next;
        if(!f(element->data, param))
        {
            return false;
        }
        free(element);
        list->first = next;
        list->count--;
        element = next;
    }
    list->last = NULL;
    return true;
}

bool single_list_element_set_array_element(void *element, void *param)
{
    buffer_t *buffer = param;
    void **data = buffer->data;
    data[buffer->len++] = element;
    return true;
}

buffer_t single_list_to_array(single_list_t *list)
{
    buffer_t buf;
    buf.len = 0;
    buf.data = safe_malloc(sizeof(buf.data) * list->count);
    single_list_iterate(list, single_list_element_set_array_element, &buf);
    return buf;
}

buffer_t single_list_to_array_copy(single_list_t *list, size_t element_size)
{
    buffer_t buf;
    buf.len = list->count;
    buf.data = safe_malloc(element_size * list->count);
    size_t i = 0;
    single_list_ref_foreach(list, element)
    {
        memcpy(((uint8_t*)buf.data) + (i++) * element_size, element->data, element_size);
    }
    return buf;
}

single_list_t *single_list_new()
{
    single_list_t *list = safe_calloc(sizeof(*list));
    return list;
}

void single_list_init(single_list_t *list)
{
    bzero(list, sizeof(*list));
}

void single_list_cat(single_list_t* left, single_list_t* right)
{
    if(left->last != NULL)
    {
        left->last->next = right->first;
    }
    else
    {
        left->first = right->first;
        left->last = right->last;
    }
    left->count += right->count;
    left->last = right->last;
}

void single_list_clear(single_list_t *list)
{
    single_list_element_t *element = list->first;
    while (element != NULL)
    {
        single_list_element_t *next = element->next;
        free(element);
        element = next;
    }
    single_list_init(list);
}

void single_list_free(single_list_t *list)
{
    if(list != NULL)
    {
        single_list_clear(list);
    }
    free(list);
}

void single_list_free_elements(single_list_t *list)
{
    if(list == NULL)
    {
        return;
    }
    single_list_element_t *current = list->first;
    while(current != NULL)
    {
        single_list_element_t *next = current->next;
        free(current->data);
        free(current);
        current = next;
    }
}

void single_list_free_with_elements(single_list_t *list)
{
    single_list_free_elements(list);
    free(list);
}

void single_list_push_front(single_list_t *list, void *data)
{
    single_list_element_t *new_element = safe_malloc(sizeof(*new_element));
    new_element->data = data;
    new_element->next = list->first;
    if (list->last == NULL)
    {
        list->last = new_element;
    }
    list->first = new_element;
    list->count++;
}

single_list_element_t *single_list_push_back(single_list_t *list, void *data)
{
    single_list_element_t *new_element = safe_malloc(sizeof(*new_element));
    new_element->data = data;
    new_element->next = NULL;
    list->count++;
    if (list->last)
    {
        list->last->next = new_element;
    }
    else
    {
        list->first = new_element;
    }
    list->last = new_element;
    return new_element;
}

/**
 * Pop the first element from a list and push it to the back.
 *
 * @param list The list to be wrapped.
 */
void single_list_wrap_first(single_list_t *list)
{
    if(list->first == NULL)
    {
        return;
    }
    list->last->next = list->first;
    list->last = list->first;
    list->first = list->first->next;
    list->last->next = NULL;
}

double_list_t* double_list_new()
{
    double_list_t *list = safe_calloc(sizeof(*list));
    return list;
}

void double_list_init(double_list_t *list)
{
    bzero(list, sizeof(*list));
}

void double_list_free(double_list_t *list_holder)
{
    double_list_element_t *list = list_holder->first;
    while (list != NULL)
    {
        double_list_element_t *next = list->next;
        free(list);
        list = next;
    }
}

void double_list_push_front(double_list_t *list, void *data)
{
    double_list_element_t *new_element = safe_malloc(sizeof(*new_element));
    new_element->data = data;
    new_element->next = list->first;
    new_element->previous = NULL;
    if (list->last == NULL)
    {
        list->last = new_element;
    }
    list->first = new_element;
    list->count++;
}

double_list_element_t *double_list_push_back(double_list_t *list, void *data)
{
    double_list_element_t *new_element = safe_malloc(sizeof(*new_element));
    new_element->data = data;
    new_element->next = NULL;
    new_element->previous = list->last;
    list->count++;
    if (list->last)
    {
        list->last->next = new_element;
    }
    else
    {
        list->first = new_element;
    }
    list->last = new_element;
    return new_element;
}

void double_list_clear(double_list_t *list)
{
    double_list_element_t *element = list->first;
    while (element != NULL)
    {
        double_list_element_t *next = element->next;
        free(element);
        element = next;
    }
    double_list_init(list);
}

void double_list_iterate(double_list_t *list, void (*f)(double_list_element_t *, size_t, void *), void *param)
{
    double_list_element_t* element = list->first;
    size_t counter = 0;
    while (element != NULL)
    {
        double_list_element_t *next = element->next;
        f(element, counter++, param);
        element = next;
    }
}

double_list_element_t* double_list_free_and_next(double_list_element_t *element)
{
    double_list_element_t *next = element->next;
    free(element);
    return next;
}

single_list_element_t* single_list_free_and_next(single_list_element_t *element)
{
    single_list_element_t *next = element->next;
    free(element);
    return next;
}

void single_list_remove(single_list_t* list, void *value)
{
    single_list_element_t *last = NULL;
    single_list_element_t *element = list->first;
    while (element != NULL)
    {
        if(element->data == value)
        {
            if(last == NULL)
            {
                list->first = list->first->next;
            }
            else
            {
                last->next = element->next;
            }
            if(element == list->last)
            {
                list->last = last;
            }
            list->count--;
            element = single_list_free_and_next(element);
        }
        else
        {
            last = element;
            element = element->next;
        }
    }
}

#endif