git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] strbuf: create strbuf_humanize() to show byte sizes

From
Antoine Pelisse <apelisse@gmail.com>
Date
Apr 10, 2013, 19:03 UTC
Message-ID
<1365620604-17851-1-git-send-email-apelisse@gmail.com>
In-Reply-To
<7vli8svgyo.fsf@alter.siamese.dyndns.org>

Currently, humanization of downloaded size is done in the same function as text formatting in 'process.c'. This is an issue if anyone else wants to use this.

Separate text formatting from size simplification and make the function public in strbuf so that it can easily be used by other clients.

We now can use strbuf_humanize() for both downloaded size and download speed calculation. One of the drawbacks is that speed will now look like this when download is stalled: "0 bytes/s" instead of "0 KiB/s".

Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
 Documentation/technical/api-strbuf.txt |    5 ++++
 progress.c                             |   43 +++++++++++---------------------
 strbuf.c                               |   19 ++++++++++++++
 strbuf.h                               |    1 +
 4 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index 2c59cb2..7b6ecda 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -230,6 +230,11 @@ which can be used by the programmer of the callback as she sees fit.
 	destination. This is useful for literal data to be fed to either
 	strbuf_expand or to the *printf family of functions.
 
+`strbuf_humanize`::
+
+	Append the given byte size as a human-readable string (i.e. 12.23 KiB,
+	3.50 MiB).
+
 `strbuf_addf`::
 
 	Add a formatted string to the buffer.
diff --git a/progress.c b/progress.c
index 3971f49..8e09058 100644
--- a/progress.c
+++ b/progress.c
@@ -10,6 +10,7 @@
 
 #include "git-compat-util.h"
 #include "progress.h"
+#include "strbuf.h"
 
 #define TP_IDX_MAX      8
 
@@ -112,34 +113,14 @@ static int display(struct progress *progress, unsigned n, const char *done)
 	return 0;
 }
 
