Skip to content

Commit d763fc9

Browse files
committed
fix #152
1 parent ae74246 commit d763fc9

2 files changed

Lines changed: 61 additions & 25 deletions

File tree

DiffPlex/Chunkers/LineEndingsPreservingChunker.cs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
22

33
namespace DiffPlex.Chunkers
44
{
55
public class LineEndingsPreservingChunker:IChunker
66
{
7-
private readonly string[] emptyArray = new string[0];
7+
private static readonly string[] EmptyArray = new string[0];
88

99
/// <summary>
1010
/// Gets the default singleton instance of the chunker.
@@ -14,37 +14,39 @@ public class LineEndingsPreservingChunker:IChunker
1414
public IReadOnlyList<string> Chunk(string text)
1515
{
1616
if (string.IsNullOrEmpty(text))
17-
return emptyArray;
17+
return EmptyArray;
1818

1919
var output = new List<string>();
2020
var lastCut = 0;
21-
for (var currentPosition = 0; currentPosition < text.Length; currentPosition++)
21+
22+
for (int i = 0; i < text.Length; i++)
2223
{
23-
char ch = text[currentPosition];
24-
switch (ch)
24+
int lineEndLen = 0;
25+
26+
if (text[i] == '\r')
2527
{
26-
case '\n':
27-
case '\r':
28-
currentPosition++;
29-
if (ch == '\r' && currentPosition < text.Length && text[currentPosition] == '\n')
30-
{
31-
currentPosition++;
32-
}
33-
var str = text.Substring(lastCut, currentPosition - lastCut);
34-
lastCut = currentPosition;
35-
output.Add(str);
36-
break;
37-
default:
38-
continue;
28+
lineEndLen = 1;
29+
if (i + 1 < text.Length && text[i + 1] == '\n')
30+
lineEndLen = 2; // CRLF
31+
}
32+
else if (text[i] == '\n')
33+
{
34+
lineEndLen = 1; // LF
3935
}
40-
}
4136

42-
if (lastCut != text.Length)
43-
{
44-
var str = text.Substring(lastCut, text.Length - lastCut);
45-
output.Add(str);
37+
if (lineEndLen > 0)
38+
{
39+
int sliceLen = i - lastCut + lineEndLen;
40+
output.Add(text.Substring(lastCut, sliceLen));
41+
42+
i += lineEndLen - 1; // we already consumed them
43+
lastCut += sliceLen;
44+
}
4645
}
4746

47+
if (lastCut != text.Length) // trailing line without EOL
48+
output.Add(text.Substring(lastCut));
49+
4850
return output;
4951
}
5052
}

Facts.DiffPlex/Chunkers/LineEndingsPreservingChunkerFacts.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using DiffPlex.Chunkers;
1+
using DiffPlex.Chunkers;
22
using Xunit;
33

44
namespace Facts.DiffPlex.Chunkers
@@ -74,5 +74,39 @@ public void should_split_when_different_line_ending()
7474
Assert.Equal("Second\r", chunks[2]);
7575
Assert.Equal("Last", chunks[3]);
7676
}
77+
78+
[Fact]
79+
public void should_preserve_empty_lines_with_lf()
80+
{
81+
//ARRANGE
82+
var chunker = new LineEndingsPreservingChunker();
83+
var sampleText = "Line1\n\nLine2";
84+
85+
//ACT
86+
var chunks = chunker.Chunk(sampleText);
87+
88+
//ASSERT
89+
Assert.Equal(3, chunks.Count);
90+
Assert.Equal("Line1\n", chunks[0]);
91+
Assert.Equal("\n", chunks[1]);
92+
Assert.Equal("Line2", chunks[2]);
93+
}
94+
95+
[Fact]
96+
public void should_preserve_empty_lines_with_cr()
97+
{
98+
//ARRANGE
99+
var chunker = new LineEndingsPreservingChunker();
100+
var sampleText = "Line1\r\rLine2";
101+
102+
//ACT
103+
var chunks = chunker.Chunk(sampleText);
104+
105+
//ASSERT
106+
Assert.Equal(3, chunks.Count);
107+
Assert.Equal("Line1\r", chunks[0]);
108+
Assert.Equal("\r", chunks[1]);
109+
Assert.Equal("Line2", chunks[2]);
110+
}
77111
}
78112
}

0 commit comments

Comments
 (0)