Ignore:
Timestamp:
Dec 28, 2008, 12:18:53 AM (15 years ago)
Author:
イグトランス (egtra)
Message:

TextWriter同様TextReaderでバッファリングし、StreamReaderはMultiByteToWideChar固定で仮実装。これで、マルチバイトモードでもStringReaderが使えるようにした。
(#235)

Location:
trunk/ab5.0/ablib/src/Classes/System/IO
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/ab5.0/ablib/src/Classes/System/IO/StreamReader.ab

    r662 r665  
    3838    End Function
    3939
    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
    6540
    6641Protected
     
    7954
    8055    /*
    81     @date 2008/02/25
     56    @date 2008/12/27
    8257    @auther Egtra
    8358    */
    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)
     59    Override Function Underflow() As Boolean
     60        Dim wcBuf[4095] As WCHAR
     61        Dim mbBuf[4095] As SByte
     62        Dim mbLen = s.Read(mbBuf As *Byte, 0, Len(buf))
     63        If mbLen = 0 Then
     64            Underflow = False
    8865            Exit Function
    8966        End If
    90         ReadImpl = readFromBuffer(buffer, n)
    91         If ReadImpl = count Then 'バッファの中身で足りた場合
    92             Exit Function
     67        Dim pNext = mbBuf As PSTR
     68        Do
     69            Dim q = CharNextExA(cp, pNext, 0)
     70            If q = pNext Then
     71                Exit Do
     72            End If
     73            pNext = q As PSTR
     74        Loop
     75        If pNext <> mbBuf + mbLen Then
     76            leadByte = mbBuf[mbLen - 1]
    9377        End If
    94         fillCharBuf()
    95         ReadImpl += ReadImpl(VarPtr(buffer[n]), count - n)
     78        Dim wcLen = MultiByteToWideChar(cp, 0, mbBuf, (pNext - mbBuf) As Long, wcBuf, 4095)
     79        Dim s = New String(wcBuf, wcLen)
     80        Dim buf = Buffer
     81        buf.Append(s)
     82        Underflow = True
    9683    End Function
     84Private
    9785
    98 Private
    9986    /*
    10087    @date 2008/02/25
     
    10390    Sub init(str As Stream)
    10491        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
     92        cp  = CP_ACP '暫定。
     93        leadByte = 0
    15894    End Sub
    15995
    16096    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
     97    cp As Word
     98    leadByte As Byte
    17499End Class
    175100
  • trunk/ab5.0/ablib/src/Classes/System/IO/StringReader.ab

    r662 r665  
    2323            Throw New ArgumentNullException("str")
    2424        End If
    25         Dim length = GetStr(str, s)
    26         If length > LONG_MAX Then
    27             Throw New ArgumentException("Must be Length <= LONG_MAX", "str")
    28         End If
    29         len = length As Long
    30         i = 0
     25        Buffer.Append(str)
    3126    End Sub
    3227
    33     /*
    34     @date 2008/02/26
    35     @auther Egtra
    36     */
    37     Override Function Peek() As Long
    38         If i >= len Then
    39             Peek = -1
    40         Else
    41             Peek = s[i]
    42         End If
    43     End Function
    4428
    45     /*
    46     @date 2008/02/26
    47     @auther Egtra
    48     */
    49     Override Function Read() As Long
    50         Read = Peek()
    51         i++
    52     End Function
    53 
    54     /*
    55     @date 2008/02/26
    56     @auther Egtra
    57     */
    58 /*
    59     Override Function ReadToEnd() As String
    60         ReadToEnd = s.Substring(i)
    61         i = s.Length
    62     End Function
    63 */
    6429Protected
    6530    /*
     
    6833    */
    6934    Override Sub Dispose(disposing As Boolean)
    70         s = Nothing
    71         i = 0
    7235    End Sub
    73 
    74     /*
    75     @date 2008/02/26
    76     @auther Egtra
    77     */
    78     Override Function ReadImpl(buffer As *WCHAR, count As Long) As Long
    79         ReadImpl = Math.Min(count, len - i)
    80         ActiveBasic.Strings.ChrCopy(buffer, VarPtr(s[i]), ReadImpl As SIZE_T) 'ToDo: ポインタに対する+演算
    81     End Function
    82 
    83 Private
    84     s As *WCHAR
    85     len As Long
    86     i As Long
    8736End Class
    8837
  • trunk/ab5.0/ablib/src/Classes/System/IO/TextReader.ab

    r655 r665  
    2020    End Sub
    2121
    22     Abstract Function Peek() As Long
    23     Abstract Function Read() As Long
     22    Virtual Function Peek() As Long
     23        If pos >= buf.Length Then
     24            If Not Underflow() Then
     25                Peek = -1
     26                Exit Function
     27            End If
     28        End If
     29        Peek = buf[pos]
     30    End Function
     31
     32    Virtual Function Read() As Long
     33        Read = Peek()
     34        pos++
     35    End Function
    2436    /*
    2537    @date 2008/02/26
    2638    @auther Egtra
    2739    */
    28     Function Read(buffer As *WCHAR, index As Long, count As Long) As Long
     40    Virtual Function Read(buffer As *Char, index As Long, count As Long) As Long
    2941        If buffer = 0 Then
    3042            Throw New ArgumentNullException("buffer")
     
    4759    @retval 有効なStringインスタンス 読み取った1行
    4860    */
    49     Function ReadLine() As String
     61    Virtual Function ReadLine() As String
    5062        If Peek() = -1 Then
    5163            Exit Function
    5264        End If
    53         Dim sb = New Collections.Generic.List<WCHAR>
     65        Dim sb = New Text.StringBuilder
     66        Dim isLead = FALSE
    5467        Do
    5568            Dim ch = Read()
    56             If ch = &h0D Then
    57                 If Peek() = &h0A Then
    58                     Read() 'CR LFの場合
     69            If ch = -1 Then Exit Do
     70            If isLead = FALSE Then
     71                If ch = &h0D Then
     72                    If Peek() = &h0A Then
     73                        Read() 'CR LFの場合
     74                    End If
     75                    Exit Do
    5976                End If
    60                 Exit Do
    61             End If
    62             Select Case ch
    63                 Case -1 'EOF
    64                     Exit Do
    65                 Case &h0A 'LF
    66                     Exit Do
    67                 Case &h0B 'VT
    68                     Exit Do
    69                 Case &h0C 'FF
    70                     Exit Do
    71                 Case &h0D 'CR
    72                     Exit Do
    73                 Case &h85 'NEL
    74                     Exit Do
    75                 Case &h2028 'LS
    76                     Exit Do
    77                 Case &h2029 'PS
    78                     Exit Do
    79             End Select
    80             sb.Add(ch As WCHAR)
    81         Loop
    82         ReadLine = New String(sb As *WCHAR, sb.Count)
    83     End Function
    84     /*
    85     @brief 現在位置からストリームの終わりまで読み込む。
    86     @date 2008/02/26
    87     @auther Egtra
    88     */
    89     Virtual Function ReadToEnd() As String
    90         Dim sb = New Text.StringBuilder(8192)
    91         Do
    92             Dim ch = Read()
    93             If ch = -1 Then
    94                 ReadToEnd = sb.ToString
    95                 Exit Function
     77                Select Case ch
     78                    Case -1 'EOF
     79                        Exit Do
     80                    Case &h0A 'LF
     81                        Exit Do
     82                    Case &h0B 'VT
     83                        Exit Do
     84                    Case &h0C 'FF
     85                        Exit Do
     86                    Case &h0D 'CR
     87                        Exit Do
     88#ifdef UNICODE
     89                    Case &h85 'NEL
     90                        Exit Do
     91                    Case &h2028 'LS
     92                        Exit Do
     93                    Case &h2029 'PS
     94                        Exit Do
     95#endif
     96                End Select
    9697            End If
    9798            sb.Append(ch As Char)
     99#ifndef UNICODE
     100            isLead = IsDBCSLeadByte(ch As Byte)
     101#endif
    98102        Loop
     103        ReadLine = sb.ToString()
     104    End Function
     105
     106    /*!
     107    @brief 現在位置からストリームの終わりまで読み込む。
     108    @date 2008/02/26
     109    @auther Egtra
     110    */
     111    Virtual Function ReadToEnd() As String
     112        buf.Remove(0, pos)
     113        While Underflow()
     114        Wend
     115        ReadToEnd = buf.ToString()
    99116    End Function
    100117
    101118Protected
    102119    Sub TextReader()
     120        buf = New Text.StringBuilder
     121        pos = 0
    103122    End Sub
    104123
     
    106125    End Sub
    107126
    108     /*
    109     @date 2008/02/26
    110     @auther Egtra
    111     */
    112     Virtual Function ReadImpl(buffer As *WCHAR, count As Long) As Long
    113         Dim i As Long
    114         For i = 0 To ELM(count)
    115             Dim c = Read()
    116             If c = -1 Then
    117                 ReadImpl = i
    118                 Exit Function
    119             Else
    120                 buffer[i] = c As Char
    121             End If
    122         Next
    123         ReadImpl = i
    124     End Function
     127    /*!
     128    @brief バッファが足りなくなったときに呼ばれる。
     129    @date 2008/12/27
     130    @auther Egtra
     131    @retval True まだEOFに達していない場合
     132    @retval False EOFに達した場合
     133    */
     134    Virtual Function Underflow() As Boolean
     135        Underflow = False
     136    End Function
     137
     138    /*!
     139    @brief 内部バッファを返す
     140    @date 2008/12/27
     141    @auther Egtra
     142    @return 内部バッファ
     143    */
     144    Function Buffer() As Text.StringBuilder
     145        Buffer = buf
     146    End Function
     147
     148    /*!
     149    @date 2008/02/26
     150    @auther Egtra
     151    */
     152    Function ReadImpl(buffer As *Char, count As Long) As Long
     153        Dim p = StrPtr(buf)
     154        While buf.Length - pos < count
     155            If Underflow() = False Then Exit While
     156        Wend
     157        ReadImpl = Math.Min(buf.Length - pos, count)
     158        ActiveBasic.Strings.ChrCopy(buffer, VarPtr(p[buf]), ReadImpl As SIZE_T)
     159        pos += ReadImpl
     160    End Function
     161
     162Private
     163    buf As Text.StringBuilder
     164    pos As Long
    125165End Class
    126166
     
    136176
    137177    Override Function Peek() As Long
     178'       Using lock = cs.Lock()
     179            Peek = base.Peek()
     180'       End Using
     181    End Function
     182
     183    Override Function Read() As Long
     184'       Using lock = cs.Lock()
     185            Read = base.Read()
     186'       End Using
     187    End Function
     188
     189    Override Function Read(buffer As *Char, index As Long, count As Long) As Long
     190'       Using lock = cs.Lock()
     191            Read = base.Read(buffer, index, count)
     192'       End Using
     193    End Function
     194
     195    Override Function ReadToEnd() As String
    138196'       Using lock = cs.Lock
    139             Peek = base.Peek
    140 '       End Using
    141     End Function
    142 
    143     Override Function Read() As Long
    144 '       Using lock = cs.Lock
    145             Read = base.Read
     197            ReadToEnd = base.ReadToEnd
    146198'       End Using
    147199    End Function
     
    159211    End Sub
    160212
    161     Override Function ReadImpl(buffer As *WCHAR, count As Long) As Long
    162 '       Using lock = cs.Lock
    163             ReadImpl = base.ReadImpl(buffer, count)
    164 '       End Using
    165     End Function
    166213Private
    167214    cs As ActiveBasic.Windows.CriticalSection
  • trunk/ab5.0/ablib/src/Classes/System/IO/TextWriter.ab

    r653 r665  
    172172    End Sub
    173173
     174    /*!
     175    @brief 内部バッファを返す
     176    @date 2008/12/27
     177    @auther Egtra
     178    @return 内部バッファ
     179    */
    174180    Function Buffer() As Text.StringBuilder
    175181        Buffer = buf
Note: See TracChangeset for help on using the changeset viewer.