From: Michael Tremer Date: Tue, 22 Oct 2024 16:35:25 +0000 (+0000) Subject: cli: progressbar: Remove the elements array X-Git-Tag: 0.9.30~942 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=325b11098b90c9bedd453796036719375fcea48b;p=pakfire.git cli: progressbar: Remove the elements array This was a dynamically allocated array which was difficult to track as it was filled in two passes. Signed-off-by: Michael Tremer --- diff --git a/src/cli/lib/progressbar.c b/src/cli/lib/progressbar.c index bf2f083ef..0fbce4a38 100644 --- a/src/cli/lib/progressbar.c +++ b/src/cli/lib/progressbar.c @@ -40,6 +40,11 @@ static const struct timespec TIMER = { }; struct cli_progressbar; +struct cli_progressbar_widget; + +typedef ssize_t (*print_callback)(struct cli_progressbar* p, + struct cli_progressbar_widget* widget, unsigned int width, void* data); +typedef void (*free_callback)(void* data); struct cli_progressbar_widget { STAILQ_ENTRY(cli_progressbar_widget) nodes; @@ -47,9 +52,9 @@ struct cli_progressbar_widget { int expandable; void* data; - const char* (*print)(struct cli_progressbar* p, - struct cli_progressbar_widget* widget, unsigned int width, void* data); - void (*free)(void* data); + // Callbacks + print_callback print; + free_callback free; char* buffer; }; @@ -144,60 +149,50 @@ static int cli_progressbar_draw(struct cli_progressbar* p) { return r; unsigned int cols_left = cols - p->num_widgets - 2; - unsigned int i = 0; - - // Create an array with the result of all print functions - const char* elements[p->num_widgets]; - - // Reset all elements - for (i = 0; i < p->num_widgets; i++) - elements[i] = NULL; - // Reset i - i = 0; + // Count how many widgets we have processed + unsigned int widgets = 0; // Process all non-expandable widgets in the first pass STAILQ_FOREACH(widget, &p->widgets, nodes) { - const char* element = NULL; - if (!widget->expandable) { - element = widget->print(p, widget, 0, widget->data); - if (element) - cols_left -= strlen(element); - } + r = widget->print(p, widget, 0, widget->data); + if (r < 0) + return r; - elements[i++] = element; + // Take away used space + cols_left -= strlen(widget->buffer); + + // Count the widget + widgets++; + } } // How many expandable widgets are left? - int num_expandables = p->num_widgets - i; + int num_expandables = p->num_widgets - widgets; // How much space do we allocate to each of them? - int width = cols_left - num_expandables; - - i = 0; + int width = cols_left / num_expandables; // Process all expandable widgets STAILQ_FOREACH(widget, &p->widgets, nodes) { - const char* element = elements[i]; - - if (widget->expandable) - element = widget->print(p, widget, width, widget->data); - - elements[i++] = element; + if (widget->expandable) { + r = widget->print(p, widget, width, widget->data); + if (r < 0) + return r; + } } // Reset the line fputs("\r", p->f); - // Print all elements - for (i = 0; i < p->num_widgets; i++) { - // Skip anything that returned nothing - if (!elements[i]) + // Print all buffers + STAILQ_FOREACH(widget, &p->widgets, nodes) { + if (!widget->buffer || !*widget->buffer) continue; fputs(" ", p->f); - fputs(elements[i], p->f); + fputs(widget->buffer, p->f); } // Flush everything @@ -272,9 +267,7 @@ static int cli_progressbar_finish(struct pakfire_ctx* ctx, struct pakfire_progre } static int cli_progressbar_add_widget(struct cli_progressbar* p, - const char* (*print)(struct cli_progressbar* p, - struct cli_progressbar_widget* widget, unsigned int width, void* data), - void (*free)(void* data), int expandable, void* data) { + print_callback print, free_callback free, int expandable, void* data) { // Allocate the widget struct cli_progressbar_widget* widget = calloc(1, sizeof(*widget)); if (!widget) @@ -293,9 +286,11 @@ static int cli_progressbar_add_widget(struct cli_progressbar* p, return 0; } -static const char* cli_progressbar_string(struct cli_progressbar* p, +static ssize_t cli_progressbar_string(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { - return (const char*)data; + widget->buffer = data; + + return strlen(widget->buffer); } static int cli_progressbar_add_string(struct cli_progressbar* p, const char* format, ...) @@ -315,16 +310,29 @@ static int cli_progressbar_add_string(struct cli_progressbar* p, const char* for return cli_progressbar_add_widget(p, cli_progressbar_string, free, 0, s); } -static const char* cli_progressbar_title(struct cli_progressbar* p, +static ssize_t cli_progressbar_title(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { - return pakfire_progress_get_title(p->progress); + const char* title = NULL; + int r; + + if (!widget->buffer) { + title = pakfire_progress_get_title(p->progress); + if (!title) + return 0; + + r = asprintf(&widget->buffer, "%s", title); + if (r < 0) + return r; + } + + return strlen(widget->buffer); } static int cli_progressbar_add_title(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_title, NULL, 0, NULL); } -static const char* cli_progressbar_counter(struct cli_progressbar* p, +static ssize_t cli_progressbar_counter(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { int r; @@ -335,16 +343,16 @@ static const char* cli_progressbar_counter(struct cli_progressbar* p, // Format the result r = asprintf(&widget->buffer, "%lu/%lu", value, max_value); if (r < 0) - return NULL; + return -errno; - return widget->buffer; + return r; } static int cli_progressbar_add_counter(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_counter, NULL, 0, NULL); } -static const char* cli_progressbar_percentage(struct cli_progressbar* p, +static ssize_t cli_progressbar_percentage(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { int r; @@ -354,23 +362,23 @@ static const char* cli_progressbar_percentage(struct cli_progressbar* p, // Format to string r = asprintf(&widget->buffer, "%3.0f%%", percentage); if (r < 0) - return NULL; + return -errno; - return widget->buffer; + return r; } static int cli_progressbar_add_percentage(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_percentage, NULL, 0, NULL); } -static const char* cli_progressbar_bar(struct cli_progressbar* p, +static ssize_t cli_progressbar_bar(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { // Allocate or adjust the buffer widget->buffer = realloc(widget->buffer, width + 1); // Fail if we could not allocate the buffer if (!widget->buffer) - return NULL; + return -errno; // Remove the bar when we are finished so that the terminal is not so cluttered if (!p->is_running) { @@ -378,7 +386,7 @@ static const char* cli_progressbar_bar(struct cli_progressbar* p, widget->buffer[i] = ' '; widget->buffer[width] = '\0'; - return widget->buffer; + return width; } unsigned int fill = pakfire_progress_get_percentage(p->progress) * (width - 2) / 100; @@ -398,35 +406,35 @@ static const char* cli_progressbar_bar(struct cli_progressbar* p, // Terminate the string widget->buffer[width] = '\0'; - return widget->buffer; + return width; } static int cli_progressbar_add_bar(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_bar, NULL, 1, NULL); } -static const char* cli_progressbar_elapsed_time(struct cli_progressbar* p, +static ssize_t cli_progressbar_elapsed_time(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { int r; // Fetch the elapsed time time_t t = pakfire_progress_get_elapsed_time(p->progress); if (t < 0) - return NULL; + return -errno; // Format the time r = asprintf(&widget->buffer, "%02ld:%02ld", t / 60, t % 60); - if (r) - return NULL; + if (r < 0) + return -errno; - return widget->buffer; + return r; } static int cli_progressbar_add_elapsed_time(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_elapsed_time, NULL, 0, NULL); } -static const char* cli_progressbar_eta(struct cli_progressbar* p, +static ssize_t cli_progressbar_eta(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { int r; @@ -441,16 +449,16 @@ static const char* cli_progressbar_eta(struct cli_progressbar* p, if (t <= 0) { r = asprintf(&widget->buffer, "%-5s: --:--:--", _("ETA")); if (r < 0) - return NULL; + return -errno; // Otherwise show the ETA } else { r = asprintf(&widget->buffer, "%-5s: %02ld:%02ld", _("ETA"), t / 60, t % 60); if (r < 0) - return NULL; + return -errno; } - return widget->buffer; + return r; } static int cli_progressbar_add_eta(struct cli_progressbar* p) { @@ -519,7 +527,7 @@ static int __cli_progressbar_format_size(char* s, const size_t length, double va } #pragma GCC diagnostic pop -static const char* cli_progressbar_bytes_transferred(struct cli_progressbar* p, +static ssize_t cli_progressbar_bytes_transferred(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { char buffer[16]; int r; @@ -530,35 +538,35 @@ static const char* cli_progressbar_bytes_transferred(struct cli_progressbar* p, // Format the size r = cli_progressbar_format_size(buffer, value); if (r < 0) - return NULL; + return r; // Add padding so that the string is always at least five characters long r = asprintf(&widget->buffer, "%-5s", buffer); if (r < 0) - return NULL; + return -errno; - return widget->buffer; + return r; } static int cli_progressbar_add_bytes_transferred(struct cli_progressbar* p) { return cli_progressbar_add_widget(p, cli_progressbar_bytes_transferred, NULL, 0, NULL); } -static const char* cli_progressbar_transfer_speed(struct cli_progressbar* p, +static ssize_t cli_progressbar_transfer_speed(struct cli_progressbar* p, struct cli_progressbar_widget* widget, unsigned int width, void* data) { int r; // Fetch the speed double speed = pakfire_progress_get_transfer_speed(p->progress); if (speed < 0) - return NULL; + return -errno; // Format the speed r = cli_progressbar_format_speed(&widget->buffer, speed); if (r < 0) - return NULL; + return r; - return widget->buffer; + return r; } static int cli_progressbar_add_transfer_speed(struct cli_progressbar* p) {