#############################################################################*/
#include <stdlib.h>
+#include <sys/queue.h>
-#include <solv/pool.h>
-#include <solv/solver.h>
-#include <solv/util.h>
+#include <solv/queue.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/packagelist.h>
#include <pakfire/pakfire.h>
#include <pakfire/private.h>
-#include <pakfire/util.h>
-#define BLOCK_SIZE 31
+struct pakfire_packagelist_element {
+ TAILQ_ENTRY(pakfire_packagelist_element) nodes;
+
+ struct pakfire_package* pkg;
+};
struct pakfire_packagelist {
struct pakfire* pakfire;
int nrefs;
- struct pakfire_package** elements;
- size_t count;
+ TAILQ_HEAD(entries, pakfire_packagelist_element) packages;
};
-static void pakfire_packagelist_free(struct pakfire_packagelist* list) {
- if (list->elements) {
- for (unsigned int i = 0; i < list->count; i++)
- pakfire_package_unref(list->elements[i]);
- free(list->elements);
+static void pakfire_packagelist_clear(struct pakfire_packagelist* list) {
+ struct pakfire_packagelist_element* element = NULL;
+
+ while (!TAILQ_EMPTY(&list->packages)) {
+ // Fetch the first element
+ element = TAILQ_FIRST(&list->packages);
+
+ // Remove it from the list
+ TAILQ_REMOVE(&list->packages, element, nodes);
+
+ // Dereference the file
+ pakfire_package_unref(element->pkg);
+
+ // Free it all
+ free(element);
}
+}
+static void pakfire_packagelist_free(struct pakfire_packagelist* list) {
+ pakfire_packagelist_clear(list);
pakfire_unref(list->pakfire);
free(list);
}
if (!l)
return 1;
+ // Store a reference to Pakfire
l->pakfire = pakfire_ref(pakfire);
+
+ // Initialize the reference counter
l->nrefs = 1;
+ // Initialise packages
+ TAILQ_INIT(&l->packages);
+
*list = l;
return 0;
}
-int pakfire_packagelist_create_from_queue(struct pakfire_packagelist** list, struct pakfire* pakfire, Queue* q) {
- int r;
-
- // Create a new package list
- r = pakfire_packagelist_create(list, pakfire);
- if (r)
- goto ERROR;
-
- r = pakfire_packagelist_import_solvables(*list, q);
- if (r)
- goto ERROR;
-
- return 0;
-
-ERROR:
- if (*list) {
- pakfire_packagelist_free(*list);
- *list = NULL;
- }
-
- return r;
-}
-
PAKFIRE_EXPORT struct pakfire_packagelist* pakfire_packagelist_ref(struct pakfire_packagelist* list) {
list->nrefs++;
return NULL;
}
-PAKFIRE_EXPORT size_t pakfire_packagelist_count(struct pakfire_packagelist* list) {
- return list->count;
-}
+PAKFIRE_EXPORT size_t pakfire_packagelist_length(struct pakfire_packagelist* list) {
+ struct pakfire_packagelist_element* element = NULL;
+ size_t size = 0;
-static int _packagelist_cmp(const void* pkg1, const void* pkg2) {
- return pakfire_package_cmp(
- *(struct pakfire_package**)pkg1,
- *(struct pakfire_package**)pkg2
- );
-}
+ TAILQ_FOREACH(element, &list->packages, nodes)
+ size++;
-PAKFIRE_EXPORT void pakfire_packagelist_sort(struct pakfire_packagelist* list) {
- qsort(list->elements, list->count, sizeof(*list->elements), _packagelist_cmp);
+ return size;
}
PAKFIRE_EXPORT struct pakfire_package* pakfire_packagelist_get(struct pakfire_packagelist* list, unsigned int index) {
- if (index < list->count)
- return pakfire_package_ref(list->elements[index]);
+ struct pakfire_packagelist_element* element = NULL;
- return NULL;
+ // Fetch the first element
+ element = TAILQ_FIRST(&list->packages);
+
+ while (element && index--)
+ element = TAILQ_NEXT(element, nodes);
+
+ return pakfire_package_ref(element->pkg);
}
PAKFIRE_EXPORT int pakfire_packagelist_push(struct pakfire_packagelist* list, struct pakfire_package* pkg) {
- list->elements = solv_extend(list->elements, list->count, 1, sizeof(pkg), BLOCK_SIZE);
- list->elements[list->count++] = pakfire_package_ref(pkg);
+ struct pakfire_packagelist_element* element = NULL;
+ struct pakfire_packagelist_element* e = NULL;
+
+ // Allocate a new element
+ element = calloc(1, sizeof *element);
+ if (!element) {
+ ERROR(list->pakfire, "Could not allocate a new packagelist element: %m\n");
+ return 1;
+ }
+
+ // Reference the package
+ element->pkg = pakfire_package_ref(pkg);
+
+ // Fetch the last element
+ e = TAILQ_LAST(&list->packages, entries);
+
+ // Skip all elements that are "greater than" the element we want to add
+ while (e) {
+ if (pakfire_package_cmp(e->pkg, pkg) <= 0)
+ break;
+
+ e = TAILQ_PREV(e, entries, nodes);
+ }
+
+ // 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->packages, e, element, nodes);
+ else
+ TAILQ_INSERT_HEAD(&list->packages, element, nodes);
return 0;
}
int pakfire_packagelist_walk(struct pakfire_packagelist* list,
- pakfire_packagelist_walk_callback callback, void* p) {
+ pakfire_packagelist_walk_callback callback, void* data) {
+ struct pakfire_packagelist_element* element = NULL;
int r = 0;
- for (unsigned int i = 0; i < list->count; i++) {
- r = callback(list->pakfire, list->elements[i], p);
+ // Call the callback once for every element on the list
+ TAILQ_FOREACH(element, &list->packages, nodes) {
+ // Call the callback
+ r = callback(list->pakfire, element->pkg, data);
if (r)
break;
}
if (r)
return r;
- pakfire_packagelist_push(list, pkg);
+ r = pakfire_packagelist_push(list, pkg);
pakfire_package_unref(pkg);
+ if (r)
+ return r;
}
return 0;