Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/LogExpert.Configuration/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ public void AddToFileHistory (string fileName)
Save(SettingsFlags.FileHistory);
}

[SupportedOSPlatform("windows")]
public void RemoveFromFileHistory (string fileName)
{
bool findName (string s) => s.ToUpperInvariant().Equals(fileName.ToUpperInvariant(), StringComparison.Ordinal);

var index = Instance.Settings.FileHistoryList.FindIndex(findName);

if (index != -1)
{
Instance.Settings.FileHistoryList.RemoveAt(index);
}

Save(SettingsFlags.FileHistory);
}


public void ClearLastOpenFilesList ()
{
lock (_loadSaveLock)
Expand Down
36 changes: 14 additions & 22 deletions src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ protected PositionAwareStreamReaderBase (Stream stream, EncodingOptions encoding

MaximumLineLength = maximumLineLength;

_preambleLength = DetectPreambleLengthAndEncoding(out var detectedEncoding);
(_preambleLength, Encoding? detectedEncoding) = DetectPreambleLength(_stream);

var usedEncoding = DetermineEncoding(encodingOptions, detectedEncoding);
_posIncPrecomputed = GetPosIncPrecomputed(usedEncoding);
Expand Down Expand Up @@ -165,11 +165,19 @@ protected void MovePosition (int offset)

#region Private Methods

public static Encoding DetermineEncoding (EncodingOptions options, Encoding detectedEncoding)
{
return options?.Encoding != null
? options.Encoding
: detectedEncoding ?? options?.DefaultEncoding ?? Encoding.Default;
}

/// <summary>
/// Determines the actual number of preamble bytes in the file.
/// Determines the actual number of preamble bytes in the file and the Encoding.
/// </summary>
/// <returns>Number of preamble bytes in the file</returns>
private int DetectPreambleLengthAndEncoding (out Encoding detectedEncoding)
/// <param name="stream"></param>
/// <returns>Number of preamble bytes in the file and the Encoding if there is one</returns>
public static (int length, Encoding? detectedEncoding) DetectPreambleLength (Stream stream)
{
/*
UTF-8: EF BB BF
Expand All @@ -179,31 +187,15 @@ private int DetectPreambleLengthAndEncoding (out Encoding detectedEncoding)
UTF-32-Little-Endian-Byteorder: FF FE 00 00
*/

var (length, encoding) = DetectPreambleLength(_stream);
// not found or less than 2 byte read
detectedEncoding = encoding;

return length;
}

public static Encoding DetermineEncoding (EncodingOptions options, Encoding detectedEncoding)
{
return options?.Encoding != null
? options.Encoding
: detectedEncoding ?? options?.DefaultEncoding ?? Encoding.Default;
}

public static (int length, Encoding? detectedEncoding) DetectPreambleLength (Stream stream)
{
if (!stream.CanSeek)
{
return (0, null);
}

var originalPos = stream.Position;
var buffer = new byte[4];
Span<byte> buffer = stackalloc byte[4];
_ = stream.Seek(0, SeekOrigin.Begin);
var readBytes = stream.Read(buffer, 0, buffer.Length);
var readBytes = stream.Read(buffer);
_ = stream.Seek(originalPos, SeekOrigin.Begin);

if (readBytes >= 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,15 @@ private int GuessNewLineSequenceLength (StreamReader reader)
var secondChar = reader.Read();
if (secondChar == CHAR_LF) // check \n
{
return Encoding.GetByteCount("\r\n");
// Use stackalloc or SpanOwner instead of string
Span<char> newline = ['\r', '\n'];
return Encoding.GetByteCount(newline);
//return Encoding.GetByteCount("\r\n");
}
}

return Encoding.GetByteCount(((char)firstChar).ToString());
Span<char> singleChar = [(char)firstChar];
return Encoding.GetByteCount(singleChar);
}

return 0;
Expand Down
6 changes: 6 additions & 0 deletions src/LogExpert.Core/Interface/IConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ public interface IConfigManager
/// This method is supported only on Windows platforms.</remarks>
/// <param name="fileName">The name of the file to add to the file history list. Comparison is case-insensitive.</param>
void AddToFileHistory (string fileName);

/// <summary>
/// Removes the specified file name from the file history list.
/// </summary>
/// <param name="fileName">The name of the file to remove from the file history list. Comparison is case-insensitive.</param>
void RemoveFromFileHistory (string fileName);

/// <summary>
/// Clears the list of recently opened files.
Expand Down
35 changes: 29 additions & 6 deletions src/LogExpert.Tests/Services/LedIndicatorServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Runtime.Versioning;

using LogExpert.UI.Services;
using LogExpert.UI.Interface.Services;
using LogExpert.UI.Services.LedService;

using NUnit.Framework;

Expand All @@ -9,11 +10,12 @@ namespace LogExpert.Tests.Services;
[TestFixture]
[Apartment(ApartmentState.STA)] // Required for UI components
[SupportedOSPlatform("windows")]
public class LedIndicatorServiceTests
public class LedIndicatorServiceTests : IDisposable
{
private LedIndicatorService? _service;
private ApplicationContext? _appContext;
private WindowsFormsSynchronizationContext? _syncContext;
private bool _disposed;

[SetUp]
public void Setup ()
Expand Down Expand Up @@ -140,9 +142,9 @@ public void StartStop_DoesNotThrowException ()
_service!.Initialize(Color.Blue);

// Act
_service.Start();
_service.StartService();
Thread.Sleep(500); // Let timer tick a few times
_service.Stop();
_service.StopService();

// Assert - no exception
Assert.That(true, Is.True, "Service started and stopped without exceptions");
Expand Down Expand Up @@ -192,7 +194,7 @@ public void Dispose_DisposesAllResources ()
{
// Arrange
_service!.Initialize(Color.Blue);
_service.Start();
_service.StartService();

// Act
_service.Dispose();
Expand All @@ -217,7 +219,7 @@ public void Start_WithoutInitialize_ThrowsException ()
// Arrange - don't initialize

// Act & Assert
_ = Assert.Throws<InvalidOperationException>(() => _service!.Start());
_ = Assert.Throws<InvalidOperationException>(() => _service!.StartService());
}

[Test]
Expand Down Expand Up @@ -316,4 +318,25 @@ public void GetIcon_WithSyncedState_ReturnsSyncedIcon ()
// The icons should be different (synced has blue indicator on left side)
Assert.That(iconSynced, Is.Not.EqualTo(iconNotSynced));
}

public void Dispose ()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose (bool disposing)
{
if (_disposed)
{
return;
}

if (disposing)
{
_service?.Dispose();
}

_disposed = true;
}
}
Loading