/*!
@file	Classes/System/Text/Encoding.ab
@brief	Encodingクラスとそれに関係するクラスなどの宣言・定義
*/

Namespace System
Namespace Text

/*!
@brief	各種の文字符号化（エンコーディング）を行うためのクラス
@date	2007/12/07
@auther	Egtra

なお、このクラスで、文字列の長さやバッファの大きさを指定するときには、
1 chars = 2バイト（UTF-16符号単位）、1 bytes = 1バイトの単位で指定する。

*/
Class Encoding
	Implements ICloneable
Public
	/*!
	@brief	簡易的複製を作成する。
	*/
	Abstract Function Clone() As Object

'	Override Function Equals(y As Object) As Boolean
'	End Function

'	Override Function GetHashCode() As Long
'	End Function

Public
	Sub Encoding()
		decoderFallback = New DecoderReplacementFallback
	End Sub

	/*!
	@brief	符号化して得られる文字列の長さを計算する。
	@param[in] s	対象文字列
	@param[in] n	sの長さ
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Function GetBytesCount(s As *WCHAR, n As Long) As Long
		If s = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytesCount: An argument is null value.", "s")
		ElseIf n < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytesCount: An argument is out of range value.", "n")
		End If
		Return GetBytesCountCore(s, n)
	End Function
#ifdef UNICODE
	/*!
	@brief	符号化して得られる文字列の長さを計算する。
	@param[in] s	対象文字列
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Function GetBytesCount(s As String) As Long
		If ActiveBasic.IsNothing(s) Then
			Throw New ArgumentNullException("Encoding.GetBytesCount: An argument is null value.", "s")
		End If
		Return GetBytesCountCore(StrPtr(s), s.Length)
	End Function
#endif
	/*!
	@brief	符号化して得られる文字列の長さを計算する。
	@param[in] s	対象文字列
	@param[in] index	開始位置
	@param[in] count	符号化する文字の数
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Function GetBytesCount(s As *WCHAR, index As Long, count As Long) As Long
		If s = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytesCount: An argument is null value.", "s")
		ElseIf index < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytesCount: An argument is out of range value.", "index")
		ElseIf count < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytesCount: An argument is out of range value.", "count")
		End If
		Return GetBytesCountCore(VarPtr(s[index]), count)
	End Function
Protected
	/*!
	@brief	GetBytesCountの実装を行う。
	@param[in] s	対象文字列
	@param[in] n	sの長さ
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Abstract Function GetBytesCountCore(s As *WCHAR, n As Long) As Long
Public
	/*!
	@brief	符号化する。
	@param[in] chars	入力
	@param[in] charCount	charsの長さ
	@param[out] bytes	出力
	@param[in] byteCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@date	2007/12/08
	*/
	Function GetBytes(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long) As Long
		If chars = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "chars")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "bytes")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "charCount")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "byteCount")
		End If

		Return GetBytesCore(chars, charCount, bytes, byteCount)
	End Function
	/*!
	@brief	符号化する。
	@param[in] chars	入力
	@param[in] index	charsの開始位置
	@param[in] count	符号化する文字の数
	@param[out] bytes	出力
	@param[in] byteCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@date	2007/12/08
	*/
	Function GetBytes(chars As *WCHAR, index As Long, count As Long, bytes As *Byte, byteCount As Long) As Long
		If chars = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "chars")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "bytes")
		ElseIf index < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytesCount: An argument is out of range value.", "index")
		ElseIf count < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytesCount: An argument is out of range value.", "count")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "byteCount")
		End If

		Return GetBytesCore(VarPtr(chars[index]), count, bytes, byteCount)
	End Function
#ifdef UNICODE
	/*!
	@brief	符号化する。
	@param[in] s	入力
	@param[in] index	sの開始位置
	@param[in] count	符号化する文字の数
	@param[out] bytes	出力
	@param[in] byteCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@date	2007/12/08
	*/
	Function GetBytes(s As String, index As Long, count As Long, bytes As *Byte, byteCount As Long) As Long
		If chars = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "chars")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetBytes: An argument is null value.", "bytes")
		ElseIf index < 0 Or index >= s.Length Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "index")
		ElseIf count < 0 Or index + count >= s.Length Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "count")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetBytes: An argument is out of range value.", "byteCount")
		End If
		Dim p = StrPtr(s)
		Return GetBytesCore(VarPtr(p[index]), count, bytes, byteCount)
	End Function
