From: Michael Tremer Date: Tue, 21 Feb 2023 16:04:57 +0000 (+0000) Subject: filelists: Refactor the entire module X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5d7737f8f640d5585e767ee118431c791835906;p=people%2Fstevee%2Fpakfire.git filelists: Refactor the entire module This carries some changes that will allow us more flexibility with filelists as they are now based on a slightly easier to manage data structure. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/filelist.c b/src/libpakfire/filelist.c index eb5e9262..82df96fd 100644 --- a/src/libpakfire/filelist.c +++ b/src/libpakfire/filelist.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -36,28 +37,19 @@ #include #include +struct pakfire_filelist_element { + TAILQ_ENTRY(pakfire_filelist_element) nodes; + + struct pakfire_file* file; +}; + struct pakfire_filelist { struct pakfire* pakfire; int nrefs; - struct pakfire_file** elements; - size_t elements_size; - - size_t size; + TAILQ_HEAD(entries, pakfire_filelist_element) files; }; -static int pakfire_filelist_grow(struct pakfire_filelist* list, size_t size) { - struct pakfire_file** elements = reallocarray(list->elements, - list->elements_size + size, sizeof(*list->elements)); - if (!elements) - return -errno; - - list->elements = elements; - list->elements_size += size; - - return 0; -} - PAKFIRE_EXPORT int pakfire_filelist_create(struct pakfire_filelist** list, struct pakfire* pakfire) { struct pakfire_filelist* l = calloc(1, sizeof(*l)); if (!l) @@ -66,6 +58,9 @@ PAKFIRE_EXPORT int pakfire_filelist_create(struct pakfire_filelist** list, struc l->pakfire = pakfire_ref(pakfire); l->nrefs = 1; + // Initialise files + TAILQ_INIT(&l->files); + *list = l; return 0; } @@ -91,76 +86,96 @@ PAKFIRE_EXPORT struct pakfire_filelist* pakfire_filelist_unref(struct pakfire_fi } PAKFIRE_EXPORT size_t pakfire_filelist_size(struct pakfire_filelist* list) { - return list->size; + struct pakfire_filelist_element* element = NULL; + size_t size = 0; + + TAILQ_FOREACH(element, &list->files, nodes) + size++; + + return size; } size_t pakfire_filelist_total_size(struct pakfire_filelist* list) { - struct pakfire_file* file = NULL; + struct pakfire_filelist_element* element = NULL; size_t size = 0; - for (unsigned int i = 0; i < list->size; i++) { - file = list->elements[i]; - - size += pakfire_file_get_size(file); - } + TAILQ_FOREACH(element, &list->files, nodes) + size += pakfire_file_get_size(element->file); return size; } PAKFIRE_EXPORT int pakfire_filelist_is_empty(struct pakfire_filelist* list) { - return list->size == 0; + return TAILQ_EMPTY(&list->files); } PAKFIRE_EXPORT void pakfire_filelist_clear(struct pakfire_filelist* list) { - if (!list->elements) - return; + struct pakfire_filelist_element* element = NULL; + + while (!TAILQ_EMPTY(&list->files)) { + // Fetch the first element + element = TAILQ_FIRST(&list->files); - for (unsigned int i = 0; i < list->size; i++) - pakfire_file_unref(list->elements[i]); + // Remove it from the list + TAILQ_REMOVE(&list->files, element, nodes); - free(list->elements); - list->elements = NULL; - list->elements_size = 0; + // Dereference the file + pakfire_file_unref(element->file); - list->size = 0; + // Free it all + free(element); + } } PAKFIRE_EXPORT struct pakfire_file* pakfire_filelist_get(struct pakfire_filelist* list, size_t index) { - if (index >= list->size) - return NULL; + struct pakfire_filelist_element* element = NULL; + + // Fetch the first element + element = TAILQ_FIRST(&list->files); + + while (element && index--) + element = TAILQ_NEXT(element, nodes); - return pakfire_file_ref(list->elements[index]); + return pakfire_file_ref(element->file); } PAKFIRE_EXPORT int pakfire_filelist_append(struct pakfire_filelist* list, struct pakfire_file* file) { - if (!file) - return EINVAL; + struct pakfire_filelist_element* element = NULL; + struct pakfire_filelist_element* e = NULL; - // Check if we have any space left - if (list->size >= list->elements_size) { - int r = pakfire_filelist_grow(list, 64); - if (r) - return r; + // Allocate a new element + element = calloc(1, sizeof *element); + if (!element) { + ERROR(list->pakfire, "Could not allocate a new filelist element: %m\n"); + return 1; } - list->elements[list->size++] = pakfire_file_ref(file); + // Reference the file + element->file = pakfire_file_ref(file); - return 0; -} + // Fetch the last element + e = TAILQ_LAST(&list->files, entries); -static int __sort(const void* ptr1, const void* ptr2) { - struct pakfire_file* file1 = (struct pakfire_file*)ptr1; - struct pakfire_file* file2 = (struct pakfire_file*)ptr2; + // Skip all elements that are "greater than" the element we want to add + while (e) { + if (pakfire_file_cmp(e->file, file) > 0) + break; + + e = TAILQ_PREV(e, entries, nodes); + } - return pakfire_file_cmp(file1, file2); + // If we found an element on the list, we will append after it, + // otherwise we add right at the start. + if (e) + TAILQ_INSERT_AFTER(&list->files, e, element, nodes); + else + TAILQ_INSERT_HEAD(&list->files, element, nodes); + + return 0; } PAKFIRE_EXPORT void pakfire_filelist_sort(struct pakfire_filelist* list) { - // Nothing to do on empty list - if (pakfire_filelist_is_empty(list)) - return; - - qsort(list->elements, list->size, sizeof(*list->elements), __sort); + return; // XXX NOOP - filelists are now always sorted } // Returns true if s contains globbing characters @@ -331,9 +346,6 @@ int pakfire_filelist_scan(struct pakfire_filelist* list, const char* root, pakfire_file_unref(file); } - // Sort the filelist - pakfire_filelist_sort(list); - // Success r = 0; @@ -346,15 +358,15 @@ ERROR: } int pakfire_filelist_contains(struct pakfire_filelist* list, const char* pattern) { + struct pakfire_filelist_element* element = NULL; + if (!pattern) { errno = EINVAL; return -1; } - for (unsigned int i = 0; i < list->size; i++) { - struct pakfire_file* file = list->elements[i]; - - const char* path = pakfire_file_get_path(file); + TAILQ_FOREACH(element, &list->files, nodes) { + const char* path = pakfire_file_get_path(element->file); if (!path) return -1; @@ -368,15 +380,13 @@ int pakfire_filelist_contains(struct pakfire_filelist* list, const char* pattern int pakfire_filelist_walk(struct pakfire_filelist* list, pakfire_filelist_walk_callback callback, void* data) { - struct pakfire_file* file = NULL; + struct pakfire_filelist_element* element = NULL; int r = 0; // Call the callback once for every element on the list - for (unsigned int i = 0; i < list->size; i++) { - file = list->elements[i]; - + TAILQ_FOREACH(element, &list->files, nodes) { // Call the callback - r = callback(list->pakfire, file, data); + r = callback(list->pakfire, element->file, data); if (r) break; } @@ -415,12 +425,14 @@ int pakfire_filelist_dump(struct pakfire_filelist* list, int debug) { Verifies all files on the filelist */ int pakfire_filelist_verify(struct pakfire_filelist* list, struct pakfire_filelist* errors) { + struct pakfire_filelist_element* element = NULL; struct pakfire_progressbar* progressbar = NULL; - struct pakfire_file* file = NULL; int status; int r; - DEBUG(list->pakfire, "Verifying filelist (%zu file(s))...\n", list->size); + const size_t length = pakfire_filelist_size(list); + + DEBUG(list->pakfire, "Verifying filelist (%zu file(s))...\n", length); // Setup progressbar r = pakfire_progressbar_create(&progressbar, NULL); @@ -448,23 +460,21 @@ int pakfire_filelist_verify(struct pakfire_filelist* list, struct pakfire_fileli goto ERROR; // Start the progressbar - r = pakfire_progressbar_start(progressbar, list->size); + r = pakfire_progressbar_start(progressbar, length); if (r) goto ERROR; // Iterate over the entire list - for (unsigned int i = 0; i < list->size; i++) { - file = list->elements[i]; - + TAILQ_FOREACH(element, &list->files, nodes) { // Verify the file - r = pakfire_file_verify(file, &status); + r = pakfire_file_verify(element->file, &status); if (r) goto ERROR; // If the verification failed, we append it to the errors list if (status) { // Append the file to the error list - r = pakfire_filelist_append(errors, file); + r = pakfire_filelist_append(errors, element->file); if (r) goto ERROR; } @@ -488,6 +498,7 @@ ERROR: } int pakfire_filelist_cleanup(struct pakfire_filelist* list) { + struct pakfire_filelist_element* element = NULL; int r; // Nothing to do if the filelist is empty @@ -495,8 +506,8 @@ int pakfire_filelist_cleanup(struct pakfire_filelist* list) { return 0; // Walk through the list backwards - for (int i = list->size - 1; i >= 0; i--) { - r = pakfire_file_cleanup(list->elements[i]); + TAILQ_FOREACH_REVERSE(element, &list->files, entries, nodes) { + r = pakfire_file_cleanup(element->file); if (r) return r; }