| 1 | 'Classes/System/IO/StreamReader.ab
|
|---|
| 2 |
|
|---|
| 3 | Namespace System
|
|---|
| 4 | Namespace IO
|
|---|
| 5 |
|
|---|
| 6 | /*
|
|---|
| 7 | @brief ストリームから読み取りを行うTextReaderの実装。
|
|---|
| 8 | @date 2008/02/25
|
|---|
| 9 | @auther Egtra
|
|---|
| 10 | */
|
|---|
| 11 | Class StreamReader
|
|---|
| 12 | Inherits TextReader
|
|---|
| 13 | Public
|
|---|
| 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 |
|
|---|
| 30 | Public
|
|---|
| 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 |
|
|---|
| 66 | Protected
|
|---|
| 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 |
|
|---|
| 98 | Private
|
|---|
| 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
|
|---|
| 174 | End Class
|
|---|
| 175 |
|
|---|
| 176 | End Namespace
|
|---|
| 177 | End Namespace
|
|---|