Ignore:
Timestamp:
Jan 13, 2009, 2:01:38 AM (15 years ago)
Author:
イグトランス (egtra)
Message:

#231に関連して、エンコーディング周りを見直し、Encoder/Decoderをストリーム用に特化。
UTF8Encodingをコンパイル可能にし、ビルドに含めるようにした。ただし、実装が不完全なためテストは不可。
(#231)

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

Legend:

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

    r636 r676  
    272272        End If
    273273        Console.err = newErr
    274         Dim sw = Console.err As IO.StreamWriter
    275         Dim fs = sw.BaseStream() As IO.FileStream
    276         Console.hconsoleerr = fs.Handle()
     274'       Dim sw = Console.err As IO.StreamWriter
     275'       Dim fs = sw.BaseStream() As IO.FileStream
     276'       Console.hconsoleerr = fs.Handle()
    277277    End Sub
    278278
     
    296296        End If
    297297        Console.out = newOut
    298         Dim sw = Console.out As IO.StreamWriter
    299         Dim fs = sw.BaseStream() As IO.FileStream
    300         Console.hconsoleout = fs.Handle()
    301298    End Sub
    302299
     
    441438        End If
    442439        Console.in = newIn
    443         Dim sr = Console.in As IO.StreamReader
    444         Dim fs = sr.BaseStream() As IO.FileStream
    445         Console.hconsolein = fs.Handle()
    446440    End Sub
    447441
     
    503497    */
    504498    Static Sub OpenStandardError()
    505         Console.SetError(System.IO.TextWriter.Synchronized(New System.IO.StreamWriter(New System.IO.FileStream(GetStdHandle(STD_ERROR_HANDLE), System.IO.FileAccess.Write, False))))
     499        Dim w = New Detail.ConsoleWriter(hconsoleerr)
     500        Console.SetOut(System.IO.TextWriter.Synchronized(w))
    506501    End Sub
    507502
     
    512507    */
    513508    Static Sub OpenStandardInput()
    514         Console.SetIn(System.IO.TextReader.Synchronized(New System.IO.StreamReader(New System.IO.FileStream(GetStdHandle(STD_INPUT_HANDLE), System.IO.FileAccess.Read, False))))
     509        Dim w = New Detail.ConsoleReader(hconsolein)
     510        Console.SetIn(System.IO.TextReader.Synchronized(w))
    515511    End Sub
    516512
     
    521517    */
    522518    Static Sub OpenStandardOutput()
    523         Console.SetOut(System.IO.TextWriter.Synchronized(New System.IO.StreamWriter(New System.IO.FileStream(GetStdHandle(STD_OUTPUT_HANDLE), System.IO.FileAccess.Write, False))))
     519        Dim w = New Detail.ConsoleWriter(hconsoleout)
     520        Console.SetOut(System.IO.TextWriter.Synchronized(w))
    524521        Console.defBC = This.ConsoleColorToTextAttribute(Console.BackgroundColor)
    525522        Console.defFC = This.ConsoleColorToTextAttribute(Console.ForegroundColor)
     
    654651    End Sub
    655652
    656     Static hconsoleerr = NULL As HANDLE
    657     Static hconsolein = NULL As HANDLE
    658     Static hconsoleout = NULL As HANDLE
     653    Static hconsoleerr = GetStdHandle(STD_ERROR_HANDLE) As HANDLE
     654    Static hconsolein = GetStdHandle(STD_INPUT_HANDLE) As HANDLE
     655    Static hconsoleout = GetStdHandle(STD_OUTPUT_HANDLE) As HANDLE
    659656    Static in = Nothing As IO.TextReader
    660657    Static out = Nothing As IO.TextWriter
     
    665662End Class
    666663
     664Namespace Detail
     665
     666Class ConsoleWriter
     667    Inherits IO.TextWriter
     668Public
     669    Sub ConsoleWriter(hOut As HANDLE)
     670        h = hOut
     671    End Sub
     672
     673    Override Sub Flush()
     674        Dim b = Buffer
     675        Dim written As DWord
     676        WriteConsole(h, StrPtr(b), b.Length As DWord, written, 0)
     677        b.Remove(0, written As Long)
     678    End Sub
     679
     680Private
     681    h As HANDLE
     682End Class
     683
     684Class ConsoleReader
     685    Inherits IO.TextReader
     686Public
     687    Sub ConsoleReader(hIn As HANDLE)
     688        h = hIn
     689    End Sub
     690
     691Protected
     692    Override Function Underflow() As Boolean
     693        Dim b = Buffer
     694        Dim currentBufLength = b.Length
     695        b.Length = currentBufLength + 256
     696        Dim p = StrPtr(b)
     697        Dim read As DWord
     698        If ReadConsole(h, VarPtr(p[currentBufLength]), 256, read, 0) = 0 Then
     699            IO.Detail.ThrowWinLastErrorIOException()
     700        End If
     701        b.Length = currentBufLength + read
     702    End Function
     703
     704Private
     705    h As HANDLE
     706End Class
     707
     708End Namespace 'Detail
     709
    667710End Namespace 'System
  • trunk/ab5.0/ablib/src/Classes/System/IO/StreamReader.ab

    r666 r676  
    11'Classes/System/IO/StreamReader.ab
     2
     3'ToDo: コンソールで入力待ちになる問題への対処
    24
    35Namespace System
     
    3840    End Function
    3941
    40 
    4142Protected
    4243    /*
     
    5859    */
    5960    Override Function Underflow() As Boolean
    60         Dim wcBuf[4095] As WCHAR
    61         Dim mbBuf[4095] As SByte
    62         Dim pNext = mbBuf As PSTR
    63         Dim mbBufSize = Len(buf)
    64         If leadByte <> 0 Then
    65             pNext[0] = leadByte
    66             leadByte = 0
    67             pNext++
    68             mbBufSize--
    69         End If
    70         Dim mbLen = s.Read(pNext As *Byte, 0, mbBufSize)
    71         If mbLen = 0 Then
    72             Underflow = False
    73             Exit Function
    74         End If
    75         Do
    76             Dim q = CharNextExA(cp, pNext, 0)
    77             If q = pNext Then
    78                 Exit Do
    79             End If
    80             pNext = q As PSTR
    81         Loop
    82         If pNext <> mbBuf + mbLen Then
    83             leadByte = mbBuf[mbLen - 1]
    84         End If
    85         Dim wcLen = MultiByteToWideChar(cp, 0, mbBuf, (pNext - mbBuf) As Long, wcBuf, 4095)
    86         Dim s = New String(wcBuf, wcLen)
    8761        Dim buf = Buffer
     62        Dim tmp = New Collections.Generic.List<WCHAR>
     63        Underflow = decoder.Decode(tmp, s)
     64        'ToDo: 非UNICODEのとき、
     65        ' サロゲートペアや結合文字列 (Combining Character Sequence)の途中でバッファが途切れている場合に対応する
     66        Dim s = New String(tmp.Data, tmp.Count)
    8867        buf.Append(s)
    89         Underflow = True
    9068    End Function
    9169Private
     
    9775    Sub init(str As Stream)
    9876        s = str
    99         cp  = CP_ACP '暫定。
    100         leadByte = 0
     77        decoder = New Text.Detail.WindowsCodePageDecoder(CP_ACP)
    10178    End Sub
    10279
    10380    s As Stream
    104     cp As Word
    105     leadByte As Byte
     81    decoder As Text.Decoder
    10682End Class
    10783
  • trunk/ab5.0/ablib/src/Classes/System/IO/StreamWriter.ab

    r653 r676  
    4141
    4242    Override Sub Flush()
    43         Dim buf = Buffer()
    44         Dim pws As PCWSTR
    45         Dim size = GetWCStr(buf.ToString(), pws)
    46         Dim pwsEnd = VarPtr(pws[size])
    47         Dim charConverted As Long
    48         Dim byteBuf[4095] As Byte
    49         Dim byteSize As Long
    50         Dim completed As Boolean
    51         Do
    52             Dim converted As Long
    53             encoder.Convert(pws, size, byteBuf, Len(byteBuf), False, charConverted, byteSize, completed)
    54             s.Write(byteBuf, 0, byteSize)
    55             pws = VarPtr(pws[charConverted])
    56             size -= charConverted
    57         Loop Until pws = pwsEnd
    58         buf.Length = 0
     43        Flush(False)
     44    End Sub
     45
     46    Sub Flush(last As Boolean)
     47#ifdef UNICODE
     48        encoder.Encode(StrPtr(buf), buf.Length As SIZE_T, s, last)
     49        buf.Remove(0, buf.Length As SIZE_T)
     50#else
     51        Dim p = StrPtr(buf)
     52        Dim i = 0 As SIZE_T
     53        Dim mbLen = 0 As SIZE_T
     54        While i <= buf.Length
     55            mbLen = i
     56            'ヌル文字で終わっていないので、CharNextは使えない
     57            If IsDBCSLeadByte(p[i]) Then
     58                i += 2
     59            Else
     60                i += 1
     61            End If
     62        Wend
     63        Dim wcBuf As PCWSTR
     64        Dim wcLen = GetStr(p, mbLen, wcBuf)
     65        encoder.Encode(wcBuf, wcLen, s, last)
     66        buf.Remove(0, mbLen)
     67        If last Then
     68            If buf.Length <> 0 Then
     69                s.WriteByte(Asc("?"))
     70                buf.Length = 0 
     71            End If
     72        End If
     73#endif
    5974    End Sub
    6075
     
    6277    Override Sub Dispose(disposing As Boolean)
    6378        If disposing Then
    64             Flush()
    65             flushLast()
     79            Flush(True)
    6680            s.Dispose()
    6781        End If
     
    7387        buf = New Text.StringBuilder(4096)
    7488        '暫定。正式版ではUTF-8を標準とする。
    75         encoding = New Text.Detail.WindowsCodePageEncoding(CP_ACP)
    76         encoder = encoding.GetEncoder()
     89        encoder = New Text.Detail.WindowsCodePageEncoder(CP_ACP)
    7790    End Sub
    7891
    79     Sub flushLast()
    80         Dim charConverted As Long
    81         Dim byteBuf[63] As Byte
    82         Dim byteSize As Long
    83         Dim completed As Boolean
    84         Do
    85             encoder.Convert(0, 0, byteBuf, Len(byteBuf), False, charConverted, byteSize, completed)
    86             s.Write(byteBuf, 0, byteSize)
    87         Loop Until completed
    88     End Sub
    89 
    90     encoding As Text.Encoding
    9192    encoder As Text.Encoder
    9293    s As System.IO.Stream
  • trunk/ab5.0/ablib/src/Classes/System/IO/StringReader.ab

    r665 r676  
    1616    @date 2008/02/26
    1717    @auther Egtra
    18     @param str 読み取るとなる文字列。
     18    @param str 読み取るとなる文字列。
    1919    @exception ArgumentNullException strがNothingのとき。
    2020    */
     
    2323            Throw New ArgumentNullException("str")
    2424        End If
    25         Buffer.Append(str)
    26     End Sub
    27 
    28 
    29 Protected
    30     /*
    31     @date 2008/02/26
    32     @auther Egtra
    33     */
    34     Override Sub Dispose(disposing As Boolean)
     25        Dim b = Buffer
     26        b.Append(str)
    3527    End Sub
    3628End Class
  • trunk/ab5.0/ablib/src/Classes/System/IO/TextReader.ab

    r668 r676  
    2222    Virtual Function Peek() As Long
    2323        If pos >= buf.Length Then
     24            buf.Length = 0
     25            pos = 0
    2426            If Not Underflow() Then
    2527                Peek = -1
     
    114116        Wend
    115117        ReadToEnd = buf.ToString()
     118        buf.Length = 0
     119        pos = 0
    116120    End Function
    117121
     
    141145    @auther Egtra
    142146    @return 内部バッファ
     147    内部バッファの既存の要素は、一切の変更をしないこと。また、空であるという仮定を置かないこと。
    143148    */
    144149    Function Buffer() As Text.StringBuilder
     
    151156    */
    152157    Function ReadImpl(buffer As *Char, count As Long) As Long
     158        'ToDo 適当なところでバッファの読み取り済みの部分を除去する処理を入れる(現在Peekのみ)。
    153159        Dim p = StrPtr(buf)
    154160        While buf.Length - pos < count
     
    156162        Wend
    157163        ReadImpl = Math.Min(buf.Length - pos, count)
    158         ActiveBasic.Strings.ChrCopy(buffer, VarPtr(p[pos]), ReadImpl As SIZE_T)
     164        ActiveBasic.Strings.ChrCopy(buffer, VarPtr(p[pos]) As *Char, ReadImpl As SIZE_T)
    159165        pos += ReadImpl
    160166    End Function
  • trunk/ab5.0/ablib/src/Classes/System/String.ab

    r657 r676  
    44
    55    Class String
    6         Implements /*IComparable, ICloneable, IConvertible, IComparable<String>, IEnumerable, IEnumerable<Char>, IEquatable<String>*/
     6        Implements /*ICloneable, IConvertible, IComparable<String>, IEnumerable<Char>, IEquatable<String>*/
    77
    88        m_Length As Long
     
    1010
    1111        Sub validPointerCheck(p As VoidPtr, size = 1 As Long)
    12             If p As ULONG_PTR < &h10000 Then
     12            If p = 0 Then
    1313                Throw New ArgumentException
    1414            ElseIf IsBadReadPtr(p, size As ULONG_PTR) Then
  • trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab

    r655 r676  
    3939    @brief  符号化して得られる文字列の長さを計算する。
    4040    @param[in] src  対象文字列
    41     @param[in] srcCount srcの長さ
    42     @return 符号化して得られる文字列の長さ
     41    @param[in] srcCount srcの長さ(要素数単位)
     42    @return 符号化して得られる文字列の長さ(要素数単位)
    4343    @date   2007/12/08
    4444    */
     
    5555    @brief  符号化して得られる文字列の長さを計算する。
    5656    @param[in] src  対象文字列
    57     @return 符号化して得られる文字列の長さ
     57    @return 符号化して得られる文字列の長さ(要素数単位)
    5858    @date   2007/12/08
    5959    */
     
    6666#endif
    6767
    68 Private
     68Protected
    6969    /*!
    7070    @brief  GetBytesCountの実装を行う。
    7171    @param[in] src  対象文字列
    72     @param[in] srcCount srcの長さ
    73     @return 符号化して得られる文字列の長さ
    74     @date   2007/12/08
    75     */
    76     Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
    77         Dim enc = GetEncoder()
    78         GetBytesCountCore = enc.GetBytesCount(src, srcCount, True)
    79     End Function
     72    @param[in] srcCount srcの長さ(要素数単位)
     73    @return 符号化して得られる文字列の長さ(要素数単位)
     74    @date   2007/12/08
     75    */
     76    Abstract Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
    8077Public
    8178    /*!
    8279    @brief  符号化する。
    8380    @param[in] src  入力
    84     @param[in] srcCount srcの長さ
     81    @param[in] srcCount srcの長さ(要素数単位)
    8582    @param[out] dst 出力
    86     @param[in] dstCount dstのバッファの大きさ
    87     @return dstに書き込まれたバイト
     83    @param[in] dstCount dstのバッファの大きさ(要素数単位)
     84    @return dstに書き込まれた要素
    8885    @date   2007/12/08
    8986    */
     
    10299    End Function
    103100
    104 Private
     101Protected
    105102    /*!
    106103    @brief  GetBytesの処理を行う。
    107104    @param[in] src  入力
    108     @param[in] srcCount srcの長さ
     105    @param[in] srcCount srcの長さ(要素数単位)
    109106    @param[out] dst 出力
    110     @param[in] dstCount dstのバッファの大きさ
    111     @return dstに書き込まれたバイト
     107    @param[in] dstCount dstのバッファの大きさ(要素数単位)
     108    @return dstに書き込まれた要素
    112109    @exception ArgumentException    バッファの大きさが足りない
    113110    @date   2007/12/08
    114111    */
    115     Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
    116         GetBytesCore = GetEncoder().GetBytes(src, srcCount, dst, dstCount, True)
    117     End Function
     112    Abstract Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
    118113Public
    119114    /*!
    120115    @brief  復号して得られる文字列の長さを計算する。
    121116    @param[in] src  対象文字列
    122     @param[in] srcCount srcの長さ
    123     @return 復号して得られる文字列の長さ
     117    @param[in] srcCount srcの長さ(要素数単位)
     118    @return 復号して得られる文字列の長さ(要素数単位)
    124119    @date   2007/12/08
    125120    */
     
    133128    End Function
    134129
    135 Private
     130Protected
    136131    /*!
    137132    @brief  GetCharsCountの処理を行う。
    138133    @param[in] src  対象文字列
    139     @param[in] srcCount srcの長さ
    140     @return 符号化して得られる文字列の長さ
    141     @date   2007/12/08
    142     */
    143     Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
    144         Dim dec = GetDecoder()
    145         GetCharsCountCore = dec.GetCharsCount(src, srcCount, True)
    146     End Function
     134    @param[in] srcCount srcの長さ(要素数単位)
     135    @return 符号化して得られる文字列の長さ(要素数単位)
     136    @date   2007/12/08
     137    */
     138    Abstract Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
    147139Public
    148140    /*!
    149141    @brief  復号する。
    150142    @param[in] src  入力
    151     @param[in] srcCount srcの長さ
     143    @param[in] srcCount srcの長さ(要素数単位)
    152144    @param[out] dst 出力
    153     @param[in] dstCount srcのバッファの大きさ
    154     @return dstに書き込まれたバイト
     145    @param[in] dstCount srcのバッファの大きさ(要素数単位)
     146    @return dstに書き込まれた要素
    155147    @date   2007/12/08
    156148    */
     
    169161    End Function
    170162
    171 Private
     163Protected
    172164    /*!
    173165    @brief  GetCharsの処理を行う。
    174166    @param[in] src  入力
    175     @param[in] srcCount srcの長さ
     167    @param[in] srcCount srcの長さ(要素数単位)
    176168    @param[out] dst 出力
    177     @param[in] dstCount dstのバッファの大きさ
    178     @return dstに書き込まれたバイト
     169    @param[in] dstCount dstのバッファの大きさ(要素数単位)
     170    @return dstに書き込まれた要素
    179171    @exception ArgumentException    バッファの大きさが足りない
    180172    @date   2007/12/08
    181173    */
    182     Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
    183         GetCharsCore = GetDecoder().GetChars(src, srcCount, dst, dstCount, True)
    184     End Function
     174    Abstract Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
    185175Public
    186176#ifdef UNICODE
     
    188178    @brief  復号し、Stringで結果を返す。
    189179    @param[in] src  入力
    190     @param[in] srcCount srcの長さ
     180    @param[in] srcCount srcの長さ(要素数単位)
    191181    @return 変換結果の文字列
    192182    @date   2007/12/08
     
    214204Public
    215205    /*!
     206    @brief  復号器を取得する。
     207    */
     208    Abstract Function GetDecoder() As Decoder
     209
     210    /*!
    216211    @brief  符号器を取得する。
    217     */
    218     Abstract Function GetDecoder() As Decoder
    219 
    220     /*!
    221     @brief  復号器を取得する。
    222212    */
    223213    Abstract Function GetEncoder() As Encoder
     
    242232
    243233    /*!
    244     @brief  GetPreambleの配列の要素数
     234    @brief  GetPreambleの配列の要素数
    245235    */
    246236    Virtual Function GetPreambleLength() As Long
     
    248238    End Function
    249239
     240Public
    250241'   Abstract Function BodyName() As String
    251242'   Abstract Function HeaderName() As String
     
    333324/*!
    334325@brief  復号を行うクラス
    335 @date   2007/12/19
     326@date   2009/01/12
    336327@auther Egtra
     328内部処理用
    337329*/
    338330Class Decoder
    339331Public
    340     /*!
    341     @brief  変換する
    342     @param[in] src  入力
    343     @param[in] srcCount 入力要素数
    344     @param[out] dst 出力
    345     @param[in] dstCount 出力要素数
    346     @param[in] flush    終了後に内部状態を初期化するかどうか
    347     @param[out] srcUsed 使用された入力の要素数
    348     @param[out] dstUsed 出力の内、実際に書き込まれた要素数
    349     @param[out] completed   入力の全ての文字が変換に使われたかどうか
    350     */
    351     Sub Convert(src As *Byte, srcCount As Long,
    352         dst As *WCHAR, dstCount As Long, flush As Boolean,
    353         ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    354 
    355         If src = 0 And srcCount > 0 Then
    356             Throw New ArgumentNullException("src")
    357         ElseIf srcCount < 0 Then
    358             Throw New ArgumentOutOfRangeException("srcCount")
    359         ElseIf dst = 0 Then
    360             Throw New ArgumentNullException("dst")
    361         ElseIf dstCount < 0 Then
    362             Throw New ArgumentOutOfRangeException("dstCount")
    363         End If
    364         ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
     332    Function Decode(dst As Collections.Generic.List<WCHAR>, st As IO.Stream) As Boolean
     333        Decode = DecodeImpl(dst, st)
     334    End Function
     335
     336Protected
     337    Abstract Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
     338End Class
     339
     340/*!
     341@brief  符号化を行うクラス
     342@date   2009/01/12
     343@auther Egtra
     344内部処理用
     345*/
     346Class Encoder
     347Public
     348    Sub Encode(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
     349        EncodeImpl(src, size, s, last)
    365350    End Sub
    366351
    367     /*!
    368     @brief  変換する
    369     @param[in] src  入力
    370     @param[in] srcCount 入力要素数
    371     @param[out] dst 出力
    372     @param[in] dstCount 出力要素数
    373     @param[in] flush    終了後に内部状態を初期化するかどうか
    374     @return 出力の内、実際に書き込まれた要素数
    375     */
    376     Function GetChars(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean) As Long
    377         Dim srcUsed As Long
    378         Dim completed As Boolean
    379         Convert(src, srcCount, dst, dstCount, flush, srcUsed, GetChars, completed)
    380         If srcUsed < srcCount Then
    381             Throw New ArgumentException("src", "buffer is too small")
    382         End If
    383     End Function
    384 
    385     /*!
    386     @brief  変換すると何文字になるか数える
    387     @param[in] src  入力
    388     @param[in] srcCount 入力要素数
    389     @param[in] flush    終了後に内部状態を初期化するとして計算するかどうか
    390     @return 必要な文字数
    391     */
    392     Function GetCharsCount(src As *Byte, srcCount As Long, flush As Boolean) As Long
    393         If src = 0 Then
    394             Throw New ArgumentNullException("src")
    395         ElseIf srcCount < 0 Then
    396             Throw New ArgumentOutOfRangeException("srcCount")
    397         End If
    398         GetCharsCountCore(src, srcCount, flush)
    399     End Function
    400 
    401     /*!
    402     @brief  内部状態を初期状態に戻す
    403     */
    404     Virtual Sub Reset()
    405     End Sub
    406 
    407 Protected
    408     /*!
    409     @brief  実際に変換する
    410     @param[in] src  入力
    411     @param[in] srcCount 入力要素数
    412     @param[out] dst 出力
    413     @param[in] dstCount 出力要素数
    414     @param[in] flush    終了後に内部状態を初期化するかどうか
    415     @param[out] dstUsed 使用された入力の要素数
    416     @param[out] srcUsed 出力の内、実際に書き込まれた要素数
    417     @param[out] completed   入力の全ての文字が変換に使われたかどうか
    418     */
    419     Abstract Sub ConvertCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean,
    420         ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    421 
    422     /*!
    423     @brief  変換すると何文字になるか数える
    424     @param[in] src  入力
    425     @param[in] srcCount 入力要素数
    426     @param[in] flush    終了後に内部状態を初期化するとして計算するかどうか
    427     @return 必要な文字数
    428     */
    429     Abstract Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
    430 End Class
    431 
    432 /*!
    433 @brief  符号化を行うクラス
    434 @date   2007/12/19
    435 @auther Egtra
    436 */
    437 Class Encoder
    438 Public
    439     /*!
    440     @brief  変換する
    441     @param[in] src  入力
    442     @param[in] srcCount 入力要素数
    443     @param[out] dst 出力
    444     @param[in] dstCount 出力要素数
    445     @param[in] flush    終了後に内部状態を初期化するかどうか
    446     @param[out] srcUsed 使用された入力の要素数
    447     @param[out] dstUsed 出力の内、実際に書き込まれた要素数
    448     @param[out] completed   入力の全ての文字が変換に使われたかどうか
    449     */
    450     Sub Convert(src As *WCHAR, srcCount As Long,
    451         dst As *Byte, dstCount As Long, flush As Boolean,
    452         ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    453 
    454         If src = 0 And srcCount > 0 Then
    455             Throw New ArgumentNullException("src")
    456         ElseIf srcCount < 0 Then
    457             Throw New ArgumentOutOfRangeException("srcCount")
    458         ElseIf dst = 0 Then
    459             Throw New ArgumentNullException("dst")
    460         ElseIf dstCount < 0 Then
    461             Throw New ArgumentOutOfRangeException("dstCount")
    462         End If
    463         ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
    464     End Sub
    465 
    466     /*!
    467     @brief  変換する
    468     @param[in] src  入力
    469     @param[in] srcCount 入力要素数
    470     @param[out] dst 出力
    471     @param[in] dstCount 出力要素数
    472     @param[in] flush    終了後に内部状態を初期化するかどうか
    473     @return 出力の内、実際に書き込まれた要素数
    474     */
    475     Function GetBytes(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean) As Long
    476         Dim srcUsed As Long
    477         Dim completed As Boolean
    478         Convert(src, srcCount, dst, dstCount, flush, srcUsed, GetBytes, completed)
    479         If srcUsed < srcCount Then
    480             Throw New ArgumentException("src", "buffer is too small")
    481         End If
    482     End Function
    483 
    484     /*!
    485     @brief  変換すると何文字になるか数える
    486     @param[in] src  入力
    487     @param[in] srcCount 入力要素数
    488     @param[in] flush    終了後に内部状態を初期化するとして計算するかどうか
    489     @return 必要な文字数
    490     */
    491     Function GetBytesCount(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
    492         If src = 0 Then
    493             Throw New ArgumentNullException("src")
    494         ElseIf srcCount < 0 Then
    495             Throw New ArgumentOutOfRangeException("srcCount")
    496         End If
    497         GetBytesCountCore(src, srcCount, flush)
    498     End Function
    499 
    500     /*!
    501     @brief  内部状態を初期状態に戻す
    502     */
    503     Virtual Sub Reset()
    504     End Sub
    505 
    506 Protected
    507     /*!
    508     @brief  実際に変換する
    509     @param[in] src  入力
    510     @param[in] srcCount 入力要素数
    511     @param[out] dst 出力
    512     @param[in] dstCount 出力要素数
    513     @param[in] flush    終了後に内部状態を初期化するかどうか
    514     @param[out] dstUsed 使用された入力の要素数
    515     @param[out] srcUsed 出力の内、実際に書き込まれた要素数
    516     @param[out] completed   入力の全ての文字が変換に使われたかどうか
    517     */
    518     Abstract Sub ConvertCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean,
    519         ByRef dstUsed As Long, ByRef srcUsed As Long, ByRef completed As Boolean)
    520 
    521     /*!
    522     @brief  変換すると何文字になるか数える
    523     @param[in] src  入力
    524     @param[in] srcCount 入力要素数
    525     @param[in] flush    終了後に内部状態を初期化するとして計算するかどうか
    526     @return 必要な文字数
    527     */
    528     Abstract Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
     352Protected
     353    Abstract Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
    529354End Class
    530355
     
    549374    End Sub
    550375
    551     /*!
    552     @brief  符号器を取得する。
    553     */
    554     Override Function GetDecoder() As Decoder
    555         GetDecoder = New WindowsCodePageDecoder(cp)
    556     End Function
    557 
    558     /*!
    559     @brief  復号器を取得する。
    560     */
    561     Override Function GetEncoder() As Encoder
    562         GetEncoder = New WindowsCodePageEncoder(cp)
    563     End Function
    564 
    565376    Override Function GetHashCode() As Long
    566377        GetHashCode = cp As Long
     
    576387    End Function
    577388
     389    Override Function GetDecoder() As Decoder
     390        GetDecoder = New WindowsCodePageDecoder(cp)
     391    End Function
     392
     393    Override Function GetEncoder() As Encoder
     394        GetEncoder = New WindowsCodePageEncoder(cp)
     395    End Function
     396
    578397    /*!
    579398    @brief  ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
     
    588407    Override Function GetMaxCharCount(srcCount As Long) As Long
    589408        GetMaxCharCount = srcCount
     409    End Function
     410
     411Protected
     412    Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
     413        GetBytesCountCore = WideCharToMultiByte(cp, 0, src, srcCount, 0, 0, 0, 0)
     414        If srcCount <> 0 And GetBytesCountCore = 0 Then
     415            ActiveBasic.Windows.ThrowWithLastError()
     416        End If
     417    End Function
     418
     419    Override Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
     420        GetBytesCore = WideCharToMultiByte(cp, 0, src, srcCount, dst As PCSTR, dstCount, 0, 0)
     421        If srcCount <> 0 And GetBytesCore = 0 Then
     422            ActiveBasic.Windows.ThrowWithLastError()
     423        End If
     424    End Function
     425
     426    Override Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
     427        GetCharsCountCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, 0, 0)
     428        If srcCount <> 0 And GetCharsCountCore = 0 Then
     429            ActiveBasic.Windows.ThrowWithLastError()
     430        End If
     431    End Function
     432
     433    Override Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
     434        GetCharsCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, dst, dstCount)
     435        If srcCount <> 0 And GetCharsCore = 0 Then
     436            ActiveBasic.Windows.ThrowWithLastError()
     437        End If
    590438    End Function
    591439
     
    594442End Class
    595443
     444/*!
     445@brief  WideCharToMultiByteで復号化を行うクラス
     446@date   2009/01/12
     447@auther Egtra
     448内部処理用
     449*/
    596450Class WindowsCodePageEncoder
    597451    Inherits Encoder
     
    601455    End Sub
    602456
    603     Override Sub Reset()
    604         nextByte = 0
     457Protected
     458    Override Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
     459        ' サロゲートペアや結合文字列 (Combining Character Sequence)の途中でバッファが途切れている場合に対応する
     460        ' ToDo: エラー処理
     461        Dim mbLen = WideCharToMultiByte(cp, 0, src, size, 0, 0, 0, 0)
     462        Dim mbBuf = GC_malloc_atomic(mbLen)
     463        WideCharToMultiByte(cp, 0, src, size, mbBuf, mbLen, 0, 0)
     464        s.Write(mbBuf, 0, mbLen)
    605465    End Sub
    606 
    607 Protected
    608     Override Sub ConvertCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long, flush As Boolean,
    609         ByRef srcUsed As Long, ByRef dstUsed As Long, ByRef completed As Boolean)
    610 
    611         Dim srcPos = 0 As Long
    612         Dim dstPos = 0 As Long
    613         If dstCount > 0 And nextByte <> 0 Then
    614             dst[0] = nextByte
    615             nextByte = 0
    616             dstPos++
    617         End If
    618         While srcPos < srcCount And dstPos < srcCount
    619             Dim buf[1] As CHAR
    620             Dim len = WideCharToMultiByte(cp, WC_COMPOSITECHECK Or WC_DEFAULTCHAR, VarPtr(src[srcPos]), 1, buf, Len(buf), 0, 0)
    621             If len = 0 Then
    622                 ActiveBasic.Windows.ThrowWithLastError()
    623             End If
    624             dst[dstPos] = buf[0] As Byte
    625             If len = 2 Then
    626                 If dstCount = 1 Then
    627                     nextByte = buf[1] As Byte
    628                     Exit While
    629                 End If
    630                 dstPos++
    631                 dst[dstPos] = buf[1] As Byte
    632                 nextByte = 0
    633             End If
    634             srcPos++
    635             dstPos++
    636         Wend
    637         srcUsed = srcPos
    638         dstUsed = dstPos
    639         completed = (srcPos = srcCount And dstPos = srcCount And nextByte = 0)
    640     End Sub
    641 
    642     Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
    643         GetBytesCountCore = srcCount * 2 + 1 '暫定
    644     End Function
    645466
    646467Private
    647468    cp As DWord
    648     nextByte As Byte
    649469End Class
    650470
     471/*!
     472@brief  MultiByteToWideCharで復号化を行うクラス
     473@date   2009/01/12
     474@auther Egtra
     475内部処理用
     476*/
    651477Class WindowsCodePageDecoder
    652478    Inherits Decoder
     
    657483
    658484Protected
    659     Override Sub ConvertCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long, flush As Boolean,
    660         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
     485    Override Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
     486        Dim i As Long
     487        For i = 0 To DefalultDecodingBufferSize - 1 'ELM
     488            Dim len As Long
    665489            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()
     490            Dim t = s.ReadByte()
     491            If t = -1 Then
     492                DecodeImpl = False
     493                Exit Function
    671494            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
     495            buf[0] = t As CHAR
     496            If IsDBCSLeadByteEx(cp, buf[0]) Then
     497                t = s.ReadByte()
     498                If t = -1 Then
     499                    dst.Add(&hfffd As WCHAR)
     500                    DecodeImpl = False
     501                    Exit For
    683502                End If
     503                buf[1] = t As CHAR
     504                len = 2
     505            Else
     506                len = 1
    684507            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()
     508            Dim wc As WCHAR
     509            If MultiByteToWideChar(cp, 0, buf, len, VarPtr(wc), 1) = 0 Then
     510                dst.Add(&hFFFD As WCHAR)
     511            Else
     512                dst.Add(wc)
    689513            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)
    696     End Sub
    697 
    698     Override Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
    699         GetCharsCountCore = srcCount + 1 '暫定
     514        Next
     515        DecodeImpl = True
    700516    End Function
    701517
    702518Private
    703519    cp As DWord
    704     nextByte As Byte
    705520End Class
     521
     522Const DefalultDecodingBufferSize = 16384
    706523
    707524End Namespace
  • trunk/ab5.0/ablib/src/Classes/System/Text/UTF8Encoding.ab

    r411 r676  
    1212    Inherits Encoder
    1313Protected
    14     Override Sub ConvertCore(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long, flush As Boolean,
    15         ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)
    16 
    17         Dim i As Long, j = 0 As Long
    18         For i = 0 To ELM(charCount)
    19             If chars[i] < &h80 Then
     14    Override Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
     15        Dim i As Long
     16        For i = 0 To ELM(size)
     17            If buffer <> 0 Then
     18                If _System_IsLowSurrogate(src[i]) Then
     19                    'UTF-16列からUnicodeコードポイントを復元
     20                    Dim c = (((buffer And &h3FF) As DWord << 10) Or (src[i] And &h3FF)) + &h10000
     21                    '4バイト変換
     22                    s.WriteByte(((c >> 18) Or &hf0) As Byte)
     23                    s.WriteByte(((c >> 12) And &h3F Or &h80) As Byte)
     24                    s.WriteByte(((c >> 6) And &h3F Or &h80) As Byte)
     25                    s.WriteByte((c And &h3F Or &h80) As Byte)
     26                Else
     27                    writeReplacementChar(s)
     28                End If
     29                buffer = 0
     30            ElseIf src[i] < &h80 Then
    2031                '1バイト変換
    21                 If j + 1 > byteCount Then
    22                     'バッファ不足
    23                     Goto *BufferOver
    24                 End If
    25                 bytes[j] = chars[i] As Byte
    26                 j++
    27             ElseIf chars[i] < &h800 Then
     32                s.WriteByte(src[i] As Byte)
     33            ElseIf src[i] < &h800 Then
    2834                '2バイト変換
    29                 If j + 2 > byteCount Then
    30                     Goto *BufferOver
    31                 End If
    32                 bytes[j] = ((chars[i] >> 6) Or &hC0) As Byte
    33                 j++
    34                 bytes[j] = (chars[i] And &h3F Or &h80) As Byte
    35                 j++
    36             ElseIf _System_IsHighSurrogate(chars[i]) Then
    37                 If i + 1 >= charCount Then
    38                     'バッファに貯め込む
    39                     If flush = False Then
    40                         buffer = chars[i]
    41                         Exit Sub
    42                     End If
    43                     'ToDo: chars[i + 1]が範囲外になる場合が考慮されていない
    44                 ElseIf _System_IsLowSurrogate(chars[i + 1]) = False Then
    45                     'EncoderFallback
    46                 End If
    47                 If j + 4 > byteCount Then
    48                     Goto *BufferOver
    49                 End If
    50                 'UTF-16列からUnicodeコードポイントを復元
    51                 Dim c = (((chars[i] And &h3FF) As DWord << 10) Or (chars[i + 1] And &h3FF)) + &h10000
    52                 '4バイト変換
    53                 bytes[j] = ((c >> 18) Or &hf0) As Byte
    54                 j++
    55                 bytes[j] = ((c >> 12) And &h3F Or &h80) As Byte
    56                 j++
    57                 bytes[j] = ((c >> 6) And &h3F Or &h80) As Byte
    58                 j++
    59                 bytes[j] = (c And &h3F Or &h80) As Byte
    60                 j++
    61                 i++
    62             ElseIf _System_IsLowSurrogate(chars[i]) Then
    63                 'EncoderFallback
     35                s.WriteByte(((src[i] >> 6) Or &hC0) As Byte)
     36                s.WriteByte((src[i] And &h3F Or &h80) As Byte)
     37            ElseIf _System_IsHighSurrogate(src[i]) Then
     38                'バッファに貯め込む
     39                buffer = src[i]
     40            ElseIf _System_IsLowSurrogate(src[i]) Then
     41                writeReplacementChar(s)
    6442            Else
    6543                '3バイト変換
    66                 If j + 3 > byteCount Then
    67                     Goto *BufferOver
    68                 End If
    69                 bytes[j] = ((chars[i] >> 12) Or &hE0) As Byte
    70                 j++
    71                 bytes[j] = ((chars[i] >> 6) And &h3F Or &h80) As Byte
    72                 j++
    73                 bytes[j] = (chars[i] And &h3F Or &h80) As Byte
    74                 j++
     44                s.WriteByte(((src[i] >> 12) Or &hE0) As Byte)
     45                s.WriteByte(((src[i] >> 6) And &h3F Or &h80) As Byte)
     46                s.WriteByte((src[i] And &h3F Or &h80) As Byte)
    7547            End If
    7648        Next
    77 
    78         Exit Sub
    79     *BufferOver
    80         'バッファ不足
    81         Throw New ArgumentException("Buffer is not enough.", "bytes")
    8249    End Sub
    8350
    8451Private
     52    ' U+FFFD Replacement CharacterのUTF-8表現、EF BF BDを書き込む。
     53    Sub writeReplacementChar(s As IO.Stream)
     54        Dim rc[2] = [&hef, &hbf, &hbd] As Byte
     55        s.Write(rc, 0, Len(rc))
     56    End Sub
     57
    8558    buffer As WCHAR
    8659End Class
     
    8962    Inherits Decoder
    9063Protected
    91     Override Sub ConvertCore(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long, flush As Boolean,
    92         ByRef bytesUsed As Long, ByRef charsUsed As Long, ByRef completed As Boolean)
    93         Dim i As Long, j = 0 As Long
    94         For i = 0 To ELM(byteCount)
    95             If state = 0 Then
    96                 If bytes[i] <= &h80 Then
     64    Override Function DecodeImpl(dst As Collections.Generic.List<WCHAR>, s As IO.Stream) As Boolean
     65        Dim i As Long
     66        For i = 0 To DefalultDecodingBufferSize - 1 'ELM
     67            Dim b = s.ReadByte()
     68            If b = -1 Then
     69                DecodeImpl = False
     70                Exit Function
     71            ElseIf state = 0 Then
     72                If b <= &h80 Then
    9773                    '1バイト変換
    98                     If j = charCount Then Goto *BufferOver
    99                     chars[j] = bytes[i]
    100                     j++
    101                 ElseIf bytes[i] < &hC0 Then
    102                     'マルチバイトの2バイト目以降
    103                     'DecoderFallback完成までの暫定
    104                     If j = charCount Then Goto *BufferOver
    105                     chars[j] = &hfffd
    106                     j++
    107                 ElseIf bytes[i] < &hD0 Then
     74                    dst.Add(b As WCHAR)
     75                ElseIf b < &hC0 Then
     76                    '先頭バイトがなく、いきなりマルチバイトの2バイト目以降
     77                    dst.Add(&hFFFD As WCHAR)
     78                ElseIf b < &hD0 Then
    10879                    '2バイト文字の始まり
    10980                    last = 2
    110                     buf = bytes[i] And &h3f
    111                     state++
    112                 ElseIf bytes[i] < &hF0 Then
     81                    buffer = b And &h3F
     82                    state++
     83                ElseIf b < &hF0 Then
    11384                    '3バイト文字の始まり
    11485                    last = 3
    115                     buf = bytes[i] And &h1f
    116                     state++
    117                 Else
     86                    buffer = b And &h1F
     87                    state++
     88                ElseIf b < &hF8 Then
    11889                    '4バイト文字の始まり
    11990                    last = 4
    120                     buf = bytes[i] And &h0f
    121                     state++
     91                    buffer = b And &h0F
     92                    state++
     93                Else
     94                    '現在のUTF-8は4バイトを超える表現を認めていない。
     95                    dst.Add(&hFFFD As WCHAR)
    12296                End If
    12397            Else
    124                 If &h80 <= bytes[i] And bytes[i] < &hC0 Then
     98                If &h80 <= b And b < &hC0 Then
    12599                    'マルチバイト文字の2バイト目以降
    126                     buf <<= 6
    127                     buf Or= bytes[i] And &h3F
     100                    buffer <<= 6
     101                    buffer Or= b And &h3F
    128102                    state++
    129103                    If state = last Then '最終バイトに到達
    130                         If state = 2 And buf >= &h80 Then
    131                             chars[j] = buf As WCHAR
    132                             j++
    133                         ElseIf state = 3 And buf >= &h800 And buf < &hD800 And &hE0000 >= buf Then
    134                             chars[j] = buf As WCHAR
    135                             j++
    136                         ElseIf state = 4 And buf <= &h10ffff Then
    137                             buf -= &h10000
    138                             chars[j] = (&hD800 Or (buf >> 10)) As WCHAR
    139                             j++
    140                             chars[j] = (&hDC00 Or (buf And &h3FF)) As WCHAR
    141                             j++
     104                        If state = 2 And buffer >= &h80 Then
     105                            dst.Add(buffer As WCHAR)
     106                        ElseIf state = 3 And buffer >= &h800 And buffer < &hD800 And &hE0000 >= buffer Then
     107                            dst.Add(buffer As WCHAR)
     108                        ElseIf state = 4 And buffer <= &h10FFFF Then
     109                            buffer -= &h10000
     110                            dst.Add((&hD800 Or (buffer >> 10)) As WCHAR)
     111                            dst.Add((&hDC00 Or (buffer And &h3FF)) As WCHAR)
    142112                        Else
    143                             'DecoderFallback
    144                             If j = charCount Then Goto *BufferOver
    145                             chars[j] = &hfffd
    146                             j++
     113                            '最短形式でないもの、4バイト形式で10FFFFを超えるコードポイントのもの
     114                            dst.Add(&hfffd As WCHAR)
    147115                        End If
    148116                        state = 0
    149117                    End If
    150118                Else
    151                     '3, 4バイト文字の先頭
    152                     'DecoderFallback
    153                     If j = charCount Then Goto *BufferOver
    154                     chars[j] = &hfffd
    155                     j++
     119                    'マルチバイト文字の途中なのに、それ以外のバイトが現れた場合
     120                    dst.Add(&hFFFD As WCHAR)
     121                    state = 0
    156122                End If
    157123            End If
    158124        Next
    159         Exit Sub
    160     *BufferOver
    161         'バッファ不足
    162         Throw New ArgumentException("Buffer is not enough.", "bytes")
    163     End Sub
     125        DecodeImpl = True
     126    End Function
    164127
    165128Private
    166     buf As DWord
     129    buffer As DWord
    167130    state As Long
    168131    last As Long
     
    180143    Inherits Encoding
    181144Public
    182 
    183145    Override Function Clone() As Object
    184         Dim c = New UTF8Encoding
    185         c.DecoderFallback = This.DecoderFallback
    186         c.EncoderFallback = This.EncoderFallback
    187         Return c
     146        Clone = New UTF8Encoding
    188147    End Function
    189148
    190149    Override Function GetDecoder() As Decoder
    191150        GetDecoder = New Detail.UTF8Decoder
    192 '       GetDecoder.Fallback = DecoderFallback
    193151    End Function
    194152
    195153    Override Function GetEncoder() As Encoder
    196154        GetEncoder = New Detail.UTF8Encoder
    197 '       GetEncoder.Fallback = EncoderFallback
    198155    End Function
    199156
    200157    Override Function GetMaxByteCount(charCount As Long) As Long
    201         Return charCount * 3
     158        GetMaxByteCount = charCount * 3
    202159        '全てがUTF-8で3バイトになる文字の場合が最大。
    203160
    204         'UTF-8で4バイトになる列は、UTF-16だとサロゲートペアで表現するので、
    205         '1単位あたりでは2バイトしか食わないことにな
     161        'なお、UTF-8で4バイトになる列は、UTF-16だとサロゲートペアで表現するので、
     162        '1単位あたりでは2バイトしか食わないことになり、最大ではない
    206163    End Function
    207164
    208165    Override Function GetMaxCharCount(byteCount As Long) As Long
    209166        '全てU+7F以下の文字だけだった場合
    210         Return byteCount
    211     End Function
    212 Protected
    213     Override Function GetBytesCountCore(s As *WCHAR, n As Long) As Long
    214     End Function
    215 
    216     Override Function GetBytesCore(chars As *WCHAR, charCount As Long, bytes As *Byte, byteCount As Long) As Long
    217     End Function
    218 
    219     Override Function GetCharsCountCore(s As *Byte, n As Long) As Long
    220     End Function
    221 
    222     Override Function GetCharsCore(bytes As *Byte, byteCount As Long, chars As *WCHAR, charCount As Long) As Long
    223     End Function
    224 Public
     167        GetMaxCharCount = byteCount
     168    End Function
     169
    225170    Override Function GetPreamble() As *Byte
    226171        Return bom
     
    230175        Return Len(bom)
    231176    End Function
    232 
    233     Override Function IsAlwaysNormalized() As Boolean
    234         IsAlwaysNormalized = False
    235     End Function
    236 
    237     Override Function IsAlwaysNormalized(f As NormalizationForm) As Boolean
    238         IsAlwaysNormalized = False
    239     End Function
    240 
     177/*
    241178    Override Function BodyName() As String
    242179        Return "utf-8"
     
    258195        Return False
    259196    End Function
     197*/
     198Protected
     199    Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
     200    End Function
     201
     202    Override Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
     203    End Function
     204
     205    Override Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
     206    End Function
     207
     208    Override Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
     209    End Function
     210
    260211Private
    261212    Static bom[2] = [&hEF, &hBB, &hBF] As Byte
Note: See TracChangeset for help on using the changeset viewer.