@@ -12,133 +12,170 @@ This Source Code Form is subject to the terms of the
1212
1313namespace 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