📄 memorystream.cls
字号:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 1 'Persistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "MemoryStream"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
' CopyRight (c) 2004 Kelly Ethridge
'
' This file is part of VBCorLib.
'
' VBCorLib is free software; you can redistribute it and/or modify
' it under the terms of the GNU Library General Public License as published by
' the Free Software Foundation; either version 2.1 of the License, or
' (at your option) any later version.
'
' VBCorLib is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU Library General Public License for more details.
'
' You should have received a copy of the GNU Library General Public License
' along with Foobar; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'
' Module: MemoryStream
'
''
' Provides an in-memory stream of data that can be read/written and modified
' using Stream methods.
'
' @remarks <p>The MemoryStream uses an array of bytes to back the data
' in memory. When the object is first created, no array is allocated until the
' first time the data must be accessed. The default capacity of the array is 4096 bytes.
' The capacity will grow by doubling the size of the current capacity.
' If The capacity needs to be larger, consider setting the Capacity directly to prevent
' the array from having to be resized as new data is written to the stream.</p>
' <p>If the MemoryStream is created using a supplied Byte array, then no internal array
' will be allocated. The MemoryStream will access the supplied Byte array as if it
' were created by the MemoryStream object. As the underlying array is modified, the
' changes can be seen by directly accessing the array. Also, by modifying the array
' directly, the underlying stream will reflect the new data.</p>
' <p><b>CAUTION:</b> If a Byte array is being supplied to the MemoryStream, then the
' array must outlive the MemoryStream object. It is the responsibility of the user to
' destroy the array after the stream has been destroyed. The MemoryStream object
' maintains a reference to the same array in memory, but does not deallocate the
' array when finished. While the object is alive, the array is locked to prevent
' it from being ReDimed or Erased. Closing the stream will release the lock and
' reference to the array, at which point the user has full control of the array.</p>
' <p>The Currency datatypes used are there for consistency across all stream objects.
' Internally, the MemoryStream only supports 2 ^ 31 bytes. Other streams may support more.</p>
'
' @see Constructors
' @see Stream
'
Option Explicit
Implements IObject
Implements Stream
Private Const DEF_CAPACITY As Long = 4096
Private mBufferSet As Boolean
Private mBuffer() As Byte
Private mCanWrite As Boolean
Private mPosition As Long
Private mCapacity As Long
Private mLength As Long
Private mIsClosed As Boolean
Private mIsUserArray As Boolean
Private mIndex As Long
''
' Returns if the MemoryStream object supports timeout events.
'
' @return Always returns False.
'
Public Property Get CanTimeout() As Boolean
CanTimeout = False
End Property
''
' Gets the timeout duration for a read operation.
'
' @return The timeout duration in milliseconds.
' @remarks This always throws an InvalidOperationException.
'
Public Property Get ReadTimeout() As Long
Throw Cor.NewInvalidOperationException(Environment.GetResourceString(InvalidOperation_Timeouts))
End Property
''
' Sets the timeout duration for a read operation.
'
' @param RHS The new duration in milliseconds
' @remarks This always throws an InvalidOperationException.
'
Public Property Let ReadTimeout(ByVal RHS As Long)
Throw Cor.NewInvalidOperationException(Environment.GetResourceString(InvalidOperation_Timeouts))
End Property
''
' Gets the timeout duration of a write operation.
'
' @return The timeout duration in milliseconds.
' @remarks This always throws an InvalidOperationException.
'
Public Property Get WriteTimeout() As Long
Throw Cor.NewInvalidOperationException(Environment.GetResourceString(InvalidOperation_Timeouts))
End Property
''
' Sets the timeout duration for a write operation.
'
' @param RHS The new timeout duration in milliseconds.
' @remarks This always throws an InvalidOperationException.
'
Public Property Let WriteTimeout(ByVal RHS As Long)
Throw Cor.NewInvalidOperationException(Environment.GetResourceString(InvalidOperation_Timeouts))
End Property
''
' Begins an asynchronous buffer read. For a MemoryStream, calling an asynchronous buffer
' read is identical to calling ReadBlock.
'
' @param Buffer The destination array to copy the bytes into.
' @param Offset The index in Buffer to begin copying to.
' @param Count The maximum number of bytes to copy.
' @param Callback A listening object to be notified that the read is finished.
' @param State User data that can be carried within the IAsyncResult object returned.
' @return An IAsyncResult object used to identify the corrisponding Endread and report
' information about the buffer read.
' @remarks <p>Since the stream is directly stored and accessed in memory, there is no
' waiting for reads to occur. The BeginRead method works identical to the Read method
' in terms of immediately reading stream data into the <i>Buffer</i>.</p>
' <p>When defining the Count for the number of maximum bytes to be read, if the
' stream does not have enough bytes, the read will copy less bytes than Count.</p>
' <p>If an exception has occurred during the read, it will not be thrown until the
' EndRead is executed.
'
Public Function BeginRead(ByRef Buffer() As Byte, ByVal Offset As Long, ByVal Count As Long, Optional ByVal Callback As AsyncCallback, Optional ByVal State As Variant) As IAsyncResult
Dim Ret As StreamAsyncResult
Set Ret = Cor.NewStreamAsyncResult(State)
On Error GoTo errTrap
With Ret
.BytesRead = ReadBlock(Buffer, Offset, Count)
.IsCompleted = True
.IsReadType = True
End With
If Not Callback Is Nothing Then Call Callback.Execute(Ret)
errTrap:
Dim Ex As Exception
If Catch(Ex, Err) Then Set Ret.Exception = Ex
Set BeginRead = Ret
End Function
''
' Begins an asynchronous buffer write. For a MemoryStream, having an asynchronous buffer
' write is of no use.
'
' @param Buffer The source array to copy the bytes from into the stream.
' @param Offset The starting index in the source <i>Buffer</i> to begin copying from.
' @param Count The maximum number of bytes to be copied into the stream.
' @param Callback A user supplied object to be notified of the finish of the writing.
' @param State User data that can be carried within the IAsyncResult object return.
' @return An IAsyncResult object used to identify the corrisponding EndBread and report
' information about the buffer read.
' @remarks <p>Since the stream is directly stored and accessed in memory, there is no
' waiting for reads to occur. The BeginWrite method works identical to the WriteBlock method
' in terms of reading immediately writing stream data to the stream.</p>
' <p>When defining the Count for the number of maximum bytes to be written, if the
' <i>Buffer</i> does not have enough bytes, an exception will be thrown in the EndWrite method.</p>
' <p>If an exception has occurred during the read, it will not be thrown until the
' EndRead is executed.
'
Public Function BeginWrite(ByRef Buffer() As Byte, ByVal Offset As Long, ByVal Count As Long, Optional ByVal Callback As AsyncCallback, Optional ByVal State As Variant) As IAsyncResult
Dim Ret As StreamAsyncResult
Set Ret = Cor.NewStreamAsyncResult(State)
On Error GoTo errTrap:
With Ret
.CompletedSynchronously = True
.IsCompleted = True
End With
Call WriteBlock(Buffer, Offset, Count)
If Not Callback Is Nothing Then Call Callback.Execute(Ret)
errTrap:
Dim Ex As Exception
If Catch(Ex, Err) Then Set Ret.Exception = Ex
Set BeginWrite = Ret
End Function
''
' Signifies the end of an asynchronous read from the stream.
'
' @param AsyncResult The IAsyncResult object returned from the BeginRead function.
' @return The number of bytes read from the stream in to <i>Buffer</i> in the BeginRead method.
' @remarks <p>This method is generally called anytime after BeginRead for a MemoryStream.
' Since the MemoryStream uses memory for the data store, there is no need to wait for
' the data to arrive. The BeginRead/EndRead calls are redundant and should not be
' used with the MemoryStream. Instead use the Read Method.</p>
' <p>If any exceptions were caused during the reading then they will be thrown
' during the call to EndRead.</p>
'
Public Function EndRead(ByVal AsyncResult As IAsyncResult) As Long
Dim Result As StreamAsyncResult
If AsyncResult Is Nothing Then _
Throw Cor.NewArgumentNullException("AsyncResult object is required.", "AsyncResult")
If Not TypeOf AsyncResult Is StreamAsyncResult Then _
Throw Cor.NewArgumentException("AsyncResult object is not part of this stream.", "AsyncResult")
Set Result = AsyncResult
If Not Result.IsReadType Then _
Throw Cor.NewArgumentException("AsyncResult object is not part of this stream.", "AsyncResult")
If Result.EndCalled Then _
Throw Cor.NewInvalidOperationException("The EndRead has already been called.")
If Not Result.Exception Is Nothing Then Throw Result.Exception
EndRead = Result.BytesRead
End Function
''
' Signifies the end of an asynchronous write to the stream.
'
' @param AsyncResult The IAsyncResult returned from the BeginWrite function.
' @remarks <p>This method is generally called anytime after BeginWrite for a MemoryStream.
' Since the MemoryStream uses memory for the data store, there is no need to wait for
' the data to be written. The BeginWrite/EndWrite calls are redundant and should not be
' used with the MemoryStream. Instead use the WriteBlock Method.</p>
' <p>If any exceptions were caused during the reading then they will be thrown
' during the call to EndRead.</p>
'
Public Sub EndWrite(ByVal AsyncResult As IAsyncResult)
Dim Result As StreamAsyncResult
If AsyncResult Is Nothing Then _
Throw Cor.NewArgumentNullException("AsyncResult object is required.", "AsyncResult")
If Not TypeOf AsyncResult Is StreamAsyncResult Then _
Throw Cor.NewArgumentException("AsyncResult object is not part of this stream.", "AsyncResult")
Set Result = AsyncResult
If Result.IsReadType Then _
Throw Cor.NewArgumentException("AsyncResult object is not part of this stream.", "AsyncResult")
If Result.EndCalled Then _
Throw Cor.NewInvalidOperationException("The EndRead has already been called.")
If Not Result.Exception Is Nothing Then Throw Result.Exception
End Sub
''
' Determines if the current MemoryStream can be read.
'
' @return The status of the ability to read the stream.
' @remarks If the MemoryStream is open, then it can be read. If it is closed, it cannot be read.
'
Public Property Get CanRead() As Boolean
CanRead = Not mIsClosed
End Property
''
' Determines if the current MemoryStream can be written to.
'
' @return The status of the ability to write to the stream.
' @remarks If the stream was created from a user-supplied array, then the user
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -