Changeset 665 for trunk


Ignore:
Timestamp:
2008/12/28 00:18:53 (3 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.