Converts the given size in bytes in two possible ways:
1) target_unit is specified (!= 0): size is converted to target unit.
2) target_unit is not specified (== 0): size is converted to the first
   unit which will bring size to below 2048.

If specified, label will point to the long label ('MB') if long_labels is
set or the short label ('M') if it is not.

Additionally, ShowSize is no longer locked to MB but will scale units as
required.

Signed-off-by: Jakob Gruber <jakob.gru...@gmail.com>
---
 src/pacman/callback.c |   45 ++++++++-------------------------
 src/pacman/package.c  |   18 +++++++------
 src/pacman/query.c    |    7 ++---
 src/pacman/sync.c     |    7 ++---
 src/pacman/util.c     |   65 ++++++++++++++++++++++++++++++++++++++----------
 src/pacman/util.h     |    1 +
 6 files changed, 79 insertions(+), 64 deletions(-)

diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index a80172b..769031a 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -491,10 +491,11 @@ void cb_dl_progress(const char *filename, off_t 
file_xfered, off_t file_total)
 
        int totaldownload = 0;
        off_t xfered, total;
-       double rate = 0.0, timediff = 0.0, f_xfered = 0.0;
+       double rate = 0.0, timediff = 0.0;
        unsigned int eta_h = 0, eta_m = 0, eta_s = 0;
+       double rate_human, xfered_human;
+       const char *rate_label, *xfered_label;
        int file_percent = 0, total_percent = 0;
-       char rate_size = 'K', xfered_size = 'K';
 
        if(config->noprogressbar || file_total == -1) {
                if(file_xfered == 0) {
@@ -556,7 +557,7 @@ void cb_dl_progress(const char *filename, off_t 
file_xfered, off_t file_total)
                diff_sec = current_time.tv_sec - initial_time.tv_sec;
                diff_usec = current_time.tv_usec - initial_time.tv_usec;
                timediff = diff_sec + (diff_usec / 1000000.0);
-               rate = xfered / (timediff * 1024.0);
+               rate = xfered / timediff;
 
                /* round elapsed time to the nearest second */
                eta_s = (int)(timediff + 0.5);
@@ -568,10 +569,10 @@ void cb_dl_progress(const char *filename, off_t 
file_xfered, off_t file_total)
                        /* return if the calling interval was too short */
                        return;
                }
-               rate = (xfered - xfered_last) / (timediff * 1024.0);
+               rate = (xfered - xfered_last) / timediff;
                /* average rate to reduce jumpiness */
                rate = (rate + 2 * rate_last) / 3;
-               eta_s = (total - xfered) / (rate * 1024.0);
+               eta_s = (total - xfered) / rate;
                rate_last = rate;
                xfered_last = xfered;
        }
@@ -625,37 +626,13 @@ void cb_dl_progress(const char *filename, off_t 
file_xfered, off_t file_total)
 
        }
 
-       /* Awesome formatting for progress bar.  We need a mess of Kb->Mb->Gb 
stuff
-        * here. We'll use limit of 2048 for each until we get some empirical */
-       /* rate_size = 'K'; was set above */
-       if(rate > 2048.0) {
-               rate /= 1024.0;
-               rate_size = 'M';
-               if(rate > 2048.0) {
-                       rate /= 1024.0;
-                       rate_size = 'G';
-                       /* we should not go higher than this for a few years 
(9999.9 Gb/s?)*/
-               }
-       }
-
-       f_xfered = xfered / 1024.0; /* convert to K by default */
-       /* xfered_size = 'K'; was set above */
-       if(f_xfered > 2048.0) {
-               f_xfered /= 1024.0;
-               xfered_size = 'M';
-               if(f_xfered > 2048.0) {
-                       f_xfered /= 1024.0;
-                       xfered_size = 'G';
-                       /* I should seriously hope that archlinux packages 
never break
-                        * the 9999.9GB mark... we'd have more serious problems 
than the progress
-                        * bar in pacman */
-               }
-       }
+       rate_human = humanize_size((off_t)rate, 0, 0, &rate_label);
+       xfered_human = humanize_size(xfered, 0, 0, &xfered_label);
 
        /* 1 space + filenamelen + 1 space + 7 for size + 1 + 7 for rate + 2 
for /s + 1 space + 8 for eta */
-       printf(" %ls%-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", wcfname,
-                       padwid, "", f_xfered, xfered_size,
-                       rate, rate_size, eta_h, eta_m, eta_s);
+       printf(" %ls%-*s %6.1f%s %#6.1f%s/s %02u:%02u:%02u", wcfname,
+                       padwid, "", xfered_human, xfered_label, rate_human, 
rate_label,
+                       eta_h, eta_m, eta_s);
 
        free(fname);
        free(wcfname);
