From b4faaca9153ea368928389c6cc5c5a385d38fe6a Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Tue, 22 May 2018 16:16:15 +0100 Subject: [PATCH 1/7] Add cfulist_delete_data It is important to let the programmer remove a node from the linked list, as it is a very common operation. --- doc/libcfu.texi | 5 +++++ src/cfulist.c | 22 ++++++++++++++++++++++ src/cfulist.h | 3 +++ 3 files changed, 30 insertions(+) diff --git a/doc/libcfu.texi b/doc/libcfu.texi index 3b1a38d..92293df 100644 --- a/doc/libcfu.texi +++ b/doc/libcfu.texi @@ -509,6 +509,11 @@ cfulist_map(). The return value is used to build a new list. Pop a value from the end of the list (removing it from the list). @end deftypefun +@deftypefun void cfulist_delete_data (cfulist_t * @var{list}, void * @var{data}) + + Deletes the entry in the list associated with value. +@end deftypefun + @deftypefun {int} cfulist_unshift_data (cfulist_t * @var{list}, void * @var{data}, size_t @var{data_size}) Add a value at the beginning of the list. diff --git a/src/cfulist.c b/src/cfulist.c index 052d515..a55c41f 100644 --- a/src/cfulist.c +++ b/src/cfulist.c @@ -412,6 +412,28 @@ cfulist_pop(cfulist_t *list) { return NULL; } +void +cfulist_delete_data(cfulist_t *list, void *data) { + cfulist_entry *ptr = NULL; + + if (!list) { + return; + } + + lock_list(list); + + if (list->entries) { + for (ptr = list->entries; ptr && ptr->data != data; ptr = ptr->next) + ; + if (ptr && ptr->data == data) { + (ptr->prev)->next = ptr->next; + free (ptr); + } + } + + unlock_list(list); +} + int cfulist_unshift(cfulist_t *list, void *data) { return cfulist_unshift_data(list, data, 0); diff --git a/src/cfulist.h b/src/cfulist.h index 52e92ec..f0d5c33 100644 --- a/src/cfulist.h +++ b/src/cfulist.h @@ -81,6 +81,9 @@ int cfulist_push_data(cfulist_t *list, void *data, size_t data_size); /* Pop a value from the end of the list. */ int cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size); +/* Deletes the entry in the list associated with value. */ +void cfulist_delete_data(cfulist_t *list, void *data); + /* Add a value at the beginning of the list. */ int cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size); From 5af4f108dc492a1df99b9c6268c830d3fba62264 Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 7 Jun 2018 22:48:07 +0100 Subject: [PATCH 2/7] cfulist_delete_data now works for the first item This function would crash for the first item. Now it calls cfulist_dequeue to remove the first element when necessary. --- src/cfulist.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cfulist.c b/src/cfulist.c index a55c41f..9a5e536 100644 --- a/src/cfulist.c +++ b/src/cfulist.c @@ -425,9 +425,14 @@ cfulist_delete_data(cfulist_t *list, void *data) { if (list->entries) { for (ptr = list->entries; ptr && ptr->data != data; ptr = ptr->next) ; + if (ptr && ptr->data == data) { - (ptr->prev)->next = ptr->next; - free (ptr); + if (!ptr->prev) { + cfulist_dequeue (list); + } else { + (ptr->prev)->next = ptr->next; + free (ptr); + } } } From d4528b8334f56af2ad4d4ab0ac3903e6cde48f1f Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 7 Jun 2018 23:38:48 +0100 Subject: [PATCH 3/7] Fixed typo on cfulist_delete_data documentation The return type should be in curly brackets --- doc/libcfu.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/libcfu.texi b/doc/libcfu.texi index 92293df..997290f 100644 --- a/doc/libcfu.texi +++ b/doc/libcfu.texi @@ -509,7 +509,7 @@ cfulist_map(). The return value is used to build a new list. Pop a value from the end of the list (removing it from the list). @end deftypefun -@deftypefun void cfulist_delete_data (cfulist_t * @var{list}, void * @var{data}) +@deftypefun {void} cfulist_delete_data (cfulist_t * @var{list}, void * @var{data}) Deletes the entry in the list associated with value. @end deftypefun From 00f09172c3f5e9d39012441ed730687f079657bd Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Fri, 8 Jun 2018 09:46:54 +0100 Subject: [PATCH 4/7] Fix cfulist_delete_data bugs 1. This function was not updating the list size 2. The first item was not being properly removed 3. Renamed some variables in order to make them more meaningful --- src/cfulist.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/cfulist.c b/src/cfulist.c index 9a5e536..661b257 100644 --- a/src/cfulist.c +++ b/src/cfulist.c @@ -414,8 +414,6 @@ cfulist_pop(cfulist_t *list) { void cfulist_delete_data(cfulist_t *list, void *data) { - cfulist_entry *ptr = NULL; - if (!list) { return; } @@ -423,16 +421,26 @@ cfulist_delete_data(cfulist_t *list, void *data) { lock_list(list); if (list->entries) { - for (ptr = list->entries; ptr && ptr->data != data; ptr = ptr->next) - ; + cfulist_entry *entry = list->entries; + while (entry && entry->data != data) + entry = entry->next; - if (ptr && ptr->data == data) { - if (!ptr->prev) { - cfulist_dequeue (list); + if (entry && entry->data == data) { + if (!entry->prev) { + if (entry->next) { + assert(list->num_entries > 1); + list->entries = entry->next; + list->entries->prev = NULL; + } else { + assert(list->num_entries == 1); + list->tail = NULL; + list->entries = NULL; + } } else { - (ptr->prev)->next = ptr->next; - free (ptr); + (entry->prev)->next = entry->next; } + free (entry); + --list->num_entries; } } From 4d6a4c0a1603e52a5e89119f4134a95b08550ca5 Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Fri, 8 Jun 2018 11:43:15 +0100 Subject: [PATCH 5/7] Add cfulist_delete_data_with_free_fn Conditionals tests in cfulist_delete_data(_with_free_fn) were simplified --- doc/libcfu.texi | 8 ++++++++ src/cfulist.c | 19 ++++++++++++++----- src/cfulist.h | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/doc/libcfu.texi b/doc/libcfu.texi index 997290f..aacca70 100644 --- a/doc/libcfu.texi +++ b/doc/libcfu.texi @@ -514,6 +514,14 @@ cfulist_map(). The return value is used to build a new list. Deletes the entry in the list associated with value. @end deftypefun +@deftypefun {void} cfulist_delete_data_with_free_fn (cfulist_t * @var{list}, void * @var{data}, cfulist_free_fn_t @var{ff}) + + Deletes the entry in the list associated with value. If ff is not NULL, it + is called for value of the entry passed as its only argument. If ff is not NULL, + it overrides any function set previously with cfulist_set_free_function(). + +@end deftypefun + @deftypefun {int} cfulist_unshift_data (cfulist_t * @var{list}, void * @var{data}, size_t @var{data_size}) Add a value at the beginning of the list. diff --git a/src/cfulist.c b/src/cfulist.c index 661b257..4bb1524 100644 --- a/src/cfulist.c +++ b/src/cfulist.c @@ -414,18 +414,25 @@ cfulist_pop(cfulist_t *list) { void cfulist_delete_data(cfulist_t *list, void *data) { + cfulist_delete_data_with_free_fn(list, data, list->free_fn); + return; +} + +void +cfulist_delete_data_with_free_fn(cfulist_t *list, void *data, cfulist_free_fn_t free_fn) { if (!list) { return; } lock_list(list); - if (list->entries) { - cfulist_entry *entry = list->entries; - while (entry && entry->data != data) + cfulist_entry *entry = list->entries; + while (entry) + { + if (entry->data != data) { entry = entry->next; - - if (entry && entry->data == data) { + continue; + } else { if (!entry->prev) { if (entry->next) { assert(list->num_entries > 1); @@ -439,8 +446,10 @@ cfulist_delete_data(cfulist_t *list, void *data) { } else { (entry->prev)->next = entry->next; } + if (free_fn) free_fn(entry->data); free (entry); --list->num_entries; + break; } } diff --git a/src/cfulist.h b/src/cfulist.h index f0d5c33..40da0fb 100644 --- a/src/cfulist.h +++ b/src/cfulist.h @@ -83,6 +83,7 @@ int cfulist_pop_data(cfulist_t *list, void **data, size_t *data_size); /* Deletes the entry in the list associated with value. */ void cfulist_delete_data(cfulist_t *list, void *data); +void cfulist_delete_data_with_free_fn(cfulist_t *list, void *data, cfulist_free_fn_t free_fn); /* Add a value at the beginning of the list. */ int cfulist_unshift_data(cfulist_t *list, void *data, size_t data_size); From 9d8fbcf53d8d4b3be91b1ee4348c033c3fbe9837 Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Fri, 8 Jun 2018 11:52:35 +0100 Subject: [PATCH 6/7] There is no cfulist_set_free_function --- doc/libcfu.texi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/libcfu.texi b/doc/libcfu.texi index aacca70..3dc1a89 100644 --- a/doc/libcfu.texi +++ b/doc/libcfu.texi @@ -517,8 +517,7 @@ cfulist_map(). The return value is used to build a new list. @deftypefun {void} cfulist_delete_data_with_free_fn (cfulist_t * @var{list}, void * @var{data}, cfulist_free_fn_t @var{ff}) Deletes the entry in the list associated with value. If ff is not NULL, it - is called for value of the entry passed as its only argument. If ff is not NULL, - it overrides any function set previously with cfulist_set_free_function(). + is called for value of the entry passed as its only argument. @end deftypefun From c25e9cee24ac4898c25905321ff37c20a89bbe0d Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Fri, 8 Jun 2018 13:57:08 +0100 Subject: [PATCH 7/7] Conditionals tests in cfulist_delete_data_with_free_fn() were simplified --- src/cfulist.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cfulist.c b/src/cfulist.c index 4bb1524..f32c7e0 100644 --- a/src/cfulist.c +++ b/src/cfulist.c @@ -429,10 +429,7 @@ cfulist_delete_data_with_free_fn(cfulist_t *list, void *data, cfulist_free_fn_t cfulist_entry *entry = list->entries; while (entry) { - if (entry->data != data) { - entry = entry->next; - continue; - } else { + if (entry->data == data) { if (!entry->prev) { if (entry->next) { assert(list->num_entries > 1); @@ -451,6 +448,7 @@ cfulist_delete_data_with_free_fn(cfulist_t *list, void *data, cfulist_free_fn_t --list->num_entries; break; } + entry = entry->next; } unlock_list(list);