void KisMemoryWindowTest::testWindow() { KisMemoryWindow memory(QString(), 1024); quint8 oddValue = 0xee; const quint8 chunkLength = 10; quint8 oddBuf[chunkLength]; memset(oddBuf, oddValue, chunkLength); KisChunkData chunk1(0, chunkLength); KisChunkData chunk2(1025, chunkLength); quint8 *ptr; ptr = memory.getWriteChunkPtr(chunk1); memcpy(ptr, oddBuf, chunkLength); ptr = memory.getWriteChunkPtr(chunk2); memcpy(ptr, oddBuf, chunkLength); ptr = memory.getReadChunkPtr(chunk2); QVERIFY(!memcmp(ptr, oddBuf, chunkLength)); ptr = memory.getWriteChunkPtr(chunk1); QVERIFY(!memcmp(ptr, oddBuf, chunkLength)); }
bool compareBlocks(HWND view1, HWND view2, const UserSettings& settings, diff_info& blockDiff1, diff_info& blockDiff2) { diff_info* pBlockDiff1 = &blockDiff1; diff_info* pBlockDiff2 = &blockDiff2; if (blockDiff1.len > blockDiff2.len) { std::swap(view1, view2); std::swap(pBlockDiff1, pBlockDiff2); } chunk_info chunk1(pBlockDiff1->off, pBlockDiff1->len); chunk_info chunk2(pBlockDiff2->off, pBlockDiff2->len); getWords(view1, settings, chunk1); getWords(view2, settings, chunk2); // Compare the two chunks const std::vector<diff_info> chunkDiff = DiffCalc<Word>(chunk1.words, chunk2.words)(); const int chunkDiffSize = static_cast<int>(chunkDiff.size()); if (chunkDiffSize == 0) return false; std::vector<std::vector<int>> linesConvergence(chunk1.lineCount, std::vector<int>(chunk2.lineCount, 0)); // Use the MATCH results to synchronize line numbers (count the match length of each line) int wordOffset = 0; for (int i = 0; i < chunkDiffSize; ++i) { const diff_info& cd = chunkDiff[i]; if (cd.type == diff_type::DIFF_DELETE) { wordOffset -= cd.len; } else if (cd.type == diff_type::DIFF_INSERT) { wordOffset += cd.len; } else // diff_type::DIFF_MATCH { for (int wordIdx = cd.off; wordIdx < (cd.off + cd.len); ++wordIdx) { const Word& word1 = chunk1.words[wordIdx]; const Word& word2 = chunk2.words[wordIdx + wordOffset]; if (word1.type != charType::SPACECHAR) linesConvergence[word1.line][word2.line] += word1.length; } } } // Select the line with the most matches (as length) for (int line1 = 0; line1 < chunk1.lineCount; ++line1) { if (pBlockDiff1->isMoved(line1)) continue; int maxConvergence = 0; int line2 = 0; for (int i = 0; i < chunk2.lineCount; ++i) { if (!pBlockDiff2->isMoved(i) && linesConvergence[line1][i] > maxConvergence) { line2 = i; maxConvergence = linesConvergence[line1][i]; } } // Make sure that the line is matched and the other line is not already matched if (maxConvergence == 0 || chunk2.lineMappings[line2] != -1) continue; int line1Size = 0; for (int i = chunk1.lineStartWordIdx[line1]; i < chunk1.lineEndWordIdx[line1]; ++i) { const Word& word1 = chunk1.words[i]; if (word1.type != charType::SPACECHAR) line1Size += word1.length; } // Is enough portion of the line matched to be significant? if (line1Size && maxConvergence > (line1Size / 3)) { chunk1.lineMappings[line1] = line2; chunk2.lineMappings[line2] = line1; } } compareLines(*pBlockDiff1, *pBlockDiff2, chunk1, chunk2); return true; }
bool compareWords(diff_edit& e1, diff_edit& e2, const DocLines_t& doc1, const DocLines_t& doc2, bool IgnoreSpaces) { unsigned int i, j; chunk_info chunk1(e1.off, e1.len); chunk_info chunk2(e2.off, e2.len); getWords(doc1, chunk1, IgnoreSpaces); getWords(doc2, chunk2, IgnoreSpaces); // Compare the two chunks std::vector<diff_edit> diff = DiffCalc<Word>(chunk1.words, chunk2.words)(); chunk1.changes.reset(new varray<diff_change>); chunk2.changes.reset(new varray<diff_change>); std::vector<std::vector<int>> lineMappings1(chunk1.lineCount); for (i = 0; i < chunk1.lineCount; ++i) lineMappings1[i].resize(chunk2.lineCount, 0); // Use the MATCH results to synchronize line numbers // count how many are on each line, then select the line with the most matches const std::size_t diffSize = diff.size(); int offset = 0; for (i = 0; i < diffSize; ++i) { diff_edit& e = diff[i]; if (e.op == DIFF_DELETE) { offset -= e.len; } else if (e.op == DIFF_INSERT) { offset += e.len; } else { for (unsigned int index = e.off; index < (e.off + e.len); ++index) { Word *word1 = &chunk1.words[index]; Word *word2 = &chunk2.words[index + offset]; if (word1->type != SPACECHAR && word1->type != EOLCHAR) { int line1a = word1->line; int line2a = word2->line; lineMappings1[line1a][line2a] += word1->length; } } } } // go through each line, and select the line with the highest strength for (i = 0; i < chunk1.lineCount; ++i) { int line = -1; int max = 0; for (j = 0; j <chunk2.lineCount; ++j) { if (lineMappings1[i][j] > max && (e2.moves.empty() || e2.moves[j] == -1)) { line = j; max = lineMappings1[i][j]; } } // make sure that the line isn't already matched to another line, // and that enough of the line is matched to be significant const int size = doc1[e1.off + i].size(); if (line != -1 && chunk2.lineMappings[line] == -1 && max > (size / 3) && (e1.moves.empty() || e1.moves[i] == -1)) { chunk1.lineMappings[i] = line; chunk2.lineMappings[line] = i; } } // find all the differences between the lines chunk1.changeCount = 0; chunk2.changeCount = 0; for (i = 0; i < diffSize; ++i) { diff_edit& e = diff[i]; if (e.op == DIFF_DELETE) { // Differences for Doc 1 checkWords(e, chunk1, chunk2); } else if (e.op == DIFF_INSERT) { // Differences for Doc2 checkWords(e, chunk2, chunk1); } } e1.changeCount = chunk1.changeCount; e1.changes = chunk1.changes; e2.changeCount = chunk2.changeCount; e2.changes = chunk2.changes; return (chunk1.changeCount + chunk2.changeCount > 0); }