[411] | 1 | /*!
|
---|
| 2 | @file Classes/System/Text/Encoding.ab
|
---|
| 3 | @brief Encodingクラスとそれに関係するクラスなどの宣言・定義
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | Namespace System
|
---|
| 7 | Namespace Text
|
---|
| 8 |
|
---|
| 9 | /*!
|
---|
| 10 | @brief 各種の文字符号化(エンコーディング)を行うためのクラス
|
---|
| 11 | @date 2007/12/07
|
---|
| 12 | @auther Egtra
|
---|
| 13 |
|
---|
| 14 | なお、このクラスで、文字列の長さやバッファの大きさを指定するときには、
|
---|
[653] | 15 | 1 WCHAR = 2バイト(UTF-16符号単位)、1 Byte = 1バイトの単位で指定する。
|
---|
[411] | 16 |
|
---|
| 17 | */
|
---|
| 18 | Class Encoding
|
---|
| 19 | Implements ICloneable
|
---|
| 20 | Public
|
---|
| 21 | /*!
|
---|
| 22 | @brief 簡易的複製を作成する。
|
---|
| 23 | */
|
---|
[653] | 24 | Virtual Function Clone() As Object
|
---|
| 25 | Clone = This
|
---|
| 26 | End Function
|
---|
[411] | 27 |
|
---|
| 28 | ' Override Function Equals(y As Object) As Boolean
|
---|
| 29 | ' End Function
|
---|
| 30 |
|
---|
| 31 | ' Override Function GetHashCode() As Long
|
---|
| 32 | ' End Function
|
---|
| 33 |
|
---|
| 34 | Public
|
---|
| 35 | Sub Encoding()
|
---|
| 36 | End Sub
|
---|
| 37 |
|
---|
| 38 | /*!
|
---|
| 39 | @brief 符号化して得られる文字列の長さを計算する。
|
---|
[653] | 40 | @param[in] src 対象文字列
|
---|
| 41 | @param[in] srcCount srcの長さ
|
---|
[411] | 42 | @return 符号化して得られる文字列の長さ
|
---|
| 43 | @date 2007/12/08
|
---|
| 44 | */
|
---|
[653] | 45 | Function GetBytesCount(src As *WCHAR, srcCount As Long) As Long
|
---|
| 46 | If src = 0 Then
|
---|
| 47 | Throw New ArgumentNullException("src")
|
---|
| 48 | ElseIf srcCount < 0 Then
|
---|
| 49 | Throw New ArgumentOutOfRangeException("srcCount")
|
---|
[411] | 50 | End If
|
---|
[653] | 51 | Return GetBytesCountCore(src, srcCount)
|
---|
[411] | 52 | End Function
|
---|
[497] | 53 | #ifdef UNICODE
|
---|
[411] | 54 | /*!
|
---|
| 55 | @brief 符号化して得られる文字列の長さを計算する。
|
---|
[653] | 56 | @param[in] src 対象文字列
|
---|
[411] | 57 | @return 符号化して得られる文字列の長さ
|
---|
| 58 | @date 2007/12/08
|
---|
| 59 | */
|
---|
[653] | 60 | Function GetBytesCount(src As String) As Long
|
---|
| 61 | If ActiveBasic.IsNothing(src) Then
|
---|
| 62 | Throw New ArgumentNullException("src")
|
---|
[411] | 63 | End If
|
---|
[653] | 64 | Return GetBytesCountCore(StrPtr(src), src.Length)
|
---|
[411] | 65 | End Function
|
---|
| 66 | #endif
|
---|
[653] | 67 |
|
---|
| 68 | Private
|
---|
[411] | 69 | /*!
|
---|
[653] | 70 | @brief GetBytesCountの実装を行う。
|
---|
| 71 | @param[in] src 対象文字列
|
---|
| 72 | @param[in] srcCount srcの長さ
|
---|
[411] | 73 | @return 符号化して得られる文字列の長さ
|
---|
| 74 | @date 2007/12/08
|
---|
| 75 | */
|
---|
[653] | 76 | Function GetBytesCountCore(src As *WCHAR, srcCount As Long) As Long
|
---|
| 77 | Dim enc = GetEncoder()
|
---|
| 78 | GetBytesCountCore = enc.GetBytesCount(src, srcCount, True)
|
---|
[411] | 79 | End Function
|
---|
| 80 | Public
|
---|
| 81 | /*!
|
---|
| 82 | @brief 符号化する。
|
---|
[653] | 83 | @param[in] src 入力
|
---|
| 84 | @param[in] srcCount srcの長さ
|
---|
| 85 | @param[out] dst 出力
|
---|
| 86 | @param[in] dstCount dstのバッファの大きさ
|
---|
| 87 | @return dstに書き込まれたバイト数
|
---|
[411] | 88 | @date 2007/12/08
|
---|
| 89 | */
|
---|
[653] | 90 | Function GetBytes(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
|
---|
| 91 | If src = 0 Then
|
---|
| 92 | Throw New ArgumentNullException("src")
|
---|
| 93 | ElseIf dst = 0 Then
|
---|
| 94 | Throw New ArgumentNullException("dst")
|
---|
| 95 | ElseIf srcCount < 0 Then
|
---|
| 96 | Throw New ArgumentOutOfRangeException("srcCount")
|
---|
| 97 | ElseIf dstCount < 0 Then
|
---|
| 98 | Throw New ArgumentOutOfRangeException("dstCount")
|
---|
[411] | 99 | End If
|
---|
| 100 |
|
---|
[653] | 101 | Return GetBytesCore(src, srcCount, dst, dstCount)
|
---|
[411] | 102 | End Function
|
---|
| 103 |
|
---|
[653] | 104 | Private
|
---|
[411] | 105 | /*!
|
---|
| 106 | @brief GetBytesの処理を行う。
|
---|
[653] | 107 | @param[in] src 入力
|
---|
| 108 | @param[in] srcCount srcの長さ
|
---|
| 109 | @param[out] dst 出力
|
---|
| 110 | @param[in] dstCount dstのバッファの大きさ
|
---|
| 111 | @return dstに書き込まれたバイト数
|
---|
[411] | 112 | @exception ArgumentException バッファの大きさが足りない
|
---|
| 113 | @date 2007/12/08
|
---|
| 114 | */
|
---|
[653] | 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
|
---|
[411] | 118 | Public
|
---|
| 119 | /*!
|
---|
| 120 | @brief 復号して得られる文字列の長さを計算する。
|
---|
[653] | 121 | @param[in] src 対象文字列
|
---|
| 122 | @param[in] srcCount srcの長さ
|
---|
[411] | 123 | @return 復号して得られる文字列の長さ
|
---|
| 124 | @date 2007/12/08
|
---|
| 125 | */
|
---|
[653] | 126 | Function GetCharsCount(src As *Byte, srcCount As Long) As Long
|
---|
| 127 | If src = 0 Then
|
---|
| 128 | Throw New ArgumentNullException("src")
|
---|
| 129 | ElseIf srcCount < 0 Then
|
---|
| 130 | Throw New ArgumentOutOfRangeException("srcCount")
|
---|
[411] | 131 | End If
|
---|
[653] | 132 | Return GetCharsCountCore(src, srcCount)
|
---|
[411] | 133 | End Function
|
---|
[653] | 134 |
|
---|
| 135 | Private
|
---|
[411] | 136 | /*!
|
---|
[653] | 137 | @brief GetCharsCountの処理を行う。
|
---|
| 138 | @param[in] src 対象文字列
|
---|
| 139 | @param[in] srcCount srcの長さ
|
---|
[411] | 140 | @return 符号化して得られる文字列の長さ
|
---|
| 141 | @date 2007/12/08
|
---|
| 142 | */
|
---|
[653] | 143 | Function GetCharsCountCore(src As *Byte, srcCount As Long) As Long
|
---|
| 144 | Dim dec = GetDecoder()
|
---|
| 145 | GetCharsCountCore = dec.GetCharsCount(src, srcCount, True)
|
---|
[411] | 146 | End Function
|
---|
| 147 | Public
|
---|
| 148 | /*!
|
---|
| 149 | @brief 復号する。
|
---|
[653] | 150 | @param[in] src 入力
|
---|
| 151 | @param[in] srcCount srcの長さ
|
---|
| 152 | @param[out] dst 出力
|
---|
| 153 | @param[in] dstCount srcのバッファの大きさ
|
---|
| 154 | @return dstに書き込まれたバイト数
|
---|
[411] | 155 | @date 2007/12/08
|
---|
| 156 | */
|
---|
[653] | 157 | Function GetChars(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
|
---|
| 158 | If dst = 0 Then
|
---|
| 159 | Throw New ArgumentNullException("dst")
|
---|
| 160 | ElseIf src = 0 Then
|
---|
| 161 | Throw New ArgumentNullException("src")
|
---|
| 162 | ElseIf dstCount < 0 Then
|
---|
| 163 | Throw New ArgumentOutOfRangeException("dstCount")
|
---|
| 164 | ElseIf srcCount < 0 Then
|
---|
| 165 | Throw New ArgumentOutOfRangeException("srcCount")
|
---|
[411] | 166 | End If
|
---|
| 167 |
|
---|
[653] | 168 | Return GetCharsCore(src, srcCount, dst, dstCount)
|
---|
[411] | 169 | End Function
|
---|
| 170 |
|
---|
[653] | 171 | Private
|
---|
[411] | 172 | /*!
|
---|
| 173 | @brief GetCharsの処理を行う。
|
---|
[653] | 174 | @param[in] src 入力
|
---|
| 175 | @param[in] srcCount srcの長さ
|
---|
| 176 | @param[out] dst 出力
|
---|
| 177 | @param[in] dstCount dstのバッファの大きさ
|
---|
| 178 | @return dstに書き込まれたバイト数
|
---|
[411] | 179 | @exception ArgumentException バッファの大きさが足りない
|
---|
| 180 | @date 2007/12/08
|
---|
| 181 | */
|
---|
[653] | 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
|
---|
[411] | 185 | Public
|
---|
[497] | 186 | #ifdef UNICODE
|
---|
[411] | 187 | /*!
|
---|
| 188 | @brief 復号し、Stringで結果を返す。
|
---|
[653] | 189 | @param[in] src 入力
|
---|
| 190 | @param[in] srcCount srcの長さ
|
---|
[411] | 191 | @return 変換結果の文字列
|
---|
| 192 | @date 2007/12/08
|
---|
| 193 | */
|
---|
[653] | 194 | Function GetString(src As *Byte, srcCount As Long) As String
|
---|
| 195 | If src = 0 Then
|
---|
| 196 | Throw New ArgumentNullException("src")
|
---|
| 197 | ElseIf srcCount < 0 Then
|
---|
| 198 | Throw New ArgumentOutOfRangeException("srcCount")
|
---|
[411] | 199 | End If
|
---|
[653] | 200 | GetString = getStringCore(src, srcCount)
|
---|
[411] | 201 | End Function
|
---|
[653] | 202 |
|
---|
[411] | 203 | Private
|
---|
[653] | 204 | Function getStringCore(src As *Byte, srcCount As Long) As String
|
---|
[411] | 205 | Dim sb = New StringBuilder
|
---|
[653] | 206 | Dim bufCount = GetMaxCharCount(srcCount)
|
---|
| 207 | sb.Length = bufCount
|
---|
| 208 | Dim len = GetCharsCore(src, srcCount, StrPtr(sb), bufCount)
|
---|
[411] | 209 | sb.Length = len
|
---|
[653] | 210 | getStringCore = sb.ToString()
|
---|
[411] | 211 | End Function
|
---|
| 212 | #endif
|
---|
| 213 |
|
---|
| 214 | Public
|
---|
| 215 | /*!
|
---|
| 216 | @brief 符号器を取得する。
|
---|
| 217 | */
|
---|
| 218 | Abstract Function GetDecoder() As Decoder
|
---|
| 219 |
|
---|
| 220 | /*!
|
---|
| 221 | @brief 復号器を取得する。
|
---|
| 222 | */
|
---|
| 223 | Abstract Function GetEncoder() As Encoder
|
---|
| 224 |
|
---|
| 225 | /*!
|
---|
| 226 | @brief ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
|
---|
| 227 | */
|
---|
[653] | 228 | Abstract Function GetMaxByteCount(srcCount As Long) As Long
|
---|
[411] | 229 |
|
---|
| 230 | /*!
|
---|
| 231 | @brief ある長さのバイト列を復号して得られる文字列の最大の長さを返す。
|
---|
| 232 | */
|
---|
[653] | 233 | Abstract Function GetMaxCharCount(srcCount As Long) As Long
|
---|
[411] | 234 |
|
---|
| 235 | /*!
|
---|
| 236 | @brief 符号化された文字列の先頭につける識別文字列の取得
|
---|
[653] | 237 | ようするにUTFのBOM。
|
---|
[411] | 238 | */
|
---|
| 239 | Virtual Function GetPreamble() As *Byte
|
---|
| 240 | Return 0
|
---|
| 241 | End Function
|
---|
| 242 |
|
---|
| 243 | /*!
|
---|
| 244 | @brief GetPreambleの配列の要素数
|
---|
| 245 | */
|
---|
| 246 | Virtual Function GetPreambleLength() As Long
|
---|
| 247 | Return 0
|
---|
| 248 | End Function
|
---|
| 249 |
|
---|
[653] | 250 | ' Abstract Function BodyName() As String
|
---|
| 251 | ' Abstract Function HeaderName() As String
|
---|
[411] | 252 |
|
---|
| 253 | /*!
|
---|
| 254 | @brief コードページの取得。
|
---|
| 255 | */
|
---|
| 256 | ' Abstract Function CodePage() As Long
|
---|
| 257 | /*!
|
---|
| 258 | @brief 最も厳密に対応するWindowsコードページの取得。
|
---|
| 259 | */
|
---|
| 260 | ' Abstract Function WindowsCodePage() As Long
|
---|
| 261 |
|
---|
| 262 | Public
|
---|
| 263 | /*!
|
---|
| 264 | @brief この符号化形式の名前の取得。
|
---|
| 265 | */
|
---|
[653] | 266 | ' Abstract Function EncodingName() As String
|
---|
[411] | 267 |
|
---|
| 268 | /*!
|
---|
| 269 | @brief この符号化形式のIANA登録名の取得。
|
---|
| 270 | */
|
---|
[653] | 271 | ' Abstract Function WebName() As String
|
---|
[411] | 272 |
|
---|
| 273 | ' Abstract Function IsBrowserDisplay() As Boolean
|
---|
| 274 | ' Abstract Function IsBrowserSave() As Boolean
|
---|
| 275 | ' Abstract Function IsMailNewsDisplay() As Boolean
|
---|
| 276 | ' Abstract Function IsMailNewsSave() As Boolean
|
---|
| 277 |
|
---|
| 278 | /*!
|
---|
| 279 | @brief この符号化形式が、1バイト文字だけを使う(複数バイト文字を使わない)かどうか。
|
---|
| 280 | */
|
---|
[653] | 281 | ' Abstract Function IsSingleByte() As Boolean
|
---|
[411] | 282 |
|
---|
| 283 | 'GetPreamble
|
---|
| 284 |
|
---|
| 285 | /*!
|
---|
| 286 | @brief ある符号化文字列から別の符号化文字列へ変換する。
|
---|
| 287 | @param[in] srcEncoding 入力の符号化方式
|
---|
| 288 | @param[in] dstEncoding 出力の符号化方式
|
---|
| 289 | @param[in] bytes 入力文字列
|
---|
| 290 | @param[in] size バイト単位での文字列の長さ
|
---|
| 291 | @return 出力文字列
|
---|
| 292 | @exception ArgumentNullException srcEncoding, dstEncoding, bytesの少なくとも1つ以上がNothing/NULLのとき。
|
---|
| 293 | @exception ArgumentOutOfRangeException sizeが明らかに範囲外(負の値など)のとき。
|
---|
| 294 | */
|
---|
[653] | 295 | ' Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, size As Long) As *Byte
|
---|
| 296 | ' End Function
|
---|
[411] | 297 |
|
---|
[653] | 298 | ' Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, index As Long, count As Long) As *Byte
|
---|
| 299 | ' End Function
|
---|
[411] | 300 |
|
---|
| 301 | /*!
|
---|
| 302 | @brief 指定したコードページ用のEncodingインスタンスの取得。
|
---|
| 303 | */
|
---|
[653] | 304 | ' Static Function GetEncoding(codepage As Long) As Encoding
|
---|
[411] | 305 | ' End Function
|
---|
| 306 | /*!
|
---|
| 307 | @brief 指定した符号化形式名用のEncodingインスタンスの取得。
|
---|
| 308 | */
|
---|
[653] | 309 | ' Static Function GetEncoding(name As String) As Encoding
|
---|
[411] | 310 | ' End Function
|
---|
| 311 | /*!
|
---|
[653] | 312 | @brief システムで標準のANSIコードページ用のEncodingインスタンスの取得。
|
---|
[411] | 313 | */
|
---|
| 314 | Static Function Default() As Encoding
|
---|
| 315 | End Function
|
---|
| 316 | /*!
|
---|
| 317 | @brief UTF-8用のEncodingインスタンスの取得。
|
---|
| 318 | */
|
---|
| 319 | Static Function UTF8() As Encoding
|
---|
| 320 | End Function
|
---|
| 321 | /*!
|
---|
| 322 | @brief UTF-16LE用のEncodingインスタンスの取得。
|
---|
| 323 | */
|
---|
| 324 | Static Function UTF16() As Encoding
|
---|
| 325 | End Function
|
---|
| 326 | /*!
|
---|
| 327 | @brief UTF-16BE用のEncodingインスタンスの取得。
|
---|
| 328 | */
|
---|
| 329 | Static Function UTF16BE() As Encoding
|
---|
| 330 | End Function
|
---|
| 331 | End Class
|
---|
| 332 |
|
---|
| 333 | /*!
|
---|
| 334 | @brief 復号を行うクラス
|
---|
| 335 | @date 2007/12/19
|
---|
| 336 | @auther Egtra
|
---|
| 337 | */
|
---|
| 338 | Class Decoder
|
---|
| 339 | Public
|
---|
| 340 | /*!
|
---|
| 341 | @brief 変換する
|
---|
[653] | 342 | @param[in] src 入力
|
---|
| 343 | @param[in] srcCount 入力要素数
|
---|
| 344 | @param[out] dst 出力
|
---|
| 345 | @param[in] dstCount 出力要素数
|
---|
[411] | 346 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
[653] | 347 | @param[out] srcUsed 使用された入力の要素数
|
---|
| 348 | @param[out] dstUsed 出力の内、実際に書き込まれた要素数
|
---|
[411] | 349 | @param[out] completed 入力の全ての文字が変換に使われたかどうか
|
---|
| 350 | */
|
---|
[653] | 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)
|
---|
[411] | 354 |
|
---|
[655] | 355 | If src = 0 And srcCount > 0 Then
|
---|
[653] | 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")
|
---|
[411] | 363 | End If
|
---|
[653] | 364 | ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
|
---|
[411] | 365 | End Sub
|
---|
| 366 |
|
---|
| 367 | /*!
|
---|
| 368 | @brief 変換する
|
---|
[653] | 369 | @param[in] src 入力
|
---|
| 370 | @param[in] srcCount 入力要素数
|
---|
| 371 | @param[out] dst 出力
|
---|
| 372 | @param[in] dstCount 出力要素数
|
---|
[411] | 373 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
[653] | 374 | @return 出力の内、実際に書き込まれた要素数
|
---|
[411] | 375 | */
|
---|
[653] | 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
|
---|
[411] | 378 | Dim completed As Boolean
|
---|
[653] | 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
|
---|
[411] | 383 | End Function
|
---|
| 384 |
|
---|
| 385 | /*!
|
---|
[653] | 386 | @brief 変換すると何文字になるか数える
|
---|
| 387 | @param[in] src 入力
|
---|
| 388 | @param[in] srcCount 入力要素数
|
---|
| 389 | @param[in] flush 終了後に内部状態を初期化するとして計算するかどうか
|
---|
| 390 | @return 必要な文字数
|
---|
[411] | 391 | */
|
---|
[653] | 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)
|
---|
[411] | 399 | End Function
|
---|
| 400 |
|
---|
| 401 | /*!
|
---|
[653] | 402 | @brief 内部状態を初期状態に戻す
|
---|
[411] | 403 | */
|
---|
[653] | 404 | Virtual Sub Reset()
|
---|
| 405 | End Sub
|
---|
[411] | 406 |
|
---|
| 407 | Protected
|
---|
| 408 | /*!
|
---|
[653] | 409 | @brief 実際に変換する
|
---|
| 410 | @param[in] src 入力
|
---|
| 411 | @param[in] srcCount 入力要素数
|
---|
| 412 | @param[out] dst 出力
|
---|
| 413 | @param[in] dstCount 出力要素数
|
---|
[411] | 414 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
[653] | 415 | @param[out] dstUsed 使用された入力の要素数
|
---|
| 416 | @param[out] srcUsed 出力の内、実際に書き込まれた要素数
|
---|
[411] | 417 | @param[out] completed 入力の全ての文字が変換に使われたかどうか
|
---|
| 418 | */
|
---|
[653] | 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)
|
---|
[411] | 421 |
|
---|
[653] | 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
|
---|
[411] | 430 | End Class
|
---|
| 431 |
|
---|
| 432 | /*!
|
---|
| 433 | @brief 符号化を行うクラス
|
---|
| 434 | @date 2007/12/19
|
---|
| 435 | @auther Egtra
|
---|
| 436 | */
|
---|
| 437 | Class Encoder
|
---|
| 438 | Public
|
---|
| 439 | /*!
|
---|
| 440 | @brief 変換する
|
---|
[653] | 441 | @param[in] src 入力
|
---|
| 442 | @param[in] srcCount 入力要素数
|
---|
| 443 | @param[out] dst 出力
|
---|
| 444 | @param[in] dstCount 出力要素数
|
---|
[411] | 445 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
[653] | 446 | @param[out] srcUsed 使用された入力の要素数
|
---|
| 447 | @param[out] dstUsed 出力の内、実際に書き込まれた要素数
|
---|
[411] | 448 | @param[out] completed 入力の全ての文字が変換に使われたかどうか
|
---|
| 449 | */
|
---|
[653] | 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)
|
---|
[411] | 453 |
|
---|
[655] | 454 | If src = 0 And srcCount > 0 Then
|
---|
[653] | 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")
|
---|
[411] | 462 | End If
|
---|
[653] | 463 | ConvertCore(src, srcCount, dst, dstCount, flush, srcUsed, dstUsed, completed)
|
---|
[411] | 464 | End Sub
|
---|
| 465 |
|
---|
| 466 | /*!
|
---|
[653] | 467 | @brief 変換する
|
---|
| 468 | @param[in] src 入力
|
---|
| 469 | @param[in] srcCount 入力要素数
|
---|
| 470 | @param[out] dst 出力
|
---|
| 471 | @param[in] dstCount 出力要素数
|
---|
| 472 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
| 473 | @return 出力の内、実際に書き込まれた要素数
|
---|
[411] | 474 | */
|
---|
[653] | 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
|
---|
[411] | 483 |
|
---|
[653] | 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")
|
---|
[411] | 496 | End If
|
---|
[653] | 497 | GetBytesCountCore(src, srcCount, flush)
|
---|
| 498 | End Function
|
---|
| 499 |
|
---|
| 500 | /*!
|
---|
| 501 | @brief 内部状態を初期状態に戻す
|
---|
| 502 | */
|
---|
| 503 | Virtual Sub Reset()
|
---|
[411] | 504 | End Sub
|
---|
| 505 |
|
---|
[653] | 506 | Protected
|
---|
[411] | 507 | /*!
|
---|
[653] | 508 | @brief 実際に変換する
|
---|
| 509 | @param[in] src 入力
|
---|
| 510 | @param[in] srcCount 入力要素数
|
---|
| 511 | @param[out] dst 出力
|
---|
| 512 | @param[in] dstCount 出力要素数
|
---|
[411] | 513 | @param[in] flush 終了後に内部状態を初期化するかどうか
|
---|
[653] | 514 | @param[out] dstUsed 使用された入力の要素数
|
---|
| 515 | @param[out] srcUsed 出力の内、実際に書き込まれた要素数
|
---|
| 516 | @param[out] completed 入力の全ての文字が変換に使われたかどうか
|
---|
[411] | 517 | */
|
---|
[653] | 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)
|
---|
[411] | 520 |
|
---|
| 521 | /*!
|
---|
[653] | 522 | @brief 変換すると何文字になるか数える
|
---|
| 523 | @param[in] src 入力
|
---|
| 524 | @param[in] srcCount 入力要素数
|
---|
| 525 | @param[in] flush 終了後に内部状態を初期化するとして計算するかどうか
|
---|
| 526 | @return 必要な文字数
|
---|
[411] | 527 | */
|
---|
[653] | 528 | Abstract Function GetBytesCountCore(src As *WCHAR, srcCount As Long, flush As Boolean) As Long
|
---|
| 529 | End Class
|
---|
| 530 |
|
---|
| 531 | Enum NormalizationForm
|
---|
| 532 | FormC
|
---|
| 533 | FormD
|
---|
| 534 | FormKC
|
---|
| 535 | FormKD
|
---|
| 536 | End Enum
|
---|
| 537 |
|
---|
| 538 | Namespace Detail
|
---|
| 539 |
|
---|
| 540 | /*!
|
---|
| 541 | @brief WideCharToMultiByte/MultiByteToWideCharで変換を行うエンコーディング。
|
---|
| 542 | DBCS/SBCS限定。UTF-8やUTF-7は非対応。
|
---|
| 543 | */
|
---|
| 544 | Class WindowsCodePageEncoding
|
---|
| 545 | Inherits Encoding
|
---|
| 546 | Public
|
---|
| 547 | Sub WindowsCodePageEncoding(codepage As DWord)
|
---|
| 548 | cp = codepage
|
---|
| 549 | End Sub
|
---|
| 550 |
|
---|
| 551 | /*!
|
---|
| 552 | @brief 符号器を取得する。
|
---|
| 553 | */
|
---|
| 554 | Override Function GetDecoder() As Decoder
|
---|
| 555 | GetDecoder = New WindowsCodePageDecoder(cp)
|
---|
[411] | 556 | End Function
|
---|
| 557 |
|
---|
| 558 | /*!
|
---|
[653] | 559 | @brief 復号器を取得する。
|
---|
[411] | 560 | */
|
---|
[653] | 561 | Override Function GetEncoder() As Encoder
|
---|
| 562 | GetEncoder = New WindowsCodePageEncoder(cp)
|
---|
[411] | 563 | End Function
|
---|
| 564 |
|
---|
[653] | 565 | Override Function GetHashCode() As Long
|
---|
| 566 | GetHashCode = cp As Long
|
---|
| 567 | End Function
|
---|
| 568 |
|
---|
| 569 | Override Function Equals(x As Object) As Boolean
|
---|
| 570 | If GetType().Equals(x.GetType()) Then
|
---|
| 571 | Dim xe = x As WindowsCodePageEncoding
|
---|
| 572 | Equals = cp = xe.cp
|
---|
| 573 | Else
|
---|
| 574 | Equals = False
|
---|
| 575 | End If
|
---|
| 576 | End Function
|
---|
| 577 |
|
---|
[411] | 578 | /*!
|
---|
[653] | 579 | @brief ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
|
---|
[411] | 580 | */
|
---|
[653] | 581 | Override Function GetMaxByteCount(srcCount As Long) As Long
|
---|
| 582 | GetMaxByteCount = srcCount * 2
|
---|
[411] | 583 | End Function
|
---|
| 584 |
|
---|
| 585 | /*!
|
---|
[653] | 586 | @brief ある長さのバイト列を復号して得られる文字列の最大の長さを返す。
|
---|
[411] | 587 | */
|
---|
[653] | 588 | Override Function GetMaxCharCount(srcCount As Long) As Long
|
---|
| 589 | GetMaxCharCount = srcCount
|
---|
| 590 | End Function
|
---|
| 591 |
|
---|
| 592 | Private
|
---|
| 593 | cp As DWord
|
---|
| 594 | End Class
|
---|
| 595 |
|
---|
| 596 | Class WindowsCodePageEncoder
|
---|
| 597 | Inherits Encoder
|
---|
| 598 | Public
|
---|
| 599 | Sub WindowsCodePageEncoder(codepage As DWord)
|
---|
| 600 | cp = codepage
|
---|
[411] | 601 | End Sub
|
---|
[653] | 602 |
|
---|
| 603 | Override Sub Reset()
|
---|
| 604 | nextByte = 0
|
---|
| 605 | End Sub
|
---|
| 606 |
|
---|
[411] | 607 | Protected
|
---|
[653] | 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)
|
---|
[411] | 610 |
|
---|
[653] | 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
|
---|
[655] | 643 | GetBytesCountCore = srcCount * 2 + 1 '暫定
|
---|
[653] | 644 | End Function
|
---|
| 645 |
|
---|
[411] | 646 | Private
|
---|
[653] | 647 | cp As DWord
|
---|
| 648 | nextByte As Byte
|
---|
[411] | 649 | End Class
|
---|
| 650 |
|
---|
[653] | 651 | Class WindowsCodePageDecoder
|
---|
| 652 | Inherits Decoder
|
---|
| 653 | Public
|
---|
| 654 | Sub WindowsCodePageDecoder(codepage As DWord)
|
---|
| 655 | cp = codepage
|
---|
| 656 | End Sub
|
---|
[411] | 657 |
|
---|
[653] | 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)
|
---|
[655] | 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)
|
---|
[653] | 696 | End Sub
|
---|
| 697 |
|
---|
| 698 | Override Function GetCharsCountCore(src As *Byte, srcCount As Long, flush As Boolean) As Long
|
---|
[655] | 699 | GetCharsCountCore = srcCount + 1 '暫定
|
---|
[653] | 700 | End Function
|
---|
| 701 |
|
---|
| 702 | Private
|
---|
| 703 | cp As DWord
|
---|
[655] | 704 | nextByte As Byte
|
---|
[411] | 705 | End Class
|
---|
| 706 |
|
---|
[653] | 707 | End Namespace
|
---|
| 708 |
|
---|
[411] | 709 | End Namespace 'Text
|
---|
| 710 | End Namespace 'System
|
---|