ircsharp/IRCTokens/StatefulDecoder.cs

80 lines
2.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IRCTokens
{
public class StatefulDecoder
{
private byte[] _buffer;
private Encoding _encoding;
private Encoding _fallback;
public StatefulDecoder()
{
Clear();
}
public Encoding Encoding
{
get => _encoding ?? Encoding.GetEncoding(Encoding.UTF8.CodePage, EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
set
{
if (value != null)
_encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback,
DecoderFallback.ReplacementFallback);
}
}
public Encoding Fallback
{
get => _fallback ?? Encoding.GetEncoding(Encoding.GetEncoding("iso-8859-1").CodePage,
EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
set
{
if (value != null)
_fallback = Encoding.GetEncoding(value.CodePage, EncoderFallback.ReplacementFallback,
DecoderFallback.ReplacementFallback);
}
}
public string Pending => Encoding.GetString(_buffer);
public void Clear()
{
_buffer = Array.Empty<byte>();
}
public List<Line> Push(string data)
{
var bytes = Encoding.GetBytes(data);
return Push(bytes, bytes.Length);
}
public List<Line> Push(byte[] data, int bytesReceived)
{
if (data == null) return null;
_buffer = _buffer == null ? Array.Empty<byte>() : _buffer.Concat(data.Take(bytesReceived)).ToArray();
var listLines = _buffer.Split((byte) '\n').Select(l => l.Trim((byte) '\r')).ToList();
_buffer = listLines.LastOrDefault() ?? Array.Empty<byte>();
var decodeLines = new List<Line>();
foreach (var line in listLines.SkipLast(1).Select(l => l.ToArray()))
try
{
decodeLines.Add(new Line(Encoding.GetString(line)));
}
catch (DecoderFallbackException)
{
decodeLines.Add(new Line(Fallback.GetString(line)));
}
return decodeLines;
}
}
}