-static void throughput_string(struct throughput *tp, off_t total,
+static void throughput_string(struct strbuf *buf, off_t total,
 			      unsigned int rate)
 {
-	int l = sizeof(tp->display);
-	if (total > 1 << 30) {
-		l -= snprintf(tp->display, l, ", %u.%2.2u GiB",
-			      (int)(total >> 30),
-			      (int)(total & ((1 << 30) - 1)) / 10737419);
-	} else if (total > 1 << 20) {
-		int x = total + 5243;  /* for rounding */
-		l -= snprintf(tp->display, l, ", %u.%2.2u MiB",
-			      x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
-	} else if (total > 1 << 10) {
-		int x = total + 5;  /* for rounding */
-		l -= snprintf(tp->display, l, ", %u.%2.2u KiB",
-			      x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
-	} else {
-		l -= snprintf(tp->display, l, ", %u bytes", (int)total);
-	}
-
-	if (rate > 1 << 10) {
-		int x = rate + 5;  /* for rounding */
-		snprintf(tp->display + sizeof(tp->display) - l, l,
-			 " | %u.%2.2u MiB/s",
-			 x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
-	} else if (rate)
-		snprintf(tp->display + sizeof(tp->display) - l, l,
-			 " | %u KiB/s", rate);
+	strbuf_addstr(buf, ", ");
+	strbuf_humanize(buf, total);
+	strbuf_addstr(buf, " | ");
+	strbuf_humanize(buf, rate * 1024);
+	strbuf_addstr(buf, "/s");
 }
 
 void display_throughput(struct progress *progress, off_t total)
@@ -183,6 +164,7 @@ void display_throughput(struct progress *progress, off_t total)
 	misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977;
 
 	if (misecs > 512) {
+		struct strbuf buf = STRBUF_INIT;
 		unsigned int count, rate;
 
 		count = total - tp->prev_total;
@@ -197,7 +179,9 @@ void display_throughput(struct progress *progress, off_t total)
 		tp->last_misecs[tp->idx] = misecs;
 		tp->idx = (tp->idx + 1) % TP_IDX_MAX;
 
-		throughput_string(tp, total, rate);
+		throughput_string(&buf, total, rate);
+		strncpy(tp->display, buf.buf, sizeof(tp->display));
+		strbuf_release(&buf);
 		if (progress->last_value != -1 && progress_update)
 			display(progress, progress->last_value, NULL);
 	}
@@ -253,9 +237,12 @@ void stop_progress_msg(struct progress **p_progress, const char *msg)
 
 		bufp = (len < sizeof(buf)) ? buf : xmalloc(len + 1);
 		if (tp) {
+			struct strbuf strbuf = STRBUF_INIT;
 			unsigned int rate = !tp->avg_misecs ? 0 :
 					tp->avg_bytes / tp->avg_misecs;
-			throughput_string(tp, tp->curr_total, rate);
+			throughput_string(&strbuf, tp->curr_total, rate);
+			strncpy(tp->display, strbuf.buf, sizeof(tp->display));
+			strbuf_release(&strbuf);
 		}
 		progress_update = 1;
 		sprintf(bufp, ", %s.\n", msg);
diff --git a/strbuf.c b/strbuf.c
index 48e9abb..8a50e66 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -528,6 +528,25 @@ void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
 	strbuf_add_urlencode(sb, s, strlen(s), reserved);
 }
 
+void strbuf_humanize(struct strbuf *buf, off_t bytes)
+{
+	if (bytes > 1 << 30) {
+		strbuf_addf(buf, "%u.%2.2u GiB",
+			    (int)(bytes >> 30),
+			    (int)(bytes & ((1 << 30) - 1)) / 10737419);
+	} else if (bytes > 1 << 20) {
+		int x = bytes + 5243;  /* for rounding */
+		strbuf_addf(buf, "%u.%2.2u MiB",
+			    x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
+	} else if (bytes > 1 << 10) {
+		int x = bytes + 5;  /* for rounding */
+		strbuf_addf(buf, "%u.%2.2u KiB",
+			    x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
+	} else {
+		strbuf_addf(buf, "%u bytes", (int)bytes);
+	}
+}
+
 int printf_ln(const char *fmt, ...)
 {
 	int ret;
diff --git a/strbuf.h b/strbuf.h
index 958822c..317c5a8 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -170,6 +170,7 @@ extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
 
 extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
 				    int reserved);
+extern void strbuf_humanize(struct strbuf *buf, off_t bytes);
 
 __attribute__((format (printf,1,2)))
 extern int printf_ln(const char *fmt, ...);
-- 
1.7.9.5
Previous: Junio C HamanoNext: Antoine Pelisse
Message 15 of 21 in “count-objects: output "KiB" instead of "kilobytes"”
  1. count-objects: output "KiB" instead of "kilobytes"Mihai Capotă, Apr 2, 2013
  2. Junio C HamanoApr 2, 2013
  3. Junio C HamanoApr 2, 2013
  4. Mihai CapotăApr 3, 2013
  5. count-objects: output "KiB" instead of "kilobytes"Mihai Capotă, Apr 3, 2013
  6. Junio C HamanoApr 3, 2013
  7. Mihai CapotăApr 4, 2013
  8. Junio C HamanoApr 4, 2013
  9. Mihai CapotăApr 5, 2013
  10. count-objects doc: document use of kibibytesMihai Capotă, Apr 5, 2013
  11. Antoine PelisseApr 5, 2013
  12. 1/2 progress: create public humanize() to show sizesAntoine Pelisse, Apr 8, 2013
  13. 2/2 count-objects: add -H option to humanize sizesAntoine Pelisse, Apr 8, 2013
  14. Junio C HamanoApr 8, 2013
  15. 1/2 strbuf: create strbuf_humanize() to show byte sizesAntoine Pelisse, Apr 10, 2013
  16. 2/2 count-objects: add -H option to humanize sizesAntoine Pelisse, Apr 10, 2013
  17. Jonathan NiederApr 10, 2013
  18. Antoine PelisseApr 10, 2013
  19. Junio C HamanoApr 10, 2013
  20. Antoine PelisseApr 10, 2013
  21. Eric SunshineApr 8, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.