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
- IgnoreFileBuildProvider.cs
- ISAPIWorkerRequest.cs
- MessageDecoder.cs
- TimeSpanMinutesConverter.cs
- DbProviderSpecificTypePropertyAttribute.cs
- XmlWrappingWriter.cs
- MailDefinition.cs
- DependencyProperty.cs
- SmtpAuthenticationManager.cs
- BamlVersionHeader.cs
- ScriptMethodAttribute.cs
- RuntimeArgumentHandle.cs
- PropertyGroupDescription.cs
- ConfigurationManager.cs
- FixedSOMTableCell.cs
- OleCmdHelper.cs
- SqlParameterizer.cs
- Sql8ExpressionRewriter.cs
- RangeValuePattern.cs
- ClonableStack.cs
- XamlReaderHelper.cs
- MenuAutoFormat.cs
- CustomGrammar.cs
- SystemNetHelpers.cs
- DrawingCollection.cs
- GenericWebPart.cs
- TypeInfo.cs
- PageRequestManager.cs
- AnnotationService.cs
- CompositeScriptReferenceEventArgs.cs
- Menu.cs
- FamilyTypeface.cs
- ValidateNames.cs
- XmlNodeChangedEventArgs.cs
- NonceToken.cs
- PageVisual.cs
- Transform3D.cs
- CssStyleCollection.cs
- ObservableCollection.cs
- InstalledFontCollection.cs
- typedescriptorpermissionattribute.cs
- Path.cs
- AuthenticationModulesSection.cs
- FrugalMap.cs
- X509AsymmetricSecurityKey.cs
- SqlSupersetValidator.cs
- DataGridViewLinkCell.cs
- RbTree.cs
- ContextMarshalException.cs
- LoginView.cs
- DataViewSettingCollection.cs
- CssClassPropertyAttribute.cs
- Hyperlink.cs
- OrderByLifter.cs
- XmlUrlEditor.cs
- TileBrush.cs
- AuthenticationManager.cs
- UserPersonalizationStateInfo.cs
- FormClosingEvent.cs
- SQLGuidStorage.cs
- PersonalizableTypeEntry.cs
- EUCJPEncoding.cs
- BuildResult.cs
- PrintingPermission.cs
- RegexCompilationInfo.cs
- InputBindingCollection.cs
- PropertyConverter.cs
- SignedInfo.cs
- ActivityStatusChangeEventArgs.cs
- DataGridViewToolTip.cs
- MeshGeometry3D.cs
- ForwardPositionQuery.cs
- CodeGenerationManager.cs
- UriSection.cs
- PreservationFileWriter.cs
- SchemaEntity.cs
- DescendentsWalkerBase.cs
- SeekStoryboard.cs
- MimeTypePropertyAttribute.cs
- ContentPosition.cs
- CodeChecksumPragma.cs
- AttributeExtensions.cs
- DataPagerFieldItem.cs
- SqlProfileProvider.cs
- ISFClipboardData.cs
- _SSPISessionCache.cs
- StructureChangedEventArgs.cs
- TableSectionStyle.cs
- BindingBase.cs
- CompositeCollectionView.cs
- SafeCryptContextHandle.cs
- HtmlElementEventArgs.cs
- Storyboard.cs
- MetadataProperty.cs
- PerformanceCounterCategory.cs
- DesignBinding.cs
- ClockGroup.cs
- DesignerActionHeaderItem.cs
- SmiEventStream.cs
- GeometryHitTestResult.cs