diff options
context:
space:
mode:
Diffstat (limited to 'source/ui-tree.c')
-rw-r--r--source/ui-tree.c29
1 file changed, 20 insertions, 9 deletions
diff --git a/source/ui-tree.c b/source/ui-tree.c
index b5a5556..bc5986b 100644
--- a/source/ui-tree.c
+++ b/source/ui-tree.c
@@ -13,6 +13,9 @@
#include "html.h"
#include "ui-shared.h"
+/* Bytes shown per row of the binary hex dump. */
+#define HEXDUMP_ROW_BYTES 32
+
struct tree_ls_entry {
struct object_id oid;
char *name;
@@ -77,18 +80,26 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size)
static void print_binary_buffer(char *buf, unsigned long size)
{
unsigned long ofs, idx;
- static char ascii[ROWLEN + 1];
+ char ascii[HEXDUMP_ROW_BYTES + 1];
+ struct strbuf row = STRBUF_INIT;
html("<table summary='blob content' class='bin-blob'>\n");
html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
- for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) {
- htmlf("<tr><td class='right'>%04lx</td><td class='hex'>", ofs);
- for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
- htmlf("%*s%02x",
- idx == 16 ? 4 : 1, "",
- buf[idx] & 0xff);
- html(" </td><td class='hex'>");
- for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
+ for (ofs = 0; ofs < size; ofs += HEXDUMP_ROW_BYTES, buf += HEXDUMP_ROW_BYTES) {
+ // One write per row rather than one per byte. At the default
+ // blob limit the per-byte form spent almost all of its time in
+ // the kernel, which made a single request for a large binary
+ // blob far more expensive than the page it produced.
+ strbuf_reset(&row);
+ strbuf_addf(&row, "<tr><td class='right'>%04lx</td><td class='hex'>", ofs);
+ for (idx = 0; idx < HEXDUMP_ROW_BYTES && ofs + idx < size; idx++)
+ strbuf_addf(&row, "%*s%02x",
+ idx == 16 ? 4 : 1, "",
+ buf[idx] & 0xff);
+ strbuf_addstr(&row, " </td><td class='hex'>");
+ html_raw(row.buf, row.len);
+
+ for (idx = 0; idx < HEXDUMP_ROW_BYTES && ofs + idx < size; idx++)
ascii[idx] = isgraph((unsigned char)buf[idx]) ? buf[idx] : '.';
ascii[idx] = '\0';
html_txt(ascii);