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
- DocumentSequenceHighlightLayer.cs
- Menu.cs
- NumberFormatter.cs
- TextServicesDisplayAttributePropertyRanges.cs
- XmlSchemaInferenceException.cs
- CompilationLock.cs
- ObjectDataSourceMethodEventArgs.cs
- SignedXmlDebugLog.cs
- DataGridViewTextBoxColumn.cs
- SQLInt64.cs
- SendMailErrorEventArgs.cs
- PropertyChangeTracker.cs
- UnregisterInfo.cs
- DbParameterCollectionHelper.cs
- SqlPersonalizationProvider.cs
- TextLineResult.cs
- XhtmlConformanceSection.cs
- EarlyBoundInfo.cs
- EntityClientCacheEntry.cs
- Task.cs
- TextEditorSpelling.cs
- HandoffBehavior.cs
- PackWebRequestFactory.cs
- FlowNode.cs
- DictionaryBase.cs
- Quad.cs
- EntityDataSourceEntitySetNameItem.cs
- DiscoveryClientChannelFactory.cs
- PKCS1MaskGenerationMethod.cs
- TextPatternIdentifiers.cs
- ValidatedControlConverter.cs
- BaseTemplateBuildProvider.cs
- SafeArrayTypeMismatchException.cs
- SqlDataSourceCache.cs
- GraphicsContext.cs
- KnownTypes.cs
- TraceLevelStore.cs
- Schema.cs
- TextSimpleMarkerProperties.cs
- QuaternionRotation3D.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- PasswordRecovery.cs
- DataGridViewRowHeaderCell.cs
- ByteStorage.cs
- SafeArrayRankMismatchException.cs
- AlternateView.cs
- ToolStripContentPanelRenderEventArgs.cs
- ListViewDeleteEventArgs.cs
- RenderCapability.cs
- SqlUtil.cs
- Token.cs
- RowBinding.cs
- DataSourceSelectArguments.cs
- RoleManagerEventArgs.cs
- SchemaCollectionPreprocessor.cs
- MatrixTransform.cs
- Marshal.cs
- CharacterShapingProperties.cs
- ClientData.cs
- ECDiffieHellmanCngPublicKey.cs
- TextTreeDeleteContentUndoUnit.cs
- SingleKeyFrameCollection.cs
- PrintDialog.cs
- SqlProviderServices.cs
- FacetDescriptionElement.cs
- TableLayoutRowStyleCollection.cs
- PropertyGeneratedEventArgs.cs
- OdbcDataAdapter.cs
- SqlSupersetValidator.cs
- KeyFrames.cs
- SafeRegistryHandle.cs
- TextDecorationCollection.cs
- PointCollectionValueSerializer.cs
- ipaddressinformationcollection.cs
- CompilerCollection.cs
- SqlCacheDependencyDatabaseCollection.cs
- KoreanCalendar.cs
- EdmEntityTypeAttribute.cs
- HttpResponseInternalWrapper.cs
- RowTypePropertyElement.cs
- Utility.cs
- HyperLinkStyle.cs
- DictionaryItemsCollection.cs
- RoleExceptions.cs
- TransformCollection.cs
- WindowsPen.cs
- TraceContext.cs
- CompModSwitches.cs
- IdentityManager.cs
- ValidationHelpers.cs
- httpapplicationstate.cs
- HtmlGenericControl.cs
- ServerIdentity.cs
- TriState.cs
- EdgeModeValidation.cs
- ListBase.cs
- COSERVERINFO.cs
- SendMessageContent.cs
- TimelineGroup.cs
- _LazyAsyncResult.cs