Index: trunk/Include/Classes/ActiveBasic/Math/Math.ab
===================================================================
--- trunk/Include/Classes/ActiveBasic/Math/Math.ab	(revision 424)
+++ trunk/Include/Classes/ActiveBasic/Math/Math.ab	(revision 426)
@@ -46,6 +46,5 @@
 
 Function IsNaN(ByVal x As Double) As Boolean
-	Dim p As *DWord
-	p = VarPtr(x) As *DWord
+	Dim p = VarPtr(x) As *DWord
 	IsNaN = False
 	If (p[1] And &H7FF00000) = &H7FF00000 Then
@@ -103,6 +102,5 @@
 	Dim s = 0 As DWord
 	If sign Then s = (1 As DWord) << 31
-	Dim p As *DWord
-	p = VarPtr(GetInf) As *DWord
+	Dim p = VarPtr(GetInf) As *DWord
 	p[0] = 0
 	p[1] = &h7FF00000 Or s
Index: trunk/Include/Classes/System/IO/FileStream.ab
===================================================================
--- trunk/Include/Classes/System/IO/FileStream.ab	(revision 424)
+++ trunk/Include/Classes/System/IO/FileStream.ab	(revision 426)
@@ -76,7 +76,7 @@
 
 		op = options As DWord
-		If Not Environment.OSVersion.Platform = PlatformID.Win32NT Then
+'		If (Environment.OSVersion.Platform As DWord) <> (PlatformID.Win32NT As DWord) Then 'ToDo: なぜかアクセス違反になる
 			op And= Not FILE_FLAG_OVERLAPPED
-		End If
+'		End If
 
 		This.handle=CreateFile(ToTCStr(path),ac,sh,ByVal NULL,mo,op,0)
@@ -305,10 +305,10 @@
 	End Sub
 
-	Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long
+	Override Function Read(buffer As *Byte, offset As Long, count As Long) As Long
 		disposedCheck()
 		If buffer = 0 Then
-'			Throw ArgumentNullException("FileStream.Read: An argument is null value.", "buffer")
+			Throw New ArgumentNullException("FileStream.Read: An argument is null value.", "buffer")
 		ElseIf Not This.CanRead() Then
-'			Throw NotSupportedException("FileStream.Read: This stream is not readable.")
+			Throw New NotSupportedException("FileStream.Read: This stream is not readable.")
 		End If
 
@@ -320,5 +320,5 @@
 			overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
 			If overlapped.hEvent = 0 Then
-'				Throw OutOfMemoryException("FileStream.Read: Failed to create an event object.")
+				Throw New OutOfMemoryException("FileStream.Read: Failed to create an event object.")
 			End If
 			Try
@@ -327,10 +327,10 @@
 					Dim error = GetLastError()
 					If error <> ERROR_IO_PENDING Then
-'						Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
+						Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
 					End If
 				End If
 				ret = GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
 				If ret = FALSE Then
-'					Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+					Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
 				End If
 				offset += Read
@@ -341,5 +341,5 @@
 			ret = ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
 			If ret = FALSE Then
-'				Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+				Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
 			End If
 		End If
Index: trunk/Include/Classes/System/IO/StreamReader.ab
===================================================================
--- trunk/Include/Classes/System/IO/StreamReader.ab	(revision 424)
+++ trunk/Include/Classes/System/IO/StreamReader.ab	(revision 426)
@@ -2,10 +2,136 @@
 Namespace IO
 
