aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs')
-rw-r--r--Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs172
1 files changed, 172 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs b/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs
new file mode 100644
index 000000000..d5004c988
--- /dev/null
+++ b/Emby.Server.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Threading;
+
+namespace SharpCifs.Util.Sharpen
+{
+ internal class PipedInputStream : InputStream
+ {
+ private byte[] _oneBuffer;
+ public const int PipeSize = 1024;
+
+ protected byte[] Buffer;
+ private bool _closed;
+ private ManualResetEvent _dataEvent;
+ private int _end;
+ private int _start;
+ private object _thisLock;
+ private bool _allowGrow = false;
+
+ public int In {
+ get { return _start; }
+ set { _start = value; }
+ }
+
+ public int Out {
+ get { return _end; }
+ set { _end = value; }
+ }
+
+ public PipedInputStream ()
+ {
+ _thisLock = new object ();
+ _dataEvent = new ManualResetEvent (false);
+ Buffer = new byte[PipeSize + 1];
+ }
+
+ public PipedInputStream (PipedOutputStream os): this ()
+ {
+ os.Attach (this);
+ }
+
+ 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);
+ }
+ }
+}