#endif
Protected
	/*!
	@brief	GetBytesの処理を行う。
	@param[in] chars	入力
	@param[in] charCount	charsの長さ
	@param[out] bytes	出力
	@param[in] byteCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@exception ArgumentException	バッファの大きさが足りない
	@exception EncoderFallbackException	フォールバックが発生した
	@date	2007/12/08
	*/
	Abstract Function GetBytesCore(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long) As Long

Public
	/*!
	@brief	復号して得られる文字列の長さを計算する。
	@param[in] s	対象文字列
	@param[in] n	sの長さ
	@return	復号して得られる文字列の長さ
	@date	2007/12/08
	*/
	Function GetCharsCount(s As *Byte, n As Long) As Long
		If s = 0 Then
			Throw New ArgumentNullException("Encoding.GetCharsCount: An argument is null value.", "s")
		ElseIf n < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetCharsCount: An argument is out of range value.", "n")
		End If
		Return GetCharsCountCore(s, n)
	End Function
	/*!
	@brief	復号して得られる文字列の長さを計算する。
	@param[in] s	対象文字列
	@param[in] index	開始位置
	@param[in] count	符号化する文字の数
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Function GetCharsCount(s As *Byte, index As Long, count As Long) As Long
		If s = 0 Then
			Throw New ArgumentNullException("Encoding.GetCharsCount: An argument is null value.", "s")
		ElseIf index < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetCharsCount: An argument is out of range value.", "index")
		ElseIf count < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetCharsCount: An argument is out of range value.", "count")
		End If
		Return GetCharsCountCore(VarPtr(s[index]), count)
	End Function
Protected
	/*!
	@brief	GetCharsCountの処理を行う。
	@param[in] s	対象文字列
	@param[in] n	sの長さ
	@return	符号化して得られる文字列の長さ
	@date	2007/12/08
	*/
	Abstract Function GetCharsCountCore(s As *Byte, n As Long) As Long
	/*!
	*/
Public
	/*!
	@brief	復号する。
	@param[in] bytes	入力
	@param[in] byteCount	charsの長さ
	@param[out] chars	出力
	@param[in] charCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@date	2007/12/08
	*/
	Function GetChars(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long) As Long
		If chars = 0 Then
			Throw New ArgumentNullException("Encoding.GetChars: An argument is null value.", "chars")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetChars: An argument is null value.", "bytes")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetChars: An argument is out of range value.", "charCount")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetChars: An argument is out of range value.", "byteCount")
		End If

		Return GetCharsCore(bytes, byteCount, chars, charCount)
	End Function
	/*!
	@brief	復号する。
	@param[in] bytes	入力
	@param[in] index	charsの開始位置
	@param[in] count	符号化する文字の数
	@param[out] chars	出力
	@param[in] charCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@date	2007/12/08
	*/
	Function GetChars(bytes As *Byte, index As Long, count As Long, chars As *WCHAR, charCount As Long) As Long
		If chars = 0 Then
			Throw New ArgumentNullException("Encoding.GetChars: An argument is null value.", "chars")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetChars: An argument is null value.", "bytes")
		ElseIf index < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetChars: An argument is out of range value.", "index")
		ElseIf count < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetChars: An argument is out of range value.", "count")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetChars: An argument is out of range value.", "byteCount")
		End If

		Return GetCharsCore(VarPtr(bytes[index]), count, chars, charCount)
	End Function
Protected
	/*!
	@brief	GetCharsの処理を行う。
	@param[in] bytes	入力
	@param[in] byteCount	charsの長さ
	@param[out] chars	出力
	@param[in] charCount	bytesのバッファの大きさ
	@return bytesに書き込まれたバイト数
	@exception ArgumentException	バッファの大きさが足りない
	@exception EncoderFallbackException	フォールバックが発生した
	@date	2007/12/08
	*/
	Abstract Function GetCharsCore(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long) As Long
