NameSpace System NameSpace IO Class MemoryStream Inherits Stream Public /*! @brief MemoryStreamクラスの新しいインスタンスを初期化します。 @author NoWest @date 2008/3/12 */ Sub MemoryStream() This.writable = True This.resizable = True This.visible = False This.create() This.pointer = This.allocate(0) This.streamLength = 0 This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを初期容量を指定して初期化します。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(capacity As Long) This.writable = True This.resizable = True This.visible = False This.create() This.pointer = This.allocate(capacity) This.streamLength = capacity This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを指定したバッファに基づいて初期化します。容量を変更することはできません。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(buffer As *Byte, length As Long) This.writable = True This.resizable = False This.visible = False This.create() This.pointer = This.allocate(length) MoveMemory(This.pointer,buffer,length) This.streamLength = length This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを指定したバッファに基づいて初期化します。容量を変更することはできません。また、書き込みをサポートするかどうかも指定できます。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(buffer As *Byte, length As Long, writable As Boolean) This.writable = writable This.resizable = False This.visible = False This.create() This.pointer = This.allocate(length) MoveMemory(This.pointer,buffer,length) This.streamLength = length This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを指定したバッファの指定された領域に基づいて初期化します。容量を変更することはできません。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(buffer As *Byte, index As Long, count As Long) This.writable = True This.resizable = False This.visible = False This.create() This.pointer = This.allocate(count) MoveMemory(This.pointer,VarPtr(buffer[index]),count) This.streamLength = count This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを指定したバッファの指定された領域に基づいて初期化します。容量を変更することはできません。また、書き込みをサポートするかどうかを指定できます。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(buffer As *Byte, index As Long, count As Long, writable As Boolean) This.writable = writable This.resizable = False This.visible = False This.create() This.pointer = This.allocate(count) MoveMemory(This.pointer,VarPtr(buffer[index]),count) This.streamLength = count This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスの新しいインスタンスを指定したバッファの指定された領域に基づいて初期化します。容量を変更することはできません。また、書き込みをサポートするかどうかを指定できます。GetBufferメソッドをサポートするかどうかを指定できます。 @author NoWest @date 2008/3/12 */ Sub MemoryStream(buffer As *Byte, index As Long, count As Long, writable As Boolean, visible As Boolean) This.writable = writable This.resizable = False This.visible = visible This.create() This.pointer = This.allocate(count) MoveMemory(This.pointer,VarPtr(buffer[index]),count) This.streamLength = count This.currentPosition = 0 End Sub /*! @brief MemoryStreamクラスのデストラクタです。 @author NoWest @date 2008/3/12 */ Sub ~MemoryStream() This.Close() End Sub Public /*! @brief ストリームが読み取りをサポートしているかどうかを示す値を取得します。 @author NoWest @date 2008/3/12 */ Override Function CanRead() As Boolean If This.pointer Then Return True Else Return False End If End Function /*! @brief ストリームがシークをサポートしているかどうかを示す値を取得します。 @author NoWest @date 2008/3/12 */ Override Function CanSeek() As Boolean If This.pointer Then Return True Else Return False End If End Function /*! @brief ストリームが書き込みをサポートしているかどうかを示す値を取得します。 @author NoWest @date 2008/3/12 */ Override Function CanWrite() As Boolean If This.pointer Then Return This.writable Else Return False End If End Function /*! @brief ストリームに割り当てるメモリ容量をバイト単位で設定します。 @author NoWest @date 2008/3/12 */ Virtual Sub Capacity(value As Long) If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If value < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Capacity: A capacity is set to negative value.", New System.Int64(value),"Capacity") If value < This.streamLength Then Throw New ArgumentOutOfRangeException("MemoryStream.Capacity: A capacity is less than the current length of the stream.",New System.Int64(value),"Capacity") This.pointer = This.reallocate(This.pointer,value) End Sub /*! @brief ストリームに割り当てられたメモリ容量をバイト単位で取得します。 @author NoWest @date 2008/3/12 */ Virtual Function Capacity() As Long If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") Return This.size(This.pointer) End Function /*! @brief ストリームの長さをバイト単位で取得します。Capacityプロパティの値より小さい場合があります。 @author NoWest @date 2008/3/12 */ Override Function Length() As Int64 If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") Return This.streamLength End Function /*! @brief ストリームの現在位置を設定します。 @author NoWest @date 2008/3/12 */ Override Sub Position(value As Int64) If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If value < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Position: The position is set to a negative value.", New System.Int64(value), "Position") If value > Int32.MaxValue() Then Throw New ArgumentOutOfRangeException("MemoryStream.Position: The position is a value greater than MaxValue.", New System.Int64(value), "Position") This.currentPosition = value As Long End Sub /*! @brief ストリームの現在位置を取得します。 @author NoWest @date 2008/3/12 */ Override Function Position() As Int64 If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") Return This.currentPosition As Int64 End Function Override Sub Flush() End Sub /* Virtual Function GetBuffer() As Array If visible = False Then Return NULL Return p End Function*/ /*! @brief ストリームから指定されたバイト数を読み取り、bufferに書き込みます。 @author NoWest @date 2008/3/12 */ Override Function Read(buffer As *Byte, offset As Long, count As Long) As Long If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If buffer = 0 Then Throw New ArgumentNullException("FileStream.Read: An argument is a null value.", "buffer") If offset < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Read: An argument is a negative value.", New System.Int64(offset), "offset") If count < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Read: An argument is a negative value.", New System.Int64(count), "count") If (This.streamLength - (This.currentPosition + count)) < 0 Then count + = (This.streamLength - (This.currentPosition + count)) ElseIf count < 1 Then Return 0 End If MoveMemory(VarPtr(buffer[offset]),VarPtr(This.pointer[This.currentPosition]),count) This.currentPosition + = count Return count End Function /*! @brief ストリームから指定された1バイト読み取ります。 @author NoWest @date 2008/3/12 */ Override Function ReadByte() As Long Dim b As Byte Dim ret = Read(VarPtr(b), 0, 1) If ret <> 0 Then Return b Else Return -1 End If End Function /*! @brief ストリーム内の位置を指定した値に設定します。 @author NoWest @date 2008/3/12 */ Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64 If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If offset > Int32.MaxValue() Then Throw New ArgumentOutOfRangeException("MemoryStream.Seek: The offset is a value greater than MaxValue.", New System.Int64(offset), "offset") Select Case origin Case SeekOrigin.Begin If offset < 0 Then Throw New IOException("MemoryStream.Seek: Seeking is attempted before the beginning of the stream.") This.currentPosition = offset As Long Case SeekOrigin.Current Beep(440,10) If (This.currentPosition + offset) < 0 Then Throw New IOException("MemoryStream.Seek: Seeking is attempted before the beginning of the stream.") This.currentPosition += offset As Long Case SeekOrigin.End If (This.streamLength + offset) < 0 Then Throw New IOException("MemoryStream.Seek: Seeking is attempted before the beginning of the stream.") This.currentPosition = (This.streamLength + offset) As Long Case Else Throw New ArgumentException("MemoryStream.Seek: An argument is an invalid SeekOrigin","origin") End Select Return This.currentPosition As Int64 End Function /*! @brief ストリームの長さを設定します。メモリ容量を超えては設定できません。 @author NoWest @date 2008/3/12 */ Override Sub SetLength(value As Int64) If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If This.writable = False Then Throw New NotSupportedException("MemoryStream: The current stream is not writable") If This.resizable = False Then Throw New NotSupportedException("MemoryStream: The current stream is not resizable") If value > This.Capacity() Then Throw New NotSupportedException("MemoryStream.SetLength: This stream length is larger than the current capacity.") If value < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Read: An argument is a negative value.", New System.Int64(value), "value") If value > Int32.MaxValue() Then Throw New ArgumentOutOfRangeException("MemoryStream.SetLength: The length is a value greater than MaxValue.", New System.Int64(value), "value") This.pointer = This.reallocate(This.pointer,value As Long) This.streamLength = value As Long End Sub /*! @brief ストリームにbufferの内容を指定したバイト数書き込みます。 @author NoWest @date 2008/3/12 */ Override Sub Write(buffer As *Byte, offset As Long, count As Long) If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If This.writable = False Then Throw New NotSupportedException("MemoryStream: The current stream is not writable") If buffer = 0 Then Throw New ArgumentNullException("MemoryStream.Write: An argument is a null value.", "buffer") If offset < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Write: An argument is a negative value.", New System.Int64(offset), "offset") If count < 0 Then Throw New ArgumentOutOfRangeException("MemoryStream.Write: An argument is a negative value.", New System.Int64(count), "count") If count > (This.streamLength - This.currentPosition) Then If This.resizable = False Then Throw New NotSupportedException("MemoryStream: The current stream is not resizable") If (This.Capacity() - This.currentPosition) < count Then This.pointer = This.reallocate(This.pointer,This.currentPosition+count) End If This.streamLength = This.currentPosition+count End If MoveMemory(VarPtr(This.pointer[This.currentPosition]),VarPtr(buffer[offset]),count) This.currentPosition + = count End Sub /*! @brief ストリームに1バイト書き込みます。 @author NoWest @date 2008/3/12 */ Override Sub WriteByte(b As Byte) Write(VarPtr(b), 0, 1) End Sub /* Virtual Function ToArray() As Array TODO: End Function*/ /*! @brief ストリームの内容全体をまるごと別のストリームに書き込みます。 @author NoWest @date 2008/3/12 */ Virtual Sub WriteTo(stream As Stream) If This.pointer = 0 Then Throw New ObjectDisposedException("MemoryStream: This stream has closed.") If ActiveBasic.IsNothing(stream) Then Throw New ArgumentNullException("MemoryStream.WriteTo: An argument is a null value.", "stream") stream.Write(This.pointer,0,This.Capacity()) End Sub Protected /*! @brief Streamクラスから継承 @author NoWest @date 2008/3/12 */ Override Sub Dispose(disposing As Boolean) This.destroy() End Sub Private /* Heap memory address */ pointer As *Byte /* MemoryStream status */ writable As Boolean resizable As Boolean visible As Boolean streamLength As Long currentPosition As Long /* バッファ管理用のPrivate関数類 一応初期設定ではGC_mallocでメモリを確保しています。 */ handle As HANDLE Sub create() #ifdef NOT_USE_GC This.handle = HeapCreate(0,0,0) #endif End Sub Sub destroy() #ifdef NOT_USE_GC HeapFree(This.handle,0,InterlockedExchangePointer(ByVal VarPtr(This.pointer) As VoidPtr,NULL) As VoidPtr) HeapDestroy(InterlockedExchangePointer(ByVal VarPtr(This.handle) As VoidPtr,NULL) As HANDLE) #endif End Sub Function allocate(length As SIZE_T) As VoidPtr #ifdef NOT_USE_GC Return HeapAlloc(This.handle,HEAP_ZERO_MEMORY,length) #else Return GC_malloc_atomic(length) #endif End Function Function reallocate(p As VoidPtr, length As SIZE_T) As VoidPtr #ifdef NOT_USE_GC Return HeapReAlloc(This.handle,HEAP_ZERO_MEMORY,p,This.currentPosition+count) #else Return _System_pGC->__realloc(p,length) #endif End Function Function size(p As VoidPtr) As Long #ifdef NOT_USE_GC Return HeapSize(This.handle,0,p) #else Dim pmemobj = _System_pGC->GetMemoryObjectPtr(p) Return pmemobj->size #endif End Function End Class End NameSpace 'IO End NameSpace 'System