source: trunk/ab5.0/ablib/src/Classes/System/IO/StreamReader.ab@ 662

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

StreamReaderとStringReaderでEOF絡みの判定漏れを修正。

File size: 3.8 KB
Line 
1'Classes/System/IO/StreamReader.ab
2
3Namespace System
4Namespace IO
5
6/*
7@brief ストリームから読み取りを行うTextReaderの実装。
8@date 2008/02/25
9@auther Egtra
10*/
11Class StreamReader
12 Inherits TextReader
13Public
14 /*
15 @date 2008/02/25
16 @auther Egtra
17 */
18 Sub StreamReader(path As String)
19 init(New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
20 End Sub
21
22 /*
23 @date 2008/02/25
24 @auther Egtra
25 */
26 Sub StreamReader(stream As Stream)
27 init(stream)
28 End Sub
29
30Public
31 /*
32 @brief 基になるストリームを取得する
33 @date 2008/09/02
34 @auther NoWest
35 */
36 Function BaseStream () As Stream
37 Return s
38 End Function
39
40 /*
41 @date 2008/02/25
42 @auther Egtra
43 */
44 Override Function Peek() As Long
45 If charSize = charCur Then
46 fillCharBuf()
47 If charSize = charCur Then
48 Peek = -1
49 Exit Function
50 End If
51 End If
52 Peek = charBuf[charCur]
53 End Function
54
55 /*
56 @date 2008/02/25
57 @auther Egtra
58 */
59 Override Function Read() As Long
60 Read = Peek()
61 If Read <> -1 Then
62 charCur++
63 End If
64 End Function
65
66Protected
67 /*
68 @date 2008/02/25
69 @auther Egtra
70 */
71 Override Sub Dispose(disposing As Boolean)
72 If disposing Then
73 If Not ActiveBasic.IsNothing(s) Then
74 s.Dispose(True)
75 End If
76 End If
77 s = Nothing
78 End Sub
79
80 /*
81 @date 2008/02/25
82 @auther Egtra
83 */
84 Override Function ReadImpl(buffer As *WCHAR, count As Long) As Long
85 Dim n = charSize - charCur '現在のバッファに溜まっている文字数
86 If count <= n And charEof <> False Then
87 ReadImpl = readFromBuffer(buffer, count)
88 Exit Function
89 End If
90 ReadImpl = readFromBuffer(buffer, n)
91 If ReadImpl = count Then 'バッファの中身で足りた場合
92 Exit Function
93 End If
94 fillCharBuf()
95 ReadImpl += ReadImpl(VarPtr(buffer[n]), count - n)
96 End Function
97
98Private
99 /*
100 @date 2008/02/25
101 @auther Egtra
102 */
103 Sub init(str As Stream)
104 s = str
105 '暫定。正式版ではUTF-8を標準とする。
106 encoding = New Text.Detail.WindowsCodePageEncoding(CP_ACP)
107 decoder = encoding.GetDecoder()
108 charCapacity = 4096
109 byteCapacity = 4096
110 charBuf = GC_malloc(charCapacity * SizeOf(WCHAR))
111 byteBuf = GC_malloc(byteCapacity)
112 charCur = 0
113 byteCur = 0
114 charSize = 0
115 byteSize = 0
116 charEof = False
117 byteEof = False
118 End Sub
119
120 /**
121 @brief バッファの中身から読み取る。
122 @date 2008/02/25
123 @auther Egtra
124 文字数が足りなくても、元のストリームまで読みには行かない。
125 */
126 Function readFromBuffer(p As *WCHAR, count As Long) As Long
127 memcpy(p, VarPtr(charBuf[charCur]), count * SizeOf (WCHAR))
128 charCur += count
129 readFromBuffer = count
130 End Function
131
132 /*!
133 @brief byteBufを基にcharBufを埋める。charBufが空になったときに用いる。
134 @date 2008/11/08
135 @auther Egtra
136 */
137 Sub fillCharBuf()
138 charCur = 0
139 charSize = 0
140 If charEof = False Then
141 If byteCur = byteSize Then
142 byteSize = s.Read(byteBuf, 0, byteCapacity)
143 byteCur = 0
144 If byteSize = 0 Then
145 byteEof = True
146 End If
147 End If
148 Dim charUsed As Long
149 Dim byteUsed As Long
150 Dim completed As Boolean
151 decoder.Convert(VarPtr(byteBuf[byteCur]), byteSize - byteCur,
152 VarPtr(charBuf[charSize]), charCapacity - charSize,
153 byteEof, charUsed, byteUsed, completed)
154 charEof = byteEof And completed And byteCur = byteSize
155 byteCur += byteUsed
156 charSize += charUsed
157 End If
158 End Sub
159
160 s As Stream
161 encoding As Text.Encoding
162 decoder As Text.Decoder
163 charBuf As *WCHAR
164 byteBuf As *Byte
165 charCur As Long '読み取っていないデータの開始位置
166 byteCur As Long
167 charSize As Long 'Bufの内、有効なデータの数
168 byteSize As Long
169 charCapacity As Long '確保済み容量 = GC_mallocしたときの引数の値
170 byteCapacity As Long
171 charEof As Boolean 'Trueのとき、次にcur = sizeになるまでしかデータがことを示す
172 byteEof As Boolean
173 '常に0 <= cur <= size <= capacity
174End Class
175
176End Namespace
177End Namespace
Note: See TracBrowser for help on using the repository browser.