From: Michael Tremer Date: Sat, 22 Feb 2025 17:04:23 +0000 (+0000) Subject: CLI: Refactor progressbar to use statically allocated buffers X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=35169eb664824e58522712a84d84f8033f7cc582;p=pakfire.git CLI: Refactor progressbar to use statically allocated buffers This might take a little bit of pressure off the allocator and we don't have to deal with asprintf() loosing memory. Signed-off-by: Michael Tremer --- diff --git a/src/cli/lib/progressbar.c b/src/cli/lib/progressbar.c index cb534ef9..c28d0d81 100644 --- a/src/cli/lib/progressbar.c +++ b/src/cli/lib/progressbar.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "progressbar.h" @@ -57,7 +58,7 @@ struct cli_progressbar_widget { print_callback print; free_callback free; - char* buffer; + char buffer[LINE_MAX]; }; struct cli_progressbar { @@ -108,9 +109,6 @@ static void cli_progressbar_widget_free(struct cli_progressbar_widget* widget) { if (widget->free && widget->data) widget->free(widget->data); - if (widget->buffer) - free(widget->buffer); - free(widget); } @@ -192,7 +190,7 @@ static int cli_progressbar_draw(struct cli_progressbar* p) { // Print all buffers STAILQ_FOREACH(widget, &p->widgets, nodes) { - if (!widget->buffer || !*widget->buffer) + if (!*widget->buffer) continue; fputs(" ", p->f); @@ -295,15 +293,13 @@ static ssize_t cli_progressbar_title(struct cli_progressbar* p, const char* title = NULL; int r; - if (!widget->buffer) { - title = pakfire_progress_get_title(p->progress); - if (!title) - return 0; + title = pakfire_progress_get_title(p->progress); + if (!title) + return 0; - r = asprintf(&widget->buffer, "%s", title); - if (r < 0) - return r; - } + r = pakfire_string_format(widget->buffer, "%s", title); + if (r < 0) + return r; return strlen(widget->buffer); } @@ -321,11 +317,11 @@ static ssize_t cli_progressbar_counter(struct cli_progressbar* p, unsigned long int max_value = pakfire_progress_get_value(p->progress); // Format the result - r = asprintf(&widget->buffer, "%lu/%lu", value, max_value); + r = pakfire_string_format(widget->buffer, "%lu/%lu", value, max_value); if (r < 0) return -errno; - return r; + return strlen(widget->buffer); } static int cli_progressbar_add_counter(struct cli_progressbar* p) { @@ -340,11 +336,11 @@ static ssize_t cli_progressbar_percentage(struct cli_progressbar* p, double percentage = pakfire_progress_get_percentage(p->progress); // Format to string - r = asprintf(&widget->buffer, "%3.0f%%", percentage); + r = pakfire_string_format(widget->buffer, "%3.0f%%", percentage); if (r < 0) return -errno; - return r; + return strlen(widget->buffer); } static int cli_progressbar_add_percentage(struct cli_progressbar* p) { @@ -357,12 +353,9 @@ static ssize_t cli_progressbar_bar(struct cli_progressbar* p, if (!width) return -ENOBUFS; - // Allocate or adjust the buffer - widget->buffer = pakfire_realloc(widget->buffer, width + 1); - - // Fail if we could not allocate the buffer - if (!widget->buffer) - return -errno; + // Cap the widths to the buffer + if (width >= sizeof(widget->buffer)) + width = sizeof(widget->buffer) - 1; // Remove the bar when we are finished so that the terminal is not so cluttered if (!p->is_running) { @@ -407,11 +400,11 @@ static ssize_t cli_progressbar_elapsed_time(struct cli_progressbar* p, return -errno; // Format the time - r = asprintf(&widget->buffer, "%02ld:%02ld", t / 60, t % 60); + r = pakfire_string_format(widget->buffer, "%02ld:%02ld", t / 60, t % 60); if (r < 0) return -errno; - return r; + return strlen(widget->buffer); } static int cli_progressbar_add_elapsed_time(struct cli_progressbar* p) { @@ -431,86 +424,24 @@ static ssize_t cli_progressbar_eta(struct cli_progressbar* p, // Print a placeholder when we have no ETA (yet) if (t <= 0) { - r = asprintf(&widget->buffer, "%-5s: --:--:--", _("ETA")); + r = pakfire_string_format(widget->buffer, "%-5s: --:--:--", _("ETA")); if (r < 0) return -errno; // Otherwise show the ETA } else { - r = asprintf(&widget->buffer, "%-5s: %02ld:%02ld", _("ETA"), t / 60, t % 60); + r = pakfire_string_format(widget->buffer, "%-5s: %02ld:%02ld", _("ETA"), t / 60, t % 60); if (r < 0) return -errno; } - return r; + return strlen(widget->buffer); } static int cli_progressbar_add_eta(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_eta, NULL, 0, NULL); } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -static int cli_progressbar_format_speed(char** s, double value) { - const char* units[] = { - "%4.0fB/s", - "%4.0fkB/s", - "%4.1fMB/s", - "%4.1fGB/s", - "%4.1fTB/s", - NULL - }; - int r; - - for (const char** unit = units; *unit; unit++) { - if (value >= 1024.0) { - value /= 1024.0; - continue; - } - - // Format the string - r = asprintf(s, *unit, value); - if (r < 0) - return r; - - return 0; - } - - return 1; -} - -#define cli_progressbar_format_size(s, size) \ - __cli_progressbar_format_size(s, sizeof(s), size) - -static int __cli_progressbar_format_size(char* s, const size_t length, double value) { - const char* units[] = { - "%.0f ", - "%.0fk", - "%.1fM", - "%.1fG", - "%.1fT", - NULL - }; - int r; - - for (const char** unit = units; *unit; unit++) { - if (value >= 1024.0) { - value /= 1024.0; - continue; - } - - // Format the string - r = snprintf(s, length, *unit, value); - if (r < 0) - return r; - - return 0; - } - - return 1; -} -#pragma GCC diagnostic pop - static ssize_t cli_progressbar_bytes_transferred(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { char buffer[16]; @@ -520,16 +451,16 @@ static ssize_t cli_progressbar_bytes_transferred(struct cli_progressbar* p, unsigned long int value = pakfire_progress_get_value(p->progress); // Format the size - r = cli_progressbar_format_size(buffer, value); + r = pakfire_format_size(buffer, value); if (r < 0) return r; // Add padding so that the string is always at least five characters long - r = asprintf(&widget->buffer, "%-5s", buffer); + r = pakfire_string_format(widget->buffer, "%-5s", buffer); if (r < 0) return -errno; - return r; + return strlen(widget->buffer); } static int cli_progressbar_add_bytes_transferred(struct cli_progressbar* p) { @@ -546,7 +477,7 @@ static ssize_t cli_progressbar_transfer_speed(struct cli_progressbar* p, return -errno; // Format the speed - r = cli_progressbar_format_speed(&widget->buffer, speed); + r = pakfire_format_speed(widget->buffer, speed); if (r < 0) return r;