diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile.am | 20 | ||||
| -rw-r--r-- | src/common/sort.c | 44 | ||||
| -rw-r--r-- | src/common/sort.h | 18 | ||||
| -rw-r--r-- | tests/common/check_sort.c | 147 | 
5 files changed, 230 insertions, 0 deletions
| @@ -81,6 +81,7 @@ blogc*.html  /tests/blogc-runserver/check_mime  /tests/common/check_config_parser  /tests/common/check_error +/tests/common/check_sort  /tests/common/check_stdin  /tests/common/check_utf8  /tests/common/check_utils diff --git a/Makefile.am b/Makefile.am index b136f9f..12f9036 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,6 +69,7 @@ noinst_HEADERS = \  	src/common/config-parser.h \  	src/common/error.h \  	src/common/file.h \ +	src/common/sort.h \  	src/common/stdin.h \  	src/common/utf8.h \  	src/common/utils.h \ @@ -151,6 +152,7 @@ libblogc_common_la_SOURCES = \  	src/common/config-parser.c \  	src/common/error.c \  	src/common/file.c \ +	src/common/sort.c \  	src/common/stdin.c \  	src/common/utf8.c \  	src/common/utils.c \ @@ -472,6 +474,7 @@ check_PROGRAMS += \  	tests/blogc/check_template_parser \  	tests/common/check_config_parser \  	tests/common/check_error \ +	tests/common/check_sort \  	tests/common/check_utf8 \  	tests/common/check_utils \  	$(NULL) @@ -746,6 +749,23 @@ tests_common_check_error_LDADD = \  	libblogc_common.la \  	$(NULL) +tests_common_check_sort_SOURCES = \ +	tests/common/check_sort.c \ +	$(NULL) + +tests_common_check_sort_CFLAGS = \ +	$(CMOCKA_CFLAGS) \ +	$(NULL) + +tests_common_check_sort_LDFLAGS = \ +	-no-install \ +	$(NULL) + +tests_common_check_sort_LDADD = \ +	$(CMOCKA_LIBS) \ +	libblogc_common.la \ +	$(NULL) +  tests_common_check_utf8_SOURCES = \  	tests/common/check_utf8.c \  	$(NULL) diff --git a/src/common/sort.c b/src/common/sort.c new file mode 100644 index 0000000..3e24706 --- /dev/null +++ b/src/common/sort.c @@ -0,0 +1,44 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include <stdbool.h> +#include "utils.h" +#include "sort.h" + + +bc_slist_t* +bc_slist_sort(bc_slist_t *l, bc_sort_func_t cmp) +{ +    if (l == NULL) { +        return NULL; +    } + +    bool swapped = false; +    bc_slist_t *lptr = NULL; +    bc_slist_t *rptr = NULL; + +    do { +        swapped = false; +        lptr = l; + +        while (lptr->next != rptr) { +            if (0 < cmp(lptr->data, lptr->next->data)) { +                void *tmp = lptr->data; +                lptr->data = lptr->next->data; +                lptr->next->data = tmp; +                swapped = true; +            } + +            lptr = lptr->next; +        } + +        rptr = lptr; +    } while(swapped); + +    return l; +} diff --git a/src/common/sort.h b/src/common/sort.h new file mode 100644 index 0000000..9f4dda2 --- /dev/null +++ b/src/common/sort.h @@ -0,0 +1,18 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _SORT_H +#define _SORT_H + +#include "utils.h" + +typedef int (*bc_sort_func_t) (const void *a, const void *b); + +bc_slist_t* bc_slist_sort(bc_slist_t *l, bc_sort_func_t cmp); + +#endif /* _SORT_H */ diff --git a/tests/common/check_sort.c b/tests/common/check_sort.c new file mode 100644 index 0000000..3c4764f --- /dev/null +++ b/tests/common/check_sort.c @@ -0,0 +1,147 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <stdlib.h> +#include "../../src/common/utils.h" +#include "../../src/common/sort.h" + + +static int +sort_func(void *a, void *b) +{ +    return strcmp((char*) a, (char*) b); +} + + +static void +test_slist_sort_empty(void **state) +{ +    bc_slist_t *l = NULL; +    assert_null(bc_slist_sort(l, sort_func)); +} + + +static void +test_slist_sort_single(void **state) +{ +    bc_slist_t *l = NULL; +    l = bc_slist_append(l, bc_strdup("a")); + +    l = bc_slist_sort(l, sort_func); + +    assert_non_null(l); +    assert_string_equal(l->data, "a"); +    assert_null(l->next); + +    bc_slist_free_full(l, free); +} + + +static void +test_slist_sort_sorted(void **state) +{ +    bc_slist_t *l = NULL; +    l = bc_slist_append(l, bc_strdup("a")); +    l = bc_slist_append(l, bc_strdup("b")); +    l = bc_slist_append(l, bc_strdup("c")); + +    l = bc_slist_sort(l, sort_func); + +    assert_non_null(l); +    assert_string_equal(l->data, "a"); +    assert_string_equal(l->next->data, "b"); +    assert_string_equal(l->next->next->data, "c"); +    assert_null(l->next->next->next); + +    bc_slist_free_full(l, free); +} + + +static void +test_slist_sort_reverse(void **state) +{ +    bc_slist_t *l = NULL; +    l = bc_slist_append(l, bc_strdup("d")); +    l = bc_slist_append(l, bc_strdup("c")); +    l = bc_slist_append(l, bc_strdup("b")); +    l = bc_slist_append(l, bc_strdup("a")); + +    l = bc_slist_sort(l, sort_func); + +    assert_non_null(l); +    assert_string_equal(l->data, "a"); +    assert_string_equal(l->next->data, "b"); +    assert_string_equal(l->next->next->data, "c"); +    assert_string_equal(l->next->next->next->data, "d"); +    assert_null(l->next->next->next->next); + +    bc_slist_free_full(l, free); +} + + +static void +test_slist_sort_mixed1(void **state) +{ +    bc_slist_t *l = NULL; +    l = bc_slist_append(l, bc_strdup("a")); +    l = bc_slist_append(l, bc_strdup("d")); +    l = bc_slist_append(l, bc_strdup("c")); +    l = bc_slist_append(l, bc_strdup("b")); + +    l = bc_slist_sort(l, sort_func); + +    assert_non_null(l); +    assert_string_equal(l->data, "a"); +    assert_string_equal(l->next->data, "b"); +    assert_string_equal(l->next->next->data, "c"); +    assert_string_equal(l->next->next->next->data, "d"); +    assert_null(l->next->next->next->next); + +    bc_slist_free_full(l, free); +} + + +static void +test_slist_sort_mixed2(void **state) +{ +    bc_slist_t *l = NULL; +    l = bc_slist_append(l, bc_strdup("c")); +    l = bc_slist_append(l, bc_strdup("b")); +    l = bc_slist_append(l, bc_strdup("a")); +    l = bc_slist_append(l, bc_strdup("d")); + +    l = bc_slist_sort(l, sort_func); + +    assert_non_null(l); +    assert_string_equal(l->data, "a"); +    assert_string_equal(l->next->data, "b"); +    assert_string_equal(l->next->next->data, "c"); +    assert_string_equal(l->next->next->next->data, "d"); +    assert_null(l->next->next->next->next); + +    bc_slist_free_full(l, free); +} + + +int +main(void) +{ +    const UnitTest tests[] = { +        unit_test(test_slist_sort_empty), +        unit_test(test_slist_sort_single), +        unit_test(test_slist_sort_sorted), +        unit_test(test_slist_sort_reverse), +        unit_test(test_slist_sort_mixed1), +        unit_test(test_slist_sort_mixed2), +    }; +    return run_tests(tests); +} | 
