| 77 | }; |
| 78 | |
| 79 | class AlgorithmMyers : public Algorithm { |
| 80 | public: |
| 81 | AlgorithmMyers() : Algorithm("hex.diffing.algorithm.myers.name", "hex.diffing.algorithm.myers.description") {} |
| 82 | |
| 83 | [[nodiscard]] std::vector<DiffTree> analyze(prv::Provider *providerA, prv::Provider *providerB) const override { |
| 84 | DiffTree differencesA, differencesB; |
| 85 | |
| 86 | EdlibAlignConfig edlibConfig; |
| 87 | edlibConfig.k = -1; |
| 88 | edlibConfig.additionalEqualities = nullptr; |
| 89 | edlibConfig.additionalEqualitiesLength = 0; |
| 90 | edlibConfig.mode = EdlibAlignMode::EDLIB_MODE_NW; |
| 91 | edlibConfig.task = EdlibAlignTask::EDLIB_TASK_PATH; |
| 92 | |
| 93 | const auto providerAStart = providerA->getBaseAddress(); |
| 94 | const auto providerBStart = providerB->getBaseAddress(); |
| 95 | const auto providerAEnd = providerAStart + providerA->getActualSize(); |
| 96 | const auto providerBEnd = providerBStart + providerB->getActualSize(); |
| 97 | |
| 98 | const auto windowStart = std::max(providerAStart, providerBStart); |
| 99 | const auto windowEnd = std::min(providerAEnd, providerBEnd); |
| 100 | |
| 101 | auto &task = TaskManager::getCurrentTask(); |
| 102 | |
| 103 | if (providerAStart > providerBStart) { |
| 104 | differencesA.insert({ providerBStart, providerAStart }, DifferenceType::Deletion); |
| 105 | differencesB.insert({ providerBStart, providerAStart }, DifferenceType::Deletion); |
| 106 | } else if (providerAStart < providerBStart) { |
| 107 | differencesA.insert({ providerAStart, providerBStart }, DifferenceType::Insertion); |
| 108 | differencesB.insert({ providerAStart, providerBStart }, DifferenceType::Insertion); |
| 109 | } |
| 110 | |
| 111 | for (u64 address = windowStart; address < windowEnd; address += m_windowSize) { |
| 112 | if (task.wasInterrupted()) |
| 113 | break; |
| 114 | |
| 115 | auto currWindowSizeA = std::min<u64>(m_windowSize, providerA->getActualSize() - address); |
| 116 | auto currWindowSizeB = std::min<u64>(m_windowSize, providerB->getActualSize() - address); |
| 117 | std::vector<u8> dataA(currWindowSizeA, 0x00), dataB(currWindowSizeB, 0x00); |
| 118 | |
| 119 | providerA->read(address, dataA.data(), dataA.size()); |
| 120 | providerB->read(address, dataB.data(), dataB.size()); |
| 121 | |
| 122 | const auto commonSize = std::min(dataA.size(), dataB.size()); |
| 123 | EdlibAlignResult result = edlibAlign( |
| 124 | reinterpret_cast<const char*>(dataA.data()), commonSize, |
| 125 | reinterpret_cast<const char*>(dataB.data()), commonSize, |
| 126 | edlibConfig |
| 127 | ); |
| 128 | |
| 129 | auto currentOperation = DifferenceType(0xFF); |
| 130 | Region regionA = {}, regionB = {}; |
| 131 | u64 currentAddressA = address, currentAddressB = address; |
| 132 | |
| 133 | const auto insertDifference = [&] { |
| 134 | switch (currentOperation) { |
| 135 | using enum DifferenceType; |
| 136 | |