NadekoBot/NadekoBot.Core/Common/Collections/PoopyRingBuffer.cs

107 lines
3.0 KiB
C#
Raw Normal View History

using System;
using System.Threading;
2017-07-17 19:42:36 +00:00
namespace NadekoBot.Common.Collections
{
public class PoopyRingBuffer : IDisposable
{
// readpos == writepos means empty
// writepos == readpos - 1 means full
2017-07-17 19:42:36 +00:00
private byte[] _buffer;
public int Capacity { get; }
2017-07-17 19:42:36 +00:00
private int ReadPos { get; set; } = 0;
private int WritePos { get; set; } = 0;
2017-07-03 18:26:17 +00:00
public int Length => ReadPos <= WritePos
? WritePos - ReadPos
: Capacity - (ReadPos - WritePos);
public int RemainingCapacity
{
2017-07-03 18:26:17 +00:00
get => Capacity - Length - 1;
}
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
2017-07-03 21:27:17 +00:00
public PoopyRingBuffer(int capacity = 81920 * 100)
{
this.Capacity = capacity + 1;
2017-07-17 19:42:36 +00:00
this._buffer = new byte[this.Capacity];
}
2017-07-03 18:26:17 +00:00
public int Read(byte[] b, int offset, int toRead)
{
2017-07-03 18:26:17 +00:00
if (WritePos == ReadPos)
return 0;
2017-07-03 18:26:17 +00:00
if (toRead > Length)
toRead = Length;
2017-07-03 18:26:17 +00:00
if (WritePos > ReadPos)
{
2017-07-17 19:42:36 +00:00
Array.Copy(_buffer, ReadPos, b, offset, toRead);
2017-07-03 18:26:17 +00:00
ReadPos += toRead;
}
2017-07-03 18:26:17 +00:00
else
{
2017-07-03 18:26:17 +00:00
var toEnd = Capacity - ReadPos;
var firstRead = toRead > toEnd ?
toEnd :
toRead;
2017-07-17 19:42:36 +00:00
Array.Copy(_buffer, ReadPos, b, offset, firstRead);
2017-07-03 18:26:17 +00:00
ReadPos += firstRead;
var secondRead = toRead - firstRead;
if (secondRead > 0)
{
2017-07-17 19:42:36 +00:00
Array.Copy(_buffer, 0, b, offset + firstRead, secondRead);
2017-07-03 18:26:17 +00:00
ReadPos = secondRead;
}
}
2017-07-03 18:26:17 +00:00
return toRead;
}
2017-07-03 18:26:17 +00:00
public bool Write(byte[] b, int offset, int toWrite)
{
while (toWrite > RemainingCapacity)
2017-07-03 18:26:17 +00:00
return false;
2017-07-02 11:53:09 +00:00
if (toWrite == 0)
2017-07-03 18:26:17 +00:00
return true;
2017-07-03 18:26:17 +00:00
if (WritePos < ReadPos)
{
2017-07-17 19:42:36 +00:00
Array.Copy(b, offset, _buffer, WritePos, toWrite);
2017-07-03 18:26:17 +00:00
WritePos += toWrite;
}
else
{
var toEnd = Capacity - WritePos;
var firstWrite = toWrite > toEnd ?
toEnd :
toWrite;
2017-07-17 19:42:36 +00:00
Array.Copy(b, offset, _buffer, WritePos, firstWrite);
2017-07-03 18:26:17 +00:00
var secondWrite = toWrite - firstWrite;
if (secondWrite > 0)
{
2017-07-17 19:42:36 +00:00
Array.Copy(b, offset + firstWrite, _buffer, 0, secondWrite);
2017-07-03 18:26:17 +00:00
WritePos = secondWrite;
}
else
{
2017-07-03 18:26:17 +00:00
WritePos += firstWrite;
if (WritePos == Capacity)
WritePos = 0;
}
}
2017-07-03 18:26:17 +00:00
return true;
}
public void Dispose()
{
2017-07-17 19:42:36 +00:00
_buffer = null;
}
}
}