Skip to content

Commit 3db95b1

Browse files
committed
more changes
1 parent 316370d commit 3db95b1

10 files changed

Lines changed: 1343 additions & 361 deletions

src/ColumnizerLib/ILogLine.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,25 @@ public interface ILogLine : ITextValue
3838
/// was replaced to better align with these performance and semantic requirements.
3939
/// </para>
4040
/// </remarks>
41-
public readonly struct LogLine (string fullLine, int lineNumber) : ILogLine
41+
public class LogLine (string fullLine, int lineNumber) : ILogLineMemory
4242
{
43-
public string FullLine { get; } = fullLine;
43+
private readonly ReadOnlyMemory<char> _lineMemory;
44+
private string _cachedString;
45+
46+
public LogLine (ReadOnlyMemory<char> lineMemory, int lineNumber) : this(lineMemory.ToString(), lineNumber)
47+
{
48+
FullLineMemory = lineMemory;
49+
LineNumber = lineNumber;
50+
}
51+
52+
public string FullLine => _cachedString ??= _lineMemory.ToString();
4453

4554
public int LineNumber { get; } = lineNumber;
4655

4756
public string Text => FullLine;
4857

58+
public ReadOnlyMemory<char> FullLineMemory { get; }
59+
4960
public override bool Equals (object obj)
5061
{
5162
return obj is LogLine other &&
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace ColumnizerLib;
2+
3+
public interface ILogLineMemory : ILogLine
4+
{
5+
ReadOnlyMemory<char> FullLineMemory { get; }
6+
}

src/LogExpert.Core/Classes/Log/LogBuffer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class LogBuffer
1414
private readonly IList<long> _filePositions = []; // file position for every line
1515
#endif
1616

17+
private readonly List<ILogLineMemory> _lineList = new();
18+
1719
private readonly IList<ILogLine> _logLines = [];
1820
private int MAX_LINES = 500;
1921
private long _size;

src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ public void Dispose ()
5959
public abstract string ReadLine ();
6060

6161
#endregion
62-
}
62+
}

src/LogExpert.Core/Classes/Log/LogfileReader.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start
10541054
var droppedLines = logBuffer.PrevBuffersDroppedLinesSum;
10551055
filePos = reader.Position;
10561056

