From ed85ded96772c45280d9d8f713894b33b52d92a4 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 13 Sep 2024 12:51:09 +0900 Subject: [PATCH] Add single-ptr variants data structures' free fns --- src/data_structures/hash_map.c | 17 ++++++++++------ src/data_structures/hash_map.h | 5 +++++ src/data_structures/linked_list.c | 14 ++++++++++---- src/data_structures/linked_list.h | 5 +++++ src/data_structures/priority_heap.c | 30 +++++++++++++++++------------ src/data_structures/priority_heap.h | 6 ++++++ 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/data_structures/hash_map.c b/src/data_structures/hash_map.c index fb2fb13..4e2df2f 100644 --- a/src/data_structures/hash_map.c +++ b/src/data_structures/hash_map.c @@ -159,16 +159,21 @@ SDArchiverHashMap *simple_archiver_hash_map_init(void) { return hash_map; } -void simple_archiver_hash_map_free(SDArchiverHashMap **hash_map) { - if (hash_map && *hash_map) { - for (size_t idx = 0; idx < (*hash_map)->buckets_size; ++idx) { - SDArchiverLinkedList **linked_list = (*hash_map)->buckets + idx; +void simple_archiver_hash_map_free_single_ptr(SDArchiverHashMap *hash_map) { + if (hash_map) { + for (size_t idx = 0; idx < hash_map->buckets_size; ++idx) { + SDArchiverLinkedList **linked_list = hash_map->buckets + idx; simple_archiver_list_free(linked_list); } - free((*hash_map)->buckets); - free(*hash_map); + free(hash_map->buckets); + free(hash_map); + } +} +void simple_archiver_hash_map_free(SDArchiverHashMap **hash_map) { + if (hash_map && *hash_map) { + simple_archiver_hash_map_free_single_ptr(*hash_map); *hash_map = NULL; } } diff --git a/src/data_structures/hash_map.h b/src/data_structures/hash_map.h index 41e0087..cc6271c 100644 --- a/src/data_structures/hash_map.h +++ b/src/data_structures/hash_map.h @@ -32,6 +32,11 @@ typedef struct SDArchiverHashMap { } SDArchiverHashMap; SDArchiverHashMap *simple_archiver_hash_map_init(void); + +/// It is recommended to use the double-pointer version of hash-map free as +/// that will ensure the variable holding the pointer will end up pointing to +/// NULL after free. +void simple_archiver_hash_map_free_single_ptr(SDArchiverHashMap *hash_map); void simple_archiver_hash_map_free(SDArchiverHashMap **hash_map); /// Returns zero on success. diff --git a/src/data_structures/linked_list.c b/src/data_structures/linked_list.c index 475ca2b..dd4717b 100644 --- a/src/data_structures/linked_list.c +++ b/src/data_structures/linked_list.c @@ -41,9 +41,9 @@ SDArchiverLinkedList *simple_archiver_list_init(void) { return list; } -void simple_archiver_list_free(SDArchiverLinkedList **list) { - if (list && *list) { - SDArchiverLLNode *node = (*list)->head; +void simple_archiver_list_free_single_ptr(SDArchiverLinkedList *list) { + if (list) { + SDArchiverLLNode *node = list->head; SDArchiverLLNode *prev; while (node) { prev = node; @@ -58,7 +58,13 @@ void simple_archiver_list_free(SDArchiverLinkedList **list) { } } - free(*list); + free(list); + } +} + +void simple_archiver_list_free(SDArchiverLinkedList **list) { + if (list && *list) { + simple_archiver_list_free_single_ptr(*list); *list = NULL; } } diff --git a/src/data_structures/linked_list.h b/src/data_structures/linked_list.h index 04c25da..6c612d5 100644 --- a/src/data_structures/linked_list.h +++ b/src/data_structures/linked_list.h @@ -35,6 +35,11 @@ typedef struct SDArchiverLinkedList { } SDArchiverLinkedList; SDArchiverLinkedList *simple_archiver_list_init(void); + +/// It is recommended to use the double-pointer version of list free as that +/// will ensure the variable holding the pointer will end up pointing to NULL +/// after free. +void simple_archiver_list_free_single_ptr(SDArchiverLinkedList *list); void simple_archiver_list_free(SDArchiverLinkedList **list); /// Returns 0 on success. Puts data at the end of the list diff --git a/src/data_structures/priority_heap.c b/src/data_structures/priority_heap.c index 437aea2..67d438a 100644 --- a/src/data_structures/priority_heap.c +++ b/src/data_structures/priority_heap.c @@ -77,23 +77,29 @@ SDArchiverPHeap *simple_archiver_priority_heap_init_less_fn( return priority_heap; } -void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap) { - if (priority_heap && *priority_heap) { - for (size_t idx = 1; idx < (*priority_heap)->size + 1; ++idx) { - if ((*priority_heap)->nodes[idx].is_valid != 0) { - if ((*priority_heap)->nodes[idx].data_cleanup_fn) { - (*priority_heap) - ->nodes[idx] - .data_cleanup_fn((*priority_heap)->nodes[idx].data); +void simple_archiver_priority_heap_free_single_ptr( + SDArchiverPHeap *priority_heap) { + if (priority_heap) { + for (size_t idx = 1; idx < priority_heap->size + 1; ++idx) { + if (priority_heap->nodes[idx].is_valid != 0) { + if (priority_heap->nodes[idx].data_cleanup_fn) { + priority_heap->nodes[idx].data_cleanup_fn( + priority_heap->nodes[idx].data); } else { - free((*priority_heap)->nodes[idx].data); + free(priority_heap->nodes[idx].data); } - (*priority_heap)->nodes[idx].is_valid = 0; + priority_heap->nodes[idx].is_valid = 0; } } - free((*priority_heap)->nodes); - free(*priority_heap); + free(priority_heap->nodes); + free(priority_heap); + } +} + +void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap) { + if (priority_heap && *priority_heap) { + simple_archiver_priority_heap_free_single_ptr(*priority_heap); *priority_heap = NULL; } } diff --git a/src/data_structures/priority_heap.h b/src/data_structures/priority_heap.h index 0ec1b02..03b1427 100644 --- a/src/data_structures/priority_heap.h +++ b/src/data_structures/priority_heap.h @@ -43,6 +43,12 @@ int simple_archiver_priority_heap_default_less(long long a, long long b); SDArchiverPHeap *simple_archiver_priority_heap_init(void); SDArchiverPHeap *simple_archiver_priority_heap_init_less_fn( int (*less_fn)(long long, long long)); + +/// It is recommended to use the double-pointer version of priority-heap free +/// as that will ensure the variable holding the pointer will end up pointing +/// to NULL after free. +void simple_archiver_priority_heap_free_single_ptr( + SDArchiverPHeap *priority_heap); void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap); /// If data_cleanup_fn is NULL, then "free()" is used on data when freed.