blame.c: prepare_lines should not call xrealloc for every line

Making a single preparation run for counting the lines will avoid memory fragmentation. Also, fix the allocated memory size which was wrong when sizeof(int *) != sizeof(int), and would have been too small for sizeof(int *) < sizeof(int), admittedly unlikely. Signed-off-by: David Kastrup <dak@gnu.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Kastrup committed Feb 12, 2014 at 15:27 UTC 352bbbd9f24b39ae863ceb78170a2685d40e6416
1 file changed +31 -15
builtin/blame.c
+31 -15
@@ -1756,25 +1756,41 @@ static int prepare_lines(struct scoreboard *sb)
1756 {
1757 const char *buf = sb->final_buf;
1758 unsigned long len = sb->final_buf_size;
1759 - int num = 0, incomplete = 0, bol = 1;
1759 + const char *end = buf + len;
1760 + const char *p;
1761 + int *lineno;
1762 + int num = 0, incomplete = 0;
1763
1761 - if (len && buf[len-1] != '\n')
1762 - incomplete++; /* incomplete line at the end */
1763 - while (len--) {
1764 - if (bol) {
1765 - sb->lineno = xrealloc(sb->lineno,
1766 - sizeof(int) * (num + 1));
1767 - sb->lineno[num] = buf - sb->final_buf;
1768 - bol = 0;
1769 - }
1770 - if (*buf++ == '\n') {
1764 + for (p = buf;;) {
1765 + p = memchr(p, '\n', end - p);
1766 + if (p) {
1767 + p++;
1768 num++;
1772 - bol = 1;
1769 + continue;
1770 }
1771 + break;
1772 }
1775 - sb->lineno = xrealloc(sb->lineno,
1776 - sizeof(int) * (num + incomplete + 1));
1777 - sb->lineno[num + incomplete] = buf - sb->final_buf;
1773 +
1774 + if (len && end[-1] != '\n')
1775 + incomplete++; /* incomplete line at the end */
1776 +
1777 + sb->lineno = xmalloc(sizeof(*sb->lineno) * (num + incomplete + 1));
1778 + lineno = sb->lineno;
1779 +
1780 + *lineno++ = 0;
1781 + for (p = buf;;) {
1782 + p = memchr(p, '\n', end - p);
1783 + if (p) {
1784 + p++;
1785 + *lineno++ = p - buf;
1786 + continue;
1787 + }
1788 + break;
1789 + }
1790 +
1791 + if (incomplete)
1792 + *lineno++ = len;
1793 +
1794 sb->num_lines = num + incomplete;
1795 return sb->num_lines;
1796 }