1057-
while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + droppedLines, out var line))
1057+
while (ReadLineMemory(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + droppedLines, out var line))
10581058
{
10591059
if (_shouldStop)
10601060
{
@@ -1447,7 +1447,7 @@ private void ReReadBuffer (LogBuffer logBuffer)
14471447
var dropCount = logBuffer.PrevBuffersDroppedLinesSum;
14481448
logBuffer.ClearLines();
14491449

1450-
while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + dropCount, out var line))
1450+
while (ReadLineMemory(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + dropCount, out var line))
14511451
{
14521452
if (lineCount >= maxLinesCount)
14531453
{
@@ -1759,9 +1759,8 @@ private ILogStreamReader CreateLogStreamReader (Stream stream, EncodingOptions e
17591759
{
17601760
ReaderType.Legacy => new PositionAwareStreamReaderLegacy(stream, encodingOptions, _maximumLineLength),
17611761
ReaderType.System => new PositionAwareStreamReaderSystem(stream, encodingOptions, _maximumLineLength),
1762-
ReaderType.Pipeline => new PositionAwareStreamReaderPipeline(stream, encodingOptions, _maximumLineLength),
1763-
_ => //Default will be Pipeline
1764-
new PositionAwareStreamReaderPipeline(stream, encodingOptions, _maximumLineLength)
1762+
//Default will be System
1763+
_ => new PositionAwareStreamReaderSystem(stream, encodingOptions, _maximumLineLength),
17651764
};
17661765
}
17671766

@@ -1800,6 +1799,23 @@ private bool ReadLine (ILogStreamReader reader, int lineNum, int realLineNum, ou
18001799
return true;
18011800
}
18021801

1802+
private bool ReadLineMemory (ILogStreamReader reader, int lineNum, int realLineNum, out string outLine)
1803+
{
1804+
if (reader is ILogStreamReaderMemory memoryReader)
1805+
{
1806+
if (memoryReader.TryReadLine(out var lineMemory))
1807+
{
1808+
var line = lineMemory.ToString(); // Still converts to string
1809+
// ... preprocessing ...
1810+
memoryReader.ReturnMemory(lineMemory);
1811+
outLine = line;
1812+
return true;
1813+
}
1814+
}
1815+
1816+
return ReadLine(reader, lineNum, realLineNum, out outLine);
1817+
}
1818+
18031819
private void AcquireBufferListUpgradeableReadLock ()
18041820
{
18051821
if (!_bufferListLock.TryEnterUpgradeableReadLock(TimeSpan.FromSeconds(10)))

src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ namespace LogExpert.Core.Classes.Log;
66

77
public abstract class PositionAwareStreamReaderBase : LogStreamReaderBase
88
{
9-
#region Fields
109

11-
private static readonly Encoding[] _preambleEncodings = [Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode, Encoding.UTF32];
10+
#region Fields
1211

1312
private readonly BufferedStream _stream;
1413
private readonly StreamReader _reader;
@@ -18,19 +17,39 @@ public abstract class PositionAwareStreamReaderBase : LogStreamReaderBase
1817

1918
private long _position;
2019

20+
private static readonly Encoding[] _preambleEncodings =
21+
[
22+
Encoding.UTF8,
23+
Encoding.Unicode,
24+
Encoding.BigEndianUnicode,
25+
Encoding.UTF32
26+
];
27+
2128
#endregion
2229

2330
#region cTor
2431

2532
protected PositionAwareStreamReaderBase (Stream stream, EncodingOptions encodingOptions, int maximumLineLength)
2633
{
34+
ArgumentNullException.ThrowIfNull(stream);
35+
36+
if (!stream.CanRead)
37+
{
38+
throw new ArgumentException("Stream must support reading.", nameof(stream));
39+
}
40+
41+
if (!stream.CanSeek)
42+
{
43+
throw new ArgumentException("Stream must support seeking.", nameof(stream));
44+
}
45+
2746
_stream = new BufferedStream(stream);
2847

2948
MaximumLineLength = maximumLineLength;
3049

3150
_preambleLength = DetectPreambleLengthAndEncoding(out var detectedEncoding);
3251

33-
var usedEncoding = GetUsedEncoding(encodingOptions, detectedEncoding);
52+
var usedEncoding = DetermineEncoding(encodingOptions, detectedEncoding);
3453
_posIncPrecomputed = GetPosIncPrecomputed(usedEncoding);
3554

3655
_reader = new StreamReader(_stream, usedEncoding, true);
@@ -59,8 +78,8 @@ public sealed override long Position
5978
* always delivers a fixed length (does not mater what kind of data)
6079
*/
6180
_position = value; // +Encoding.GetPreamble().Length; // 1
62-
//stream.Seek(pos, SeekOrigin.Begin); // 2
63-
//stream.Seek(pos + Encoding.GetPreamble().Length, SeekOrigin.Begin); // 3
81+
//stream.Seek(pos, SeekOrigin.Begin); // 2
82+
//stream.Seek(pos + Encoding.GetPreamble().Length, SeekOrigin.Begin); // 3
6483
_ = _stream.Seek(_position + _preambleLength, SeekOrigin.Begin); // 4
6584

6685
ResetReader();
@@ -124,6 +143,8 @@ public override unsafe int ReadChar ()
124143
}
125144
}
126145

146+
147+
127148
protected virtual void ResetReader ()
128149
{
129150
_reader.DiscardBufferedData();
@@ -158,19 +179,42 @@ private int DetectPreambleLengthAndEncoding (out Encoding detectedEncoding)
158179
UTF-32-Little-Endian-Byteorder: FF FE 00 00
159180
*/
160181

161-
var readPreamble = new byte[4];
182+
var (length, encoding) = DetectPreambleLength(_stream);
183+
// not found or less than 2 byte read
184+
detectedEncoding = encoding;
185+
186+
return length;
187+
}
162188

163-
var readLen = _stream.Read(readPreamble, 0, 4);
189+
public static Encoding DetermineEncoding (EncodingOptions options, Encoding detectedEncoding)
190+
{
191+
return options?.Encoding != null
192+
? options.Encoding
193+
: detectedEncoding ?? options?.DefaultEncoding ?? Encoding.Default;
194+
}
164195

165-
if (readLen >= 2)
196+
public static (int length, Encoding? detectedEncoding) DetectPreambleLength (Stream stream)
197+
{
198+
if (!stream.CanSeek)
199+
{
200+
return (0, null);
201+
}
202+
203+
var originalPos = stream.Position;
204+
var buffer = new byte[4];
205+
_ = stream.Seek(0, SeekOrigin.Begin);
206+
var readBytes = stream.Read(buffer, 0, buffer.Length);
207+
_ = stream.Seek(originalPos, SeekOrigin.Begin);
208+
209+
if (readBytes >= 2)
166210
{
167211
foreach (var encoding in _preambleEncodings)
168212
{
169213
var preamble = encoding.GetPreamble();
170214
var fail = false;
171-
for (var i = 0; i < readLen && i < preamble.Length; ++i)
215+
for (var i = 0; i < readBytes && i < preamble.Length; ++i)
172216
{
173-
if (readPreamble[i] != preamble[i])
217+
if (buffer[i] != preamble[i])
174218
{
175219
fail = true;
176220
break;
@@ -179,26 +223,15 @@ private int DetectPreambleLengthAndEncoding (out Encoding detectedEncoding)
179223

180224
if (!fail)
181225
{
182-
detectedEncoding = encoding;
183-
return preamble.Length;
226+
return (preamble.Length, encoding);
184227
}
185228
}
186229
}
187230

188-
// not found or less than 2 byte read
189-
detectedEncoding = null;
190-
191-
return 0;
231+
return (0, null);
192232
}
193233

194-
private static Encoding GetUsedEncoding (EncodingOptions encodingOptions, Encoding detectedEncoding)
195-
{
196-
return encodingOptions.Encoding ??
197-
detectedEncoding ??
198-
encodingOptions.DefaultEncoding ??
199-
Encoding.Default;
200-
}
201-
private static int GetPosIncPrecomputed (Encoding usedEncoding)
234+
public static int GetPosIncPrecomputed (Encoding usedEncoding)
202235
{
203236
switch (usedEncoding)
204237
{

0 commit comments

Comments
 (0)