source: trunk/ab5.0/ablib/src/Classes/System/IO/TextReader.ab

Last change on this file was 702, checked in by イグトランス (egtra), 15 years ago

テキスト読み取り時、EOF周りの扱いの誤りを修正

File size: 4.7 KB
RevLine 
[655]1Namespace System
2Namespace IO
[420]3
4Class TextReader
5 Implements System.IDisposable
6Public
[426]7 Virtual Sub ~TextReader()
8 Dispose(False)
9 End Sub
[420]10
[426]11' Static Null = StreamReader.Null As TextReader
[420]12
13Public
[426]14 Sub Close()
15 Dispose(True)
[420]16 End Sub
[426]17
18 Sub Dispose()
19 Dispose(True)
20 End Sub
21
[665]22 Virtual Function Peek() As Long
23 If pos >= buf.Length Then
[676]24 buf.Length = 0
25 pos = 0
[702]26 Underflow()
27 If buf.Length = 0 Then
[665]28 Peek = -1
29 Exit Function
30 End If
31 End If
32 Peek = buf[pos]
33 End Function
34
35 Virtual Function Read() As Long
36 Read = Peek()
37 pos++
38 End Function
[432]39 /*
40 @date 2008/02/26
41 @auther Egtra
42 */
[665]43 Virtual Function Read(buffer As *Char, index As Long, count As Long) As Long
[432]44 If buffer = 0 Then
[655]45 Throw New ArgumentNullException("buffer")
[432]46 ElseIf index < 0 Then
[655]47 Throw New ArgumentOutOfRangeException("index")
[432]48 ElseIf count < 0 Then
[655]49 Throw New ArgumentOutOfRangeException("count")
[432]50 End If
[655]51 Read = ReadImpl(VarPtr(buffer[index]), count)
[426]52 End Function
[432]53
[655]54 Static Function Synchronized(reader As TextReader) As TextReader
55 Synchronized = New Detail.SynchronizedTextReader(reader)
56 End Function
57
[432]58 /*
59 @date 2008/02/26
60 @auther Egtra
61 @retval Nothing EOFに達しているとき
62 @retval 有効なStringインスタンス 読み取った1行
63 */
[665]64 Virtual Function ReadLine() As String
[432]65 If Peek() = -1 Then
66 Exit Function
67 End If
[665]68 Dim sb = New Text.StringBuilder
69 Dim isLead = FALSE
[432]70 Do
71 Dim ch = Read()
[665]72 If ch = -1 Then Exit Do
73 If isLead = FALSE Then
74 If ch = &h0D Then
75 If Peek() = &h0A Then
76 Read() 'CR LFの場合
77 End If
78 Exit Do
[432]79 End If
[665]80 Select Case ch
81 Case -1 'EOF
82 Exit Do
83 Case &h0A 'LF
84 Exit Do
85 Case &h0B 'VT
86 Exit Do
87 Case &h0C 'FF
88 Exit Do
89 Case &h0D 'CR
90 Exit Do
91#ifdef UNICODE
92 Case &h85 'NEL
93 Exit Do
94 Case &h2028 'LS
95 Exit Do
96 Case &h2029 'PS
97 Exit Do
98#endif
99 End Select
[432]100 End If
[665]101 sb.Append(ch As Char)
102#ifndef UNICODE
103 isLead = IsDBCSLeadByte(ch As Byte)
104#endif
[432]105 Loop
[665]106 ReadLine = sb.ToString()
[432]107 End Function
[665]108
109 /*!
[457]110 @brief 現在位置からストリームの終わりまで読み込む。
[432]111 @date 2008/02/26
112 @auther Egtra
113 */
114 Virtual Function ReadToEnd() As String
[665]115 buf.Remove(0, pos)
116 While Underflow()
117 Wend
118 ReadToEnd = buf.ToString()
[676]119 buf.Length = 0
120 pos = 0
[432]121 End Function
122
[655]123Protected
124 Sub TextReader()
[665]125 buf = New Text.StringBuilder
126 pos = 0
[655]127 End Sub
[457]128
[468]129 Virtual Sub Dispose(disposing As Boolean)
130 End Sub
[432]131
[665]132 /*!
133 @brief バッファが足りなくなったときに呼ばれる。
134 @date 2008/12/27
135 @auther Egtra
136 @retval True まだEOFに達していない場合
137 @retval False EOFに達した場合
138 */
139 Virtual Function Underflow() As Boolean
140 Underflow = False
141 End Function
142
143 /*!
144 @brief 内部バッファを返す
145 @date 2008/12/27
146 @auther Egtra
147 @return 内部バッファ
[676]148 内部バッファの既存の要素は、一切の変更をしないこと。また、空であるという仮定を置かないこと。
[665]149 */
150 Function Buffer() As Text.StringBuilder
151 Buffer = buf
152 End Function
153
154 /*!
[432]155 @date 2008/02/26
156 @auther Egtra
157 */
[665]158 Function ReadImpl(buffer As *Char, count As Long) As Long
[676]159 'ToDo 適当なところでバッファの読み取り済みの部分を除去する処理を入れる(現在Peekのみ)。
[665]160 Dim p = StrPtr(buf)
161 While buf.Length - pos < count
162 If Underflow() = False Then Exit While
163 Wend
164 ReadImpl = Math.Min(buf.Length - pos, count)
[676]165 ActiveBasic.Strings.ChrCopy(buffer, VarPtr(p[pos]) As *Char, ReadImpl As SIZE_T)
[665]166 pos += ReadImpl
[432]167 End Function
[665]168
169Private
170 buf As Text.StringBuilder
171 pos As Long
[420]172End Class
173
[457]174Namespace Detail
175
176Class SynchronizedTextReader
177 Inherits TextReader
178Public
179 Sub SynchronizedTextReader(reader As TextReader)
180 cs = New ActiveBasic.Windows.CriticalSection
181 base = reader
182 End Sub
183
184 Override Function Peek() As Long
[665]185' Using lock = cs.Lock()
186 Peek = base.Peek()
[457]187' End Using
188 End Function
189
190 Override Function Read() As Long
[665]191' Using lock = cs.Lock()
192 Read = base.Read()
193' End Using
194 End Function
195
196 Override Function Read(buffer As *Char, index As Long, count As Long) As Long
197' Using lock = cs.Lock()
198 Read = base.Read(buffer, index, count)
199' End Using
200 End Function
201
202 Override Function ReadToEnd() As String
[457]203' Using lock = cs.Lock
[665]204 ReadToEnd = base.ReadToEnd
[457]205' End Using
206 End Function
207
208Protected
209 Override Sub Dispose(disposing As Boolean)
210 Dim s = Nothing As Stream
211 SetPointer(VarPtr(s) As *VoidPtr, InterlockedExchangePointer(ByVal VarPtr(base) As *VoidPtr, 0))
212 If disposing Then
213 If Not ActiveBasic.IsNothing(s) Then
214 s.Dispose()
215 End If
216 cs.Dispose()
217 End If
218 End Sub
219
220Private
221 cs As ActiveBasic.Windows.CriticalSection
222 base As TextReader
223End Class
224
225End Namespace
226
[655]227End Namespace
228End Namespace
Note: See TracBrowser for help on using the repository browser.