Changeset 673


Ignore:
Timestamp:
Jan 5, 2009, 1:40:11 AM (15 years ago)
Author:
イグトランス (egtra)
Message:

Encoder/Decoderを排除した実装(UTF8Encodingは修正していません)。

Location:
branch/egtra-stream-without-en_dec/Classes/System
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branch/egtra-stream-without-en_dec/Classes/System/IO/StreamReader.ab

    r666 r673  
    5858    */
    5959    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
     60        Dim nextRead As *Byte
     61        Dim readSize = s.Read(mbBuf + bufSize, 0, bufCapacity - bufSize)
     62        If readSize = 0 Then
     63            If bufSize <> 0 Then
     64#ifdef UNCODE
     65                Buffer.Append(&hfffd As WCHAR)
     66#else
     67                Buffer.Append("?")
     68#endif
     69            End If
    7270            Underflow = False
    7371            Exit Function
    7472        End If
     73        Dim mbLen = bufSize + readSize
     74        '文字全体が揃っている部分を抽出する。
     75        Dim pNext = mbBuf
    7576        Do
    76             Dim q = CharNextExA(cp, pNext, 0)
     77            Dim q = e.NextChar(pNext, ((mbBuf + mbLen) - pNext) As Long)
    7778            If q = pNext Then
    7879                Exit Do
    7980            End If
    80             pNext = q As PSTR
     81            pNext = q
    8182        Loop
    82         If pNext <> mbBuf + mbLen Then
    83             leadByte = mbBuf[mbLen - 1]
     83        '文字全体が揃っている部分を変換しTextReaderのバッファに送る。
     84        Dim wcBufCapacity = e.GetMaxCharCount(mbLen)
     85        Dim wcBuf = GC_malloc_atomic(wcBufCapacity * SizeOf (WCHAR)) As *WCHAR
     86        Dim wcLen = e.GetChars(mbBuf, (pNext - mbBuf) As Long, wcBuf, wcBufCapacity)
     87        Dim appendStr As PCTSTR
     88        Dim appendLen = GetStr(wcBuf, wcLen As SIZE_T, appendStr)
     89        Dim readerBuffer = Buffer
     90        readerBuffer.Append(appendStr, 0, appendLen)
     91        'マルチバイトの揃っていない部分を手前に連れてくる。
     92        bufSize = ((mbBuf + mbLen) - pNext) As Long
     93        If bufSize <> 0 Then
     94            memmove(mbBuf, mbBuf + mbLen, bufSize)
    8495        End If
    85         Dim wcLen = MultiByteToWideChar(cp, 0, mbBuf, (pNext - mbBuf) As Long, wcBuf, 4095)
    86         Dim s = New String(wcBuf, wcLen)
    87         Dim buf = Buffer
    88         buf.Append(s)
    8996        Underflow = True
    9097    End Function
     
    97104    Sub init(str As Stream)
    98105        s = str
    99         cp  = CP_ACP '暫定。
    100         leadByte = 0
     106        e = New Text.Detail.WindowsCodePageEncoding(CP_ACP) '暫定。
     107        bufCapacity = 8192
     108        mbBuf = GC_malloc_atomic(bufCapacity) As *Byte
     109        bufSize = 0
    101110    End Sub
    102111
    103112    s As Stream
    104     cp As Word
    105     leadByte As Byte
     113    e As Text.Encoding
     114    mbBuf As *Byte
     115    bufSize As Long
     116    bufCapacity As Long
    106117End Class
    107118
  • branch/egtra-stream-without-en_dec/Classes/System/IO/StreamWriter.ab

    r653 r673  
    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        softFlush()
     44        s.Flush()
     45    End Sub
     46
     47    Override Sub WriteLine()
     48        Super.WriteLine()
     49        softFlush()
    5950    End Sub
    6051
     
    6354        If disposing Then
    6455            Flush()
    65             flushLast()
    6656            s.Dispose()
    6757        End If
     
    7363        buf = New Text.StringBuilder(4096)
    7464        '暫定。正式版ではUTF-8を標準とする。
    75         encoding = New Text.Detail.WindowsCodePageEncoding(CP_ACP)
    76         encoder = encoding.GetEncoder()
     65        e = New Text.Detail.WindowsCodePageEncoding(CP_ACP)
    7766    End Sub
    7867
    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
     68    Sub softFlush()
     69        Dim buf = Buffer()
     70        Dim pws As PCWSTR
     71        Dim wcSize = GetWCStr(buf.ToString(), pws)
     72        Dim mbMaxSize = e.GetMaxByteCount(wcSize)
     73        Dim mbBuf = GC_malloc_atomic(mbMaxSize) As *Byte
     74        Dim mbBufSize = e.GetBytes(pws, wcSize, mbBuf, mbMaxSize)
     75        s.Write(mbBuf, 0, mbBufSize)
    8876    End Sub
    8977
    90     encoding As Text.Encoding
    91     encoder As Text.Encoder
     78    e As Text.Encoding
    9279    s As System.IO.Stream
    9380End Class
  • branch/egtra-stream-without-en_dec/Classes/System/IO/TextWriter.ab

    r665 r673  
    8686    End Sub
    8787
    88     Sub WriteLine()
     88    Virtual Sub WriteLine()
    8989        Write(Environment.NewLine)
    9090    End Sub
  • branch/egtra-stream-without-en_dec/Classes/System/Text/Encoding.ab

    r655 r673  
    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    /*!
    216     @brief  符号器を取得する。
    217     */
    218     Abstract Function GetDecoder() As Decoder
    219 
    220     /*!
    221     @brief  復号器を取得する。
    222     */
    223     Abstract Function GetEncoder() As Encoder
    224 
    225     /*!
    226206    @brief  ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
    227207    */
     
    242222
    243223    /*!
    244     @brief  GetPreambleの配列の要素数
     224    @brief  GetPreambleの配列の要素数
    245225    */
    246226    Virtual Function GetPreambleLength() As Long
     
    248228    End Function
    249229
     230    /*!
     231    @brief 与えられたバイト文字列から2文字目の開始地点を探す。
     232    @param[in] s (マルチバイト)文字列
     233    @param[in] count sの要素数
     234    @return 2文字目の開始位置。2文字が存在しない場合、sを返す。
     235    */
     236    Function NextChar(s As *Byte, count As Long) As *Byte
     237        If count = 0 Then
     238            NextChar = s
     239        ElseIf s = 0 Then
     240            Throw New ArgumentNullException("s")
     241        ElseIf count < 0 Then
     242            Throw New ArgumentException("count")
     243        Else
     244            NextChar = NextCharCore(s, count)
     245        End If
     246    End Function
     247Protected
     248    /*!
     249    @brief NextCharの処理を行う。
     250    @param[in] s (マルチバイト)文字列
     251    @param[in] count sの要素数
     252    @return 2文字目の開始位置。2文字が存在しない場合、sを返す。
     253    */
     254    Abstract Function NextCharCore(s As *Byte, count As Long) As *Byte
     255
     256Public
    250257'   Abstract Function BodyName() As String
    251258'   Abstract Function HeaderName() As String
     
    331338End Class
    332339
    333 /*!
    334 @brief  復号を行うクラス
    335 @date   2007/12/19
    336 @auther Egtra
    337 */
    338 Class Decoder
    339 Public
    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)
    365     End Sub
    366 
    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
    529 End Class
    530 
    531340Enum NormalizationForm
    532341    FormC
     
    549358    End Sub
    550359
    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 
    565360    Override Function GetHashCode() As Long
    566361        GetHashCode = cp As Long
     
    590385    End Function
    591386
     387Protected
     388    Override Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
     389        GetBytesCountCore = WideCharToMultiByte(cp, 0, src, srcCount, 0, 0, 0, 0)
     390        If srcCount <> 0 And GetBytesCountCore = 0 Then
     391            ActiveBasic.Windows.ThrowWithLastError()
     392        End If
     393    End Function
     394
     395    Override Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
     396        GetBytesCore = WideCharToMultiByte(cp, 0, src, srcCount, dst As PCSTR, dstCount, 0, 0)
     397        If srcCount <> 0 And GetBytesCore = 0 Then
     398            ActiveBasic.Windows.ThrowWithLastError()
     399        End If
     400    End Function
     401
     402    Override Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
     403        GetCharsCountCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, 0, 0)
     404        If srcCount <> 0 And GetCharsCountCore = 0 Then
     405            ActiveBasic.Windows.ThrowWithLastError()
     406        End If
     407    End Function
     408
     409    Override Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
     410        GetCharsCore = MultiByteToWideChar(cp, 0, src As PCSTR, srcCount, dst, dstCount)
     411        If srcCount <> 0 And GetCharsCore = 0 Then
     412            ActiveBasic.Windows.ThrowWithLastError()
     413        End If
     414    End Function
     415
     416    Override Function NextCharCore(s As *Byte, count As Long) As *Byte
     417        NextCharCore = CharNextExA(cp As Word, s As PCSTR, 0) As *Byte
     418    End Function
     419
    592420Private
    593421    cp As DWord
    594422End Class
    595423
    596 Class WindowsCodePageEncoder
    597     Inherits Encoder
    598 Public
    599     Sub WindowsCodePageEncoder(codepage As DWord)
    600         cp = codepage
    601     End Sub
    602 
    603     Override Sub Reset()
    604         nextByte = 0
    605     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
    645 
    646 Private
    647     cp As DWord
    648     nextByte As Byte
    649 End Class
    650 
    651 Class WindowsCodePageDecoder
    652     Inherits Decoder
    653 Public
    654     Sub WindowsCodePageDecoder(codepage As DWord)
    655         cp = codepage
    656     End Sub
    657 
    658 Protected
    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
    665             Dim buf[1] As CHAR
    666             buf[0] = nextByte As CHAR
    667             buf[1] = src[1] As CHAR
    668             Dim len = MultiByteToWideChar(cp, 0, buf, Len(buf), VarPtr(dst[dstPos]), 10)
    669             If len = 0 Then
    670                 ActiveBasic.Windows.ThrowWithLastError()
    671             End If
    672             srcPos++
    673             dstPos++
    674             nextByte = 0
    675         End If
    676         While srcPos < srcCount And dstPos < srcCount
    677             Dim srcCharSize = 1 As Long
    678             If IsDBCSLeadByteEx(cp, src[srcPos]) Then
    679                 srcCharSize = 2
    680                 If srcPos + 1 = srcCount Then
    681                     nextByte = src[srcPos]
    682                     Exit While
    683                 End If
    684             End If
    685             '将来的には行毎に変換しMB_USEGLYPHCHARSを使うようにしたい。
    686             Dim len = MultiByteToWideChar(cp, 0, VarPtr(src[srcPos]) As *CHAR, srcCharSize, VarPtr(dst[dstPos]), 1)
    687             If len = 0 Then
    688                 ActiveBasic.Windows.ThrowWithLastError()
    689             End If
    690             srcPos += srcCharSize
    691             dstPos++
    692         Wend
    693         srcUsed = srcPos
    694         dstUsed = dstPos
    695         completed = (srcPos = srcCount And dstPos = srcCount And nextByte = 0)
    696     End Sub
    697 
    698     Override Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
    699         GetCharsCountCore = srcCount + 1 '暫定
    700     End Function
    701 
    702 Private
    703     cp As DWord
    704     nextByte As Byte
    705 End Class
    706 
    707424End Namespace
    708425
Note: See TracChangeset for help on using the changeset viewer.