diff --git a/src/pacman/package.c b/src/pacman/package.c
index 77a5ee7..39e36f6 100644
--- a/src/pacman/package.c
+++ b/src/pacman/package.c
@@ -51,6 +51,8 @@ void dump_pkg_full(pmpkg_t *pkg, int level)
        const char *reason;
        time_t bdate, idate;
        char bdatestr[50] = "", idatestr[50] = "";
+       const char *label;
+       double size;
        const alpm_list_t *i;
        alpm_list_t *requiredby = NULL, *depstrings = NULL;
 
@@ -105,17 +107,17 @@ void dump_pkg_full(pmpkg_t *pkg, int level)
        }
        list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg));
        list_display(_("Replaces       :"), alpm_pkg_get_replaces(pkg));
+
+       size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label);
        if(level < 0) {
-               printf(_("Download Size  : %6.2f K\n"),
-                       (double)alpm_pkg_get_size(pkg) / 1024.0);
-       }
-       if(level == 0) {
-               printf(_("Compressed Size: %6.2f K\n"),
-                       (double)alpm_pkg_get_size(pkg) / 1024.0);
+               printf(_("Download Size  : %6.2f %s\n"), size, label);
+       } else if(level == 0) {
+               printf(_("Compressed Size: %6.2f %s\n"), size, label);
        }
 
-       printf(_("Installed Size : %6.2f K\n"),
-                       (double)alpm_pkg_get_isize(pkg) / 1024.0);
+       size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 1, &label);
+       printf(_("Installed Size : %6.2f %s\n"), size, label);
+
        string_display(_("Packager       :"), alpm_pkg_get_packager(pkg));
        string_display(_("Architecture   :"), alpm_pkg_get_arch(pkg));
        string_display(_("Build Date     :"), bdatestr);
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 18c6992..d3a90ff 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -247,10 +247,9 @@ static int query_search(alpm_list_t *targets)
 
                /* print the package size with the output if ShowSize option 
set */
                if(!config->quiet && config->showsize) {
-                       /* Convert byte size to MB */
-                       double mbsize = (double)alpm_pkg_get_size(pkg) / 
(1024.0 * 1024.0);
-
-                       printf(" [%.2f MB]", mbsize);
+                       const char *label;
+                       double size = humanize_size(alpm_pkg_get_size(pkg), 0, 
1, &label);
+                       printf(" [%.2f %s]", size, label);
                }
 
 
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 26f6f82..aadb9e5 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -349,10 +349,9 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t 
*targets)
 
                        /* print the package size with the output if ShowSize 
option set */
                        if(!config->quiet && config->showsize) {
-                               /* Convert byte size to MB */
-                               double mbsize = (double)alpm_pkg_get_size(pkg) 
/ (1024.0 * 1024.0);
-
-                               printf(" [%.2f MB]", mbsize);
+                               const char *label;
+                               double size = 
humanize_size(alpm_pkg_get_size(pkg), 0, 1, &label);
+                               printf(" [%.2f %s]", size, label);
                        }
 
                        if (!config->quiet) {
diff --git a/src/pacman/util.c b/src/pacman/util.c
index c08ebb1..ba93963 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -502,9 +502,10 @@ void list_display_linebreak(const char *title, const 
alpm_list_t *list)
 void display_targets(const alpm_list_t *pkgs, int install)
 {
        char *str;
+       const char *label;
+       double size;
        const alpm_list_t *i;
        off_t isize = 0, dlsize = 0;
-       double mbisize = 0.0, mbdlsize = 0.0;
        alpm_list_t *targets = NULL;
 
        if(!pkgs) {
@@ -522,10 +523,9 @@ void display_targets(const alpm_list_t *pkgs, int install)
 
                /* print the package size with the output if ShowSize option 
set */
                if(config->showsize) {
-                       double mbsize = (double)alpm_pkg_get_size(pkg) / 
(1024.0 * 1024.0);
-
-                       pm_asprintf(&str, "%s-%s [%.2f MB]", 
alpm_pkg_get_name(pkg),
-                                       alpm_pkg_get_version(pkg), mbsize);
+                       size = humanize_size(alpm_pkg_get_size(pkg), 0, 1, 
&label);
+                       pm_asprintf(&str, "%s-%s [%.2f %s]", 
alpm_pkg_get_name(pkg),
+                                       alpm_pkg_get_version(pkg), size, label);
                } else {
                        pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg),
                                        alpm_pkg_get_version(pkg));
@@ -533,19 +533,17 @@ void display_targets(const alpm_list_t *pkgs, int install)
                targets = alpm_list_add(targets, str);
        }
 
-       /* Convert byte sizes to MB */
-       mbdlsize = (double)dlsize / (1024.0 * 1024.0);
-       mbisize = (double)isize / (1024.0 * 1024.0);
-
        if(install) {
                pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets));
                list_display(str, targets);
                free(str);
                printf("\n");
 
