Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HandlerBase.cs
- Section.cs
- WindowsStatic.cs
- JapaneseLunisolarCalendar.cs
- ITextView.cs
- SafeTokenHandle.cs
- AbsoluteQuery.cs
- CellIdBoolean.cs
- PowerModeChangedEventArgs.cs
- _SecureChannel.cs
- HijriCalendar.cs
- DataTable.cs
- PeerApplicationLaunchInfo.cs
- DtdParser.cs
- DrawingGroupDrawingContext.cs
- NotCondition.cs
- ConfigurationManagerHelperFactory.cs
- ExpressionVisitor.cs
- CreateUserErrorEventArgs.cs
- ResourceExpressionBuilder.cs
- Registry.cs
- Models.cs
- COM2ComponentEditor.cs
- AttributeConverter.cs
- CurrentChangingEventManager.cs
- Scalars.cs
- GlobalizationAssembly.cs
- ModuleConfigurationInfo.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- XPathExpr.cs
- EntityDataSourceWrapperCollection.cs
- TemplatedWizardStep.cs
- _IPv6Address.cs
- QueryCacheManager.cs
- XmlSchemaComplexContentRestriction.cs
- QuaternionRotation3D.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- XamlNamespaceHelper.cs
- StreamUpgradeAcceptor.cs
- DataRowView.cs
- Rotation3D.cs
- FileUtil.cs
- PointKeyFrameCollection.cs
- AutomationPropertyInfo.cs
- RowToFieldTransformer.cs
- ISFTagAndGuidCache.cs
- RequestCachingSection.cs
- CngUIPolicy.cs
- Block.cs
- AnchoredBlock.cs
- SelectedCellsCollection.cs
- XmlName.cs
- HMACRIPEMD160.cs
- grammarelement.cs
- AddressHeaderCollection.cs
- DoubleCollection.cs
- ObjectKeyFrameCollection.cs
- Soap.cs
- Subset.cs
- CatalogPart.cs
- TrustManager.cs
- DataBoundControlHelper.cs
- ProfileEventArgs.cs
- FixedHyperLink.cs
- MemberAssignment.cs
- DataStreamFromComStream.cs
- CssClassPropertyAttribute.cs
- FixedTextPointer.cs
- Msec.cs
- TextLineResult.cs
- XmlSchemaSimpleContentExtension.cs
- ItemsControlAutomationPeer.cs
- BaseResourcesBuildProvider.cs
- UnsettableComboBox.cs
- ByValueEqualityComparer.cs
- CannotUnloadAppDomainException.cs
- OleDbSchemaGuid.cs
- ListBoxChrome.cs
- InvokeProviderWrapper.cs
- RadialGradientBrush.cs
- panel.cs
- CategoryGridEntry.cs
- XmlMapping.cs
- SafeThreadHandle.cs
- PageParser.cs
- TableSectionStyle.cs
- COAUTHIDENTITY.cs
- TransactedReceiveData.cs
- PartialCachingControl.cs
- ReadOnlyHierarchicalDataSource.cs
- PkcsMisc.cs
- Clock.cs
- ServiceNameElement.cs
- EventSinkHelperWriter.cs
- AssociationTypeEmitter.cs
- ConfigXmlCDataSection.cs
- FontWeightConverter.cs
- SizeFConverter.cs
- DbConnectionPoolGroup.cs
- MultipartContentParser.cs