+Class StreamReader
+	Inherits TextReader
+Public
+	Sub StreamReader(path As String)
+		init(New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+	End Sub
 
-Class StreamReader
-	Inherits System.IO.TextReader
-	' TODO: 実装
+	Sub StreamReader(stream As Stream)
+		init(stream)
+	End Sub
+
+	Override Sub Dispose(disposing As Boolean)
+		s.Dispose(disposing)
+		size = 0
+		cur = 0
+		last = 0
+	End Sub
+
+	Override Function Peek() As Long
+		If cur = last Then
+			last = s.Read(buf, 0, size)
+			cur = 0
+			If last = 0 Then
+				Peek = -1
+				Exit Function
+			End If
+		End If
+		Peek = buf[cur]
+	End Function
+
+	Override Function Read() As Long
+		Read = Peek()
+		cur++
+	End Function
+
+	Override Function Read(buffer As *StrChar, index As Long, count As Long) As Long
+		If buffer = 0 Then
+		ElseIf index < 0 Then
+		ElseIf count < 0 Then
+		End If
+
+		Dim n = last - cur
+		If count <= n Then
+			Read = ReadFromBuffer(buffer, index, count)
+			Exit Function
+		End If
+		Dim p = VarPtr(buffer[index])
+		Read = ReadFromBuffer(p, 0, n)
+		If Read = count Then 'バッファの中身で足りた場合
+			Exit Function
+		End If
+		p = VarPtr(p[n])
+		count -= n
+		If count > size Then
+			n = (count \ size) * size 'sizeの倍数分だけは直接bufferへ読み込ませる
+			Dim read = s.Read(p, 0, n)
+			If read = 0 Then 'EOF
+				Exit Function
+			End If
+			p = VarPtr(p[n])
+			Read += n
+			count -= n
+		End If
+		last = s.Read(buffer, 0, size)
+		cur = 0
+		If last = 0 Then 'EOF
+			Exit Function
+		End If
+		Read += ReadFromBuffer(p, 0, Math.Min(last, count))
+	End Function
+
+	Override Function ReadLine() As String
+		Dim sb = New Text.StringBuilder(256)
+		Do
+			Dim ch = Read()
+			If ch = &h0D Then
+				If Peek() = &h0A Then
+					Read() 'CR LFの場合
+				End If
+				Exit Do
+			End If
+			Select Case ch
+				Case -1 'EOF
+					Exit Do
+				Case &h0A 'LF
+					Exit Do
+				Case &h0B 'VT
+					Exit Do
+				Case &h0C 'FF
+					Exit Do
+				Case &h0D 'CR
+					Exit Do
+'				Case &h85 'NEL
+'					Exit Do
+'				Case &h2028 'LS
+'					Exit Do
+'				Case &h2029 'PS
+'					Exit Do
+			End Select
+			sb.Append(ch As StrChar) 'ToDo キャスト不要にすべきというチケットを書くこと
+		Loop
+		ReadLine = sb.ToString
+	End Function
+
+	Override Function ReadToEnd() As String
+	End Function
+
+Private
+	Sub init(str As Stream)
+		s = str
+		size = 4096
+		last = 0
+		cur = 0
+		buf = GC_malloc(size)
+	End Sub
+
+	/**
+	@brief バッファの中身から読み取る。
+	文字数が足りなくても、元のストリームまで読みには行かない。
+	*/
+	Function ReadFromBuffer(p As *StrChar, index As Long, count As Long) As Long
+		memcpy(VarPtr(p[index]), VarPtr(buf[cur]), count * SizeOf (StrChar))
+		cur += count
+		ReadFromBuffer = count
+	End Function
+
+	s As Stream
+	size As Long
+	cur As Long
+	last As Long '中身の終わり
+	buf As *Byte '暫定
 End Class
-
 
 End Namespace
Index: trunk/Include/Classes/System/IO/TextReader.ab
===================================================================
--- trunk/Include/Classes/System/IO/TextReader.ab	(revision 424)
+++ trunk/Include/Classes/System/IO/TextReader.ab	(revision 426)
@@ -6,32 +6,33 @@
 
 Public
-	Virtual Sub TextReader()	:End Sub
-	Virtual Sub ~TextReader()	:End Sub
+'Protected
+	Sub TextReader()
+	End Sub
+Public
+	Virtual Sub ~TextReader()
+		Dispose(False)
+	End Sub
 
-/* Null*/
+'	Static Null = StreamReader.Null As TextReader
 
 Public
-	Virtual Sub Close()
-		This.Dispose()
+	Sub Close()
+		Dispose(True)
 	End Sub
-/*	CreateObjRef*/
-/*	Dispose*/
-/*	Equals*/
-/*	GetHashCode*/
-/*	GetLifetimeService*/
-/*	GetType*/
-/*	InitializeLifetimeService*/
+
+	Sub Dispose()
+		Dispose(True)
+	End Sub
+
+	Abstract Sub Dispose(disposing As Boolean)
+
 	Abstract Function Peek() As Long
 	Abstract Function Read() As Long
-	Abstract Function Read(buffer As LPTSTR, index As Long, count As Long) As Long
-	Abstract Function ReadBlock(buffer As LPTSTR, index As Long, count As Long) As Long
+	Abstract Function Read(buffer As *StrChar, index As Long, count As Long) As Long
+	Virtual Function ReadBlock(buffer As *StrChar, index As Long, count As Long) As Long
+		ReadBlock = Read(buffer, index, count)
+	End Function
 	Abstract Function ReadLine() As String
 	Abstract Function ReadToEnd() As String
-/*	ReferenceEquals*/
-/*	Synchronized*/
-/*	ToString*/
-/*	Dispose*/
-/*	Finalize*/
-/*	MemberwiseClone*/
 End Class
 
Index: trunk/Include/Classes/System/String.ab
===================================================================
--- trunk/Include/Classes/System/String.ab	(revision 424)
+++ trunk/Include/Classes/System/String.ab	(revision 426)
@@ -117,13 +117,25 @@
 
 		Const Function Operator + (y As PCSTR) As String
-			Return Concat(y, lstrlenA(y))
+			If y = 0 Then
+				Return This
+			Else
+				Return Concat(y, lstrlenA(y))
+			End If
 		End Function
 
 		Const Function Operator + (y As PCWSTR) As String
-			Return Concat(y, lstrlenW(y))
+			If y = 0 Then
+				Return This
+			Else
+				Return Concat(y, lstrlenW(y))
+			End If
 		End Function
 
 		Const Function Operator + (y As String) As String
-			Return Concat(y.Chars, y.m_Length)
+			If ActiveBasic.IsNothing(y) Then
+				Return This
+			Else
+				Return Concat(y.Chars, y.m_Length)
+			End If
 		End Function
 
@@ -133,11 +145,9 @@
 
 		Const Function Operator & (y As PCWSTR) As String
-			Dim tempString = This + y
-			Return tempString
+			Return This + y
 		End Function
 
 		Const Function Operator & (y As String) As String
-			Dim tempString = This + y
-			Return tempString
+			Return This + y
 		End Function
 
