2017-04-02 00:36:06 +00:00
|
|
|
using System;
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
namespace SharpCifs.Util.Sharpen
|
|
|
|
{
|
2017-06-21 06:46:57 +00:00
|
|
|
internal class PipedInputStream : InputStream
|
|
|
|
{
|
|
|
|
private byte[] _oneBuffer;
|
|
|
|
public const int PipeSize = 1024;
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
protected byte[] Buffer;
|
|
|
|
private bool _closed;
|
|
|
|
private ManualResetEvent _dataEvent;
|
|
|
|
private int _end;
|
|
|
|
private int _start;
|
|
|
|
private object _thisLock;
|
|
|
|
private bool _allowGrow = false;
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
public int In
|
|
|
|
{
|
|
|
|
get { return _start; }
|
|
|
|
set { _start = value; }
|
|
|
|
}
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
public int Out
|
|
|
|
{
|
|
|
|
get { return _end; }
|
|
|
|
set { _end = value; }
|
|
|
|
}
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
public PipedInputStream()
|
|
|
|
{
|
|
|
|
_thisLock = new object();
|
|
|
|
_dataEvent = new ManualResetEvent(false);
|
|
|
|
Buffer = new byte[PipeSize + 1];
|
|
|
|
}
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
public PipedInputStream(PipedOutputStream os) : this()
|
|
|
|
{
|
|
|
|
os.Attach(this);
|
|
|
|
}
|
2017-04-02 00:36:06 +00:00
|
|
|
|
2017-06-21 06:46:57 +00:00
|
|
|
public override void Close()
|
|
|
|
{
|
|
|
|
lock (_thisLock)
|
|
|
|
{
|
|
|
|
_closed = true;
|
|
|
|
_dataEvent.Set();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override int Available()
|
|
|
|
{
|
|
|
|
lock (_thisLock)
|
|
|
|
{
|
|
|
|
if (_start <= _end)
|
|
|
|
{
|
|
|
|
return (_end - _start);
|
|
|
|
}
|
|
|
|
return ((Buffer.Length - _start) + _end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override int Read()
|
|
|
|
{
|
|
|
|
if (_oneBuffer == null)
|
|
|
|
_oneBuffer = new byte[1];
|
|
|
|
if (Read(_oneBuffer, 0, 1) == -1)
|
|
|
|
return -1;
|
|
|
|
return _oneBuffer[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
public override int Read(byte[] b, int offset, int len)
|
|
|
|
{
|
|
|
|
int length = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
_dataEvent.WaitOne();
|
|
|
|
lock (_thisLock)
|
|
|
|
{
|
|
|
|
if (_closed && Available() == 0)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (_start < _end)
|
|
|
|
{
|
|
|
|
length = Math.Min(len, _end - _start);
|
|
|
|
Array.Copy(Buffer, _start, b, offset, length);
|
|
|
|
_start += length;
|
|
|
|
}
|
|
|
|
else if (_start > _end)
|
|
|
|
{
|
|
|
|
length = Math.Min(len, Buffer.Length - _start);
|
|
|
|
Array.Copy(Buffer, _start, b, offset, length);
|
|
|
|
len -= length;
|
|
|
|
_start = (_start + length) % Buffer.Length;
|
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
int i = Math.Min(len, _end);
|
|
|
|
Array.Copy(Buffer, 0, b, offset + length, i);
|
|
|
|
_start += i;
|
|
|
|
length += i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_start == _end && !_closed)
|
|
|
|
{
|
|
|
|
_dataEvent.Reset();
|
|
|
|
}
|
|
|
|
Monitor.PulseAll(_thisLock);
|
|
|
|
}
|
|
|
|
} while (length == 0);
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
private int Allocate(int len)
|
|
|
|
{
|
|
|
|
int alen;
|
|
|
|
while ((alen = TryAllocate(len)) == 0)
|
|
|
|
{
|
|
|
|
// Wait until somebody reads data
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Monitor.Wait(_thisLock);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
_closed = true;
|
|
|
|
_dataEvent.Set();
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return alen;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TryAllocate(int len)
|
|
|
|
{
|
|
|
|
int free;
|
|
|
|
if (_start <= _end)
|
|
|
|
{
|
|
|
|
free = (Buffer.Length - _end) + _start;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free = _start - _end;
|
|
|
|
}
|
|
|
|
if (free <= len)
|
|
|
|
{
|
|
|
|
if (!_allowGrow)
|
|
|
|
return free > 0 ? free - 1 : 0;
|
|
|
|
int sizeInc = (len - free) + 1;
|
|
|
|
byte[] destinationArray = new byte[Buffer.Length + sizeInc];
|
|
|
|
if (_start <= _end)
|
|
|
|
{
|
|
|
|
Array.Copy(Buffer, _start, destinationArray, _start, _end - _start);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Array.Copy(Buffer,
|
|
|
|
0,
|
|
|
|
destinationArray,
|
|
|
|
0,
|
|
|
|
_end);
|
|
|
|
Array.Copy(Buffer,
|
|
|
|
_start,
|
|
|
|
destinationArray,
|
|
|
|
_start + sizeInc,
|
|
|
|
Buffer.Length - _start);
|
|
|
|
_start += sizeInc;
|
|
|
|
}
|
|
|
|
Buffer = destinationArray;
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Write(int b)
|
|
|
|
{
|
|
|
|
lock (_thisLock)
|
|
|
|
{
|
|
|
|
Allocate(1);
|
|
|
|
Buffer[_end] = (byte)b;
|
|
|
|
_end = (_end + 1) % Buffer.Length;
|
|
|
|
_dataEvent.Set();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Write(byte[] b, int offset, int len)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
lock (_thisLock)
|
|
|
|
{
|
|
|
|
int alen = Allocate(len);
|
|
|
|
int length = Math.Min(Buffer.Length - _end, alen);
|
|
|
|
Array.Copy(b, offset, Buffer, _end, length);
|
|
|
|
_end = (_end + length) % Buffer.Length;
|
|
|
|
if (length < alen)
|
|
|
|
{
|
|
|
|
Array.Copy(b, offset + length, Buffer, 0, alen - length);
|
|
|
|
_end += alen - length;
|
|
|
|
}
|
|
|
|
_dataEvent.Set();
|
|
|
|
len -= alen;
|
|
|
|
offset += alen;
|
|
|
|
}
|
|
|
|
} while (len > 0);
|
|
|
|
}
|
|
|
|
}
|
2017-04-02 00:36:06 +00:00
|
|
|
}
|