source: trunk/ab5.0/ablib/src/Classes/System/Text/Encoding.ab@ 676

Last change on this file since 676 was 676, checked in by イグトランス (egtra), 15 years ago

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

File size: 13.6 KB
Line 
1/*!
2@file Classes/System/Text/Encoding.ab
3@brief Encodingクラスとそれに関係するクラスなどの宣言・定義
4*/
5
6Namespace System
7Namespace Text
8
9/*!
10@brief 各種の文字符号化(エンコーディング)を行うためのクラス
11@date 2007/12/07
12@auther Egtra
13
14なお、このクラスで、文字列の長さやバッファの大きさを指定するときには、
151 WCHAR = 2バイト(UTF-16符号単位)、1 Byte = 1バイトの単位で指定する。
16
17*/
18Class Encoding
19 Implements ICloneable
20Public
21 /*!
22 @brief 簡易的複製を作成する。
23 */
24 Virtual Function Clone() As Object
25 Clone = This
26 End Function
27
28' Override Function Equals(y As Object) As Boolean
29' End Function
30
31' Override Function GetHashCode() As Long
32' End Function
33
34Public
35 Sub Encoding()
36 End Sub
37
38 /*!
39 @brief 符号化して得られる文字列の長さを計算する。
40 @param[in] src 対象文字列
41 @param[in] srcCount srcの長さ(要素数単位)
42 @return 符号化して得られる文字列の長さ(要素数単位)
43 @date 2007/12/08
44 */
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")
50 End If
51 Return GetBytesCountCore(src, srcCount)
52 End Function
53#ifdef UNICODE
54 /*!
55 @brief 符号化して得られる文字列の長さを計算する。
56 @param[in] src 対象文字列
57 @return 符号化して得られる文字列の長さ(要素数単位)
58 @date 2007/12/08
59 */
60 Function GetBytesCount(src As String) As Long
61 If ActiveBasic.IsNothing(src) Then
62 Throw New ArgumentNullException("src")
63 End If
64 Return GetBytesCountCore(StrPtr(src), src.Length)
65 End Function
66#endif
67
68Protected
69 /*!
70 @brief GetBytesCountの実装を行う。
71 @param[in] src 対象文字列
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
77Public
78 /*!
79 @brief 符号化する。
80 @param[in] src 入力
81 @param[in] srcCount srcの長さ(要素数単位)
82 @param[out] dst 出力
83 @param[in] dstCount dstのバッファの大きさ(要素数単位)
84 @return dstに書き込まれた要素数
85 @date 2007/12/08
86 */
87 Function GetBytes(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
88 If src = 0 Then
89 Throw New ArgumentNullException("src")
90 ElseIf dst = 0 Then
91 Throw New ArgumentNullException("dst")
92 ElseIf srcCount < 0 Then
93 Throw New ArgumentOutOfRangeException("srcCount")
94 ElseIf dstCount < 0 Then
95 Throw New ArgumentOutOfRangeException("dstCount")
96 End If
97
98 Return GetBytesCore(src, srcCount, dst, dstCount)
99 End Function
100
101Protected
102 /*!
103 @brief GetBytesの処理を行う。
104 @param[in] src 入力
105 @param[in] srcCount srcの長さ(要素数単位)
106 @param[out] dst 出力
107 @param[in] dstCount dstのバッファの大きさ(要素数単位)
108 @return dstに書き込まれた要素数
109 @exception ArgumentException バッファの大きさが足りない
110 @date 2007/12/08
111 */
112 Abstract Function GetBytesCore(src As *WCHAR, srcCount As Long, dst As *Byte, dstCount As Long) As Long
113Public
114 /*!
115 @brief 復号して得られる文字列の長さを計算する。
116 @param[in] src 対象文字列
117 @param[in] srcCount srcの長さ(要素数単位)
118 @return 復号して得られる文字列の長さ(要素数単位)
119 @date 2007/12/08
120 */
121 Function GetCharsCount(src As *Byte, srcCount As Long) As Long
122 If src = 0 Then
123 Throw New ArgumentNullException("src")
124 ElseIf srcCount < 0 Then
125 Throw New ArgumentOutOfRangeException("srcCount")
126 End If
127 Return GetCharsCountCore(src, srcCount)
128 End Function
129
130Protected
131 /*!
132 @brief GetCharsCountの処理を行う。
133 @param[in] src 対象文字列
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
139Public
140 /*!
141 @brief 復号する。
142 @param[in] src 入力
143 @param[in] srcCount srcの長さ(要素数単位)
144 @param[out] dst 出力
145 @param[in] dstCount srcのバッファの大きさ(要素数単位)
146 @return dstに書き込まれた要素数
147 @date 2007/12/08
148 */
149 Function GetChars(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
150 If dst = 0 Then
151 Throw New ArgumentNullException("dst")
152 ElseIf src = 0 Then
153 Throw New ArgumentNullException("src")
154 ElseIf dstCount < 0 Then
155 Throw New ArgumentOutOfRangeException("dstCount")
156 ElseIf srcCount < 0 Then
157 Throw New ArgumentOutOfRangeException("srcCount")
158 End If
159
160 Return GetCharsCore(src, srcCount, dst, dstCount)
161 End Function
162
163Protected
164 /*!
165 @brief GetCharsの処理を行う。
166 @param[in] src 入力
167 @param[in] srcCount srcの長さ(要素数単位)
168 @param[out] dst 出力
169 @param[in] dstCount dstのバッファの大きさ(要素数単位)
170 @return dstに書き込まれた要素数
171 @exception ArgumentException バッファの大きさが足りない
172 @date 2007/12/08
173 */
174 Abstract Function GetCharsCore(src As *Byte, srcCount As Long, dst As *WCHAR, dstCount As Long) As Long
175Public
176#ifdef UNICODE
177 /*!
178 @brief 復号し、Stringで結果を返す。
179 @param[in] src 入力
180 @param[in] srcCount srcの長さ(要素数単位)
181 @return 変換結果の文字列
182 @date 2007/12/08
183 */
184 Function GetString(src As *Byte, srcCount As Long) As String
185 If src = 0 Then
186 Throw New ArgumentNullException("src")
187 ElseIf srcCount < 0 Then
188 Throw New ArgumentOutOfRangeException("srcCount")
189 End If
190 GetString = getStringCore(src, srcCount)
191 End Function
192
193Private
194 Function getStringCore(src As *Byte, srcCount As Long) As String
195 Dim sb = New StringBuilder
196 Dim bufCount = GetMaxCharCount(srcCount)
197 sb.Length = bufCount
198 Dim len = GetCharsCore(src, srcCount, StrPtr(sb), bufCount)
199 sb.Length = len
200 getStringCore = sb.ToString()
201 End Function
202#endif
203
204Public
205 /*!
206 @brief 復号器を取得する。
207 */
208 Abstract Function GetDecoder() As Decoder
209
210 /*!
211 @brief 符号器を取得する。
212 */
213 Abstract Function GetEncoder() As Encoder
214
215 /*!
216 @brief ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
217 */
218 Abstract Function GetMaxByteCount(srcCount As Long) As Long
219
220 /*!
221 @brief ある長さのバイト列を復号して得られる文字列の最大の長さを返す。
222 */
223 Abstract Function GetMaxCharCount(srcCount As Long) As Long
224
225 /*!
226 @brief 符号化された文字列の先頭につける識別文字列の取得
227 ようするにUTFのBOM。
228 */
229 Virtual Function GetPreamble() As *Byte
230 Return 0
231 End Function
232
233 /*!
234 @brief GetPreambleの配列の要素数。
235 */
236 Virtual Function GetPreambleLength() As Long
237 Return 0
238 End Function
239
240Public
241' Abstract Function BodyName() As String
242' Abstract Function HeaderName() As String
243
244 /*!
245 @brief コードページの取得。
246 */
247' Abstract Function CodePage() As Long
248 /*!
249 @brief 最も厳密に対応するWindowsコードページの取得。
250 */
251' Abstract Function WindowsCodePage() As Long
252
253Public
254 /*!
255 @brief この符号化形式の名前の取得。
256 */
257' Abstract Function EncodingName() As String
258
259 /*!
260 @brief この符号化形式のIANA登録名の取得。
261 */
262' Abstract Function WebName() As String
263
264' Abstract Function IsBrowserDisplay() As Boolean
265' Abstract Function IsBrowserSave() As Boolean
266' Abstract Function IsMailNewsDisplay() As Boolean
267' Abstract Function IsMailNewsSave() As Boolean
268
269 /*!
270 @brief この符号化形式が、1バイト文字だけを使う(複数バイト文字を使わない)かどうか。
271 */
272' Abstract Function IsSingleByte() As Boolean
273
274 'GetPreamble
275
276 /*!
277 @brief ある符号化文字列から別の符号化文字列へ変換する。
278 @param[in] srcEncoding 入力の符号化方式
279 @param[in] dstEncoding 出力の符号化方式
280 @param[in] bytes 入力文字列
281 @param[in] size バイト単位での文字列の長さ
282 @return 出力文字列
283 @exception ArgumentNullException srcEncoding, dstEncoding, bytesの少なくとも1つ以上がNothing/NULLのとき。
284 @exception ArgumentOutOfRangeException sizeが明らかに範囲外(負の値など)のとき。
285 */
286' Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, size As Long) As *Byte
287' End Function
288
289' Static Function Convert(srcEncoding As Encoding, dstEncoding As Encoding, bytes As *Byte, index As Long, count As Long) As *Byte
290' End Function
291
292 /*!
293 @brief 指定したコードページ用のEncodingインスタンスの取得。
294 */
295' Static Function GetEncoding(codepage As Long) As Encoding
296' End Function
297 /*!
298 @brief 指定した符号化形式名用のEncodingインスタンスの取得。
299 */
300' Static Function GetEncoding(name As String) As Encoding
301' End Function
302 /*!
303 @brief システムで標準のANSIコードページ用のEncodingインスタンスの取得。
304 */
305 Static Function Default() As Encoding
306 End Function
307 /*!
308 @brief UTF-8用のEncodingインスタンスの取得。
309 */
310 Static Function UTF8() As Encoding
311 End Function
312 /*!
313 @brief UTF-16LE用のEncodingインスタンスの取得。
314 */
315 Static Function UTF16() As Encoding
316 End Function
317 /*!
318 @brief UTF-16BE用のEncodingインスタンスの取得。
319 */
320 Static Function UTF16BE() As Encoding
321 End Function
322End Class
323
324/*!
325@brief 復号を行うクラス
326@date 2009/01/12
327@auther Egtra
328内部処理用
329*/
330Class Decoder
331Public
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)
350 End Sub
351
352Protected
353 Abstract Sub EncodeImpl(src As *WCHAR, size As SIZE_T, s As IO.Stream, last As Boolean)
354End Class
355
356Enum NormalizationForm
357 FormC
358 FormD
359 FormKC
360 FormKD
361End Enum
362
363Namespace Detail
364
365/*!
366@brief WideCharToMultiByte/MultiByteToWideCharで変換を行うエンコーディング。
367DBCS/SBCS限定。UTF-8やUTF-7は非対応。
368*/
369Class WindowsCodePageEncoding
370 Inherits Encoding
371Public
372 Sub WindowsCodePageEncoding(codepage As DWord)
373 cp = codepage
374 End Sub
375
376 Override Function GetHashCode() As Long
377 GetHashCode = cp As Long
378 End Function
379
380 Override Function Equals(x As Object) As Boolean
381 If GetType().Equals(x.GetType()) Then
382 Dim xe = x As WindowsCodePageEncoding
383 Equals = cp = xe.cp
384 Else
385 Equals = False
386 End If
387 End Function
388
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
397 /*!
398 @brief ある長さの文字列を符号化して得られるバイト列の最大の長さを返す。
399 */
400 Override Function GetMaxByteCount(srcCount As Long) As Long
401 GetMaxByteCount = srcCount * 2
402 End Function
403
404 /*!
405 @brief ある長さのバイト列を復号して得られる文字列の最大の長さを返す。
406 */
407 Override Function GetMaxCharCount(srcCount As Long) As Long
408 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
438 End Function
439
440Private
441 cp As DWord
442End Class
443
444/*!
445@brief WideCharToMultiByteで復号化を行うクラス
446@date 2009/01/12
447@auther Egtra
448内部処理用
449*/
450Class WindowsCodePageEncoder
451 Inherits Encoder
452Public
453 Sub WindowsCodePageEncoder(codepage As DWord)
454 cp = codepage
455 End Sub
456
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)
465 End Sub
466
467Private
468 cp As DWord
469End Class
470
471/*!
472@brief MultiByteToWideCharで復号化を行うクラス
473@date 2009/01/12
474@auther Egtra
475内部処理用
476*/
477Class WindowsCodePageDecoder
478 Inherits Decoder
479Public
480 Sub WindowsCodePageDecoder(codepage As DWord)
481 cp = codepage
482 End Sub
483
484Protected
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
489 Dim buf[1] As CHAR
490 Dim t = s.ReadByte()
491 If t = -1 Then
492 DecodeImpl = False
493 Exit Function
494 End If
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
502 End If
503 buf[1] = t As CHAR
504 len = 2
505 Else
506 len = 1
507 End If
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)
513 End If
514 Next
515 DecodeImpl = True
516 End Function
517
518Private
519 cp As DWord
520End Class
521
522Const DefalultDecodingBufferSize = 16384
523
524End Namespace
525
526End Namespace 'Text
527End Namespace 'System
Note: See TracBrowser for help on using the repository browser.