Changeset 676


Ignore:
Timestamp:
2009/01/13 02:01:38 (3 years ago)
Author:
egtra
Message:

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

Location:
trunk/ab5.0/ablib/src/Classes
Files:
9 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 
  • trunk/ab5.0/ablib/src/Classes/index.ab

    r653 r676  
    9393#require "./System/Text/StringBuilder.ab" 
    9494#require "./System/Text/Encoding.ab" 
    95 '#require "./System/Text/UTF8Encoding.ab" 
     95#require "./System/Text/UTF8Encoding.ab" 
    9696#require "./System/Threading/AutoResetEvent.ab" 
    9797#require "./System/Threading/EventWaitHandle.ab" 
Note: See TracChangeset for help on using the changeset viewer.