Line data Source code
1 : #include "WordDiffSegmenter.h"
2 :
3 : namespace wikidiff2 {
4 :
5 : WordDiffSegmenter::PointerVector WordDiffSegmenter::empty;
6 :
7 0 : void WordDiffSegmenter::segment(WordDiff & diff)
8 : {
9 0 : WordDiff result;
10 0 : PointerVectorIterator pWord, segmentStart;
11 0 : result.edits.reserve(diff.size());
12 :
13 0 : for (int i = 0; i < diff.size(); i++) {
14 0 : DiffOp<Word> & edit = diff[i];
15 :
16 0 : if (edit.op == DiffOp<Word>::change) {
17 0 : segmentStart = edit.to.begin();
18 0 : bool isFirstSegment = true;
19 :
20 0 : for (pWord = edit.to.begin(); pWord != edit.to.end(); pWord++) {
21 0 : if ((*pWord)->isNewline()) {
22 0 : if (isFirstSegment) {
23 0 : isFirstSegment = false;
24 0 : if (pWord - segmentStart > 0) {
25 : // Emit the part from the start to the line break as a change op
26 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::change, edit.from, PointerVector(segmentStart, pWord)));
27 : } else {
28 : // Line break at the start of the RHS: emit the LHS as a delete op
29 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::del, edit.from, empty));
30 : }
31 : } else {
32 : // More than one line break: the whole LHS has already been emitted so we
33 : // just need to emit the RHS part not including the line break as an add op
34 0 : if (pWord - segmentStart > 0) {
35 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(segmentStart, pWord)));
36 : }
37 : }
38 : // Add the newline marker
39 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(pWord, pWord + 1)));
40 0 : segmentStart = pWord + 1;
41 : }
42 : }
43 :
44 0 : if (isFirstSegment) {
45 : // No line break detected
46 0 : result.add_edit(edit);
47 0 : } else if (pWord - segmentStart > 0) {
48 : // Emit the trailing part after the last line break
49 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(segmentStart, pWord)));
50 : }
51 0 : } else if (edit.op == DiffOp<Word>::add) {
52 0 : segmentStart = edit.to.begin();
53 0 : bool isFirstSegment = true;
54 :
55 0 : for (pWord = edit.to.begin(); pWord != edit.to.end(); pWord++) {
56 0 : if ((*pWord)->isNewline()) {
57 0 : isFirstSegment = false;
58 0 : if (pWord - segmentStart > 0) {
59 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(segmentStart, pWord)));
60 : }
61 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(pWord, pWord + 1)));
62 0 : segmentStart = pWord + 1;
63 : }
64 : }
65 :
66 0 : if (isFirstSegment) {
67 0 : result.add_edit(edit);
68 0 : } else if (pWord - segmentStart > 0) {
69 0 : result.add_edit(DiffOp<Word>(DiffOp<Word>::add, empty, PointerVector(segmentStart, pWord)));
70 : }
71 : } else {
72 0 : result.add_edit(edit);
73 : }
74 : }
75 0 : diff.swap(result);
76 0 : }
77 :
78 : } // namespace wikidiff2
|