-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathStreamExtensions.cs
128 lines (115 loc) · 4.94 KB
/
StreamExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
namespace Easy.Common.Extensions
{
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
/// <summary>
/// A set of extension methods for <see cref="Stream"/>.
/// </summary>
public static class StreamExtensions
{
private const char CR = '\r';
private const char LF = '\n';
private const char NULL = (char)0;
/// <summary>
/// Returns the number of lines in the given <paramref name="stream"/>.
/// </summary>
[DebuggerStepThrough]
public static long CountLines(this Stream stream, Encoding encoding = default)
{
Ensure.NotNull(stream, nameof(stream));
var lineCount = 0L;
var byteBuffer = new byte[1024 * 1024];
var detectedEOL = NULL;
var currentChar = NULL;
int bytesRead;
if (encoding is null || Equals(encoding, Encoding.ASCII) || Equals(encoding, Encoding.UTF8))
{
while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
for (var i = 0; i < bytesRead; i++)
{
currentChar = (char)byteBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL)
{
lineCount++;
}
}
else if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
}
}
}
else
{
var charBuffer = new char[byteBuffer.Length];
while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
var charCount = encoding.GetChars(byteBuffer, 0, bytesRead, charBuffer, 0);
for (var i = 0; i < charCount; i++)
{
currentChar = charBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL)
{
lineCount++;
}
}
else if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
}
}
}
if (currentChar != LF && currentChar != CR && currentChar != NULL)
{
lineCount++;
}
return lineCount;
}
/// <summary>
/// Gets a sequence containing every element with the name equal to <paramref name="name"/>.
/// </summary>
/// <param name="stream">The stream containing XML</param>
/// <param name="name">The name of the elements to return</param>
/// <param name="ignoreCase">The flag indicating whether the name should be looked up in a case sensitive manner</param>
/// <returns>The sequence containing all the elements <see cref="XElement"/> matching the <paramref name="name"/></returns>
[DebuggerStepThrough]
public static IEnumerable<XElement> GetElements(this Stream stream, XName name, bool ignoreCase = true)
{
Ensure.NotNull(stream, nameof(stream));
return stream.GetElements(name, new XmlReaderSettings(), ignoreCase);
}
/// <summary>
/// Gets a sequence containing every element with the name equal to <paramref name="name"/>.
/// </summary>
/// <param name="stream">The stream containing XML</param>
/// <param name="name">The name of the elements to return</param>
/// <param name="settings">The settings used by the <see cref="XmlReader"/></param>
/// <param name="ignoreCase">The flag indicating whether the name should be looked up in a case sensitive manner</param>
/// <returns>The sequence containing all the elements <see cref="XElement"/> matching the <paramref name="name"/></returns>
[DebuggerStepThrough]
public static IEnumerable<XElement> GetElements(this Stream stream, XName name, XmlReaderSettings settings, bool ignoreCase = true)
{
Ensure.NotNull(stream, nameof(stream));
Ensure.NotNull(name, nameof(name));
Ensure.NotNull(settings, nameof(settings));
using var reader = XmlReader.Create(stream, settings);
foreach (var xElement in reader.GetEelements(name, ignoreCase))
{
yield return xElement;
}
}
}
}