Namespace System
Namespace IO

Class Stream
	Implements IDisposable

Protected
	Sub Stream()
	End Sub
Public
	Sub ~Stream()
		This.Dispose(False)
	End Sub
Public
	Abstract Function CanRead() As Boolean
	Abstract Function CanSeek() As Boolean

	Virtual Function CanTimeout() As Boolean
		Return False
	End Function

	Abstract Function CanWrite() As Boolean
	Abstract Function Length() As QWord
	Abstract Sub Position(value As QWord)
	Abstract Function Position() As QWord

	Virtual Sub ReadTimeout(value As Long)
		Throw New InvalidOperationException("Stream does not support Timeout.")
	End Sub

	Virtual Function ReadTimeout() As Long
		Throw New InvalidOperationException("Stream does not support Timeout.")
	End Function

	Virtual Sub WriteTimeout(value As Long)
		Throw New InvalidOperationException("Stream does not support Timeout.")
	End Sub

	Virtual Function WriteTimeout() As Long
		Throw New InvalidOperationException("Stream does not support Timeout.")
	End Function

Public
	Virtual Function BeginRead(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
		Dim r = Read(buffer,offset,count)
		Return New Detail.SyncStreamResultImpl(r, state)
	End Function
	Virtual Function BeginWrite(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
		Write(buffer,offset,count)
		Return New Detail.SyncStreamResultImpl(0, state)
	End Function
	Sub Close()
		Dispose(True)
	End Sub
	Sub Dispose()
		Dispose(True)
	End Sub
	Virtual Function EndRead(asyncResult As System.IAsyncResult) As Long
		Dim ar = asyncResult As Detail.IAsyncStreamResult
		EndRead = ar.WaitAndGetResult
	End Function
	Virtual Sub EndWrite(asyncResult As System.IAsyncResult)
	End Sub
	Abstract Sub Flush()
	Abstract Function Read(buffer As *Byte, offset As Long, count As Long) As Long

	Virtual 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

	Abstract Function Seek(offset As Int64, origin As SeekOrigin) As Int64
	Abstract Sub SetLength(value As QWord)
	Abstract Sub Write(buffer As *Byte, offset As Long, count As Long)
	Virtual Sub WriteByte(b As Byte)
		Write(VarPtr(b), 0, 1)
	End Sub

	Static Function Null() As Stream
		'（Constではなく）読み取り専用にはこうするしかないはず。
		If ActiveBasic.IsNothing(null) Then
			null = New Detail.NullStream
		End If
		Null = null
	End Function
Protected
	Virtual Sub Dispose(disposing As Boolean)
	End Sub

Private
	Static null = Nothing As Stream
End Class

Namespace Detail

/*!
@brief ヌルストリーム
@date 2008/08/21
@auther Egtra
*/
Class NullStream
	Inherits Stream
Public
	Override Function CanRead() As Boolean
		CanRead = True
	End Function

	Override Function Read(buffer As *Byte, offset As Long, count As Long) As Long
		Read = 0
	End Function

	Override Function ReadByte() As Long
		ReadByte = -1
	End Function

	Override Function CanWrite() As Boolean
		CanWrite = True
	End Function

	Override Sub Write(buffer As *Byte, offset As Long, count As Long)
	End Sub

	Override Sub WriteByte(b As Byte)
	End Sub

	Override Sub Flush()
	End Sub

	Override Function CanSeek() As Boolean
		CanSeek = True
	End Function

	Override Function Length() As QWord
		Length = 0
	End Function

	Override Sub Position(value As QWord)
	End Sub

	Override Function Position() As QWord
		Position = 0
	End Function

	Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64
		Seek = 0
	End Function

	Override Sub SetLength(value As QWord)
	End Sub
End Class

/*!
@brief 書き込みバイト数を記憶するヌルストリーム
Encoding関連で使用
@date 2009/02/16
@auther Egtra
*/
Class WriteCountingNullStream
	Inherits NullStream
Public
	Sub WriteCountingNullStream()
		writeCount = 0
	End Sub

	Override Sub Write(buffer As *Byte, offset As Long, count As Long)
		If count < 0 Then
			Throw New ArgumentOutOfRangeException("count")
		End If
		writeCount += count
	End Sub

	Override Sub WriteByte(b As Byte)
		writeCount++
	End Sub

	/*!
	@brief 書き込まれたバイト数を返す。
	*/
	Function WriteCount() As Long
		WriteCount = writeCount
	End Function

Private
	writeCount As Long
End Class

End Namespace

End Namespace
End Namespace