-               printf(_("Total Download Size:    %.2f MB\n"), mbdlsize);
+               size = humanize_size(dlsize, 'M', 1, &label);
+               printf(_("Total Download Size:    %.2f %s\n"), size, label);
                if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY)) {
-                       printf(_("Total Installed Size:   %.2f MB\n"), mbisize);
+                       size = humanize_size(isize, 'M', 1, &label);
+                       printf(_("Total Installed Size:   %.2f %s\n"), size, 
label);
                }
        } else {
                pm_asprintf(&str, _("Remove (%d):"), alpm_list_count(targets));
@@ -553,7 +551,8 @@ void display_targets(const alpm_list_t *pkgs, int install)
                free(str);
                printf("\n");
 
-               printf(_("Total Removed Size:   %.2f MB\n"), mbisize);
+               size = humanize_size(isize, 'M', 1, &label);
+               printf(_("Total Removed Size:   %.2f %s\n"), size, label);
        }
 
        FREELIST(targets);
@@ -594,6 +593,45 @@ static char *pkg_get_location(pmpkg_t *pkg)
        }
 }
 
+/** Converts sizes in bytes into human readable units.
+ *
+ * @param bytes the size in bytes
+ * @param target_unit if equal to one of the short unit labels ('B', 'K', ...)
+ *                             bytes is converted to target_unit; if equal to 
0, the first
+ *                             unit which will bring the value to below a 
threshold of 2048
+ *                             will be chosen.
+ * @param long_labels whether to use short ("K") or long ("KB") unit labels
+ * @param label will be set to the appropriate unit label
+ *
+ * @return the size in the appropriate unit
+ */
+double humanize_size(off_t bytes, const char target_unit, int long_labels,
+               const char **label)
+{
+       static const char *shortlabels[] = {"B", "K", "M", "G", "T", "P"};
+       static const char *longlabels[] = {"B", "KB", "MB", "GB", "TB", "PB"};
+       static const int unitcount = sizeof(shortlabels) / 
sizeof(shortlabels[0]);
+
+       const char **labels = long_labels ? longlabels : shortlabels;
+       double val = (double)bytes;
+       int index;
+
+       for(index = 0; index < unitcount - 1; index++) {
+               if(target_unit != 0 && shortlabels[index][0] == target_unit) {
+                       break;
+               } else if(target_unit == 0 && val <= 2048.0) {
+                       break;
+               }
+               val /= 1024.0;
+       }
+
+       if(label) {
+               *label = labels[index];
+       }
+
+       return(val);
+}
+
 void print_packages(const alpm_list_t *packages)
 {
        const alpm_list_t *i;
@@ -638,8 +676,7 @@ void print_packages(const alpm_list_t *packages)
                /* %s : size */
                if(strstr(temp,"%s")) {
                        char *size;
-                       double mbsize = (double)pkg_get_size(pkg) / (1024.0 * 
1024.0);
-                       pm_asprintf(&size, "%.2f", mbsize);
+                       pm_asprintf(&size, "%.2f", 
humanize_size(pkg_get_size(pkg), 'M', 0, NULL));
                        string = strreplace(temp, "%s", size);
                        free(size);
                        free(temp);
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 234a631..6a20ba4 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -52,6 +52,7 @@ char *strtrim(char *str);
 char *strreplace(const char *str, const char *needle, const char *replace);
 alpm_list_t *strsplit(const char *str, const char splitchar);
 void string_display(const char *title, const char *string);
+double humanize_size(off_t bytes, const char target_unit, int long_labels, 
const char **label);
 void list_display(const char *title, const alpm_list_t *list);
 void list_display_linebreak(const char *title, const alpm_list_t *list);
 void display_targets(const alpm_list_t *pkgs, int install);
-- 
1.7.4.1


Reply via email to