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
}