Skip to content

Commit a5a45e2

Browse files
committed
some
1 parent 3845405 commit a5a45e2

File tree

1 file changed

+114
-77
lines changed

1 file changed

+114
-77
lines changed

src/OneScript.StandardLibrary/CustomLineFeedStreamReader.cs

Lines changed: 114 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -12,133 +12,170 @@ This Source Code Form is subject to the terms of the
1212

1313
namespace OneScript.StandardLibrary
1414
{
15-
1615
public class CustomLineFeedStreamReader : IDisposable
1716
{
1817
private TextReader _reader;
1918
private readonly string _eolDelimiter;
20-
private Queue<char> _buffer = new Queue<char> ();
21-
private bool _analyzeDefaults = false;
19+
private readonly char[] _buffer;
20+
private int _bufferPosition;
21+
private int _bufferLength;
22+
private bool _analyzeDefaults;
23+
24+
private const int DefaultBufferSize = 4096;
2225

23-
public CustomLineFeedStreamReader (TextReader underlyingReader, string eolDelimiter, bool analyzeDefaults)
26+
public CustomLineFeedStreamReader(TextReader underlyingReader, string eolDelimiter, bool analyzeDefaults)
2427
{
25-
if(underlyingReader == null)
26-
throw new ArgumentNullException(nameof(underlyingReader));
27-
if(eolDelimiter == null)
28-
throw new ArgumentNullException(nameof(eolDelimiter));
28+
_reader = underlyingReader ?? throw new ArgumentNullException(nameof(underlyingReader));
29+
_eolDelimiter = eolDelimiter ?? throw new ArgumentNullException(nameof(eolDelimiter));
2930

30-
_reader = underlyingReader;
31-
_eolDelimiter = eolDelimiter;
31+
_buffer = new char[Math.Max(DefaultBufferSize, eolDelimiter.Length * 2)];
32+
_bufferPosition = 0;
33+
_bufferLength = 0;
3234
_analyzeDefaults = analyzeDefaults;
3335
}
3436

35-
private void UpdateCharQueue (int minimalLentgh = 1)
37+
private void EnsureBuffer(int minimalLength)
3638
{
37-
while (_buffer.Count < minimalLentgh) {
38-
int ic = _reader.Read ();
39-
if (ic == -1)
40-
break;
41-
_buffer.Enqueue ((char)ic);
39+
if (_bufferPosition + minimalLength <= _bufferLength)
40+
return;
41+
42+
// Сдвигаем оставшиеся символы в начало буфера
43+
if (_bufferPosition > 0)
44+
{
45+
Array.Copy(_buffer, _bufferPosition, _buffer, 0, _bufferLength - _bufferPosition);
46+
_bufferLength -= _bufferPosition;
47+
_bufferPosition = 0;
48+
}
49+
50+
// Читаем новые символы
51+
while (_bufferLength < _buffer.Length && _bufferLength < minimalLength)
52+
{
53+
int readCount = _reader.Read(_buffer, _bufferLength, _buffer.Length - _bufferLength);
54+
if (readCount == 0) break;
55+
_bufferLength += readCount;
4256
}
4357
}
4458

45-
public int Read ()
59+
public int Read()
4660
{
47-
if (_buffer.Count == 0)
61+
if (_bufferPosition >= _bufferLength)
4862
{
49-
UpdateCharQueue ();
50-
if (_buffer.Count == 0)
63+
EnsureBuffer(1);
64+
if (_bufferPosition >= _bufferLength)
5165
return -1;
5266
}
5367

54-
if (_analyzeDefaults && _buffer.Peek () == '\r') {
68+
char currentChar = _buffer[_bufferPosition];
5569

56-
_buffer.Dequeue ();
57-
UpdateCharQueue ();
70+
// Обработка стандартных разделителей строк
71+
if (_analyzeDefaults && currentChar == '\r')
72+
{
73+
_bufferPosition++;
74+
EnsureBuffer(1);
5875

59-
if (_buffer.Count > 0 && _buffer.Peek () == '\n') {
60-
_buffer.Dequeue ();
61-
UpdateCharQueue ();
76+
if (_bufferPosition < _bufferLength && _buffer[_bufferPosition] == '\n')
77+
{
78+
_bufferPosition++;
79+
return '\n';
6280
}
63-
6481
return '\n';
6582
}
6683

67-
if (_eolDelimiter.Length > 0 && _buffer.Peek() == _eolDelimiter [0])
84+
// Проверка пользовательского разделителя
85+
if (_eolDelimiter.Length > 0 && currentChar == _eolDelimiter[0])
6886
{
69-
UpdateCharQueue (_eolDelimiter.Length);
70-
71-
var eolIndex = 0;
72-
foreach (var bufChar in _buffer)
87+
if (CheckEolDelimiter())
7388
{
74-
if (bufChar != _eolDelimiter[eolIndex])
75-
break;
76-
77-
++eolIndex;
78-
79-
if (eolIndex == _eolDelimiter.Length)
80-
{
81-
while (eolIndex > 0)
82-
{
83-
_buffer.Dequeue();
84-
--eolIndex;
85-
}
86-
87-
return '\n';
88-
}
89+
return '\n';
8990
}
9091
}
9192

92-
return _buffer.Dequeue ();
93+
_bufferPosition++;
94+
return currentChar;
9395
}
9496

95-
public string ReadUntil(string endOfString, out bool eosMet)
97+
private bool CheckEolDelimiter()
9698
{
97-
var sb = new StringBuilder ();
98-
eosMet = false;
99+
EnsureBuffer(_eolDelimiter.Length);
99100

100-
while (!eosMet) {
101-
var ic = Read ();
102-
if (ic == -1) {
103-
break;
104-
}
101+
if (_bufferPosition + _eolDelimiter.Length > _bufferLength)
102+
return false;
105103

106-
var c = (char)ic;
104+
for (int i = 0; i < _eolDelimiter.Length; i++)
105+
{
106+
if (_buffer[_bufferPosition + i] != _eolDelimiter[i])
107+
return false;
108+
}
107109

108-
sb.Append (c);
110+
_bufferPosition += _eolDelimiter.Length;
111+
return true;
112+
}
113+
114+
public string ReadUntil(string endOfString, out bool eosMet)
115+
{
116+
if (string.IsNullOrEmpty(endOfString))
117+
{
118+
eosMet = false;
119+
return ReadToEnd();
120+
}
109121

110-
if (endOfString.Length > 0 && c == endOfString [endOfString.Length - 1]) {
111-
if (sb.Length >= endOfString.Length) {
122+
var sb = new StringBuilder();
123+
eosMet = false;
124+
125+
while (!eosMet)
126+
{
127+
int ic = Read();
128+
if (ic == -1) break;
112129

113-
var substring = sb.ToString (sb.Length - endOfString.Length, endOfString.Length);
114-
if (substring.Equals (endOfString, StringComparison.InvariantCulture)) {
115-
eosMet = true;
116-
sb.Remove (sb.Length - endOfString.Length, endOfString.Length);
117-
}
130+
char c = (char)ic;
131+
sb.Append(c);
118132

133+
// Оптимизированная проверка окончания строки
134+
if (c == endOfString[endOfString.Length - 1] && sb.Length >= endOfString.Length)
135+
{
136+
if (EndsWith(sb, endOfString))
137+
{
138+
eosMet = true;
139+
sb.Length -= endOfString.Length;
119140
}
120141
}
121142
}
122143

123-
if (sb.Length == 0 && !eosMet)
124-
return null;
125-
return sb.ToString ();
144+
return sb.Length == 0 && !eosMet ? null : sb.ToString();
126145
}
127146

128-
public string ReadLine (string lineDelimiter)
147+
private bool EndsWith(StringBuilder sb, string endString)
129148
{
130-
bool eol;
131-
var l = ReadUntil (lineDelimiter, out eol);
132-
return l;
149+
int startIndex = sb.Length - endString.Length;
150+
for (int i = 0; i < endString.Length; i++)
151+
{
152+
if (sb[startIndex + i] != endString[i])
153+
return false;
154+
}
155+
return true;
133156
}
134157

135-
public void Dispose ()
158+
public string ReadLine(string lineDelimiter)
136159
{
137-
if (_reader != null) {
138-
_reader.Dispose ();
139-
_reader = null;
160+
bool eol;
161+
return ReadUntil(lineDelimiter, out eol);
162+
}
163+
164+
public string ReadToEnd()
165+
{
166+
var sb = new StringBuilder();
167+
int ch;
168+
while ((ch = Read()) != -1)
169+
{
170+
sb.Append((char)ch);
140171
}
172+
return sb.ToString();
173+
}
174+
175+
public void Dispose()
176+
{
177+
_reader?.Dispose();
178+
_reader = null;
141179
}
142180
}
143-
144181
}

0 commit comments

Comments
 (0)