]> git.ipfire.org Git - pakfire.git/commitdiff
solution: Refactor creating string
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 3 Jul 2021 12:15:29 +0000 (12:15 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 3 Jul 2021 12:15:29 +0000 (12:15 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/solution.h
src/libpakfire/solution.c

index 268a6179d1aa17ec4029f6d3aacde774ad5bad12..bf26dc633dd6b2480f3697c988cbf83e87d1e943 100644 (file)
@@ -32,6 +32,6 @@ int pakfire_solution_create(struct pakfire_solution** solution,
 struct pakfire_solution* pakfire_solution_ref(struct pakfire_solution* solution);
 struct pakfire_solution* pakfire_solution_unref(struct pakfire_solution* solution);
 
-char* pakfire_solution_to_string(struct pakfire_solution* solution);
+const char* pakfire_solution_to_string(struct pakfire_solution* solution);
 
 #endif /* PAKFIRE_SOLUTION_H */
index c91806d43ee0d1fb3cd2efc53100c5e05f37797a..d9d530fa8a37b51e82c2e2963294fd08477aace9 100644 (file)
@@ -37,24 +37,89 @@ struct pakfire_solution {
 
        struct pakfire_problem* problem;
        Id id;
-       char** elements;
+       char* string;
 };
 
-static void import_elements(struct pakfire_solution* solution) {
-       struct pakfire_request* request = pakfire_problem_get_request(solution->problem);
+PAKFIRE_EXPORT int pakfire_solution_create(struct pakfire_solution** solution,
+               struct pakfire_problem* problem, Id id) {
+       struct pakfire_solution* s = calloc(1, sizeof(*s));
+       if (!s)
+               return 1;
+
+       s->pakfire = pakfire_problem_get_pakfire(problem);
+       s->nrefs = 1;
+
+       // Store a reference to the problem
+       s->problem = pakfire_problem_ref(problem);
+       s->id = id;
+
+       *solution = s;
+       return 0;
+}
+
+PAKFIRE_EXPORT struct pakfire_solution* pakfire_solution_ref(struct pakfire_solution* solution) {
+       solution->nrefs++;
+
+       return solution;
+}
+
+static void pakfire_solution_free(struct pakfire_solution* solution) {
+       pakfire_problem_unref(solution->problem);
+
+       if (solution->string)
+               free(solution->string);
 
+       pakfire_unref(solution->pakfire);
+       free(solution);
+}
+
+PAKFIRE_EXPORT struct pakfire_solution* pakfire_solution_unref(struct pakfire_solution* solution) {
+       if (!solution)
+               return NULL;
+
+       if (--solution->nrefs > 0)
+               return solution;
+
+       pakfire_solution_free(solution);
+       return NULL;
+}
+
+static char* pakfire_solution_make_string(struct pakfire_solution* solution) {
+       struct pakfire_request* request = pakfire_problem_get_request(solution->problem);
        Solver* solver = pakfire_request_get_solver(request);
        Pool* pool = solver->pool;
 
-       // Reserve memory
-       unsigned int num = solver_solutionelement_count(solver, pakfire_problem_get_id(solution->problem), solution->id);
-       char** elements = solution->elements = calloc(num + 1, sizeof(*elements));
+       // Fetch the problem ID
+       Id problem_id = pakfire_problem_get_id(solution->problem);
+
+       // How many elements do we have?
+       unsigned int count = solver_solutionelement_count(solver, problem_id, solution->id);
+       if (!count) {
+               pakfire_request_unref(request);
+               return NULL;
+       }
+
+       // Allocate memory for all strings
+       char* elements[count + 1];
+
+       // Initialize the array
+       for (unsigned int i = 0; i < count; i++)
+               elements[i] = NULL;
+
+       // The result string
+       char* s = NULL;
 
        Id p;
        Id rp;
-       Id element = 0;
-       while ((element = solver_next_solutionelement(solver, pakfire_problem_get_id(solution->problem), solution->id, element, &p, &rp)) != 0) {
-               char line[1024];
+       Id e = 0;
+       int r;
+
+       for (unsigned int i = 0; i < count; i++) {
+               e = solver_next_solutionelement(solver, problem_id, solution->id, e, &p, &rp);
+               if (!e)
+                       break;
+
+               char* element = NULL;
 
                if (p == SOLVER_SOLUTION_JOB || p == SOLVER_SOLUTION_POOLJOB) {
                        if (p == SOLVER_SOLUTION_JOB)
@@ -64,142 +129,69 @@ static void import_elements(struct pakfire_solution* solution) {
                        Id what = solver->job.elements[rp];
 
                        // XXX pool_job2str must be localised
-                       snprintf(line, sizeof(line) - 1, _("do not ask to %s"),
-                               pool_job2str(pool, how, what, 0));
+                       r = asprintf(&element, _("do not ask to %s"), pool_job2str(pool, how, what, 0));
 
                } else if (p == SOLVER_SOLUTION_INFARCH) {
                        Solvable* s = pool->solvables + rp;
 
                        if (pool->installed && s->repo == pool->installed)
-                               snprintf(line, sizeof(line) - 1, _("keep %s despite the inferior architecture"),
+                               r = asprintf(&element, _("keep %s despite the inferior architecture"),
                                        pool_solvable2str(pool, s));
                        else
-                               snprintf(line, sizeof(line) - 1, _("install %s despite the inferior architecture"),
+                               r = asprintf(&element, _("install %s despite the inferior architecture"),
                                        pool_solvable2str(pool, s));
 
                } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
                        Solvable* s = pool->solvables + rp;
 
                        if (pool->installed && s->repo == pool->installed)
-                               snprintf(line, sizeof(line) - 1, _("keep obsolete %s"),
-                                       pool_solvable2str(pool, s));
+                               r = asprintf(&element, _("keep obsolete %s"), pool_solvable2str(pool, s));
                        else
-                               snprintf(line, sizeof(line) - 1, _("install %s"),
-                                       pool_solvable2str(pool, s));
+                               r = asprintf(&element, _("install %s"), pool_solvable2str(pool, s));
 
                } else if (p == SOLVER_SOLUTION_BEST) {
                        Solvable* s = pool->solvables + rp;
 
                        if (pool->installed && s->repo == pool->installed)
-                               snprintf(line, sizeof(line) - 1, _("keep old %s"),
-                                       pool_solvable2str(pool, s));
+                               r = asprintf(&element, _("keep old %s"), pool_solvable2str(pool, s));
                        else
-                               snprintf(line, sizeof(line) - 1, _("install %s despite the old version"),
+                               r = asprintf(&element, _("install %s despite the old version"),
                                        pool_solvable2str(pool, s));
 
                } else if (p > 0 && rp == 0)
-                       snprintf(line, sizeof(line) - 1, _("allow deinstallation of %s"),
+                       r = asprintf(&element, _("allow deinstallation of %s"),
                                pool_solvid2str(pool, p));
 
                else if (p > 0 && rp > 0)
-                       snprintf(line, sizeof(line) - 1, _("allow replacement of %s with %s"),
+                       r = asprintf(&element, _("allow replacement of %s with %s"),
                                pool_solvid2str(pool, p), pool_solvid2str(pool, rp));
 
                else
-                       snprintf(line, sizeof(line) - 1, _("bad solution element"));
+                       r = asprintf(&element, _("bad solution element"));
+
+               if (r < 0)
+                       goto ERROR;
 
                // Save line in elements array
-               *elements++ = strdup(line);
+               elements[i] = element;
        }
 
-       // Terminate array
-       *elements = NULL;
+       // All okay, concat result string
+       s = pakfire_string_join(elements, "\n");
 
+ERROR:
        pakfire_request_unref(request);
-}
-
-PAKFIRE_EXPORT int pakfire_solution_create(struct pakfire_solution** solution,
-               struct pakfire_problem* problem, Id id) {
-       struct pakfire_solution* s = calloc(1, sizeof(*s));
-       if (!s)
-               return 1;
-
-       s->pakfire = pakfire_problem_get_pakfire(problem);
-       s->nrefs = 1;
 
-       // Store a reference to the problem
-       s->problem = pakfire_problem_ref(problem);
-       s->id = id;
+       // Free all elements
+       for (char** element = elements; *element; element++)
+               free(*element);
 
-       // Extract information from solver
-       import_elements(s);
-
-       *solution = s;
-       return 0;
+       return s;
 }
 
-PAKFIRE_EXPORT struct pakfire_solution* pakfire_solution_ref(struct pakfire_solution* solution) {
-       solution->nrefs++;
-
-       return solution;
-}
-
-static void pakfire_solution_free(struct pakfire_solution* solution) {
-       pakfire_unref(solution->pakfire);
-
-       pakfire_problem_unref(solution->problem);
-
-       if (solution->elements)
-               while (*solution->elements)
-                       free(*solution->elements++);
-
-       free(solution);
-}
-
-PAKFIRE_EXPORT struct pakfire_solution* pakfire_solution_unref(struct pakfire_solution* solution) {
-       if (!solution)
-               return NULL;
-
-       if (--solution->nrefs > 0)
-               return solution;
-
-       pakfire_solution_free(solution);
-       return NULL;
-}
-
-static size_t count_elements_length(struct pakfire_solution* solution) {
-       size_t length = 0;
-
-       char** elements = solution->elements;
-       while (*elements) {
-               length += strlen(*elements++) + 1;
-       }
-
-       return length;
-}
-
-PAKFIRE_EXPORT char* pakfire_solution_to_string(struct pakfire_solution* solution) {
-       // Determine length of output string
-       size_t length = count_elements_length(solution);
-
-       // Allocate string
-       char s[length];
-       char* p = s;
-
-       char** elements = solution->elements;
-       while (*elements) {
-               // Copy line
-               char* e = *elements++;
-               while (*e)
-                       *p++ = *e++;
-
-               // Add newline
-               *p++ = '\n';
-       }
-
-       // Terminate string
-       if (p > s)
-               *(p-1) = '\0';
+PAKFIRE_EXPORT const char* pakfire_solution_to_string(struct pakfire_solution* solution) {
+       if (!solution->string)
+               solution->string = pakfire_solution_make_string(solution);
 
-       return strdup(s);
+       return solution->string;
 }