107 lines
3.0 KiB
C#
107 lines
3.0 KiB
C#
using System;
|
|
using System.Threading;
|
|
|
|
namespace NadekoBot.Common.Collections
|
|
{
|
|
public class PoopyRingBuffer : IDisposable
|
|
{
|
|
// readpos == writepos means empty
|
|
// writepos == readpos - 1 means full
|
|
|
|
private byte[] _buffer;
|
|
public int Capacity { get; }
|
|
|
|
private int ReadPos { get; set; } = 0;
|
|
private int WritePos { get; set; } = 0;
|
|
|
|
public int Length => ReadPos <= WritePos
|
|
? WritePos - ReadPos
|
|
: Capacity - (ReadPos - WritePos);
|
|
|
|
public int RemainingCapacity
|
|
{
|
|
get => Capacity - Length - 1;
|
|
}
|
|
|
|
private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
|
|
|
|
public PoopyRingBuffer(int capacity = 81920 * 100)
|
|
{
|
|
this.Capacity = capacity + 1;
|
|
this._buffer = new byte[this.Capacity];
|
|
}
|
|
|
|
public int Read(byte[] b, int offset, int toRead)
|
|
{
|
|
if (WritePos == ReadPos)
|
|
return 0;
|
|
|
|
if (toRead > Length)
|
|
toRead = Length;
|
|
|
|
if (WritePos > ReadPos)
|
|
{
|
|
Array.Copy(_buffer, ReadPos, b, offset, toRead);
|
|
ReadPos += toRead;
|
|
}
|
|
else
|
|
{
|
|
var toEnd = Capacity - ReadPos;
|
|
var firstRead = toRead > toEnd ?
|
|
toEnd :
|
|
toRead;
|
|
Array.Copy(_buffer, ReadPos, b, offset, firstRead);
|
|
ReadPos += firstRead;
|
|
var secondRead = toRead - firstRead;
|
|
if (secondRead > 0)
|
|
{
|
|
Array.Copy(_buffer, 0, b, offset + firstRead, secondRead);
|
|
ReadPos = secondRead;
|
|
}
|
|
}
|
|
return toRead;
|
|
}
|
|
|
|
public bool Write(byte[] b, int offset, int toWrite)
|
|
{
|
|
while (toWrite > RemainingCapacity)
|
|
return false;
|
|
|
|
if (toWrite == 0)
|
|
return true;
|
|
|
|
if (WritePos < ReadPos)
|
|
{
|
|
Array.Copy(b, offset, _buffer, WritePos, toWrite);
|
|
WritePos += toWrite;
|
|
}
|
|
else
|
|
{
|
|
var toEnd = Capacity - WritePos;
|
|
var firstWrite = toWrite > toEnd ?
|
|
toEnd :
|
|
toWrite;
|
|
Array.Copy(b, offset, _buffer, WritePos, firstWrite);
|
|
var secondWrite = toWrite - firstWrite;
|
|
if (secondWrite > 0)
|
|
{
|
|
Array.Copy(b, offset + firstWrite, _buffer, 0, secondWrite);
|
|
WritePos = secondWrite;
|
|
}
|
|
else
|
|
{
|
|
WritePos += firstWrite;
|
|
if (WritePos == Capacity)
|
|
WritePos = 0;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_buffer = null;
|
|
}
|
|
}
|
|
}
|