X-Git-Url: https://git.cameronkatri.com/cgit.git/blobdiff_plain/6a8f65bf184d85a0c51ffecca16f48e6f4b1ff12..HEAD:/ui-ssdiff.c diff --git a/ui-ssdiff.c b/ui-ssdiff.c index 408e620..af8bc9e 100644 --- a/ui-ssdiff.c +++ b/ui-ssdiff.c @@ -1,10 +1,13 @@ #include "cgit.h" +#include "ui-ssdiff.h" #include "html.h" #include "ui-shared.h" +#include "ui-diff.h" extern int use_ssdiff; static int current_old_line, current_new_line; +static int **L = NULL; struct deferred_lines { int line_no; @@ -15,16 +18,40 @@ struct deferred_lines { static struct deferred_lines *deferred_old, *deferred_old_last; static struct deferred_lines *deferred_new, *deferred_new_last; +static void create_or_reset_lcs_table(void) +{ + int i; + + if (L != NULL) { + memset(*L, 0, sizeof(int) * MAX_SSDIFF_SIZE); + return; + } + + // xcalloc will die if we ran out of memory; + // not very helpful for debugging + L = (int**)xcalloc(MAX_SSDIFF_M, sizeof(int *)); + *L = (int*)xcalloc(MAX_SSDIFF_SIZE, sizeof(int)); + + for (i = 1; i < MAX_SSDIFF_M; i++) { + L[i] = *L + i * MAX_SSDIFF_N; + } +} + static char *longest_common_subsequence(char *A, char *B) { int i, j, ri; int m = strlen(A); int n = strlen(B); - int L[m + 1][n + 1]; int tmp1, tmp2; int lcs_length; char *result; + // We bail if the lines are too long + if (m >= MAX_SSDIFF_M || n >= MAX_SSDIFF_N) + return NULL; + + create_or_reset_lcs_table(); + for (i = m; i >= 0; i--) { for (j = n; j >= 0; j--) { if (A[i] == '\0' || B[j] == '\0') { @@ -58,13 +85,14 @@ static char *longest_common_subsequence(char *A, char *B) j += 1; } } + return result; } static int line_from_hunk(char *line, char type) { char *buf1, *buf2; - int len; + int len, res; buf1 = strchr(line, type); if (buf1 == NULL) @@ -75,9 +103,8 @@ static int line_from_hunk(char *line, char type) return 0; len = buf2 - buf1; buf2 = xmalloc(len + 1); - strncpy(buf2, buf1, len); - buf2[len] = '\0'; - int res = atoi(buf2); + strlcpy(buf2, buf1, len + 1); + res = atoi(buf2); free(buf2); return res; } @@ -86,11 +113,11 @@ static char *replace_tabs(char *line) { char *prev_buf = line; char *cur_buf; - int linelen = strlen(line); + size_t linelen = strlen(line); int n_tabs = 0; int i; char *result; - char *spaces = " "; + size_t result_len; if (linelen == 0) { result = xmalloc(1); @@ -98,21 +125,26 @@ static char *replace_tabs(char *line) return result; } - for (i = 0; i < linelen; i++) + for (i = 0; i < linelen; i++) { if (line[i] == '\t') n_tabs += 1; - result = xmalloc(linelen + n_tabs * 8 + 1); + } + result_len = linelen + n_tabs * 8; + result = xmalloc(result_len + 1); result[0] = '\0'; - while (1) { + for (;;) { cur_buf = strchr(prev_buf, '\t'); if (!cur_buf) { - strcat(result, prev_buf); + linelen = strlen(result); + strlcpy(&result[linelen], prev_buf, result_len - linelen + 1); break; } else { - strcat(result, " "); - strncat(result, spaces, 8 - (strlen(result) % 8)); - strncat(result, prev_buf, cur_buf - prev_buf); + linelen = strlen(result); + strlcpy(&result[linelen], prev_buf, cur_buf - prev_buf + 1); + linelen = strlen(result); + memset(&result[linelen], ' ', 8 - (linelen % 8)); + result[linelen + 8 - (linelen % 8)] = '\0'; } prev_buf = cur_buf + 1; } @@ -177,11 +209,13 @@ static void print_part_with_lcs(char *class, char *line, char *lcs) } } else if (line[i] == lcs[j]) { same = 1; - htmlf(""); + html(""); j += 1; } html_txt(c); } + if (!same) + html(""); } static void print_ssdiff_line(char *class, @@ -191,17 +225,26 @@ static void print_ssdiff_line(char *class, char *new_line, int individual_chars) { char *lcs = NULL; + if (old_line) old_line = replace_tabs(old_line + 1); if (new_line) new_line = replace_tabs(new_line + 1); if (individual_chars && old_line && new_line) lcs = longest_common_subsequence(old_line, new_line); - html("