Public
#ifdef UNICODE
	/*!
	@brief	復号し、Stringで結果を返す。
	@param[in] bytes	入力
	@param[in] byteCount	charsの長さ
	@return	変換結果の文字列
	@date	2007/12/08
	*/
	Function GetString(bytes As *Byte, byteCount As Long) As String
		If bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetString: An argument is null value.", "bytes")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetString: An argument is out of range value.", "byteCount")
		End If
		Return getStringCore(bytes, byteCount)
	End Function
	/*!
	@brief	復号し、Stringで結果を返す。
	@param[in] bytes	入力
	@param[in] index	charsの開始位置
	@param[in] count	符号化する文字の数
	@return	変換結果の文字列
	@date	2007/12/08
	*/
	Function GetString(bytes As *Byte, index As Long, count As Long) As String
		If bytes = 0 Then
			Throw New ArgumentNullException("Encoding.GetString: An argument is null value.", "bytes")
		ElseIf index < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetString: An argument is out of range value.", "index")
		ElseIf count < 0 Then
			Throw New ArgumentOutOfRangeException("Encoding.GetString: An argument is out of range value.", "count")
		End If
		Return getStringCore(VarPtr(bytes[index]), count)
	End Function
Private

	Function getStringCore(bytes As *Byte, byteCount As Long) As String
		Dim sb = New StringBuilder
		Dim bufSize = GetMaxCharCount(byteCount)
		sb.Length = bufSize
		Dim len = GetCharsCore(bytes, byteCount, StrPtr(sb), bufSize)
		sb.Length = len
		getStringCore = sb.ToString
	End Function
#endif

Public
	/*!
	@brief	符号器を取得する。
	*/
	Abstract Function GetDecoder() As Decoder

	/*!
	@brief	復号器を取得する。
	*/
	Abstract Function GetEncoder() As Encoder

	/*!
	@brief	ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
	*/
	Abstract Function GetMaxByteCount(charCount As Long) As Long

	/*!
	@brief	ある長さのバイト列を復号して得られる文字列の最大の長さを返す。
	*/
	Abstract Function GetMaxCharCount(charCount As Long) As Long

	/*!
	@brief	符号化された文字列の先頭につける識別文字列の取得
	ようするにUTFのBOM
	*/
	Virtual Function GetPreamble() As *Byte
		Return 0
	End Function

	/*!
	@brief	GetPreambleの配列の要素数
	*/
	Virtual Function GetPreambleLength() As Long
		Return 0
	End Function

	/*!
	@brief	正規化されるかどうか。
	*/
	Abstract Function IsAlwaysNormalized() As Boolean

	/*!
	@brief	指定された方式で正規化されるかどうか。
	*/
	Abstract Function IsAlwaysNormalized(form As NormalizationForm) As Boolean

	Abstract Function BodyName() As String
	Abstract Function HeaderName() As String

	/*!
	@brief	コードページの取得。
	*/
'	Abstract Function CodePage() As Long
	/*!
	@brief	最も厳密に対応するWindowsコードページの取得。
	*/
'	Abstract Function WindowsCodePage() As Long

	Function DecoderFallback() As DecoderFallback
		Return decoderFallback
	End Function

	Sub DecoderFallback(f As DecoderFallback)
		If ActiveBasic.IsNothing(f) Then
			Throw New ArgumentNullException("f")
		End If
		decoderFallback = f
	End Sub

	Function EncoderFallback() As EncoderFallback
		Return encoderFallback
	End Function

	Sub EncoderFallback(f As EncoderFallback)
		If ActiveBasic.IsNothing(f) Then
			Throw New ArgumentNullException("f")
		End If
		encoderFallback = f
	End Sub

Private
	decoderFallback As DecoderFallback
	encoderFallback As EncoderFallback
Public
	/*!
	@brief	この符号化形式の名前の取得。
	*/
	Abstract Function EncodingName() As String

	/*!
	@brief	この符号化形式のIANA登録名の取得。
	*/
	Abstract Function WebName() As String

'	Abstract Function IsBrowserDisplay() As Boolean
'	Abstract Function IsBrowserSave() As Boolean
'	Abstract Function IsMailNewsDisplay() As Boolean
'	Abstract Function IsMailNewsSave() As Boolean

