Skip to content

Commit

Permalink
[+] adding list_extend, list_deep_extend and list_apply.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ximaz committed Mar 30, 2024
1 parent fb72529 commit 2f3d8e9
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ liblist.a: clean $(OBJS)
ar -rcs $@ $(OBJS)

tests_run: CFLAGS = -g -Wall -Wextra -Werror -pedantic -ansi --coverage
tests_run: clean $(OBJS) $(TESTS_OBJS)
tests_run: $(OBJS) $(TESTS_OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(OBJS) $(TESTS_OBJS) -o unit_tests -lcriterion
CRITERION_NO_EARLY_EXIT=1 ./unit_tests
gcovr -e tests .
Expand Down
38 changes: 38 additions & 0 deletions include/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,42 @@ int list_all(list_t const *list, list_filter_t filter);
*/
int list_any(list_t const *list, list_filter_t filter);

/**
* @brief Extends the output list from the input list
*
* Both output and input must have the same destroyer function. Else, -1 will
* be returned.
*
* @param[out] output
* @param[in] input
* @returns 0 on success, -1 on error
*/
int list_extend(list_t *output, list_t const *input);

/**
* @brief Deeply extends the output list from the input list
*
* Both output and input must have the same destroyer function. Else, -1 will
* be returned.
*
* @param[out] output
* @param[in] input
* @param[in] copy may be NULL, calling list_extend instead
* @returns 0 on success, -1 on error
*/
int list_deep_extend(list_t *output, list_t const *input, list_copy_t copy);

/**
* @brief Modifies the existing element
*/
typedef void (*list_apply_t)(void *elem);

/**
* @brief Applies a function to each elements of the list
*
* @param[in] list
* @param[in] apply
*/
void list_apply(list_t *list, list_apply_t apply);

#endif /* __LIST_H_ */
18 changes: 18 additions & 0 deletions src/list_apply.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
** EPITECH PROJECT, 2024
** List in C
** File description:
** list_apply.c
*/

#include "list.h"

void list_apply(list_t *list, list_apply_t apply)
{
list_elem_t *e = list->elems_head;

while (NULL != e) {
apply(e->elem);
e = e->next;
}
}
25 changes: 25 additions & 0 deletions src/list_deep_extend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
** EPITECH PROJECT, 2024
** List in C
** File description:
** list_deep_extend.c
*/

#include <stdio.h>
#include "list.h"

int list_deep_extend(list_t *output, list_t const *input, list_copy_t copy)
{
list_elem_t *input_head = input->elems_head;

if (NULL == copy)
return list_extend(output, input);
if (output->destroy != input->destroy)
return -1;
while (NULL != input_head) {
if (-1 == list_push_back(output, copy(input_head->elem)))
return -1;
input_head = input_head->next;
}
return 0;
}
22 changes: 22 additions & 0 deletions src/list_extend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
** EPITECH PROJECT, 2024
** List in C
** File description:
** list_extend.c
*/

#include "list.h"

int list_extend(list_t *output, list_t const *input)
{
list_elem_t *input_head = input->elems_head;

if (output->destroy != input->destroy)
return -1;
while (NULL != input_head) {
if (-1 == list_push_back(output, input_head->elem))
return -1;
input_head = input_head->next;
}
return 0;
}
47 changes: 47 additions & 0 deletions tests/tests_list_apply.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
** EPITECH PROJECT, 2024
** Tests of List in C
** File description:
** tests_list_apply.c
*/

#include <stdlib.h>
#include <criterion/criterion.h>
#include <criterion/redirect.h>
#include <criterion/new/assert.h>
#include <unistd.h>
#include "list.h"

typedef struct s_elem {
void *elem;
int status;
} elem_t;

static void apply(void *e)
{
elem_t *elem = (elem_t *) e;

write(STDOUT_FILENO, (char const *) elem->elem,
strlen((char const *) elem->elem));
elem->status = 1;
}

Test(list_apply, test_impl, .init = cr_redirect_stdout)
{
list_t list = { 0 };
elem_t elems[] = {
{ .elem = "A", 0 },
{ .elem = "AB", 0 },
{ .elem = "ABC", 0 },
};

cr_assert(eq(int, 0, list_push_back(&list, &elems[0])));
cr_assert(eq(int, 0, list_push_back(&list, &elems[1])));
cr_assert(eq(int, 0, list_push_back(&list, &elems[2])));
list_apply(&list, apply);
cr_assert(eq(int, 1, ((elem_t *) (list_value_at(&list, 0)))->status));
cr_assert(eq(int, 1, ((elem_t *) (list_value_at(&list, 1)))->status));
cr_assert(eq(int, 1, ((elem_t *) (list_value_at(&list, 2)))->status));
list_clear(&list);
cr_assert_stdout_eq_str("AABABC");
}
95 changes: 95 additions & 0 deletions tests/tests_list_extend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
** EPITECH PROJECT, 2024
** Tests of List in C
** File description:
** tests_list_extend.c
*/


#include <stdlib.h>
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include "list.h"
#include <string.h>

static int my_strcmp(void const *e1, void const *e2)
{
return strcmp((char const *) e1, (char const *) e2);
}

static void *my_strdup(void const *e)
{
return (void *) strdup((char const *) e);
}

Test(list_extend, test_impl)
{
list_t output = { 0 };
list_t input = { 0 };
list_t expected = { 0 };

cr_assert(eq(int, 0, list_push_back(&output, "o-first")));
cr_assert(eq(int, 0, list_push_back(&output, "o-second")));
cr_assert(eq(int, 0, list_push_back(&output, "o-third")));
cr_assert(eq(int, 0, list_push_back(&input, "i-third")));
cr_assert(eq(int, 0, list_push_back(&input, "i-third")));
cr_assert(eq(int, 0, list_push_back(&input, "i-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "o-first")));
cr_assert(eq(int, 0, list_push_back(&expected, "o-second")));
cr_assert(eq(int, 0, list_push_back(&expected, "o-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_extend(&output, &input)));
cr_assert(eq(int, 1, list_equal(&output, &expected, my_strcmp)));
list_clear(&output);
list_clear(&input);
list_clear(&expected);
}

Test(list_extend, test_impl_bad_destroyer)
{
list_t output = { 0 };
list_t input = { 0 };

input.destroy = &free;
cr_assert(eq(int, -1, list_extend(&output, &input)));
}

Test(list_deep_extend, test_impl)
{
list_t output = { 0 };
list_t input = { 0 };
list_t expected = { 0 };

output.destroy = &free;
input.destroy = &free;
cr_assert(eq(int, 0, list_push_back(&output, my_strdup("o-first"))));
cr_assert(eq(int, 0, list_push_back(&output, my_strdup("o-second"))));
cr_assert(eq(int, 0, list_push_back(&output, my_strdup("o-third"))));
cr_assert(eq(int, 0, list_push_back(&input, my_strdup("i-third"))));
cr_assert(eq(int, 0, list_push_back(&input, my_strdup("i-third"))));
cr_assert(eq(int, 0, list_push_back(&input, my_strdup("i-third"))));
cr_assert(eq(int, 0, list_push_back(&expected, "o-first")));
cr_assert(eq(int, 0, list_push_back(&expected, "o-second")));
cr_assert(eq(int, 0, list_push_back(&expected, "o-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_push_back(&expected, "i-third")));
cr_assert(eq(int, 0, list_deep_extend(&output, &input, my_strdup)));
cr_assert(eq(int, 1, list_equal(&output, &expected, my_strcmp)));
list_clear(&output);
list_clear(&input);
list_clear(&expected);
}

Test(list_deep_extend, test_impl_bad_destroyer)
{
list_t output = { 0 };
list_t input = { 0 };

input.destroy = &free;
cr_assert(eq(int, -1, list_deep_extend(&output, &input, my_strdup)));
input.destroy = NULL;
cr_assert(eq(int, 0, list_deep_extend(&output, &input, NULL)));
}

0 comments on commit 2f3d8e9

Please sign in to comment.