Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Remoting / Channels / CORE / ChunkedMemoryStream.cs / 1305376 / ChunkedMemoryStream.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //========================================================================== // File: ChunkedMemoryStream.cs // // Summary: Memory stream that doesn't need to be resized. // //========================================================================= using System; using System.IO; using System.Runtime.Remoting.Channels; namespace System.Runtime.Remoting.Channels { internal class ChunkedMemoryStream : Stream { private class MemoryChunk { public byte[] Buffer = null; public MemoryChunk Next = null; } private static IByteBufferPool s_defaultBufferPool = new ByteBufferAllocator(1024); // state private MemoryChunk _chunks = null; // data private IByteBufferPool _bufferPool = null; // pool of byte buffers to use private bool _bClosed = false; // has the stream been closed. private MemoryChunk _writeChunk = null; // current chunk to write to private int _writeOffset = 0; // offset into chunk to write to private MemoryChunk _readChunk = null; // current chunk to read from private int _readOffset = 0; // offset into chunk to read from public ChunkedMemoryStream(IByteBufferPool bufferPool) { _bufferPool = bufferPool; } // ChunkedMemoryStream public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override long Length { get { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } int length = 0; MemoryChunk chunk = _chunks; while (chunk != null) { MemoryChunk next = chunk.Next; if (next != null) length += chunk.Buffer.Length; else length += _writeOffset; chunk = next; } return (long)length; } } // Length public override long Position { get { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) return 0; int pos = 0; MemoryChunk chunk = _chunks; while (chunk != _readChunk) { pos += chunk.Buffer.Length; chunk = chunk.Next; } pos += _readOffset; return (long)pos; } set { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (value < 0) throw new ArgumentOutOfRangeException("value"); // back up current position in case new position is out of range MemoryChunk backupReadChunk = _readChunk; int backupReadOffset = _readOffset; _readChunk = null; _readOffset = 0; int leftUntilAtPos = (int)value; MemoryChunk chunk = _chunks; while (chunk != null) { if ((leftUntilAtPos < chunk.Buffer.Length) || ((leftUntilAtPos == chunk.Buffer.Length) && (chunk.Next == null))) { // the desired position is in this chunk _readChunk = chunk; _readOffset = leftUntilAtPos; break; } leftUntilAtPos -= chunk.Buffer.Length; chunk = chunk.Next; } if (_readChunk == null) { // position is out of range _readChunk = backupReadChunk; _readOffset = backupReadOffset; throw new ArgumentOutOfRangeException("value"); } } } // Position public override long Seek(long offset, SeekOrigin origin) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } switch(origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current: Position = Position + offset; break; case SeekOrigin.End: Position = Length + offset; break; } return Position; } // Seek public override void SetLength(long value) { throw new NotSupportedException(); } protected override void Dispose(bool disposing) { try { _bClosed = true; if (disposing) ReleaseMemoryChunks(_chunks); _chunks = null; _writeChunk = null; _readChunk = null; } finally { base.Dispose(disposing); } } // Close public override void Flush() { } // Flush public override int Read(byte[] buffer, int offset, int count) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) { if (_chunks == null) return 0; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; int bytesRead = 0; while (count > 0) { if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) break; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } int readCount = Math.Min(count, chunkSize - _readOffset); Buffer.BlockCopy(chunkBuffer, _readOffset, buffer, offset, readCount); offset += readCount; count -= readCount; _readOffset += readCount; bytesRead += readCount; } return bytesRead; } // Read public override int ReadByte() { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) { if (_chunks == null) return 0; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) return -1; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } return chunkBuffer[_readOffset++]; } // ReadByte public override void Write(byte[] buffer, int offset, int count) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_chunks == null) { _chunks = AllocateMemoryChunk(); _writeChunk = _chunks; _writeOffset = 0; } byte[] chunkBuffer = _writeChunk.Buffer; int chunkSize = chunkBuffer.Length; while (count > 0) { if (_writeOffset == chunkSize) { // allocate a new chunk if the current one is full _writeChunk.Next = AllocateMemoryChunk(); _writeChunk = _writeChunk.Next; _writeOffset = 0; chunkBuffer = _writeChunk.Buffer; chunkSize = chunkBuffer.Length; } int copyCount = Math.Min(count, chunkSize - _writeOffset); Buffer.BlockCopy(buffer, offset, chunkBuffer, _writeOffset, copyCount); offset += copyCount; count -= copyCount; _writeOffset += copyCount; } } // Write public override void WriteByte(byte value) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_chunks == null) { _chunks = AllocateMemoryChunk(); _writeChunk = _chunks; _writeOffset = 0; } byte[] chunkBuffer = _writeChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_writeOffset == chunkSize) { // allocate a new chunk if the current one is full _writeChunk.Next = AllocateMemoryChunk(); _writeChunk = _writeChunk.Next; _writeOffset = 0; chunkBuffer = _writeChunk.Buffer; chunkSize = chunkBuffer.Length; } chunkBuffer[_writeOffset++] = value; } // WriteByte // copy entire buffer into an array public virtual byte[] ToArray() { int length = (int)Length; // this will throw if stream is closed byte[] copy = new byte[Length]; MemoryChunk backupReadChunk = _readChunk; int backupReadOffset = _readOffset; _readChunk = _chunks; _readOffset = 0; Read(copy, 0, length); _readChunk = backupReadChunk; _readOffset = backupReadOffset; return copy; } // ToArray // write remainder of this stream to another stream public virtual void WriteTo(Stream stream) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (stream == null) throw new ArgumentNullException("stream"); if (_readChunk == null) { if (_chunks == null) return; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; // following code mirrors Read() logic (_readChunk/_readOffset should // point just past last byte of last chunk when done) for (;;) // loop until end of chunks is found { if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) break; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } int writeCount = chunkSize - _readOffset; stream.Write(chunkBuffer, _readOffset, writeCount); _readOffset = chunkSize; } } // WriteTo private MemoryChunk AllocateMemoryChunk() { MemoryChunk chunk = new MemoryChunk(); chunk.Buffer = _bufferPool.GetBuffer(); chunk.Next = null; return chunk; } // AllocateMemoryChunk private void ReleaseMemoryChunks(MemoryChunk chunk) { // If the buffer pool always allocates a new buffer, // there's no point to trying to return all of the buffers. if (_bufferPool is ByteBufferAllocator) return; while (chunk != null) { _bufferPool.ReturnBuffer(chunk.Buffer); chunk = chunk.Next; } } // FreeMemoryChunk } // ChunkedMemoryStream } // namespace System.IO // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //========================================================================== // File: ChunkedMemoryStream.cs // // Summary: Memory stream that doesn't need to be resized. // //========================================================================= using System; using System.IO; using System.Runtime.Remoting.Channels; namespace System.Runtime.Remoting.Channels { internal class ChunkedMemoryStream : Stream { private class MemoryChunk { public byte[] Buffer = null; public MemoryChunk Next = null; } private static IByteBufferPool s_defaultBufferPool = new ByteBufferAllocator(1024); // state private MemoryChunk _chunks = null; // data private IByteBufferPool _bufferPool = null; // pool of byte buffers to use private bool _bClosed = false; // has the stream been closed. private MemoryChunk _writeChunk = null; // current chunk to write to private int _writeOffset = 0; // offset into chunk to write to private MemoryChunk _readChunk = null; // current chunk to read from private int _readOffset = 0; // offset into chunk to read from public ChunkedMemoryStream(IByteBufferPool bufferPool) { _bufferPool = bufferPool; } // ChunkedMemoryStream public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override long Length { get { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } int length = 0; MemoryChunk chunk = _chunks; while (chunk != null) { MemoryChunk next = chunk.Next; if (next != null) length += chunk.Buffer.Length; else length += _writeOffset; chunk = next; } return (long)length; } } // Length public override long Position { get { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) return 0; int pos = 0; MemoryChunk chunk = _chunks; while (chunk != _readChunk) { pos += chunk.Buffer.Length; chunk = chunk.Next; } pos += _readOffset; return (long)pos; } set { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (value < 0) throw new ArgumentOutOfRangeException("value"); // back up current position in case new position is out of range MemoryChunk backupReadChunk = _readChunk; int backupReadOffset = _readOffset; _readChunk = null; _readOffset = 0; int leftUntilAtPos = (int)value; MemoryChunk chunk = _chunks; while (chunk != null) { if ((leftUntilAtPos < chunk.Buffer.Length) || ((leftUntilAtPos == chunk.Buffer.Length) && (chunk.Next == null))) { // the desired position is in this chunk _readChunk = chunk; _readOffset = leftUntilAtPos; break; } leftUntilAtPos -= chunk.Buffer.Length; chunk = chunk.Next; } if (_readChunk == null) { // position is out of range _readChunk = backupReadChunk; _readOffset = backupReadOffset; throw new ArgumentOutOfRangeException("value"); } } } // Position public override long Seek(long offset, SeekOrigin origin) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } switch(origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current: Position = Position + offset; break; case SeekOrigin.End: Position = Length + offset; break; } return Position; } // Seek public override void SetLength(long value) { throw new NotSupportedException(); } protected override void Dispose(bool disposing) { try { _bClosed = true; if (disposing) ReleaseMemoryChunks(_chunks); _chunks = null; _writeChunk = null; _readChunk = null; } finally { base.Dispose(disposing); } } // Close public override void Flush() { } // Flush public override int Read(byte[] buffer, int offset, int count) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) { if (_chunks == null) return 0; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; int bytesRead = 0; while (count > 0) { if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) break; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } int readCount = Math.Min(count, chunkSize - _readOffset); Buffer.BlockCopy(chunkBuffer, _readOffset, buffer, offset, readCount); offset += readCount; count -= readCount; _readOffset += readCount; bytesRead += readCount; } return bytesRead; } // Read public override int ReadByte() { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_readChunk == null) { if (_chunks == null) return 0; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) return -1; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } return chunkBuffer[_readOffset++]; } // ReadByte public override void Write(byte[] buffer, int offset, int count) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_chunks == null) { _chunks = AllocateMemoryChunk(); _writeChunk = _chunks; _writeOffset = 0; } byte[] chunkBuffer = _writeChunk.Buffer; int chunkSize = chunkBuffer.Length; while (count > 0) { if (_writeOffset == chunkSize) { // allocate a new chunk if the current one is full _writeChunk.Next = AllocateMemoryChunk(); _writeChunk = _writeChunk.Next; _writeOffset = 0; chunkBuffer = _writeChunk.Buffer; chunkSize = chunkBuffer.Length; } int copyCount = Math.Min(count, chunkSize - _writeOffset); Buffer.BlockCopy(buffer, offset, chunkBuffer, _writeOffset, copyCount); offset += copyCount; count -= copyCount; _writeOffset += copyCount; } } // Write public override void WriteByte(byte value) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (_chunks == null) { _chunks = AllocateMemoryChunk(); _writeChunk = _chunks; _writeOffset = 0; } byte[] chunkBuffer = _writeChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_writeOffset == chunkSize) { // allocate a new chunk if the current one is full _writeChunk.Next = AllocateMemoryChunk(); _writeChunk = _writeChunk.Next; _writeOffset = 0; chunkBuffer = _writeChunk.Buffer; chunkSize = chunkBuffer.Length; } chunkBuffer[_writeOffset++] = value; } // WriteByte // copy entire buffer into an array public virtual byte[] ToArray() { int length = (int)Length; // this will throw if stream is closed byte[] copy = new byte[Length]; MemoryChunk backupReadChunk = _readChunk; int backupReadOffset = _readOffset; _readChunk = _chunks; _readOffset = 0; Read(copy, 0, length); _readChunk = backupReadChunk; _readOffset = backupReadOffset; return copy; } // ToArray // write remainder of this stream to another stream public virtual void WriteTo(Stream stream) { if (_bClosed) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Stream_StreamIsClosed")); } if (stream == null) throw new ArgumentNullException("stream"); if (_readChunk == null) { if (_chunks == null) return; _readChunk = _chunks; _readOffset = 0; } byte[] chunkBuffer = _readChunk.Buffer; int chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; // following code mirrors Read() logic (_readChunk/_readOffset should // point just past last byte of last chunk when done) for (;;) // loop until end of chunks is found { if (_readOffset == chunkSize) { // exit if no more chunks are currently available if (_readChunk.Next == null) break; _readChunk = _readChunk.Next; _readOffset = 0; chunkBuffer = _readChunk.Buffer; chunkSize = chunkBuffer.Length; if (_readChunk.Next == null) chunkSize = _writeOffset; } int writeCount = chunkSize - _readOffset; stream.Write(chunkBuffer, _readOffset, writeCount); _readOffset = chunkSize; } } // WriteTo private MemoryChunk AllocateMemoryChunk() { MemoryChunk chunk = new MemoryChunk(); chunk.Buffer = _bufferPool.GetBuffer(); chunk.Next = null; return chunk; } // AllocateMemoryChunk private void ReleaseMemoryChunks(MemoryChunk chunk) { // If the buffer pool always allocates a new buffer, // there's no point to trying to return all of the buffers. if (_bufferPool is ByteBufferAllocator) return; while (chunk != null) { _bufferPool.ReturnBuffer(chunk.Buffer); chunk = chunk.Next; } } // FreeMemoryChunk } // ChunkedMemoryStream } // namespace System.IO // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RequiredFieldValidator.cs
- OwnerDrawPropertyBag.cs
- RegionData.cs
- remotingproxy.cs
- ConnectionStringSettingsCollection.cs
- InputManager.cs
- ExtendedPropertyDescriptor.cs
- SecurityPermission.cs
- Selection.cs
- Span.cs
- DataSourceControlBuilder.cs
- DbDataRecord.cs
- ModuleConfigurationInfo.cs
- SettingsAttributes.cs
- BaseAddressPrefixFilterElement.cs
- CfgRule.cs
- Label.cs
- SynchronizedInputAdaptor.cs
- ZoneButton.cs
- GestureRecognitionResult.cs
- Hashtable.cs
- PropertyRecord.cs
- NetTcpSecurity.cs
- NodeLabelEditEvent.cs
- ProfileModule.cs
- TransformGroup.cs
- Exceptions.cs
- VisualStyleTypesAndProperties.cs
- ControlValuePropertyAttribute.cs
- WorkflowTransactionOptions.cs
- WebPartManagerInternals.cs
- SwitchCase.cs
- Pair.cs
- BaseCollection.cs
- PopupRoot.cs
- RuleValidation.cs
- TextOutput.cs
- DnsPermission.cs
- ProfileServiceManager.cs
- QfeChecker.cs
- ActivityDesignerResources.cs
- OleDbError.cs
- GridViewUpdateEventArgs.cs
- OleDbTransaction.cs
- BindingManagerDataErrorEventArgs.cs
- PasswordTextContainer.cs
- NeutralResourcesLanguageAttribute.cs
- System.Data_BID.cs
- ChangeNode.cs
- SystemIPGlobalProperties.cs
- BitmapFrameEncode.cs
- InProcStateClientManager.cs
- VectorAnimation.cs
- SchemaTypeEmitter.cs
- MaterialGroup.cs
- SqlDataSourceCache.cs
- CodeLabeledStatement.cs
- SqlDataSourceCache.cs
- CompareInfo.cs
- CachedCompositeFamily.cs
- TraceContextEventArgs.cs
- Pair.cs
- ThicknessConverter.cs
- ADConnectionHelper.cs
- SignatureToken.cs
- HelpKeywordAttribute.cs
- CapiSafeHandles.cs
- TextChange.cs
- HostAdapter.cs
- FolderNameEditor.cs
- ProfileService.cs
- WebPartDisplayMode.cs
- DocumentEventArgs.cs
- FactoryId.cs
- ColumnHeader.cs
- GuidTagList.cs
- DynamicPropertyReader.cs
- HierarchicalDataSourceControl.cs
- GraphicsPathIterator.cs
- WebPartChrome.cs
- UpdateRecord.cs
- ImmComposition.cs
- AttachedPropertyBrowsableAttribute.cs
- AttributeSetAction.cs
- HandleRef.cs
- ButtonPopupAdapter.cs
- ChangeToolStripParentVerb.cs
- TagNameToTypeMapper.cs
- DesignColumn.cs
- WeakReferenceEnumerator.cs
- ProjectionPlan.cs
- CompositeFontParser.cs
- SamlAssertionDirectKeyIdentifierClause.cs
- EmbeddedMailObjectsCollection.cs
- SafeNativeMethods.cs
- StateDesigner.CommentLayoutGlyph.cs
- InArgumentConverter.cs
- Html32TextWriter.cs
- DispatcherSynchronizationContext.cs
- ShaderEffect.cs