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
Line 
1Namespace System
2Namespace IO
3
4Class TextReader
5 Implements System.IDisposable
6Public
7 Virtual Sub ~TextReader()
8 Dispose(False)
9 End Sub
10
11' Static Null = StreamReader.Null As TextReader
12
13Public
14 Sub Close()
15 Dispose(True)
16 End Sub
17
18 Sub Dispose()
19 Dispose(True)
20 End Sub
21
22 Virtual Function Peek() As Long
23 If pos >= buf.Length Then
24 buf.Length = 0
25 pos = 0
26 Underflow()
27 If buf.Length = 0 Then
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
39 /*
40 @date 2008/02/26
41 @auther Egtra
42 */
43 Virtual Function Read(buffer As *Char, index As Long, count As Long) As Long
44 If buffer = 0 Then
45 Throw New ArgumentNullException("buffer")
46 ElseIf index < 0 Then
47 Throw New ArgumentOutOfRangeException("index")
48 ElseIf count < 0 Then
49 Throw New ArgumentOutOfRangeException("count")
50 End If
51 Read = ReadImpl(VarPtr(buffer[index]), count)
52 End Function
53
54 Static Function Synchronized(reader As TextReader) As TextReader
55 Synchronized = New Detail.SynchronizedTextReader(reader)
56 End Function
57
58 /*
59 @date 2008/02/26
60 @auther Egtra
61 @retval Nothing EOFに達しているとき
62 @retval 有効なStringインスタンス 読み取った1行
63 */
64 Virtual Function ReadLine() As String
65 If Peek() = -1 Then
66 Exit Function
67 End If
68 Dim sb = New Text.StringBuilder
69 Dim isLead = FALSE
70 Do
71 Dim ch = Read()
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
79 End If
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
100 End If
101 sb.Append(ch As Char)
102#ifndef UNICODE
103 isLead = IsDBCSLeadByte(ch As Byte)
104#endif
105 Loop
106 ReadLine = sb.ToString()
107 End Function
108
109 /*!
110 @brief 現在位置からストリームの終わりまで読み込む。
111 @date 2008/02/26
112 @auther Egtra
113 */
114 Virtual Function ReadToEnd() As String
115 buf.Remove(0, pos)
116 While Underflow()
117 Wend
118 ReadToEnd = buf.ToString()
119 buf.Length = 0
120 pos = 0
121 End Function
122
123Protected
124 Sub TextReader()
125 buf = New Text.StringBuilder
126 pos = 0
127 End Sub
128
129 Virtual Sub Dispose(disposing As Boolean)
130 End Sub
131
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 内部バッファ
148 内部バッファの既存の要素は、一切の変更をしないこと。また、空であるという仮定を置かないこと。
149 */
150 Function Buffer() As Text.StringBuilder
151 Buffer = buf
152 End Function
153
154 /*!
155 @date 2008/02/26
156 @auther Egtra
157 */
158 Function ReadImpl(buffer As *Char, count As Long) As Long
159 'ToDo 適当なところでバッファの読み取り済みの部分を除去する処理を入れる(現在Peekのみ)。
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)
165 ActiveBasic.Strings.ChrCopy(buffer, VarPtr(p[pos]) As *Char, ReadImpl As SIZE_T)
166 pos += ReadImpl
167 End Function
168
169Private
170 buf As Text.StringBuilder
171 pos As Long
172End Class
173
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
185' Using lock = cs.Lock()
186 Peek = base.Peek()
187' End Using
188 End Function
189
190 Override Function Read() As Long
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
203' Using lock = cs.Lock
204 ReadToEnd = base.ReadToEnd
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
227End Namespace
228End Namespace
Note: See TracBrowser for help on using the repository browser.