refactor(diff.c): factor out hunk processing

This commit is contained in:
Lewis Russell
2022-10-24 09:54:02 +01:00
parent 29f138d5ad
commit b15f7007eb

View File

@@ -1598,68 +1598,39 @@ static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
} }
} }
/// Read the diff output and add each entry to the diff list. static void process_hunk(diff_T **dpp, diff_T **dprevp, int idx_orig, int idx_new, diffhunk_T *hunk,
/// bool *notsetp)
/// @param idx_orig idx of original file
/// @param idx_new idx of new file
/// @dout diff output
static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
{ {
FILE *fd = NULL; diff_T *dp = *dpp;
int line_idx = 0; diff_T *dprev = *dprevp;
diff_T *dprev = NULL;
diff_T *dp = curtab->tp_first_diff;
diffout_T *dout = &dio->dio_diff;
int notset = true; // block "*dp" not set yet
diffstyle_T diffstyle = DIFF_NONE;
if (dio->dio_internal) {
diffstyle = DIFF_UNIFIED;
} else {
fd = os_fopen(dout->dout_fname, "r");
if (fd == NULL) {
emsg(_("E98: Cannot read diff output"));
return;
}
}
for (;;) {
diffhunk_T hunk = { 0 };
bool eof = dio->dio_internal
? extract_hunk_internal(dout, &hunk, &line_idx)
: extract_hunk(fd, &hunk, &diffstyle);
if (eof) {
break;
}
// Go over blocks before the change, for which orig and new are equal. // Go over blocks before the change, for which orig and new are equal.
// Copy blocks from orig to new. // Copy blocks from orig to new.
while (dp != NULL while (dp != NULL
&& hunk.lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) { && hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
if (notset) { if (*notsetp) {
diff_copy_entry(dprev, dp, idx_orig, idx_new); diff_copy_entry(dprev, dp, idx_orig, idx_new);
} }
dprev = dp; dprev = dp;
dp = dp->df_next; dp = dp->df_next;
notset = true; *notsetp = true;
} }
if ((dp != NULL) if ((dp != NULL)
&& (hunk.lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) && (hunk->lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
&& (hunk.lnum_orig + hunk.count_orig >= dp->df_lnum[idx_orig])) { && (hunk->lnum_orig + hunk->count_orig >= dp->df_lnum[idx_orig])) {
// New block overlaps with existing block(s). // New block overlaps with existing block(s).
// First find last block that overlaps. // First find last block that overlaps.
diff_T *dpl; diff_T *dpl;
for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) { for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) {
if (hunk.lnum_orig + hunk.count_orig < dpl->df_next->df_lnum[idx_orig]) { if (hunk->lnum_orig + hunk->count_orig < dpl->df_next->df_lnum[idx_orig]) {
break; break;
} }
} }
// If the newly found block starts before the old one, set the // If the newly found block starts before the old one, set the
// start back a number of lines. // start back a number of lines.
linenr_T off = dp->df_lnum[idx_orig] - hunk.lnum_orig; linenr_T off = dp->df_lnum[idx_orig] - hunk->lnum_orig;
if (off > 0) { if (off > 0) {
for (int i = idx_orig; i < idx_new; i++) { for (int i = idx_orig; i < idx_new; i++) {
@@ -1667,15 +1638,15 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
dp->df_lnum[i] -= off; dp->df_lnum[i] -= off;
} }
} }
dp->df_lnum[idx_new] = hunk.lnum_new; dp->df_lnum[idx_new] = hunk->lnum_new;
dp->df_count[idx_new] = (linenr_T)hunk.count_new; dp->df_count[idx_new] = (linenr_T)hunk->count_new;
} else if (notset) { } else if (*notsetp) {
// new block inside existing one, adjust new block // new block inside existing one, adjust new block
dp->df_lnum[idx_new] = hunk.lnum_new + off; dp->df_lnum[idx_new] = hunk->lnum_new + off;
dp->df_count[idx_new] = (linenr_T)hunk.count_new - off; dp->df_count[idx_new] = (linenr_T)hunk->count_new - off;
} else { } else {
// second overlap of new block with existing block // second overlap of new block with existing block
dp->df_count[idx_new] += (linenr_T)hunk.count_new - (linenr_T)hunk.count_orig dp->df_count[idx_new] += (linenr_T)hunk->count_new - (linenr_T)hunk->count_orig
+ dpl->df_lnum[idx_orig] + + dpl->df_lnum[idx_orig] +
dpl->df_count[idx_orig] dpl->df_count[idx_orig]
- (dp->df_lnum[idx_orig] + - (dp->df_lnum[idx_orig] +
@@ -1684,13 +1655,13 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
// Adjust the size of the block to include all the lines to the // Adjust the size of the block to include all the lines to the
// end of the existing block or the new diff, whatever ends last. // end of the existing block or the new diff, whatever ends last.
off = (hunk.lnum_orig + (linenr_T)hunk.count_orig) off = (hunk->lnum_orig + (linenr_T)hunk->count_orig)
- (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]); - (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]);
if (off < 0) { if (off < 0) {
// new change ends in existing block, adjust the end if not // new change ends in existing block, adjust the end if not
// done already // done already
if (notset) { if (*notsetp) {
dp->df_count[idx_new] += -off; dp->df_count[idx_new] += -off;
} }
off = 0; off = 0;
@@ -1716,10 +1687,10 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
// Allocate a new diffblock. // Allocate a new diffblock.
dp = diff_alloc_new(curtab, dprev, dp); dp = diff_alloc_new(curtab, dprev, dp);
dp->df_lnum[idx_orig] = hunk.lnum_orig; dp->df_lnum[idx_orig] = hunk->lnum_orig;
dp->df_count[idx_orig] = (linenr_T)hunk.count_orig; dp->df_count[idx_orig] = (linenr_T)hunk->count_orig;
dp->df_lnum[idx_new] = hunk.lnum_new; dp->df_lnum[idx_new] = hunk->lnum_new;
dp->df_count[idx_new] = (linenr_T)hunk.count_new; dp->df_count[idx_new] = (linenr_T)hunk->count_new;
// Set values for other buffers, these must be equal to the // Set values for other buffers, these must be equal to the
// original buffer, otherwise there would have been a change // original buffer, otherwise there would have been a change
@@ -1730,7 +1701,47 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
} }
} }
} }
notset = false; // "*dp" has been set *notsetp = false; // "*dp" has been set
*dpp = dp;
*dprevp = dprev;
}
/// Read the diff output and add each entry to the diff list.
///
/// @param idx_orig idx of original file
/// @param idx_new idx of new file
/// @dout diff output
static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
{
FILE *fd = NULL;
int line_idx = 0;
diff_T *dprev = NULL;
diff_T *dp = curtab->tp_first_diff;
diffout_T *dout = &dio->dio_diff;
bool notset = true; // block "*dp" not set yet
diffstyle_T diffstyle = DIFF_NONE;
if (dio->dio_internal) {
diffstyle = DIFF_UNIFIED;
} else {
fd = os_fopen(dout->dout_fname, "r");
if (fd == NULL) {
emsg(_("E98: Cannot read diff output"));
return;
}
}
for (;;) {
diffhunk_T hunk = { 0 };
bool eof = dio->dio_internal
? extract_hunk_internal(dout, &hunk, &line_idx)
: extract_hunk(fd, &hunk, &diffstyle);
if (eof) {
break;
}
process_hunk(&dp, &dprev, idx_orig, idx_new, &hunk, &notset);
} }
// for remaining diff blocks orig and new are equal // for remaining diff blocks orig and new are equal