'	Abstract Function IsReadOnly() Boolean

	/*!
	@brief	この符号化形式が、1バイト文字だけを使う（複数バイト文字を使わない）かどうか。
	*/
	Abstract Function IsSingleByte() As Boolean

	'GetPreamble

	/*!
	@brief	ある符号化文字列から別の符号化文字列へ変換する。
	@param[in] srcEncoding	入力の符号化方式
	@param[in] dstEncoding	出力の符号化方式
	@param[in] bytes	入力文字列
	@param[in] size	バイト単位での文字列の長さ
	@return	出力文字列
	@exception ArgumentNullException	srcEncoding, dstEncoding, bytesの少なくとも1つ以上がNothing/NULLのとき。
	@exception ArgumentOutOfRangeException	sizeが明らかに範囲外（負の値など）のとき。
	@exception DecoderFallbackException
	@exception EncoderFallbackException
	*/
	Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, size As Long) As *Byte
	End Function
	
	Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, index As Long, count As Long) As *Byte
	End Function

	/*!
	@brief	指定したコードページ用のEncodingインスタンスの取得。
	*/
	Static Function GetEncoding(codepage As Long) As Encoding
	End Function
'	Static Function GetEncoding(codepage As Long, encoderFallback As EncoderFallback, decoderFallback As DecoderFallback) As Encoding
'	End Function
	/*!
	@brief	指定した符号化形式名用のEncodingインスタンスの取得。
	*/
	Static Function GetEncoding(name As String) As Encoding
	End Function
'	Static Function GetEncoding(name As String, encoderFallback As EncoderFallback, decoderFallback As DecoderFallback) As Encoding
'	End Function

	/*!
	@brief	システム既定のANSIコードページ用のEncodingインスタンスの取得。
	*/
	Static Function Default() As Encoding
	End Function
	/*!
	@brief	UTF-7用のEncodingインスタンスの取得。
	*/
	Static Function UTF7() As Encoding
	End Function
	/*!
	@brief	UTF-8用のEncodingインスタンスの取得。
	*/
	Static Function UTF8() As Encoding
	End Function
	/*!
	@brief	UTF-16LE用のEncodingインスタンスの取得。
	*/
	Static Function UTF16() As Encoding
	End Function
	/*!
	@brief	UTF-16BE用のEncodingインスタンスの取得。
	*/
	Static Function UTF16BE() As Encoding
	End Function
	/*!
	@brief	UTF-32LE用のEncodingインスタンスの取得。
	*/
	Static Function UTF32() As Encoding
	End Function
End Class

/*!
@brief	復号を行うクラス
@date	2007/12/19
@auther	Egtra
*/
Class Decoder
Public
	/*!
	@brief	変換する
	@param[in] bytes	入力
	@param[in] byteIndex 入力開始位置
	@param[in] byteCount 入力要素数
	@param[out] chars	出力
	@param[in] charIndex 出力開始位置
	@param[in] charCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@param[out] charsUsed	使用された入力の要素数
	@param[out] bytesUsed	出力の内、実際に書き込まれた要素数
	@param[out] completed	入力の全ての文字が変換に使われたかどうか
	*/
	Sub Convert(bytes As *Byte, byteIndex As Long, byteCount As Long,
		chars As *WCHAR, charIndex As Long, charCount As Long, flush As Boolean,
		ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)

		If bytes = 0 Then
			Throw New ArgumentNullException("bytes")
		ElseIf byteIndex < 0 Then
			Throw New ArgumentOutOfRangeException("byteIndex")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("byteCount")
		ElseIf chars = 0 Then
			Throw New ArgumentNullException("chars")
		ElseIf charIndex < 0 Then
			Throw New ArgumentOutOfRangeException("charIndex")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("charCount")
		End If
		ConvertCore(VarPtr(bytes[byteIndex]), byteCount, VarPtr(chars[charIndex]), charCount, flush, bytesUsed, charsUsed, completed)
	End Sub

	/*!
	@overload Sub Convert(bytes As *Byte, byteIndex As Long, byteCount As Long,
		chars As *WCHAR, charIndex As Long, charCount As Long, flush As Boolean,
		ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)
	*/
	Sub Convert(bytes As *Byte, byteCount As Long,
		chars As *WCHAR, charCount As Long, flush As Boolean,
		ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)

		If bytes = 0 Then
			Throw New ArgumentNullException("bytes")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("byteCount")
		ElseIf chars = 0 Then
			Throw New ArgumentNullException("chars")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("charCount")
		End If
		ConvertCore(bytes, byteCount, chars, charCount, flush, bytesUsed, charsUsed, completed)
	End Sub

	/*!
	@brief	変換する
	@param[in] bytes	入力
	@param[in] byteIndex 入力開始位置
	@param[in] byteCount 入力要素数
	@param[out] chars	出力
	@param[in] charIndex 出力開始位置
	@param[in] charCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@return	出力の内、実際に書き込まれた要素数
	*/
	Function GetChars(bytes As *Byte, byteIndex As Long, byteCount As Long, chars As *WCHAR, charIndex As Long, charCount As Long, flush As Boolean) As Long
		Dim bytesUsed As Long
		Dim completed As Boolean
		Convert(bytes, byteIndex, byteCount, chars, charIndex, charCount, flush, bytesUsed, GetChars, completed)
	End Function

	/*!
	@overload Function GetChars(bytes As *Byte, byteIndex As Long, byteCount As Long, chars As *WCHAR, charIndex As Long, charCount As Long, flush As Boolean) As Long
	*/
	Function GetChars(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long, flush As Boolean) As Long
		Dim bytesUsed As Long
		Dim completed As Boolean
		Convert(bytes, byteCount, chars, charCount, flush, bytesUsed, GetChars, completed)
	End Function

	/*!
	@overload Function GetChars(bytes As *Byte, byteIndex As Long, byteCount As Long, chars As *WCHAR, charIndex As Long, charCount As Long, flush As Boolean) As Long
	*/
	Function GetChars(bytes As *Byte, byteIndex As Long, byteCount As Long, chars As *WCHAR, charIndex As Long, charCount As Long) As Long
		GetChars = GetChars(bytes, byteIndex, byteCount, chars, charIndex, charCount, False)
	End Function

	/*!
	@brief	フォールバックの取得
	*/
	Function Fallback() As DecoderFallback
		Return fallback
	End Function

	/*!
	@brief	フォールバックの設定
	*/
	Sub Fallback(newFallback As DecoderFallback)
		If ActiveBasic.IsNothing(newFallback) Then
			Throw New ArgumentNullException("newFallback")
		End If
		fallback = newFallback
	End Sub
Protected
	/*!
	@brief	実際に変換するメソッド
	@param[in] bytes	入力
	@param[in] byteCount 入力要素数
	@param[out] chars	出力
	@param[in] charCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@param[out] charsUsed	使用された入力の要素数
	@param[out] bytesUsed	出力の内、実際に書き込まれた要素数
	@param[out] completed	入力の全ての文字が変換に使われたかどうか
	*/
	Abstract Sub ConvertCore(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long, flush As Boolean,
		ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)

Private
	fallback As DecoderFallback
End Class

/*!
@brief	符号化を行うクラス
@date	2007/12/19
@auther	Egtra
*/
Class Encoder
Public
	/*!
	@brief	変換する
	@param[in] chars	入力
	@param[in] charIndex 入力開始位置
	@param[in] charCount 入力要素数
	@param[out] bytes	出力
	@param[in] byteIndex 出力開始位置
	@param[in] byteCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@param[out] charsUsed	使用された入力の要素数
	@param[out] bytesUsed	出力の内、実際に書き込まれた要素数
	@param[out] completed	入力の全ての文字が変換に使われたかどうか
	*/
	Sub Convert(chars As *WCHAR, charIndex As Long, charCount As Long,
		bytes As *Byte, byteIndex As Long, byteCount As Long, flush As Boolean,
		ByRef charsUsed As Long, ByRef bytesUsed As Long, ByRef completed As Boolean)

		If chars = 0 Then
			Throw New ArgumentNullException("chars")
		ElseIf charIndex < 0 Then
			Throw New ArgumentOutOfRangeException("charIndex")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("charCount")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("bytes")
		ElseIf byteIndex < 0 Then
			Throw New ArgumentOutOfRangeException("byteIndex")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("byteCount")
		End If
		ConvertCore(VarPtr(chars[charIndex]), charCount, VarPtr(bytes[byteIndex]), byteCount, flush, charsUsed, bytesUsed, completed)
	End Sub

	/*!
	@overload Sub Convert(chars As *WCHAR, charIndex As Long, charCount As Long,
		bytes As *Byte, byteIndex As Long, byteCount As Long, flush As Boolean,
		ByRef charsUsed As Long, ByRef bytesUsed As Long, ByRef completed As Boolean)
	*/
	Sub Convert(chars As *WCHAR, charCount As Long,
		bytes As *Byte, byteCount As Long, flush As Boolean,
		ByRef charsUsed As Long, ByRef bytesUsed As Long, ByRef completed As Boolean)

		If chars = 0 Then
			Throw New ArgumentNullException("chars")
		ElseIf charCount < 0 Then
			Throw New ArgumentOutOfRangeException("charCount")
		ElseIf bytes = 0 Then
			Throw New ArgumentNullException("bytes")
		ElseIf byteCount < 0 Then
			Throw New ArgumentOutOfRangeException("byteCount")
		End If
		ConvertCore(chars, charCount, bytes, byteCount, flush, charsUsed, bytesUsed, completed)
	End Sub

	/*!
	@brief	変換する
	@param[in] chars	入力
	@param[in] charIndex 入力開始位置
	@param[in] charCount 入力要素数
	@param[out] bytes	出力
	@param[in] byteIndex 出力開始位置
	@param[in] byteCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@return bytesUsed	出力の内、実際に書き込まれた要素数
	*/
	Function GetBytes(chars As *WCHAR, charIndex As Long, charCount As Long, bytes As *Byte, byteIndex As Long, byteCount As Long, flush As Boolean) As Long
		Dim charsUsed As Long
		Dim completed As Boolean
		Convert(chars, charIndex, charCount, bytes, byteIndex, byteCount, flush, charsUsed, GetBytes, completed)
	End Function

	/*!
	@overload Function GetBytes(chars As *WCHAR, charIndex As Long, charCount As Long, bytes As *Byte, byteIndex As Long, byteCount As Long, flush As Boolean) As Long
	*/
	Function GetBytes(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long, flush As Boolean) As Long
		Dim charsUsed As Long
		Dim completed As Boolean
		Convert(chars, charCount, bytes, byteCount, flush, charsUsed, GetBytes, completed)
	End Function

	/*!
	@overload Function GetBytes(chars As *WCHAR, charIndex As Long, charCount As Long, bytes As *Byte, byteIndex As Long, byteCount As Long, flush As Boolean) As Long
	*/
	Function GetBytes(chars As *WCHAR, charIndex As Long, charCount As Long, bytes As *Byte, byteIndex As Long, byteCount As Long) As Long
		GetBytes = GetBytes(chars, charIndex, charCount, bytes, byteIndex, byteCount, False)
	End Function

	/*!
	@brief	フォールバックの取得
	*/
	Function Fallback() As EncoderFallback
		Return fallback
	End Function

	/*!
	@brief	フォールバックの設定
	*/
	Sub Fallback(newFallback As EncoderFallback)
		If ActiveBasic.IsNothing(newFallback) Then
			Throw New ArgumentNullException("newFallback")
		End If
		fallback = newFallback
	End Sub
Protected
	/*!
	@brief	実際に変換するメソッド
	@param[in] chars	入力
	@param[in] charCount 入力要素数
	@param[out] bytes	出力
	@param[in] byteCount 出力要素数
	@param[in] flush	終了後に内部状態を初期化するかどうか
	@param[out] bytesUsed	使用された入力の要素数
	@param[out] charsUsed	出力の内、実際に書き込まれた要素数
	@param[out] completed	入力の全ての文字が変換に使われたかどうか
	*/
	Abstract Sub ConvertCore(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long, flush As Boolean,
		ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)

Private
	fallback As EncoderFallback
End Class

Enum NormalizationForm
	FormC
	FormD
	FormKC
	FormKD
End Enum

Class EncoderFallback
End Class

End Namespace 'Text
End Namespace 'System
