From: Michael Tremer Date: Sat, 3 Jul 2021 12:15:29 +0000 (+0000) Subject: solution: Refactor creating string X-Git-Tag: 0.9.28~1120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cd440ebcf40cc11ae5bb56cbcffc9fec1c6e053;p=pakfire.git solution: Refactor creating string Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/solution.h b/src/libpakfire/include/pakfire/solution.h index 268a6179d..bf26dc633 100644 --- a/src/libpakfire/include/pakfire/solution.h +++ b/src/libpakfire/include/pakfire/solution.h @@ -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 */ diff --git a/src/libpakfire/solution.c b/src/libpakfire/solution.c index c91806d43..d9d530fa8 100644 --- a/src/libpakfire/solution.c +++ b/src/libpakfire/solution.c @@ -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; }