From b8edda8527ee92ee3b165cec08a7bd5f90be848c Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sat, 22 Feb 2014 22:55:33 +0100 Subject: [PATCH 1/2] sys: added a single linked list implementation --- sys/include/slist.h | 243 +++++++++++++++++++++++++++++++++++++++++++ sys/slist/Makefile | 1 + sys/slist/slist.c | 175 +++++++++++++++++++++++++++++++ tests/slist/Makefile | 6 ++ tests/slist/main.c | 215 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 640 insertions(+) create mode 100644 sys/include/slist.h create mode 100644 sys/slist/Makefile create mode 100644 sys/slist/slist.c create mode 100644 tests/slist/Makefile create mode 100644 tests/slist/main.c diff --git a/sys/include/slist.h b/sys/include/slist.h new file mode 100644 index 000000000000..ba32e2caa636 --- /dev/null +++ b/sys/include/slist.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @file + * @brief simple single linked list implementation with iterators + * + * A list entry is a struct of an arbitrary type but with the only constraint that + * it's first entry is a pointer of the same type as the struct with the name next. + * + * A list is defined by it's first entry, called head. Since the first entry may + * change, a pointer to the first entry is used to refer to the list. + * + * The list automatically allocates and deallocates memory when list elements + * are added or removed + * + * @author Benjamin Valentin + */ + + +#ifndef SIMPLE_LIST_H_ +#define SIMPLE_LIST_H_ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct simple_list_elem; + +/** + * @brief allocates memory for a new list entry and appends it before the head. The new entry is the new head. + * + * @param head pointer to the list + * @return the new list entry, NULL if no new list entry could be allocated + */ +#define simple_list_add_head(head) __simple_list_add_head((struct simple_list_elem**) (head), calloc(1, sizeof **(head))) + + +/** + * @brief appends a preallocated element to the top of the list. The new entry is the new head. + * + * @param head pointer to the list + * @param node preallocated list element + * @return the new list entry (node) + */ +#define simple_list_set_head(head, node) __simple_list_add_head((struct simple_list_elem**) (head), (node)) + +/** +* @brief allocates memory for a new list entry and appends it at the end of the list. +* +* @param head pointer to pointer to the first list element +* @param head pointer to the list +* @return the new list entry, NULL if no new list entry could be allocated +*/ +#define simple_list_add_tail(head) __simple_list_add_tail((struct simple_list_elem**) (head), calloc(1, sizeof **(head))) + +/** + * @brief appends a preallocated element to the end of the list. + * + * @param head pointer to the list + * @param node preallocated list element + * @return the new list entry (node) + */ +#define simple_list_set_tail(head, node) __simple_list_add_tail((struct simple_list_elem**) (head), (node)) + +/** +* @brief allocates memory for a new list entry and adds it before an existing entry. +* The new entry is added before the existing element where old_entry->value > value +* If no such entry could be found, the new entry will be added at the end of the list +* +* @param head pointer to the list +* @param value value to compare list entries +* has to be the same name as the element in the list entry structure that is be used for comparison +* @return pointer to the new element, NULL if no new list element could be allocated +*/ +#define simple_list_add_before(head, value) (\ + *(head) == NULL ? \ + simple_list_add_head((head)) \ + : \ + __simple_list_add_before((struct simple_list_elem**) (head), \ + calloc(1, sizeof **(head)), \ + (value), \ + (char*) &(*(head))->value - (char*) *(head)) ) + +/** +* @brief adds an preallocated list element before an existing one. +* The new entry is added before the existing element where old_entry->value > value +* If no such entry could be found, the new entry will be added at the end of the list * +* @param head pointer to the list +* @param value value to compare list entries +* has to be the same name as the element in the list entry structure that is be used for comparison +* @param node preallocated list element +* @return the new list entry (node) +*/ +#define simple_list_set_before(head, node, value) (\ + *(head) == NULL ? \ + __simple_list_add_before((head)) \ + : \ + __simple_list_add_before((struct simple_list_elem**) (head), \ + (node), \ + (value), \ + (char*) &(*(head))->value - (char*) *(head)) ) + +/** +* @brief searches for a list element by simple comparison of a struct value +* +* @param head pointer to the list +* @param value the member value of a list entry that is to be found +* has to be the same name as the value in the list element struct +* @return pointer the list entry if found, otherwise NULL +*/ +#define simple_list_find(head, value) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ + (0)) ) + +/** +* @brief searches for a list element by comparing a buffer in the list element struct +* +* @param head pointer to the list +* @param value pointer to the buffer that is to be found in the list +* has to be the same name as the value in the list element struct +* @return pointer the list entry if found, otherwise NULL +*/ +#define simple_list_find_memcmp(head, value) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ + sizeof(*(value))) ) + +/** +* @brief searches for a list element by applying a comparator function to each list entry +* +* @param head pointer to the list +* @param value input to the comparator function +* @param comperator a function that takes (value, node) and returns 0 if they match +* @return pointer the list entry if found, otherwise NULL +*/ +#define simple_list_find_cmp(head, value, comperator) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find_cmp( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ + (comperator)) ) +/** + * @brief removes an entry from the list and frees it's memory + * + * @param head pointer to the list + * @param node entry to be removed + * @returns a non-zero value if the element was found and removed + */ +#define simple_list_remove(head, node) __simple_list_remove((struct simple_list_elem**) (head), (struct simple_list_elem*) (node), 0) + +/** + * @brief removes an entry from the list, doesn't free it's memory but returns the element + * + * @param head pointer to the list + * @param node entry to be extracted + * @returns pointer to the element, NULL if it couldn't be found + */ +#define simple_list_extract(head, node) __simple_list_remove((struct simple_list_elem**) (head), (struct simple_list_elem*) (node), 1) + +/** + * @brief removes all entries from the list and frees their memory + * + * @param head pointer to the list + */ +#define simple_list_clear(head) __simple_list_clear((struct simple_list_elem**) (head)) + +/** + * @brief starts a loop to iterate over all list entries. Read-only list access only. + * needs to be provided with a local loop variable + * + * @param head pointer to the list + * @param node to the current entry (loop variable) + */ +#define simple_list_for_each(head, node) \ + for ((node) = (head); (node); (node) = (node)->next) + +/** + * @brief starts a loop to iterate over all list elements with the possibility to remove elements + to remove an element, use simple_list_for_each_remove + needs to be provided with a local loop variable as well as two local auxiliary variables + * + * @param head pointer to the list + * @param node to the current entry (loop variable) + * @param prev internal variable, pointer to previous list entry - do not modify + * @param skipped internal variable, integer - do not modify + */ +#define simple_list_for_each_safe(head, node, prev, skipped) \ + for ((skipped) = 0, (prev) = NULL, (node) = (head); \ + (node); \ + (prev) = ((skipped) ? (prev) : (node)), \ + (node) = ((skipped) ? (node) : (node)->next), (skipped) = 0) + +/** + * @brief removes an element in a simple_list_for_each_safe context + * + * @param head pointer to the list + * @param node pointer to the current entry (loop variable) + * @param prev internal variable, provided by simple_list_for_each_safe + */ +#define simple_list_for_each_remove(head, node, prev) \ + do { \ + if (!(prev)) { \ + (skipped) = 1; \ + *(head) = (*(head))->next; \ + } else { \ + (prev)->next = (node)->next; \ + } \ + free(node); \ + (node) = (prev) ? (prev) : *(head); \ + } while (0) + +void *__simple_list_add_head(struct simple_list_elem **head, void *mem); +void *__simple_list_add_tail(struct simple_list_elem **head, void *mem); +void *__simple_list_add_before(struct simple_list_elem **head, void *mem, int needle, size_t offset); +void *__simple_list_find(struct simple_list_elem *head, void *needle, size_t offset, size_t size); +void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, size_t offset, int compare(void *, void *)); +void *__simple_list_remove(struct simple_list_elem **head, struct simple_list_elem *node, int keep); +void __simple_list_clear(struct simple_list_elem **head); + +#ifdef __cplusplus +} +#endif + +#endif /* SIMPLE_LIST_H_ */ diff --git a/sys/slist/Makefile b/sys/slist/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/sys/slist/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/slist/slist.c b/sys/slist/slist.c new file mode 100644 index 000000000000..8f5894e1e7a3 --- /dev/null +++ b/sys/slist/slist.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** +* @file slist.c +* @author Benjamin Valentin +*/ + +#include +#include + +#include "slist.h" + +struct simple_list_elem { + struct simple_list_elem *next; +}; + +void *__simple_list_add_tail(struct simple_list_elem **head, void *mem) +{ + struct simple_list_elem *_head = *head; + + /* check out-of-memory condition */ + if (mem == NULL) { + return NULL; + } + + if (_head == NULL) { + *head = mem; + return *head; + } + + while (_head->next != NULL) { + _head = _head->next; + } + + _head = _head->next = mem; + return _head; +} + +void *__simple_list_add_head(struct simple_list_elem **head, void *mem) +{ + struct simple_list_elem *_head = *head; + + /* check out-of-memory condition */ + if (mem == NULL) { + return NULL; + } + + *head = mem; + (*head)->next = _head; + + return *head; +} + +void *__simple_list_add_before(struct simple_list_elem **head, void *mem, int needle, size_t offset) +{ + struct simple_list_elem *_head = *head; + struct simple_list_elem *prev = 0; + + /* check out-of-memory condition */ + if (mem == NULL) { + return NULL; + } + + if (_head == NULL) { + *head = mem; + return *head; + } + + while (_head != NULL) { + int *buff = (void *) ((char *) _head + offset); + + if (*buff > needle) { + if (prev != NULL) { + prev->next = mem; + prev->next->next = _head; + return prev->next; + } + + prev = mem; + prev->next = _head; + *head = prev; + return prev; + } + + prev = _head; + _head = _head->next; + } + + _head = prev->next = mem; + return _head; +} + +void *__simple_list_find(struct simple_list_elem *head, void *needle, size_t offset, size_t size) +{ + while (head != NULL) { + void **buff = (void *) ((char *) head + offset); + + if (size == 0 && *buff == needle) { + return head; + } + + if (size > 0 && memcmp(*buff, needle, size) == 0) { + return head; + } + + head = head->next; + } + + return 0; +} + +void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, size_t offset, int compare(void *, void *)) +{ + while (head != NULL) { + void **buff = (void *) ((char *) head + offset); + + if (compare(*buff, needle) == 0) { + return head; + } + + head = head->next; + } + + return 0; +} + +void *__simple_list_remove(struct simple_list_elem **head, struct simple_list_elem *node, int keep) +{ + struct simple_list_elem *_head = *head; + struct simple_list_elem *prev = 0; + + while (_head != NULL && _head != node) { + prev = _head; + _head = _head->next; + } + + /* not found */ + if (_head != node) { + return NULL; + } + + /* remove head */ + if (prev == NULL) { + *head = _head->next; + } + else { + prev->next = node->next; + } + + if (keep) { + return node; + } + + free(node); + return (void *) 1; +} + +void __simple_list_clear(struct simple_list_elem **head) +{ + struct simple_list_elem *tmp, *_head = *head; + + while (_head != NULL) { + tmp = _head; + _head = _head->next; + free(tmp); + } + + *head = NULL; +} diff --git a/tests/slist/Makefile b/tests/slist/Makefile new file mode 100644 index 000000000000..c531bcb32c6b --- /dev/null +++ b/tests/slist/Makefile @@ -0,0 +1,6 @@ +export APPLICATION = slist +include ../Makefile.tests_common + +USEMODULE += slist + +include $(RIOTBASE)/Makefile.include diff --git a/tests/slist/main.c b/tests/slist/main.c new file mode 100644 index 000000000000..85e7f3a15429 --- /dev/null +++ b/tests/slist/main.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2014 Benjamin Valentin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief slist (simple list) test application + * + * @author Benjamin Valentin + * + * @} + */ + +#include +#include +#include +#include "slist.h" + +int fail = 0; +void cunit_named_check(int cond, const char *name, int line, const char *format, ...) +{ + va_list ap; + + if (cond) { + return; + } + + fail++; + + va_start(ap, format); + + printf("\t%s (%d) fail: ", name, line); + vprintf(format, ap); + puts("\n"); + va_end(ap); +} +#define CHECK_TRUE(cond, format, args...) cunit_named_check(cond, __func__, __LINE__, format, ##args); + +char foo[] = "Hello World!"; +char bar[] = "Hello CUnit!"; +char baz[] = "c-c-c-combobreaker"; + +char print_buffer[128]; + +struct test_list { + struct test_list *next; + char *buffer; + int value; +}; + +struct number_list { + struct number_list *next; + int value; +}; + +struct test_list *_get_by_buffer(struct test_list *head, char *buffer) +{ + return simple_list_find(head, buffer); +} + +struct test_list *_get_by_value(struct test_list *head, int value) +{ + return simple_list_find(head, value); +} + +struct test_list *_add_test_list(struct test_list **head, char *buffer, int value) +{ + struct test_list *node = simple_list_add_tail(head); + + node->buffer = buffer; + node->value = value; + + return node; +} + +char *_print_result(struct test_list *result) +{ + if (result) { + snprintf(print_buffer, sizeof print_buffer, "%d, %s\n", result->value, result->buffer); + } + else { + snprintf(print_buffer, sizeof print_buffer, "Not found\n"); + } + + return print_buffer; +} + +int _is_equal(struct test_list *node, const int value, const char *buffer) +{ + return node != 0 && node->value == value && !strcmp(node->buffer, buffer); +} + +void test_simple_list_fill(struct test_list *_head) +{ + CHECK_TRUE(_is_equal(_get_by_buffer(_head, bar), 42, bar), "%s", _print_result(_get_by_buffer(_head, bar))); + CHECK_TRUE(_is_equal(_get_by_value(_head, 23), 23, foo), "%s", _print_result(_get_by_value(_head, 23))); +} + +void test_simple_list_remove(struct test_list **__head) +{ + struct test_list *_head; + simple_list_remove(__head, _get_by_buffer(*__head, foo)); + _head = *__head; + + CHECK_TRUE(_is_equal(_head, 42, bar), "%s", _print_result(_head)); + CHECK_TRUE(_is_equal(_head->next, 1337, baz), "%s", _print_result(_head->next)); +} + +void test_simple_list_find(struct test_list *_head) +{ + char buffer[sizeof bar]; + memcpy(buffer, bar, sizeof buffer); + + CHECK_TRUE(_is_equal(simple_list_find_memcmp(_head, buffer), 42, bar), "%s", + _print_result(simple_list_find_memcmp(_head, buffer))); + + CHECK_TRUE(_is_equal(simple_list_find_cmp(_head, buffer, (int ( *)(void *, void *)) strcmp), 42, bar), "%s", + _print_result(simple_list_find_cmp(_head, buffer, (int ( *)(void *, void *)) strcmp))); +} + +void _add_number_list(struct number_list **head, int value) +{ + struct number_list *node = simple_list_add_before(head, value); + node->value = value; +} + +void test_number_list(void) +{ + struct number_list *head = 0; + + _add_number_list(&head, 23); + _add_number_list(&head, 42); + _add_number_list(&head, 17); + _add_number_list(&head, 32); + _add_number_list(&head, 1); + + int prev = 0; + struct number_list *node; + simple_list_for_each(head, node) { + CHECK_TRUE(node->value >= prev, "%d < %d", node->value, prev); + prev = node->value; + } +} + +void test_for_each_remove(void) +{ + struct number_list *head = 0; + + int i = 0; + int max = 11; + + for (i = 1; i < max; ++i) { + if (i == 2) { + _add_number_list(&head, 3); + } + else { + _add_number_list(&head, i); + } + } + + char skipped; + struct number_list *node, *prev; + simple_list_for_each_safe(head, node, prev, skipped) { + if (node->value % 2) { + printf("removing %d\n", node->value); + simple_list_for_each_remove(&head, node, prev); + } + else { + printf("keeping %d\n", node->value); + } + } + + i = 0; + simple_list_for_each(head, node) { + CHECK_TRUE(node->value % 2 == 0, "%d", node->value); + ++i; + } + CHECK_TRUE(i == max / 2 - 1, "missed an entry"); + + simple_list_clear(&head); + + CHECK_TRUE(head == NULL, "list not cleared properly"); +} + +int main(void) +{ + struct test_list *_head = 0; + + _add_test_list(&_head, foo, 23); + _add_test_list(&_head, bar, 42); + _add_test_list(&_head, baz, 1337); + + struct test_list *node; + simple_list_for_each(_head, node) + printf("%s\n", _print_result(node)); + + test_simple_list_fill(_head); + test_simple_list_remove(&_head); + test_simple_list_find(_head); + + test_number_list(); + test_for_each_remove(); + + puts("-----------------"); + printf("End, %d errors\n", fail); + + return fail; +} From ed722b251af592b76ace6dd4a449b723bb7a68d8 Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Tue, 13 Jan 2015 19:50:38 +0100 Subject: [PATCH 2/2] SQUASH ME: fixed line length --- sys/include/slist.h | 176 +++++++++++++++++++++++++++----------------- sys/slist/slist.c | 14 ++-- tests/slist/main.c | 21 ++++-- 3 files changed, 130 insertions(+), 81 deletions(-) diff --git a/sys/include/slist.h b/sys/include/slist.h index ba32e2caa636..de0eb0eb0365 100644 --- a/sys/include/slist.h +++ b/sys/include/slist.h @@ -35,31 +35,39 @@ extern "C" { struct simple_list_elem; /** - * @brief allocates memory for a new list entry and appends it before the head. The new entry is the new head. + * @brief allocates memory for a new list entry and appends it before the + * head. The new entry is the new head. * * @param head pointer to the list * @return the new list entry, NULL if no new list entry could be allocated */ -#define simple_list_add_head(head) __simple_list_add_head((struct simple_list_elem**) (head), calloc(1, sizeof **(head))) +#define simple_list_add_head(head) \ + __simple_list_add_head((struct simple_list_elem**) \ + (head), calloc(1, sizeof **(head))) /** - * @brief appends a preallocated element to the top of the list. The new entry is the new head. + * @brief appends a preallocated element to the top of the list. The new + * entry is the new head. * * @param head pointer to the list * @param node preallocated list element * @return the new list entry (node) */ -#define simple_list_set_head(head, node) __simple_list_add_head((struct simple_list_elem**) (head), (node)) +#define simple_list_set_head(head, node) \ + __simple_list_add_head((struct simple_list_elem**) (head), (node)) /** -* @brief allocates memory for a new list entry and appends it at the end of the list. +* @brief allocates memory for a new list entry and appends it at the end of +* the list. * * @param head pointer to pointer to the first list element * @param head pointer to the list * @return the new list entry, NULL if no new list entry could be allocated */ -#define simple_list_add_tail(head) __simple_list_add_tail((struct simple_list_elem**) (head), calloc(1, sizeof **(head))) +#define simple_list_add_tail(head) \ + __simple_list_add_tail((struct simple_list_elem**) \ + (head), calloc(1, sizeof **(head))) /** * @brief appends a preallocated element to the end of the list. @@ -68,44 +76,55 @@ struct simple_list_elem; * @param node preallocated list element * @return the new list entry (node) */ -#define simple_list_set_tail(head, node) __simple_list_add_tail((struct simple_list_elem**) (head), (node)) +#define simple_list_set_tail(head, node) \ + __simple_list_add_tail((struct simple_list_elem**) (head), (node)) /** -* @brief allocates memory for a new list entry and adds it before an existing entry. -* The new entry is added before the existing element where old_entry->value > value -* If no such entry could be found, the new entry will be added at the end of the list +* @brief allocates memory for a new list entry and adds it before an +* existing entry. The new entry is added before the existing element +* where old_entry->value > value +* If no such entry could be found, the new entry will be added at the +* end of the list * * @param head pointer to the list * @param value value to compare list entries -* has to be the same name as the element in the list entry structure that is be used for comparison -* @return pointer to the new element, NULL if no new list element could be allocated +* has to be the same name as the element in the list entry +* structure that is be used for comparison +* +* @return pointer to the new element, NULL if no new list element could be +* allocated */ -#define simple_list_add_before(head, value) (\ - *(head) == NULL ? \ - simple_list_add_head((head)) \ - : \ - __simple_list_add_before((struct simple_list_elem**) (head), \ - calloc(1, sizeof **(head)), \ - (value), \ - (char*) &(*(head))->value - (char*) *(head)) ) +#define simple_list_add_before(head, value) (\ + *(head) == NULL ? \ + simple_list_add_head((head)) \ + : \ + __simple_list_add_before((struct simple_list_elem**) (head), \ + calloc(1, sizeof **(head)), \ + (value), \ + (char*) &(*(head))->value - (char*) *(head)) ) /** * @brief adds an preallocated list element before an existing one. -* The new entry is added before the existing element where old_entry->value > value -* If no such entry could be found, the new entry will be added at the end of the list * +* The new entry is added before the existing element where +* old_entry->value > value +* If no such entry could be found, the new entry will be added at the +* end of the list * +* * @param head pointer to the list * @param value value to compare list entries -* has to be the same name as the element in the list entry structure that is be used for comparison +* has to be the same name as the element in the list entry +* structure that is be used for comparison * @param node preallocated list element +* * @return the new list entry (node) */ -#define simple_list_set_before(head, node, value) (\ - *(head) == NULL ? \ - __simple_list_add_before((head)) \ - : \ - __simple_list_add_before((struct simple_list_elem**) (head), \ - (node), \ - (value), \ +#define simple_list_set_before(head, node, value) (\ + *(head) == NULL ? \ + __simple_list_add_before((head)) \ + : \ + __simple_list_add_before((struct simple_list_elem**) (head), \ + (node), \ + (value), \ (char*) &(*(head))->value - (char*) *(head)) ) /** @@ -113,50 +132,57 @@ struct simple_list_elem; * * @param head pointer to the list * @param value the member value of a list entry that is to be found -* has to be the same name as the value in the list element struct +* has to be the same name as the value in the list element +* struct +* * @return pointer the list entry if found, otherwise NULL */ -#define simple_list_find(head, value) (\ - (head) == NULL ? \ - NULL \ - : \ - __simple_list_find( (struct simple_list_elem*) (head), \ - (value), \ - (char*) &((head)->value) - (char*) (head), \ +#define simple_list_find(head, value) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ (0)) ) /** -* @brief searches for a list element by comparing a buffer in the list element struct +* @brief searches for a list element by comparing a buffer in the list +* element struct * * @param head pointer to the list * @param value pointer to the buffer that is to be found in the list -* has to be the same name as the value in the list element struct +* has to be the same name as the value in the list element +* struct +* * @return pointer the list entry if found, otherwise NULL */ -#define simple_list_find_memcmp(head, value) (\ - (head) == NULL ? \ - NULL \ - : \ - __simple_list_find( (struct simple_list_elem*) (head), \ - (value), \ - (char*) &((head)->value) - (char*) (head), \ +#define simple_list_find_memcmp(head, value) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ sizeof(*(value))) ) /** -* @brief searches for a list element by applying a comparator function to each list entry +* @brief searches for a list element by applying a comparator function to +* each list entry * * @param head pointer to the list * @param value input to the comparator function -* @param comperator a function that takes (value, node) and returns 0 if they match +* @param comperator a function that takes (value, node) and returns 0 if +* they match * @return pointer the list entry if found, otherwise NULL */ -#define simple_list_find_cmp(head, value, comperator) (\ - (head) == NULL ? \ - NULL \ - : \ - __simple_list_find_cmp( (struct simple_list_elem*) (head), \ - (value), \ - (char*) &((head)->value) - (char*) (head), \ +#define simple_list_find_cmp(head, value, comperator) (\ + (head) == NULL ? \ + NULL \ + : \ + __simple_list_find_cmp( (struct simple_list_elem*) (head), \ + (value), \ + (char*) &((head)->value) - (char*) (head), \ (comperator)) ) /** * @brief removes an entry from the list and frees it's memory @@ -165,27 +191,33 @@ struct simple_list_elem; * @param node entry to be removed * @returns a non-zero value if the element was found and removed */ -#define simple_list_remove(head, node) __simple_list_remove((struct simple_list_elem**) (head), (struct simple_list_elem*) (node), 0) +#define simple_list_remove(head, node) \ + __simple_list_remove((struct simple_list_elem**) \ + (head), (struct simple_list_elem*) (node), 0) /** - * @brief removes an entry from the list, doesn't free it's memory but returns the element + * @brief removes an entry from the list, doesn't free it's memory but returns + * the element * * @param head pointer to the list * @param node entry to be extracted * @returns pointer to the element, NULL if it couldn't be found */ -#define simple_list_extract(head, node) __simple_list_remove((struct simple_list_elem**) (head), (struct simple_list_elem*) (node), 1) +#define simple_list_extract(head, node) \ + __simple_list_remove((struct simple_list_elem**) \ + (head), (struct simple_list_elem*) (node), 1) /** * @brief removes all entries from the list and frees their memory * * @param head pointer to the list */ -#define simple_list_clear(head) __simple_list_clear((struct simple_list_elem**) (head)) +#define simple_list_clear(head) \ + __simple_list_clear((struct simple_list_elem**) (head)) /** - * @brief starts a loop to iterate over all list entries. Read-only list access only. - * needs to be provided with a local loop variable + * @brief starts a loop to iterate over all list entries. Read-only list + * access only. needs to be provided with a local loop variable * * @param head pointer to the list * @param node to the current entry (loop variable) @@ -194,13 +226,16 @@ struct simple_list_elem; for ((node) = (head); (node); (node) = (node)->next) /** - * @brief starts a loop to iterate over all list elements with the possibility to remove elements - to remove an element, use simple_list_for_each_remove - needs to be provided with a local loop variable as well as two local auxiliary variables + * @brief starts a loop to iterate over all list elements with the + * possibility to remove elements + * to remove an element, use simple_list_for_each_remove + * needs to be provided with a local loop variable as well as two + * local auxiliary variables * * @param head pointer to the list * @param node to the current entry (loop variable) - * @param prev internal variable, pointer to previous list entry - do not modify + * @param prev internal variable, pointer to previous list entry - do not + * modify * @param skipped internal variable, integer - do not modify */ #define simple_list_for_each_safe(head, node, prev, skipped) \ @@ -230,9 +265,12 @@ struct simple_list_elem; void *__simple_list_add_head(struct simple_list_elem **head, void *mem); void *__simple_list_add_tail(struct simple_list_elem **head, void *mem); -void *__simple_list_add_before(struct simple_list_elem **head, void *mem, int needle, size_t offset); -void *__simple_list_find(struct simple_list_elem *head, void *needle, size_t offset, size_t size); -void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, size_t offset, int compare(void *, void *)); +void *__simple_list_add_before(struct simple_list_elem **head, void *mem, + int needle, size_t offset); +void *__simple_list_find(struct simple_list_elem *head, void *needle, + size_t offset, size_t size); +void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, + size_t offset, int compare(void *, void *)); void *__simple_list_remove(struct simple_list_elem **head, struct simple_list_elem *node, int keep); void __simple_list_clear(struct simple_list_elem **head); diff --git a/sys/slist/slist.c b/sys/slist/slist.c index 8f5894e1e7a3..8c01eddd5ab8 100644 --- a/sys/slist/slist.c +++ b/sys/slist/slist.c @@ -7,7 +7,7 @@ */ /** -* @file slist.c +* @file * @author Benjamin Valentin */ @@ -57,7 +57,8 @@ void *__simple_list_add_head(struct simple_list_elem **head, void *mem) return *head; } -void *__simple_list_add_before(struct simple_list_elem **head, void *mem, int needle, size_t offset) +void *__simple_list_add_before(struct simple_list_elem **head, void *mem, + int needle, size_t offset) { struct simple_list_elem *_head = *head; struct simple_list_elem *prev = 0; @@ -96,7 +97,8 @@ void *__simple_list_add_before(struct simple_list_elem **head, void *mem, int ne return _head; } -void *__simple_list_find(struct simple_list_elem *head, void *needle, size_t offset, size_t size) +void *__simple_list_find(struct simple_list_elem *head, void *needle, + size_t offset, size_t size) { while (head != NULL) { void **buff = (void *) ((char *) head + offset); @@ -115,7 +117,8 @@ void *__simple_list_find(struct simple_list_elem *head, void *needle, size_t off return 0; } -void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, size_t offset, int compare(void *, void *)) +void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, + size_t offset, int compare(void *, void *)) { while (head != NULL) { void **buff = (void *) ((char *) head + offset); @@ -130,7 +133,8 @@ void *__simple_list_find_cmp(struct simple_list_elem *head, void *needle, size_t return 0; } -void *__simple_list_remove(struct simple_list_elem **head, struct simple_list_elem *node, int keep) +void *__simple_list_remove(struct simple_list_elem **head, + struct simple_list_elem *node, int keep) { struct simple_list_elem *_head = *head; struct simple_list_elem *prev = 0; diff --git a/tests/slist/main.c b/tests/slist/main.c index 85e7f3a15429..da17d36c31ef 100644 --- a/tests/slist/main.c +++ b/tests/slist/main.c @@ -24,7 +24,8 @@ #include "slist.h" int fail = 0; -void cunit_named_check(int cond, const char *name, int line, const char *format, ...) +void cunit_named_check(int cond, const char *name, int line, + const char *format, ...) { va_list ap; @@ -41,7 +42,8 @@ void cunit_named_check(int cond, const char *name, int line, const char *format, puts("\n"); va_end(ap); } -#define CHECK_TRUE(cond, format, args...) cunit_named_check(cond, __func__, __LINE__, format, ##args); +#define CHECK_TRUE(cond, format, args...) \ + cunit_named_check(cond, __func__, __LINE__, format, ##args); char foo[] = "Hello World!"; char bar[] = "Hello CUnit!"; @@ -83,7 +85,8 @@ struct test_list *_add_test_list(struct test_list **head, char *buffer, int valu char *_print_result(struct test_list *result) { if (result) { - snprintf(print_buffer, sizeof print_buffer, "%d, %s\n", result->value, result->buffer); + snprintf(print_buffer, sizeof print_buffer, "%d, %s\n", result->value, + result->buffer); } else { snprintf(print_buffer, sizeof print_buffer, "Not found\n"); @@ -99,8 +102,10 @@ int _is_equal(struct test_list *node, const int value, const char *buffer) void test_simple_list_fill(struct test_list *_head) { - CHECK_TRUE(_is_equal(_get_by_buffer(_head, bar), 42, bar), "%s", _print_result(_get_by_buffer(_head, bar))); - CHECK_TRUE(_is_equal(_get_by_value(_head, 23), 23, foo), "%s", _print_result(_get_by_value(_head, 23))); + CHECK_TRUE(_is_equal(_get_by_buffer(_head, bar), 42, bar), "%s", + _print_result(_get_by_buffer(_head, bar))); + CHECK_TRUE(_is_equal(_get_by_value(_head, 23), 23, foo), "%s", + _print_result(_get_by_value(_head, 23))); } void test_simple_list_remove(struct test_list **__head) @@ -121,8 +126,10 @@ void test_simple_list_find(struct test_list *_head) CHECK_TRUE(_is_equal(simple_list_find_memcmp(_head, buffer), 42, bar), "%s", _print_result(simple_list_find_memcmp(_head, buffer))); - CHECK_TRUE(_is_equal(simple_list_find_cmp(_head, buffer, (int ( *)(void *, void *)) strcmp), 42, bar), "%s", - _print_result(simple_list_find_cmp(_head, buffer, (int ( *)(void *, void *)) strcmp))); + CHECK_TRUE(_is_equal(simple_list_find_cmp(_head, buffer, + (int ( *)(void *, void *)) strcmp), 42, bar), "%s", + _print_result(simple_list_find_cmp(_head, buffer, + (int ( *)(void *, void *)) strcmp))); } void _add_number_list(struct number_list **head, int value)