]> git.ipfire.org Git - pakfire.git/commitdiff
CLI: Refactor progressbar to use statically allocated buffers
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 22 Feb 2025 17:04:23 +0000 (17:04 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 22 Feb 2025 17:04:23 +0000 (17:04 +0000)
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 <michael.tremer@ipfire.org>
src/cli/lib/progressbar.c

index cb534ef9bcb7329d0536139badb92c28acbab2e8..c28d0d813275acc66de4aa51edb52a0a20e32052 100644 (file)
@@ -28,6 +28,7 @@
 #include <pakfire/i18n.h>
 #include <pakfire/pakfire.h>
 #include <pakfire/progress.h>
+#include <pakfire/string.h>
 #include <pakfire/util.h>
 
 #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;