Scale to the first unit with which the value will be less or equal to
2048. size_to_human_string_short uses short unit labels ("K","M",...)
instead of the default ("KB", "MB"), uses only one decimal digit and has
no space between the value and the label.
For example, size_to_human_string: "1.31 MB", short: "1.3M".
- /* 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 */
- }
- }
+ ratestr = size_to_human_string_short((off_t)rate);
+ xferedstr = size_to_human_string_short(xfered);
/* 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 %7s %7s/s %02u:%02u:%02u", wcfname,
+ padwid, "", xferedstr, ratestr, eta_h, eta_m, eta_s);
+/** Converts sizes in bytes into strings.
+ *
+ * @param bytes the size in bytes
+ * @param format the format string to use. The first argument is of type
+ * float and represents the size. The second argument is of type
+ * char* and represents the unit label. for example, "%.2f %s"
+ * could result in "1.23 MB"
+ * @param unit the target unit. can be either one of the short unit
+ * labels ("B", "K", ...); or NULL, in which case the first
+ * unit which will bring the value to below a threshold of 2048
+ * will be chosen.
+ * @param long_units whether to use short ("K") or long ("KB") unit labels
+ *
+ * @return the size string
+ */
+static char *size_to_human_string_format(off_t bytes, const char *format,
+ const char *unit, int long_labels)
+{
+ char *ret;
+ static const char *shortlabels[] = {"B", "K", "M", "G", "T", "P"};
+ static const char *longlabels[] = {"B", "KB", "MB", "GB", "TB", "PB"};
+ const char **labels = long_labels ? longlabels : shortlabels;
+ const int unitcount = sizeof(shortlabels) / sizeof(shortlabels[0]);
+ int index;
+ float val = (float)bytes;
+
+ /* stop conditions:
+ * 1) a target unit is specified and we are at target unit,
+ * 2) target unit is NOT specified and value is leq 2048,
+ * and 3) we are already at the largest unit.s
+ * note that if an invalid target is specified in 1),
+ * we convert to the largest unit */
+ for(index = 0; index < unitcount - 1; index++) {
+ if(unit != NULL && strcmp(shortlabels[index], unit) == 0) break;
+ else if(unit == NULL && val <= 2048.0) break;
+
+ val /= 1024.0;
+ }
+
+ pm_asprintf(&ret, format, val, labels[index]);
+
+ return ret;
+}
+
+char *size_to_human_string(off_t bytes)
+{
+ return size_to_human_string_format(bytes, "%.2f %s", NULL, 1);
+}
+
+char *size_to_human_string_mb(off_t bytes)
+{
+ return size_to_human_string_format(bytes, "%.2f %s", "M", 1);
+}
+
+char *size_to_human_string_kb(off_t bytes)
+{
+ return size_to_human_string_format(bytes, "%.2f %s", "K", 1);
+}
+
+char *size_to_human_string_short(off_t bytes)
+{
+ return size_to_human_string_format(bytes, "%.1f%s", NULL, 0);
+}
+
void print_packages(const alpm_list_t *packages)
{
const alpm_list_t *i;
@@ -638,8 +703,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);
+ size = size_to_human_string_format(pkg_get_size(pkg), "%.2f", "M", 0);
string = strreplace(temp, "%s", size);
free(size);
free(temp);
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 234a631..ed03c13 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -51,6 +51,10 @@ char *strtoupper(char *str);
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);
+char *size_to_human_string(off_t bytes);
+char *size_to_human_string_mb(off_t bytes);
+char *size_to_human_string_kb(off_t bytes);
+char *size_to_human_string_short(off_t bytes);
void string_display(const char *title, const char *string);
void list_display(const char *title, const alpm_list_t *list);
void list_display_linebreak(const char *title, const alpm_list_t *list);
--
1.7.4.1