ircsharp/IRCTokens/StatefulDecoder.cs

89 lines
2.7 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2020-04-20 21:24:59 +00:00
using System.Linq;
using System.Text;
2020-05-15 03:06:10 +00:00
namespace IRCTokens
2020-04-20 21:24:59 +00:00
{
public class StatefulDecoder
{
private byte[] _buffer;
private Encoding _encoding;
private Encoding _fallback;
2020-04-20 21:24:59 +00:00
2020-04-28 04:35:52 +00:00
public StatefulDecoder()
{
Clear();
}
public Encoding Encoding
{
2020-04-22 14:50:30 +00:00
get => _encoding ?? Encoding.GetEncoding(Encoding.UTF8.CodePage, EncoderFallback.ExceptionFallback,
2020-04-28 04:35:52 +00:00
DecoderFallback.ExceptionFallback);
2020-04-22 14:50:30 +00:00
set
{
if (value != null)
_encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback,
DecoderFallback.ReplacementFallback);
}
}
public Encoding Fallback
{
2020-04-22 14:50:30 +00:00
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,
2020-04-22 14:50:30 +00:00
DecoderFallback.ReplacementFallback);
}
}
public string Pending => Encoding.GetString(_buffer);
2020-04-20 21:24:59 +00:00
public void Clear()
{
_buffer = Array.Empty<byte>();
2020-04-20 21:24:59 +00:00
}
public List<Line> Push(string data)
{
2020-04-29 01:07:23 +00:00
var bytes = Encoding.GetBytes(data);
return Push(bytes, bytes.Length);
}
2020-04-29 01:07:23 +00:00
public List<Line> Push(byte[] data, int bytesReceived)
{
2020-04-29 01:07:23 +00:00
if (data == null) return null;
2020-04-20 21:24:59 +00:00
2020-04-29 01:07:23 +00:00
_buffer = _buffer == null ? Array.Empty<byte>() : _buffer.Concat(data.Take(bytesReceived)).ToArray();
2020-05-17 02:08:40 +00:00
// truncate message at NUL if found
if (_buffer.Contains((byte) 0))
{
_buffer = _buffer
.Take(Array.IndexOf(_buffer, (byte) 0))
.Concat(new []{(byte) '\n'})
.ToArray();
}
2020-04-28 15:08:01 +00:00
var listLines = _buffer.Split((byte) '\n').Select(l => l.Trim((byte) '\r')).ToList();
2020-04-29 01:16:38 +00:00
_buffer = listLines.LastOrDefault() ?? Array.Empty<byte>();
2020-04-28 05:52:24 +00:00
var decodeLines = new List<Line>();
foreach (var line in listLines.SkipLast(1).Select(l => l.ToArray()))
try
{
2020-04-28 05:52:24 +00:00
decodeLines.Add(new Line(Encoding.GetString(line)));
}
catch (DecoderFallbackException)
{
2020-04-28 05:52:24 +00:00
decodeLines.Add(new Line(Fallback.GetString(line)));
}
2020-04-28 05:52:24 +00:00
return decodeLines;
2020-04-20 21:24:59 +00:00
}
}
}