From 96ebd49533ed77b76be5395f5ae67e29da94a1e4 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Sun, 31 Aug 2025 18:02:52 +0200 Subject: [PATCH] fix(diff): split myers into header and source file to mitigate import errors --- include/myers.h | 101 +---------------------------------------------- src/myers.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 100 deletions(-) create mode 100644 src/myers.c diff --git a/include/myers.h b/include/myers.h index b0233ec..0eb0730 100644 --- a/include/myers.h +++ b/include/myers.h @@ -4,105 +4,6 @@ #include "file.h" #include "action_list.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; -} +ActionList* myers_diff(File*, File*, size_t, size_t); #endif // MYERS_H diff --git a/src/myers.c b/src/myers.c new file mode 100644 index 0000000..7ba3a3d --- /dev/null +++ b/src/myers.c @@ -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; +}