changeset 8:9525fb2d14ec

Small fix and new functions in PrebufferingStream
author Ivo Smits <Ivo@UCIS.nl>
date Wed, 16 Jan 2013 23:27:06 +0100
parents 4b78cc5f116b
children 9533a87363f3
files Util/PrebufferingStream.cs
diffstat 1 files changed, 71 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Util/PrebufferingStream.cs	Sun Jan 13 18:44:17 2013 +0100
+++ b/Util/PrebufferingStream.cs	Wed Jan 16 23:27:06 2013 +0100
@@ -7,13 +7,18 @@
 namespace UCIS.Util {
 	public class PrebufferingStream : Stream {
 		class AsyncResult : AsyncResultBase {
-			public int Count { get; private set; }
+			public Byte[] Buffer { get; set; }
+			public int Offset { get; set; }
 			public int Left { get; set; }
+			public int Count { get; set; }
 			public AsyncResult(AsyncCallback callback, Object state) : base(callback, state) { }
 			public void SetCompleted(Boolean synchronously, int count, Exception error) {
 				this.Count = count;
 				base.SetCompleted(synchronously, error);
 			}
+			public void SetCompleted(Boolean synchronously, Exception error) {
+				base.SetCompleted(synchronously, error);
+			}
 			public int WaitForCompletion() {
 				WaitHandle wh = null;
 				lock (this) if (!IsCompleted) wh = AsyncWaitHandle;
@@ -43,10 +48,11 @@
 		}
 		public IAsyncResult BeginPrebuffering(int count, AsyncCallback callback, Object state) {
 			AsyncResult ar = new AsyncResult(callback, state);
-			if (prebuffercount > count) {
-				ar.SetCompleted(true, count, null);
+			if (prebuffercount >= count) {
+				ar.SetCompleted(true, prebuffercount, null);
 			} else {
 				PrepareBuffer(count);
+				ar.Left = count - prebuffercount;
 				int off = prebufferoffset + prebuffercount;
 				baseStream.BeginRead(prebuffer, off, prebuffer.Length - off, asyncPrebufferReadCallback, ar);
 			}
@@ -153,6 +159,21 @@
 			}
 		}
 
+		public void ReadAll(Byte[] buffer, int offset, int count) {
+			while (count > 0) {
+				int read = Read(buffer, offset, count);
+				if (read <= 0) throw new EndOfStreamException();
+				offset += read;
+				count -= read;
+			}
+		}
+
+		public Byte[] ReadAll(int count) {
+			Byte[] buffer = new Byte[count];
+			ReadAll(buffer, 0, count);
+			return buffer;
+		}
+
 		public override int ReadByte() {
 			if (Prebuffer(1) < 1) return -1;
 			int v = prebuffer[prebufferoffset];
@@ -184,6 +205,53 @@
 			}
 		}
 
+		public IAsyncResult BeginReadAll(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
+			AsyncResult ar = new AsyncResult(callback, state);
+			ar.Buffer = buffer;
+			ar.Offset = 0;
+			ar.Left = count;
+			ar.Count = 0;
+			if (prebuffercount > 0) {
+				int read = Math.Min(ar.Left, prebuffercount);
+				Buffer.BlockCopy(prebuffer, prebufferoffset, ar.Buffer, ar.Offset, read);
+				prebufferoffset += read;
+				prebuffercount -= read;
+				ar.Offset += read;
+				ar.Left -= read;
+				ar.Count += read;
+			}
+			if (ar.Left > 0) {
+				baseStream.BeginRead(ar.Buffer, ar.Offset, ar.Left, asyncReadAllReadCallback, ar);
+			} else {
+				ar.SetCompleted(true, count, null);
+			}
+			return ar;
+		}
+
+		private void asyncReadAllReadCallback(IAsyncResult ar) {
+			AsyncResult myar = (AsyncResult)ar.AsyncState;
+			try {
+				int len = baseStream.EndRead(ar);
+				if (len <= 0) throw new EndOfStreamException();
+				myar.Offset += len;
+				myar.Left -= len;
+				myar.Count += len;
+				if (myar.Left > 0) {
+					int off = prebufferoffset + prebuffercount;
+					baseStream.BeginRead(myar.Buffer, myar.Offset, myar.Left, asyncReadAllReadCallback, ar);
+				} else {
+					myar.SetCompleted(false, myar.Count, null);
+				}
+			} catch (Exception ex) {
+				myar.SetCompleted(false, ex);
+			}
+		}
+
+		public int EndReadAll(IAsyncResult asyncResult) {
+			AsyncResult myar = asyncResult as AsyncResult;
+			return myar.WaitForCompletion();
+		}
+
 		public override void Close() {
 			base.Close();
 			baseStream.Close();