fix(diff): split myers into header and source file to mitigate import errors
This commit is contained in:
parent
0e07d4b63c
commit
96ebd49533
2 changed files with 103 additions and 100 deletions
101
include/myers.h
101
include/myers.h
|
|
@ -4,105 +4,6 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "action_list.h"
|
#include "action_list.h"
|
||||||
|
|
||||||
// minimum helper
|
ActionList* myers_diff(File*, File*, size_t, size_t);
|
||||||
static inline uint64_t min(uint64_t a, uint64_t b) {
|
|
||||||
return (a < b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// maxmium helper
|
|
||||||
static inline uint64_t max(uint64_t a, uint64_t b) {
|
|
||||||
return (a > b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// diffing function based on Myers Diff Algorithm with LCS for the maximum matching
|
|
||||||
ActionList* myers_diff(File* old_version, File* new_version, uint64_t old_offset, uint64_t new_offset) {
|
|
||||||
uint64_t old_len = old_version->lines;
|
|
||||||
uint64_t new_len = new_version->lines;
|
|
||||||
ActionList* result = new_list();
|
|
||||||
|
|
||||||
// old file is empty
|
|
||||||
if (old_len == 0) {
|
|
||||||
for (uint64_t i = 0; i < new_len; i++) {
|
|
||||||
Action action = (Action){.type=INSERT, .line_original=old_offset, .line_changed=new_offset + i};
|
|
||||||
add_action(result, action);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new file is empty
|
|
||||||
if (new_len == 0) {
|
|
||||||
for (uint64_t i = 0; i < old_len; i++) {
|
|
||||||
Action action = (Action){.type=DELETE, .line_original=old_offset + i, .line_changed=0};
|
|
||||||
add_action(result, action);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the LCS table
|
|
||||||
uint64_t** lcs_table = calloc(old_len + 1, sizeof(uint64_t*));
|
|
||||||
if (!lcs_table) return result;
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i <= old_len; i++) {
|
|
||||||
lcs_table[i] = calloc(new_len + 1, sizeof(uint64_t));
|
|
||||||
if (!lcs_table[i]) {
|
|
||||||
for (uint64_t j = 0; j < i; j++) free(lcs_table[j]);
|
|
||||||
free(lcs_table);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filling the LCS table
|
|
||||||
for (uint64_t i = 1; i <= old_len; i++) {
|
|
||||||
for (uint64_t j = 1; j <= new_len; j++) {
|
|
||||||
if (strcmp(old_version->content[i-1], new_version->content[j-1]) == 0) {
|
|
||||||
lcs_table[i][j] = lcs_table[i-1][j-1] + 1;
|
|
||||||
} else {
|
|
||||||
lcs_table[i][j] = max(lcs_table[i-1][j], lcs_table[i][j-1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t i = old_len, j = new_len;
|
|
||||||
|
|
||||||
// actions need to be collected temporarily because they are in reverse order
|
|
||||||
Action* temp_actions = calloc(old_len + new_len, sizeof(Action));
|
|
||||||
uint64_t temp_count = 0;
|
|
||||||
|
|
||||||
if (!temp_actions) {
|
|
||||||
for (uint64_t k = 0; k <= old_len; k++) free(lcs_table[k]);
|
|
||||||
free(lcs_table);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i > 0 || j > 0) {
|
|
||||||
if (i > 0 && j > 0 && strcmp(old_version->content[i-1], new_version->content[j-1]) == 0) {
|
|
||||||
i--;
|
|
||||||
j--;
|
|
||||||
} else if (j > 0 && (i == 0 || lcs_table[i][j-1] >= lcs_table[i-1][j])) {
|
|
||||||
temp_actions[temp_count].type = INSERT;
|
|
||||||
temp_actions[temp_count].line_original = old_offset + i;
|
|
||||||
temp_actions[temp_count].line_changed = new_offset + j - 1;
|
|
||||||
temp_count++;
|
|
||||||
j--;
|
|
||||||
} else if (i > 0) {
|
|
||||||
temp_actions[temp_count].type = DELETE;
|
|
||||||
temp_actions[temp_count].line_original = old_offset + i - 1;
|
|
||||||
temp_actions[temp_count].line_changed = 0;
|
|
||||||
temp_count++;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reversing the actions into the correct order
|
|
||||||
for (int64_t k = temp_count - 1; k >= 0; k--) {
|
|
||||||
add_action(result, temp_actions[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(temp_actions);
|
|
||||||
for (uint64_t k = 0; k <= old_len; k++) free(lcs_table[k]);
|
|
||||||
free(lcs_table);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MYERS_H
|
#endif // MYERS_H
|
||||||
|
|
|
||||||
102
src/myers.c
Normal file
102
src/myers.c
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include "myers.h"
|
||||||
|
|
||||||
|
// minimum helper
|
||||||
|
static inline uint64_t min(uint64_t a, uint64_t b) {
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maxmium helper
|
||||||
|
static inline uint64_t max(uint64_t a, uint64_t b) {
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffing function based on Myers Diff Algorithm with LCS for the maximum matching
|
||||||
|
ActionList* myers_diff(File* old_version, File* new_version, uint64_t old_offset, uint64_t new_offset) {
|
||||||
|
uint64_t old_len = old_version->lines;
|
||||||
|
uint64_t new_len = new_version->lines;
|
||||||
|
ActionList* result = new_list();
|
||||||
|
|
||||||
|
// old file is empty
|
||||||
|
if (old_len == 0) {
|
||||||
|
for (uint64_t i = 0; i < new_len; i++) {
|
||||||
|
Action action = (Action){.type=INSERT, .line_original=old_offset, .line_changed=new_offset + i};
|
||||||
|
add_action(result, action);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new file is empty
|
||||||
|
if (new_len == 0) {
|
||||||
|
for (uint64_t i = 0; i < old_len; i++) {
|
||||||
|
Action action = (Action){.type=DELETE, .line_original=old_offset + i, .line_changed=0};
|
||||||
|
add_action(result, action);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the LCS table
|
||||||
|
uint64_t** lcs_table = calloc(old_len + 1, sizeof(uint64_t*));
|
||||||
|
if (!lcs_table) return result;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i <= old_len; i++) {
|
||||||
|
lcs_table[i] = calloc(new_len + 1, sizeof(uint64_t));
|
||||||
|
if (!lcs_table[i]) {
|
||||||
|
for (uint64_t j = 0; j < i; j++) free(lcs_table[j]);
|
||||||
|
free(lcs_table);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filling the LCS table
|
||||||
|
for (uint64_t i = 1; i <= old_len; i++) {
|
||||||
|
for (uint64_t j = 1; j <= new_len; j++) {
|
||||||
|
if (strcmp(old_version->content[i-1], new_version->content[j-1]) == 0) {
|
||||||
|
lcs_table[i][j] = lcs_table[i-1][j-1] + 1;
|
||||||
|
} else {
|
||||||
|
lcs_table[i][j] = max(lcs_table[i-1][j], lcs_table[i][j-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t i = old_len, j = new_len;
|
||||||
|
|
||||||
|
// actions need to be collected temporarily because they are in reverse order
|
||||||
|
Action* temp_actions = calloc(old_len + new_len, sizeof(Action));
|
||||||
|
uint64_t temp_count = 0;
|
||||||
|
|
||||||
|
if (!temp_actions) {
|
||||||
|
for (uint64_t k = 0; k <= old_len; k++) free(lcs_table[k]);
|
||||||
|
free(lcs_table);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i > 0 || j > 0) {
|
||||||
|
if (i > 0 && j > 0 && strcmp(old_version->content[i-1], new_version->content[j-1]) == 0) {
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
} else if (j > 0 && (i == 0 || lcs_table[i][j-1] >= lcs_table[i-1][j])) {
|
||||||
|
temp_actions[temp_count].type = INSERT;
|
||||||
|
temp_actions[temp_count].line_original = old_offset + i;
|
||||||
|
temp_actions[temp_count].line_changed = new_offset + j - 1;
|
||||||
|
temp_count++;
|
||||||
|
j--;
|
||||||
|
} else if (i > 0) {
|
||||||
|
temp_actions[temp_count].type = DELETE;
|
||||||
|
temp_actions[temp_count].line_original = old_offset + i - 1;
|
||||||
|
temp_actions[temp_count].line_changed = 0;
|
||||||
|
temp_count++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reversing the actions into the correct order
|
||||||
|
for (int64_t k = temp_count - 1; k >= 0; k--) {
|
||||||
|
add_action(result, temp_actions[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp_actions);
|
||||||
|
for (uint64_t k = 0; k <= old_len; k++) free(lcs_table[k]);
|
||||||
|
free(lcs_table);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue