Index: trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab
===================================================================
--- trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab	(revision 664)
+++ trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab	(revision 676)
@@ -39,6 +39,6 @@
 	@brief	符号化して得られる文字列の長さを計算する。
 	@param[in] src	対象文字列
-	@param[in] srcCount	srcの長さ
-	@return	符号化して得られる文字列の長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
+	@return	符号化して得られる文字列の長さ（要素数単位）
 	@date	2007/12/08
 	*/
@@ -55,5 +55,5 @@
 	@brief	符号化して得られる文字列の長さを計算する。
 	@param[in] src	対象文字列
-	@return	符号化して得られる文字列の長さ
+	@return	符号化して得られる文字列の長さ（要素数単位）
 	@date	2007/12/08
 	*/
@@ -66,24 +66,21 @@
 #endif
 
-Private
+Protected
 	/*!
 	@brief	GetBytesCountの実装を行う。
 	@param[in] src	対象文字列
-	@param[in] srcCount	srcの長さ
-	@return	符号化して得られる文字列の長さ
-	@date	2007/12/08
-	*/
-	Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
-		Dim enc = GetEncoder()
-		GetBytesCountCore = enc.GetBytesCount(src, srcCount, True)
-	End Function
+	@param[in] srcCount	srcの長さ（要素数単位）
+	@return	符号化して得られる文字列の長さ（要素数単位）
+	@date	2007/12/08
+	*/
+	Abstract Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
 Public
 	/*!
 	@brief	符号化する。
 	@param[in] src	入力
-	@param[in] srcCount	srcの長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
 	@param[out] dst	出力
-	@param[in] dstCount	dstのバッファの大きさ
-	@return dstに書き込まれたバイト数
+	@param[in] dstCount	dstのバッファの大きさ（要素数単位）
+	@return dstに書き込まれた要素数
 	@date	2007/12/08
 	*/
@@ -102,24 +99,22 @@
 	End Function
 
-Private
+Protected
 	/*!
 	@brief	GetBytesの処理を行う。
 	@param[in] src	入力
-	@param[in] srcCount	srcの長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
 	@param[out] dst	出力
-	@param[in] dstCount	dstのバッファの大きさ
-	@return dstに書き込まれたバイト数
+	@param[in] dstCount	dstのバッファの大きさ（要素数単位）
+	@return dstに書き込まれた要素数
 	@exception ArgumentException	バッファの大きさが足りない
 	@date	2007/12/08
 	*/
-	Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
-		GetBytesCore = GetEncoder().GetBytes(src, srcCount, dst, dstCount, True)
-	End Function
+	Abstract Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
 Public
 	/*!
 	@brief	復号して得られる文字列の長さを計算する。
 	@param[in] src	対象文字列
-	@param[in] srcCount	srcの長さ
-	@return	復号して得られる文字列の長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
+	@return	復号して得られる文字列の長さ（要素数単位）
 	@date	2007/12/08
 	*/
@@ -133,24 +128,21 @@
 	End Function
 
-Private
+Protected
 	/*!
 	@brief	GetCharsCountの処理を行う。
 	@param[in] src	対象文字列
-	@param[in] srcCount	srcの長さ
-	@return	符号化して得られる文字列の長さ
-	@date	2007/12/08
-	*/
-	Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
-		Dim dec = GetDecoder()
-		GetCharsCountCore = dec.GetCharsCount(src, srcCount, True)
-	End Function
+	@param[in] srcCount	srcの長さ（要素数単位）
+	@return	符号化して得られる文字列の長さ（要素数単位）
+	@date	2007/12/08
+	*/
+	Abstract Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
 Public
 	/*!
 	@brief	復号する。
 	@param[in] src	入力
-	@param[in] srcCount	srcの長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
 	@param[out] dst	出力
-	@param[in] dstCount	srcのバッファの大きさ
-	@return dstに書き込まれたバイト数
+	@param[in] dstCount	srcのバッファの大きさ（要素数単位）
+	@return dstに書き込まれた要素数
 	@date	2007/12/08
 	*/
@@ -169,18 +161,16 @@
 	End Function
 
-Private
+Protected
 	/*!
 	@brief	GetCharsの処理を行う。
 	@param[in] src	入力
-	@param[in] srcCount	srcの長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
 	@param[out] dst	出力
-	@param[in] dstCount	dstのバッファの大きさ
-	@return dstに書き込まれたバイト数
+	@param[in] dstCount	dstのバッファの大きさ（要素数単位）
+	@return dstに書き込まれた要素数
 	@exception ArgumentException	バッファの大きさが足りない
 	@date	2007/12/08
 	*/
-	Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
-		GetCharsCore = GetDecoder().GetChars(src, srcCount, dst, dstCount, True)
-	End Function
+	Abstract Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
 Public
 #ifdef UNICODE
@@ -188,5 +178,5 @@
 	@brief	復号し、Stringで結果を返す。
 	@param[in] src	入力
-	@param[in] srcCount	srcの長さ
+	@param[in] srcCount	srcの長さ（要素数単位）
 	@return	変換結果の文字列
 	@date	2007/12/08
@@ -214,10 +204,10 @@
 Public
 	/*!
+	@brief	復号器を取得する。
+	*/
+	Abstract Function GetDecoder() As Decoder
+
+	/*!
 	@brief	符号器を取得する。
-	*/
-	Abstract Function GetDecoder() As Decoder
-
-	/*!
-	@brief	復号器を取得する。
 	*/
 	Abstract Function GetEncoder() As Encoder
@@ -242,5 +232,5 @@
 
 	/*!
-	@brief	GetPreambleの配列の要素数
+	@brief	GetPreambleの配列の要素数。
 	*/
 	Virtual Function GetPreambleLength() As Long
@@ -248,4 +238,5 @@
 	End Function
 
+Public
 '	Abstract Function BodyName() As String
 '	Abstract Function HeaderName() As String
@@ -333,198 +324,32 @@
 /*!
 @brief	復号を行うクラス
-@date	2007/12/19
+@date	2009/01/12
 @auther	Egtra
+内部処理用
 */
 Class Decoder
 Public
-	/*!
-	@brief	変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@param[out] srcUsed	使用された入力の要素数
-	@param[out] dstUsed	出力の内、実際に書き込まれた要素数
-	@param[out] completed	入力の全ての文字が変換に使われたかどうか
-	*/
-	Sub Convert(src As *Byte, srcCount As Long,
-		dst As *WCHAR, dstCount As Long, flush As Boolean,
-		ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
-
-		If src = 0 And srcCount > 0 Then
-			Throw New ArgumentNullException("src")
-		ElseIf srcCount < 0 Then
-			Throw New ArgumentOutOfRangeException("srcCount")
-		ElseIf dst = 0 Then
-			Throw New ArgumentNullException("dst")
-		ElseIf dstCount < 0 Then
-			Throw New ArgumentOutOfRangeException("dstCount")
-		End If
-		ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
+	Function Decode(dst As Collections.Generic.List<WCHAR>, st As IO.Stream) As Boolean
+		Decode = DecodeImpl(dst, st)
+	End Function
+
+Protected
+	Abstract Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
+End Class
+
+/*!
+@brief	符号化を行うクラス
+@date	2009/01/12
+@auther	Egtra
+内部処理用
+*/
+Class Encoder
+Public
+	Sub Encode(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
+		EncodeImpl(src, size, s, last)
 	End Sub
 
-	/*!
-	@brief	変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@return 出力の内、実際に書き込まれた要素数
-	*/
-	Function GetChars(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean) As Long
-		Dim srcUsed As Long
-		Dim completed As Boolean
-		Convert(src, srcCount, dst, dstCount, flush, srcUsed, GetChars, completed)
-		If srcUsed < srcCount Then
-			Throw New ArgumentException("src", "buffer is too small")
-		End If
-	End Function
-
-	/*!
-	@brief	変換すると何文字になるか数える
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[in] flush	終了後に内部状態を初期化するとして計算するかどうか
-	@return	必要な文字数
-	*/
-	Function GetCharsCount(src As *Byte, srcCount As Long, flush As Boolean) As Long
-		If src = 0 Then
-			Throw New ArgumentNullException("src")
-		ElseIf srcCount < 0 Then
-			Throw New ArgumentOutOfRangeException("srcCount")
-		End If
-		GetCharsCountCore(src, srcCount, flush)
-	End Function
-
-	/*!
-	@brief	内部状態を初期状態に戻す
-	*/
-	Virtual Sub Reset()
-	End Sub
-
-Protected
-	/*!
-	@brief	実際に変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@param[out] dstUsed	使用された入力の要素数
-	@param[out] srcUsed	出力の内、実際に書き込まれた要素数
-	@param[out] completed	入力の全ての文字が変換に使われたかどうか
-	*/
-	Abstract Sub ConvertCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean,
-		ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
-
-	/*!
-	@brief	変換すると何文字になるか数える
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[in] flush	終了後に内部状態を初期化するとして計算するかどうか
-	@return	必要な文字数
-	*/
-	Abstract Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
-End Class
-
-/*!
-@brief	符号化を行うクラス
-@date	2007/12/19
-@auther	Egtra
-*/
-Class Encoder
-Public
-	/*!
-	@brief	変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@param[out] srcUsed	使用された入力の要素数
-	@param[out] dstUsed	出力の内、実際に書き込まれた要素数
-	@param[out] completed	入力の全ての文字が変換に使われたかどうか
-	*/
-	Sub Convert(src As *WCHAR, srcCount As Long,
-		dst As *Byte, dstCount As Long, flush As Boolean,
-		ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
-
-		If src = 0 And srcCount > 0 Then
-			Throw New ArgumentNullException("src")
-		ElseIf srcCount < 0 Then
-			Throw New ArgumentOutOfRangeException("srcCount")
-		ElseIf dst = 0 Then
-			Throw New ArgumentNullException("dst")
-		ElseIf dstCount < 0 Then
-			Throw New ArgumentOutOfRangeException("dstCount")
-		End If
-		ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
-	End Sub
-
-	/*!
-	@brief	変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@return 出力の内、実際に書き込まれた要素数
-	*/
-	Function GetBytes(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean) As Long
-		Dim srcUsed As Long
-		Dim completed As Boolean
-		Convert(src, srcCount, dst, dstCount, flush, srcUsed, GetBytes, completed)
-		If srcUsed < srcCount Then
-			Throw New ArgumentException("src", "buffer is too small")
-		End If
-	End Function
-
-	/*!
-	@brief	変換すると何文字になるか数える
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[in] flush	終了後に内部状態を初期化するとして計算するかどうか
-	@return	必要な文字数
-	*/
-	Function GetBytesCount(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
-		If src = 0 Then
-			Throw New ArgumentNullException("src")
-		ElseIf srcCount < 0 Then
-			Throw New ArgumentOutOfRangeException("srcCount")
-		End If
-		GetBytesCountCore(src, srcCount, flush)
-	End Function
-
-	/*!
-	@brief	内部状態を初期状態に戻す
-	*/
-	Virtual Sub Reset()
-	End Sub
-
-Protected
-	/*!
-	@brief	実際に変換する
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[out] dst	出力
-	@param[in] dstCount 出力要素数
-	@param[in] flush	終了後に内部状態を初期化するかどうか
-	@param[out] dstUsed	使用された入力の要素数
-	@param[out] srcUsed	出力の内、実際に書き込まれた要素数
-	@param[out] completed	入力の全ての文字が変換に使われたかどうか
-	*/
-	Abstract Sub ConvertCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean,
-		ByRef dstUsed As Long, ByRef srcUsed As Long, ByRef completed As Boolean)
-
-	/*!
-	@brief	変換すると何文字になるか数える
-	@param[in] src	入力
-	@param[in] srcCount 入力要素数
-	@param[in] flush	終了後に内部状態を初期化するとして計算するかどうか
-	@return	必要な文字数
-	*/
-	Abstract Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
+Protected
+	Abstract Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
 End Class
 
@@ -549,18 +374,4 @@
 	End Sub
 
-	/*!
-	@brief	符号器を取得する。
-	*/
-	Override Function GetDecoder() As Decoder
-		GetDecoder = New WindowsCodePageDecoder(cp)
-	End Function
-
-	/*!
-	@brief	復号器を取得する。
-	*/
-	Override Function GetEncoder() As Encoder
-		GetEncoder = New WindowsCodePageEncoder(cp)
-	End Function
-
 	Override Function GetHashCode() As Long
 		GetHashCode = cp As Long
@@ -576,4 +387,12 @@
 	End Function
 
+	Override Function GetDecoder() As Decoder
+		GetDecoder = New WindowsCodePageDecoder(cp)
+	End Function
+
+	Override Function GetEncoder() As Encoder
+		GetEncoder = New WindowsCodePageEncoder(cp)
+	End Function
+
 	/*!
 	@brief	ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
@@ -588,4 +407,33 @@
 	Override Function GetMaxCharCount(srcCount As Long) As Long
 		GetMaxCharCount = srcCount
+	End Function
+
+Protected
+	Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
+		GetBytesCountCore = WideCharToMultiByte(cp, 0, src, srcCount, 0, 0, 0, 0)
+		If srcCount <> 0 And GetBytesCountCore = 0 Then
+			ActiveBasic.Windows.ThrowWithLastError()
+		End If
+	End Function
+
+	Override Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
+		GetBytesCore = WideCharToMultiByte(cp, 0, src, srcCount, dst As PCSTR, dstCount, 0, 0)
+		If srcCount <> 0 And GetBytesCore = 0 Then
+			ActiveBasic.Windows.ThrowWithLastError()
+		End If
+	End Function
+
+	Override Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
+		GetCharsCountCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, 0, 0)
+		If srcCount <> 0 And GetCharsCountCore = 0 Then
+			ActiveBasic.Windows.ThrowWithLastError()
+		End If
+	End Function
+
+	Override Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
+		GetCharsCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, dst, dstCount)
+		If srcCount <> 0 And GetCharsCore = 0 Then
+			ActiveBasic.Windows.ThrowWithLastError()
+		End If
 	End Function
 
@@ -594,4 +442,10 @@
 End Class
 
+/*!
+@brief	WideCharToMultiByteで復号化を行うクラス
+@date	2009/01/12
+@auther	Egtra
+内部処理用
+*/
 Class WindowsCodePageEncoder
 	Inherits Encoder
@@ -601,52 +455,24 @@
 	End Sub
 
-	Override Sub Reset()
-		nextByte = 0
+Protected
+	Override Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
+		' サロゲートペアや結合文字列 (Combining Character Sequence)の途中でバッファが途切れている場合に対応する
+		' ToDo: エラー処理
+		Dim mbLen = WideCharToMultiByte(cp, 0, src, size, 0, 0, 0, 0)
+		Dim mbBuf = GC_malloc_atomic(mbLen)
+		WideCharToMultiByte(cp, 0, src, size, mbBuf, mbLen, 0, 0)
+		s.Write(mbBuf, 0, mbLen)
 	End Sub
-
-Protected
-	Override Sub ConvertCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean,
-		ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
-
-		Dim srcPos = 0 As Long
-		Dim dstPos = 0 As Long
-		If dstCount > 0 And nextByte <> 0 Then
-			dst[0] = nextByte
-			nextByte = 0
-			dstPos++
-		End If
-		While srcPos < srcCount And dstPos < srcCount
-			Dim buf[1] As CHAR
-			Dim len = WideCharToMultiByte(cp, WC_COMPOSITECHECK Or WC_DEFAULTCHAR, VarPtr(src[srcPos]), 1, buf, Len(buf), 0, 0)
-			If len = 0 Then
-				ActiveBasic.Windows.ThrowWithLastError()
-			End If
-			dst[dstPos] = buf[0] As Byte
-			If len = 2 Then
-				If dstCount = 1 Then
-					nextByte = buf[1] As Byte
-					Exit While
-				End If
-				dstPos++
-				dst[dstPos] = buf[1] As Byte
-				nextByte = 0
-			End If
-			srcPos++
-			dstPos++
-		Wend
-		srcUsed = srcPos
-		dstUsed = dstPos
-		completed = (srcPos = srcCount And dstPos = srcCount And nextByte = 0)
-	End Sub
-
-	Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
-		GetBytesCountCore = srcCount * 2 + 1 '暫定
-	End Function
 
 Private
 	cp As DWord
-	nextByte As Byte
 End Class
 
+/*!
+@brief	MultiByteToWideCharで復号化を行うクラス
+@date	2009/01/12
+@auther	Egtra
+内部処理用
+*/
 Class WindowsCodePageDecoder
 	Inherits Decoder
@@ -657,51 +483,42 @@
 
 Protected
-	Override Sub ConvertCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean,
-		ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
-
-		Dim srcPos = 0 As Long
-		Dim dstPos = 0 As Long
-		If dstCount > 0 And nextByte <> 0 Then
+	Override Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
+		Dim i As Long
+		For i = 0 To DefalultDecodingBufferSize - 1 'ELM
+			Dim len As Long
 			Dim buf[1] As CHAR
-			buf[0] = nextByte As CHAR
-			buf[1] = src[1] As CHAR
-			Dim len = MultiByteToWideChar(cp, 0, buf, Len(buf), VarPtr(dst[dstPos]), 10)
-			If len = 0 Then
-				ActiveBasic.Windows.ThrowWithLastError()
+			Dim t = s.ReadByte()
+			If t = -1 Then
+				DecodeImpl = False
+				Exit Function
 			End If
-			srcPos++
-			dstPos++
-			nextByte = 0
-		End If
-		While srcPos < srcCount And dstPos < srcCount
-			Dim srcCharSize = 1 As Long
-			If IsDBCSLeadByteEx(cp, src[srcPos]) Then
-				srcCharSize = 2
-				If srcPos + 1 = srcCount Then
-					nextByte = src[srcPos]
-					Exit While
+			buf[0] = t As CHAR
+			If IsDBCSLeadByteEx(cp, buf[0]) Then
+				t = s.ReadByte()
+				If t = -1 Then
+					dst.Add(&hfffd As WCHAR)
+					DecodeImpl = False
+					Exit For
 				End If
+				buf[1] = t As CHAR
+				len = 2
+			Else
+				len = 1
 			End If
-			'将来的には行毎に変換しMB_USEGLYPHCHARSを使うようにしたい。
-			Dim len = MultiByteToWideChar(cp, 0, VarPtr(src[srcPos]) As *CHAR, srcCharSize, VarPtr(dst[dstPos]), 1)
-			If len = 0 Then
-				ActiveBasic.Windows.ThrowWithLastError()
+			Dim wc As WCHAR
+			If MultiByteToWideChar(cp, 0, buf, len, VarPtr(wc), 1) = 0 Then
+				dst.Add(&hFFFD As WCHAR)
+			Else
+				dst.Add(wc)
 			End If
-			srcPos += srcCharSize
-			dstPos++
-		Wend
-		srcUsed = srcPos
-		dstUsed = dstPos
-		completed = (srcPos = srcCount And dstPos = srcCount And nextByte = 0)
-	End Sub
-
-	Override Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
-		GetCharsCountCore = srcCount + 1 '暫定
+		Next
+		DecodeImpl = True
 	End Function
 
 Private
 	cp As DWord
-	nextByte As Byte
 End Class
+
+Const DefalultDecodingBufferSize = 16384
 
 End Namespace
Index: trunk/ab5.0/ablib/src/Classes/System/Text/UTF8Encoding.ab
===================================================================
--- trunk/ab5.0/ablib/src/Classes/System/Text/UTF8Encoding.ab	(revision 664)
+++ trunk/ab5.0/ablib/src/Classes/System/Text/UTF8Encoding.ab	(revision 676)
@@ -12,75 +12,48 @@
 	Inherits Encoder
 Protected
-	Override 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)
-
-		Dim i As Long, j = 0 As Long
-		For i = 0 To ELM(charCount)
-			If chars[i] < &h80 Then
+	Override Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
+		Dim i As Long
+		For i = 0 To ELM(size)
+			If buffer <> 0 Then
+				If _System_IsLowSurrogate(src[i]) Then
+					'UTF-16列からUnicodeコードポイントを復元
+					Dim c = (((buffer And &h3FF) As DWord << 10) Or (src[i] And &h3FF)) + &h10000
+					'4バイト変換
+					s.WriteByte(((c >> 18) Or &hf0) As Byte)
+					s.WriteByte(((c >> 12) And &h3F Or &h80) As Byte)
+					s.WriteByte(((c >> 6) And &h3F Or &h80) As Byte)
+					s.WriteByte((c And &h3F Or &h80) As Byte)
+				Else
+					writeReplacementChar(s)
+				End If
+				buffer = 0
+			ElseIf src[i] < &h80 Then
 				'1バイト変換
-				If j + 1 > byteCount Then
-					'バッファ不足
-					Goto *BufferOver
-				End If
-				bytes[j] = chars[i] As Byte
-				j++
-			ElseIf chars[i] < &h800 Then
+				s.WriteByte(src[i] As Byte)
+			ElseIf src[i] < &h800 Then
 				'2バイト変換
-				If j + 2 > byteCount Then
-					Goto *BufferOver
-				End If
-				bytes[j] = ((chars[i] >> 6) Or &hC0) As Byte
-				j++
-				bytes[j] = (chars[i] And &h3F Or &h80) As Byte
-				j++
-			ElseIf _System_IsHighSurrogate(chars[i]) Then
-				If i + 1 >= charCount Then
-					'バッファに貯め込む
-					If flush = False Then
-						buffer = chars[i]
-						Exit Sub
-					End If
-					'ToDo: chars[i + 1]が範囲外になる場合が考慮されていない
-				ElseIf _System_IsLowSurrogate(chars[i + 1]) = False Then
-					'EncoderFallback
-				End If
-				If j + 4 > byteCount Then
-					Goto *BufferOver
-				End If
-				'UTF-16列からUnicodeコードポイントを復元
-				Dim c = (((chars[i] And &h3FF) As DWord << 10) Or (chars[i + 1] And &h3FF)) + &h10000
-				'4バイト変換
-				bytes[j] = ((c >> 18) Or &hf0) As Byte
-				j++
-				bytes[j] = ((c >> 12) And &h3F Or &h80) As Byte
-				j++
-				bytes[j] = ((c >> 6) And &h3F Or &h80) As Byte
-				j++
-				bytes[j] = (c And &h3F Or &h80) As Byte
-				j++
-				i++
-			ElseIf _System_IsLowSurrogate(chars[i]) Then
-				'EncoderFallback
+				s.WriteByte(((src[i] >> 6) Or &hC0) As Byte)
+				s.WriteByte((src[i] And &h3F Or &h80) As Byte)
+			ElseIf _System_IsHighSurrogate(src[i]) Then
+				'バッファに貯め込む
+				buffer = src[i]
+			ElseIf _System_IsLowSurrogate(src[i]) Then
+				writeReplacementChar(s)
 			Else
 				'3バイト変換
-				If j + 3 > byteCount Then
-					Goto *BufferOver
-				End If
-				bytes[j] = ((chars[i] >> 12) Or &hE0) As Byte
-				j++
-				bytes[j] = ((chars[i] >> 6) And &h3F Or &h80) As Byte
-				j++
-				bytes[j] = (chars[i] And &h3F Or &h80) As Byte
-				j++
+				s.WriteByte(((src[i] >> 12) Or &hE0) As Byte)
+				s.WriteByte(((src[i] >> 6) And &h3F Or &h80) As Byte)
+				s.WriteByte((src[i] And &h3F Or &h80) As Byte)
 			End If
 		Next
-
-		Exit Sub
-	*BufferOver
-		'バッファ不足
-		Throw New ArgumentException("Buffer is not enough.", "bytes")
 	End Sub
 
 Private
+	' U+FFFD Replacement CharacterのUTF-8表現、EF BF BDを書き込む。
+	Sub writeReplacementChar(s As IO.Stream)
+		Dim rc[2] = [&hef, &hbf, &hbd] As Byte
+		s.Write(rc, 0, Len(rc))
+	End Sub
+
 	buffer As WCHAR
 End Class
@@ -89,80 +62,70 @@
 	Inherits Decoder
 Protected
-	Override 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)
-		Dim i As Long, j = 0 As Long
-		For i = 0 To ELM(byteCount)
-			If state = 0 Then
-				If bytes[i] <= &h80 Then
+	Override Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
+		Dim i As Long
+		For i = 0 To DefalultDecodingBufferSize - 1 'ELM
+			Dim b = s.ReadByte()
+			If b = -1 Then
+				DecodeImpl = False
+				Exit Function
+			ElseIf state = 0 Then
+				If b <= &h80 Then
 					'1バイト変換
-					If j = charCount Then Goto *BufferOver
-					chars[j] = bytes[i]
-					j++
-				ElseIf bytes[i] < &hC0 Then
-					'マルチバイトの2バイト目以降
-					'DecoderFallback完成までの暫定
-					If j = charCount Then Goto *BufferOver
-					chars[j] = &hfffd
-					j++
-				ElseIf bytes[i] < &hD0 Then
+					dst.Add(b As WCHAR)
+				ElseIf b < &hC0 Then
+					'先頭バイトがなく、いきなりマルチバイトの2バイト目以降
+					dst.Add(&hFFFD As WCHAR)
+				ElseIf b < &hD0 Then
 					'2バイト文字の始まり
 					last = 2
-					buf = bytes[i] And &h3f
-					state++
-				ElseIf bytes[i] < &hF0 Then
+					buffer = b And &h3F
+					state++
+				ElseIf b < &hF0 Then
 					'3バイト文字の始まり
 					last = 3
-					buf = bytes[i] And &h1f
-					state++
-				Else
+					buffer = b And &h1F
+					state++
+				ElseIf b < &hF8 Then
 					'4バイト文字の始まり
 					last = 4
-					buf = bytes[i] And &h0f
-					state++
+					buffer = b And &h0F
+					state++
+				Else
+					'現在のUTF-8は4バイトを超える表現を認めていない。
+					dst.Add(&hFFFD As WCHAR)
 				End If
 			Else
-				If &h80 <= bytes[i] And bytes[i] < &hC0 Then
+				If &h80 <= b And b < &hC0 Then
 					'マルチバイト文字の2バイト目以降
-					buf <<= 6
-					buf Or= bytes[i] And &h3F
+					buffer <<= 6
+					buffer Or= b And &h3F
 					state++
 					If state = last Then '最終バイトに到達
-						If state = 2 And buf >= &h80 Then
-							chars[j] = buf As WCHAR
-							j++
-						ElseIf state = 3 And buf >= &h800 And buf < &hD800 And &hE0000 >= buf Then
-							chars[j] = buf As WCHAR
-							j++
-						ElseIf state = 4 And buf <= &h10ffff Then
-							buf -= &h10000
-							chars[j] = (&hD800 Or (buf >> 10)) As WCHAR
-							j++
-							chars[j] = (&hDC00 Or (buf And &h3FF)) As WCHAR
-							j++
+						If state = 2 And buffer >= &h80 Then
+							dst.Add(buffer As WCHAR)
+						ElseIf state = 3 And buffer >= &h800 And buffer < &hD800 And &hE0000 >= buffer Then
+							dst.Add(buffer As WCHAR)
+						ElseIf state = 4 And buffer <= &h10FFFF Then
+							buffer -= &h10000
+							dst.Add((&hD800 Or (buffer >> 10)) As WCHAR)
+							dst.Add((&hDC00 Or (buffer And &h3FF)) As WCHAR)
 						Else
-							'DecoderFallback
-							If j = charCount Then Goto *BufferOver
-							chars[j] = &hfffd
-							j++
+							'最短形式でないもの、4バイト形式で10FFFFを超えるコードポイントのもの
+							dst.Add(&hfffd As WCHAR)
 						End If
 						state = 0
 					End If
 				Else
-					'3, 4バイト文字の先頭
-					'DecoderFallback
-					If j = charCount Then Goto *BufferOver
-					chars[j] = &hfffd
-					j++
+					'マルチバイト文字の途中なのに、それ以外のバイトが現れた場合
+					dst.Add(&hFFFD As WCHAR)
+					state = 0
 				End If
 			End If
 		Next
-		Exit Sub
-	*BufferOver
-		'バッファ不足
-		Throw New ArgumentException("Buffer is not enough.", "bytes")
-	End Sub
+		DecodeImpl = True
+	End Function
 
 Private
-	buf As DWord
+	buffer As DWord
 	state As Long
 	last As Long
@@ -180,47 +143,29 @@
 	Inherits Encoding
 Public
-
 	Override Function Clone() As Object
-		Dim c = New UTF8Encoding
-		c.DecoderFallback = This.DecoderFallback
-		c.EncoderFallback = This.EncoderFallback
-		Return c
+		Clone = New UTF8Encoding
 	End Function
 
 	Override Function GetDecoder() As Decoder
 		GetDecoder = New Detail.UTF8Decoder
-'		GetDecoder.Fallback = DecoderFallback
 	End Function
 
 	Override Function GetEncoder() As Encoder
 		GetEncoder = New Detail.UTF8Encoder
-'		GetEncoder.Fallback = EncoderFallback
 	End Function
 
 	Override Function GetMaxByteCount(charCount As Long) As Long
-		Return charCount * 3
+		GetMaxByteCount = charCount * 3
 		'全てがUTF-8で3バイトになる文字の場合が最大。
 
-		'UTF-8で4バイトになる列は、UTF-16だとサロゲートペアで表現するので、
-		'1単位あたりでは2バイトしか食わないことになる。
+		'なお、UTF-8で4バイトになる列は、UTF-16だとサロゲートペアで表現するので、
+		'1単位あたりでは2バイトしか食わないことになり、最大ではない。
 	End Function
 
 	Override Function GetMaxCharCount(byteCount As Long) As Long
 		'全てU+7F以下の文字だけだった場合
-		Return byteCount
-	End Function
-Protected
-	Override Function GetBytesCountCore(s As *WCHAR, n As Long) As Long
-	End Function
-
-	Override Function GetBytesCore(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long) As Long
-	End Function
-
-	Override Function GetCharsCountCore(s As *Byte, n As Long) As Long
-	End Function
-
-	Override Function GetCharsCore(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long) As Long
-	End Function
-Public
+		GetMaxCharCount = byteCount
+	End Function
+
 	Override Function GetPreamble() As *Byte
 		Return bom
@@ -230,13 +175,5 @@
 		Return Len(bom)
 	End Function
-
-	Override Function IsAlwaysNormalized() As Boolean
-		IsAlwaysNormalized = False
-	End Function
-
-	Override Function IsAlwaysNormalized(f As NormalizationForm) As Boolean
-		IsAlwaysNormalized = False
-	End Function
-
+/*
 	Override Function BodyName() As String
 		Return "utf-8"
@@ -258,4 +195,18 @@
 		Return False
 	End Function
+*/
+Protected
+	Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
+	End Function
+
+	Override Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
+	End Function
+
+	Override Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
+	End Function
+
+	Override Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
+	End Function
+
 Private
 	Static bom[2] = [&hEF, &hBB, &hBF] As Byte
