Ignore:
Timestamp:
Nov 9, 2008, 2:21:49 PM (15 years ago)
Author:
イグトランス (egtra)
Message:

#161完了。StreamReaderのUnicode対応。

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

Legend:

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

    r627 r655  
    4343    */
    4444    Override Function Peek() As Long
    45         If cur = last Then
    46             last = s.Read(buf As *Byte, 0, size)
    47             cur = 0
    48             If last = 0 Then
     45        If charSize = charCur Then
     46            fillCharBuf()
     47            If charSize = charCur Then
    4948                Peek = -1
    5049                Exit Function
    5150            End If
    5251        End If
    53         Peek = buf[cur]
     52        Peek = charBuf[charCur]
    5453    End Function
    5554
     
    6160        Read = Peek()
    6261        If Read <> -1 Then
    63             cur++
     62            charCur++
    6463        End If
    65     End Function
    66 
    67     /*
    68     @date 2008/02/26
    69     @auther Egtra
    70     */
    71     Override Function ReadToEnd() As String
    72         Dim sb = New Text.StringBuilder(65536)
    73         sb.Append(buf, cur, last - cur)
    74         Do
    75             Dim read = Read(buf, 0, size)
    76             sb.Append(buf, 0, read)
    77             If read < size Then
    78                 ReadToEnd = sb.ToString
    79                 Exit Function
    80             End If
    81         Loop
    8264    End Function
    8365
     
    9476        End If
    9577        s = Nothing
    96         size = 0
    97         cur = 0
    98         last = 0
    9978    End Sub
    10079
     
    10382    @auther Egtra
    10483    */
    105     Override Function ReadImpl(buffer As *Char, index As Long, count As Long) As Long
    106         Dim n = last - cur
    107         If count <= n Then
    108             ReadImpl = ReadFromBuffer(buffer, index, count)
     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)
    10988            Exit Function
    11089        End If
    111         Dim p = VarPtr(buffer[index])
    112         ReadImpl = ReadFromBuffer(p, 0, n)
     90        ReadImpl = readFromBuffer(buffer, n)
    11391        If ReadImpl = count Then 'バッファの中身で足りた場合
    11492            Exit Function
    11593        End If
    116         p = VarPtr(p[n])
    117         count -= n
    118         If count > size Then
    119             n = (count \ size) * size 'sizeの倍数分だけは直接bufferへ読み込ませる
    120             Dim read = s.Read(p As *Byte, 0, n)
    121             If read = 0 Then 'EOF
    122                 Exit Function
    123             End If
    124             p = VarPtr(p[n])
    125             ReadImpl += n
    126             count -= n
    127         End If
    128         last = s.Read(buffer As *Byte, 0, size)
    129         cur = 0
    130         If last = 0 Then 'EOF
    131             Exit Function
    132         End If
    133         ReadImpl += ReadFromBuffer(p, 0, Math.Min(last, count))
     94        fillCharBuf()
     95        ReadImpl += ReadImpl(VarPtr(buffer[n]), count - n)
    13496    End Function
    13597
     
    141103    Sub init(str As Stream)
    142104        s = str
    143         size = 4096
    144         last = 0
    145         cur = 0
    146         buf = GC_malloc(size)
     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
    147118    End Sub
    148119
     
    153124    文字数が足りなくても、元のストリームまで読みには行かない。
    154125    */
    155     Function ReadFromBuffer(p As *Char, index As Long, count As Long) As Long
    156         memcpy(VarPtr(p[index]), VarPtr(buf[cur]), count * SizeOf (Char))
    157         cur += count
    158         ReadFromBuffer = count
     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
    159130    End Function
    160131
     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            decoder.Convert(VarPtr(byteBuf[byteCur]), byteSize - byteCur,
     151                VarPtr(charBuf[charSize]), charCapacity - charSize,
     152                byteEof, charUsed, byteUsed, charEof)
     153            byteCur += byteUsed
     154            charSize += charUsed
     155        End If
     156    End Sub
     157
    161158    s As Stream
    162     size As Long
    163     cur As Long
    164     last As Long '中身の終わり
    165     buf As *SByte '暫定
     159    encoding As Text.Encoding
     160    decoder As Text.Decoder
     161    charBuf As *WCHAR
     162    byteBuf As *Byte
     163    charCur As Long '読み取っていないデータの開始位置
     164    byteCur As Long
     165    charSize As Long 'Bufの内、有効なデータの数
     166    byteSize As Long
     167    charCapacity As Long '確保済み容量 = GC_mallocしたときの引数の値
     168    byteCapacity As Long
     169    charEof As Boolean 'Trueのとき、次にcur = sizeになるまでしかデータがことを示す
     170    byteEof As Boolean
     171    '常に0 <= cur <= size <= capacity
    166172End Class
    167173
  • trunk/ab5.0/ablib/src/Classes/System/IO/StringReader.ab

    r497 r655  
    2323            Throw New ArgumentNullException("str")
    2424        End If
    25         s = str
     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
    2630        i = 0
    2731    End Sub
     
    3236    */
    3337    Override Function Peek() As Long
    34         If i = s.Length Then
     38        If i = len Then
    3539            Peek = -1
    3640        Else
     
    4448    */
    4549    Override Function Read() As Long
    46         If i = s.Length Then
    47             Read = -1
    48         Else
    49             Read = s[i]
    50             i++
    51         End If
     50        Read = Peek()
     51        i++
    5252    End Function
    5353
     
    5656    @auther Egtra
    5757    */
     58/*
    5859    Override Function ReadToEnd() As String
    5960        ReadToEnd = s.Substring(i)
    6061        i = s.Length
    6162    End Function
    62 
     63*/
    6364Protected
    6465    /*
     
    7576    @auther Egtra
    7677    */
    77     Override Function ReadImpl(buffer As *Char, index As Long, count As Long) As Long
    78         ReadImpl = Math.Min(count, s.Length - i)
    79         ActiveBasic.Strings.ChrCopy(VarPtr(buffer[index]) As *Char, (StrPtr(s) + i * SizeOf (Char)) As *Char, ReadImpl As SIZE_T) 'ToDo: ポインタに対する+演算
     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: ポインタに対する+演算
    8081    End Function
    8182
    8283Private
    83     s As String
     84    s As *WCHAR
     85    len As Long
    8486    i As Long
    8587End Class
  • trunk/ab5.0/ablib/src/Classes/System/IO/TextReader.ab

    r497 r655  
    1 NameSpace System
    2 NameSpace IO
     1Namespace System
     2Namespace IO
    33
    44Class TextReader
    55    Implements System.IDisposable
    6 
    7 Public
    8 'Protected
    9     Sub TextReader()
    10     End Sub
    116Public
    127    Virtual Sub ~TextReader()
     
    3126    @auther Egtra
    3227    */
    33     Function Read(buffer As *Char, index As Long, count As Long) As Long
     28    Function Read(buffer As *WCHAR, index As Long, count As Long) As Long
    3429        If buffer = 0 Then
     30            Throw New ArgumentNullException("buffer")
    3531        ElseIf index < 0 Then
     32            Throw New ArgumentOutOfRangeException("index")
    3633        ElseIf count < 0 Then
     34            Throw New ArgumentOutOfRangeException("count")
    3735        End If
    38         Read = ReadImpl(buffer, index, count)
     36        Read = ReadImpl(VarPtr(buffer[index]), count)
     37    End Function
     38
     39    Static Function Synchronized(reader As TextReader) As TextReader
     40        Synchronized = New Detail.SynchronizedTextReader(reader)
    3941    End Function
    4042
     
    4547    @retval 有効なStringインスタンス 読み取った1行
    4648    */
    47     Virtual Function ReadLine() As String
     49    Function ReadLine() As String
    4850        If Peek() = -1 Then
    4951            Exit Function
    5052        End If
    51         Dim sb = New Text.StringBuilder(256)
     53        Dim sb = New Collections.Generic.List<WCHAR>
    5254        Do
    5355            Dim ch = Read()
     
    6971                Case &h0D 'CR
    7072                    Exit Do
    71 '               Case &h85 'NEL
    72 '                   Exit Do
    73 '               Case &h2028 'LS
    74 '                   Exit Do
    75 '               Case &h2029 'PS
    76 '                   Exit Do
     73                Case &h85 'NEL
     74                    Exit Do
     75                Case &h2028 'LS
     76                    Exit Do
     77                Case &h2029 'PS
     78                    Exit Do
    7779            End Select
    78             sb.Append(ch As Char) 'ToDo キャスト不要にすべきというチケットを書くこと
     80            sb.Add(ch As WCHAR)
    7981        Loop
    80         ReadLine = sb.ToString
     82        ReadLine = New String(sb As *WCHAR, sb.Count)
    8183    End Function
    8284    /*
     
    9799    End Function
    98100
    99     Static Function Synchronized(reader As TextReader) As TextReader
    100         Synchronized = New Detail.SynchronizedTextReader(reader)
    101     End Function
     101Protected
     102    Sub TextReader()
     103    End Sub
    102104
    103 Protected
    104105    Virtual Sub Dispose(disposing As Boolean)
    105106    End Sub
     
    109110    @auther Egtra
    110111    */
    111     Virtual Function ReadImpl(buffer As *Char, index As Long, count As Long) As Long
     112    Virtual Function ReadImpl(buffer As *WCHAR, count As Long) As Long
    112113        Dim i As Long
    113         Dim p = VarPtr(buffer[index])
    114114        For i = 0 To ELM(count)
    115115            Dim c = Read()
    116116            If c = -1 Then
    117                 ReadImpl = i - 1
     117                ReadImpl = i
    118118                Exit Function
    119119            Else
    120                 p[i] = c As Char
     120                buffer[i] = c As Char
    121121            End If
    122122        Next
    123         ReadImpl = i - 1
     123        ReadImpl = i
    124124    End Function
    125125End Class
     
    147147    End Function
    148148
    149     Override Function ReadLine() As String
    150 '       Using lock = cs.Lock
    151             ReadLine = base.ReadLine
    152 '       End Using
    153     End Function
    154 
    155     Override Function ReadToEnd() As String
    156 '       Using lock = cs.Lock
    157             ReadToEnd = base.ReadToEnd
    158 '       End Using
    159     End Function
    160 
    161149Protected
    162150    Override Sub Dispose(disposing As Boolean)
     
    171159    End Sub
    172160
    173     Override Function ReadImpl(buffer As *Char, index As Long, count As Long) As Long
     161    Override Function ReadImpl(buffer As *WCHAR, count As Long) As Long
    174162'       Using lock = cs.Lock
    175             ReadImpl = base.ReadImpl(buffer, index, count)
     163            ReadImpl = base.ReadImpl(buffer, count)
    176164'       End Using
    177165    End Function
     
    183171End Namespace
    184172
    185 End NameSpace
    186 End NameSpace
     173End Namespace
     174End Namespace
  • trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab

    r653 r655  
    353353        ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    354354
    355         If src = 0 Then
     355        If src = 0 And srcCount > 0 Then
    356356            Throw New ArgumentNullException("src")
    357357        ElseIf srcCount < 0 Then
     
    452452        ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    453453
    454         If src = 0 Then
     454        If src = 0 And srcCount > 0 Then
    455455            Throw New ArgumentNullException("src")
    456456        ElseIf srcCount < 0 Then
     
    641641
    642642    Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
     643        GetBytesCountCore = srcCount * 2 + 1 '暫定
    643644    End Function
    644645
     
    658659    Override Sub ConvertCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean,
    659660        ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
     661
     662        Dim srcPos = 0 As Long
     663        Dim dstPos = 0 As Long
     664        If dstCount > 0 And nextByte <> 0 Then
     665            Dim buf[1] As CHAR
     666            buf[0] = nextByte As CHAR
     667            buf[1] = src[1] As CHAR
     668            Dim len = MultiByteToWideChar(cp, 0, buf, Len(buf), VarPtr(dst[dstPos]), 10)
     669            If len = 0 Then
     670                ActiveBasic.Windows.ThrowWithLastError()
     671            End If
     672            srcPos++
     673            dstPos++
     674            nextByte = 0
     675        End If
     676        While srcPos < srcCount And dstPos < srcCount
     677            Dim srcCharSize = 1 As Long
     678            If IsDBCSLeadByteEx(cp, src[srcPos]) Then
     679                srcCharSize = 2
     680                If srcPos + 1 = srcCount Then
     681                    nextByte = src[srcPos]
     682                    Exit While
     683                End If
     684            End If
     685            '将来的には行毎に変換しMB_USEGLYPHCHARSを使うようにしたい。
     686            Dim len = MultiByteToWideChar(cp, 0, VarPtr(src[srcPos]) As *CHAR, srcCharSize, VarPtr(dst[dstPos]), 1)
     687            If len = 0 Then
     688                ActiveBasic.Windows.ThrowWithLastError()
     689            End If
     690            srcPos += srcCharSize
     691            dstPos++
     692        Wend
     693        srcUsed = srcPos
     694        dstUsed = dstPos
     695        completed = (srcPos = srcCount And dstPos = srcCount And nextByte = 0)
    660696    End Sub
    661697
    662698    Override Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
     699        GetCharsCountCore = srcCount + 1 '暫定
    663700    End Function
    664701
    665702Private
    666703    cp As DWord
     704    nextByte As Byte
    667705End Class
    668706
  • trunk/ab5.0/ablib/src/Classes/System/Xml/XmlDocument.ab

    r497 r655  
    9595    /*!
    9696    @brief  指定したストリームからXML文書を読み込む。
     97    @param  reader 読み込むリーダ。
     98    */
     99    Virtual Sub Load( reader As System.IO.TextReader )
     100        This.RemoveAll()
     101        ActiveBasic.Xml.Parser.Parse( reader.ReadToEnd(), This )
     102    End Sub
     103
     104    /*!
     105    @brief  指定したストリームからXML文書を読み込む。
    97106    @param  stream 読み込み先のストリーム。
    98107    */
    99108    Virtual Sub Load( inStream As System.IO.Stream )
    100         Dim length = inStream.Length As DWord
    101         Dim xmlBuffer = calloc( length + 1 ) As *Char
    102         inStream.Read( xmlBuffer As *Byte, 0, length )
    103         inStream.Close()
    104         Dim xmlString = New String( xmlBuffer )
    105         free( xmlBuffer )
    106 
    107         This.RemoveAll()
    108         ActiveBasic.Xml.Parser.Parse( xmlString, This )
     109        Load( New System.IO.StreamReader( inStream ) )
    109110    End Sub
    110111
     
    114115    */
    115116    Virtual Sub Load( filename As String )
    116         Dim fileStream As System.IO.FileStream( filename, System.IO.FileMode.Open, System.IO.FileAccess.Read )
    117         Load( fileStream )
     117        Dim r = New System.IO.StreamReader( filename )
     118        Load( r )
     119        r.Dispose()
    118120    End Sub
    119121
     
    123125    */
    124126    Virtual Sub Save( outStream As System.IO.Stream )
    125         Dim xmlStr = InnerXmlSupportedIndent( True )
    126         outStream.Write( xmlStr.StrPtr As *Byte, 0, xmlStr.Length * SizeOf( Char ) )
    127         outStream.Close()
     127        Dim writer = New IO.StreamWriter( outStream )
     128        Save( writer )
     129        writer.Flush()
    128130    End Sub
    129131
     
    133135    */
    134136    Virtual Sub Save( filename As String )
    135         Dim fileStream As System.IO.FileStream( filename, System.IO.FileMode.Create, System.IO.FileAccess.Write )
    136         Save( fileStream )
     137        Dim w = New IO.StreamWriter( filename )
     138        Save( w )
     139        w.Dispose()
    137140    End Sub
    138141
     
    142145    */
    143146    Virtual Sub Save( writer As System.IO.TextWriter )
    144         writer.Write(InnerXmlSupportedIndent( True ))
     147        writer.Write( InnerXmlSupportedIndent( True ) )
    145148    End Sub
    146149End Class
Note: See TracChangeset for help on using the changeset viewer.