5 // Hye-Shik Chang (perky@FreeBSD.org)
6 // Atsushi Enomoto <atsushi@ximian.com>
16 internal class CP949 : KoreanEncoding
18 // Magic number used by Windows for the UHC code page.
19 private const int UHC_CODE_PAGE = 949;
22 public CP949 () : base (UHC_CODE_PAGE, true)
26 // Get the mail body name for this encoding.
27 public override String BodyName
29 get { return "ks_c_5601-1987"; }
32 // Get the human-readable name for this encoding.
33 public override String EncodingName
35 get { return "Korean (UHC)"; }
38 // Get the mail agent header name for this encoding.
39 public override String HeaderName
41 get { return "ks_c_5601-1987"; }
44 // Get the IANA-preferred Web name for this encoding.
45 public override String WebName
47 get { return "ks_c_5601-1987"; }
51 // Get the Windows code page represented by this object.
52 public override int WindowsCodePage
54 get { return UHC_PAGE; }
60 internal class CP51949 : KoreanEncoding
62 // Magic number used by Windows for the euc-kr code page.
63 private const int EUCKR_CODE_PAGE = 51949;
66 public CP51949 () : base (EUCKR_CODE_PAGE, false)
70 // Get the mail body name for this encoding.
71 public override String BodyName
73 get { return "euc-kr"; }
76 // Get the human-readable name for this encoding.
77 public override String EncodingName
79 get { return "Korean (EUC)"; }
82 // Get the mail agent header name for this encoding.
83 public override String HeaderName
85 get { return "euc-kr"; }
88 // Get the IANA-preferred Web name for this encoding.
89 public override String WebName
91 get { return "euc-kr"; }
95 // Get the Windows code page represented by this object.
96 public override int WindowsCodePage
98 get { return UHC_PAGE; }
105 internal class KoreanEncoding : DbcsEncoding
108 public KoreanEncoding (int codepage, bool useUHC)
109 : base (codepage, 949) {
110 this.useUHC = useUHC;
113 internal override DbcsConvert GetConvert ()
115 return DbcsConvert.KS;
121 // Get the bytes that result from encoding a character buffer.
122 public unsafe override int GetByteCountImpl (char* chars, int count)
127 DbcsConvert convert = GetConvert ();
130 for (int i = 0; i < end; i++, charCount--) {
132 if (c <= 0x80 || c == 0xFF) { // ASCII
136 byte b1 = convert.u2n[((int)c) * 2];
137 byte b2 = convert.u2n[((int)c) * 2 + 1];
138 if (b1 == 0 && b2 == 0) {
140 // FIXME: handle fallback for GetByteCountImpl().
152 // Get the bytes that result from encoding a character buffer.
153 public unsafe override int GetBytesImpl (char* chars, int charCount,
154 byte* bytes, int byteCount)
159 DbcsConvert convert = GetConvert ();
161 EncoderFallbackBuffer buffer = null;
165 int origIndex = byteIndex;
166 for (int = charIndex; i < end; i++, charCount--) {
168 if (c <= 0x80 || c == 0xFF) { // ASCII
169 bytes[byteIndex++] = (byte)c;
172 byte b1 = convert.u2n[((int)c) * 2];
173 byte b2 = convert.u2n[((int)c) * 2 + 1];
174 if (b1 == 0 && b2 == 0) {
176 HandleFallback (ref buffer, chars, ref i, ref charCount,
177 bytes, ref byteIndex, ref byteCount, null);
179 bytes[byteIndex++] = (byte)'?';
182 bytes[byteIndex++] = b1;
183 bytes[byteIndex++] = b2;
186 return byteIndex - origIndex;
189 // Get the bytes that result from encoding a character buffer.
190 public override int GetByteCount(char[] chars, int index, int count)
193 DbcsConvert convert = GetConvert();
198 char c = chars[index++];
199 if (c <= 0x80 || c == 0xFF)
204 byte b1 = convert.u2n[((int)c) * 2];
205 byte b2 = convert.u2n[((int)c) * 2 + 1];
206 if (b1 == 0 && b2 == 0)
209 // FIXME: handle fallback for GetByteCountImpl().
221 // Get the bytes that result from encoding a character buffer.
222 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
224 int byteCount = bytes.Length;
225 int end = charIndex + charCount;
227 DbcsConvert convert = GetConvert();
229 EncoderFallbackBuffer buffer = null;
233 int origIndex = byteIndex;
234 for (int i = charIndex; i < end; i++, charCount--)
237 if (c <= 0x80 || c == 0xFF)
239 bytes[byteIndex++] = (byte)c;
242 byte b1 = convert.u2n[((int)c) * 2];
243 byte b2 = convert.u2n[((int)c) * 2 + 1];
244 if (b1 == 0 && b2 == 0)
247 HandleFallback (ref buffer, chars, ref i, ref charCount,
248 bytes, ref byteIndex, ref byteCount, null);
250 bytes[byteIndex++] = (byte)'?';
255 bytes[byteIndex++] = b1;
256 bytes[byteIndex++] = b2;
259 return byteIndex - origIndex;
262 // Get the characters that result from decoding a byte buffer.
263 public override int GetCharCount (byte[] bytes, int index, int count)
265 return GetDecoder ().GetCharCount (bytes, index, count);
268 // Get the characters that result from decoding a byte buffer.
269 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
270 char[] chars, int charIndex)
272 return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
275 // Get a decoder that handles a rolling UHC state.
276 public override Decoder GetDecoder()
278 return new KoreanDecoder (GetConvert (), useUHC);
281 // Decoder that handles a rolling UHC state.
282 private sealed class KoreanDecoder : DbcsDecoder
285 public KoreanDecoder (DbcsConvert convert, bool useUHC)
288 this.useUHC = useUHC;
291 int last_byte_count, last_byte_conv;
293 public override int GetCharCount (byte[] bytes, int index, int count)
295 return GetCharCount (bytes, index, count, false);
301 int GetCharCount (byte [] bytes, int index, int count, bool refresh)
303 CheckRange (bytes, index, count);
305 int lastByte = last_byte_count;
308 while (count-- > 0) {
309 int b = bytes[index++];
311 if (b <= 0x80 || b == 0xFF) { // ASCII
321 if (useUHC && lastByte < 0xa1) { // UHC Level 1
322 int ord = 8836 + (lastByte - 0x81) * 178;
324 if (b >= 0x41 && b <= 0x5A)
326 else if (b >= 0x61 && b <= 0x7A)
327 ord += b - 0x61 + 26;
328 else if (b >= 0x81 && b <= 0xFE)
329 ord += b - 0x81 + 52;
333 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
334 c1 = (char)(convert.n2u[ord*2] +
335 convert.n2u[ord*2 + 1] * 256);
338 } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2
339 int ord = 14532 + (lastByte - 0xA1) * 84;
341 if (b >= 0x41 && b <= 0x5A)
343 else if (b >= 0x61 && b <= 0x7A)
344 ord += b - 0x61 + 26;
345 else if (b >= 0x81 && b <= 0xA0)
346 ord += b - 0x81 + 52;
350 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
351 c1 = (char)(convert.n2u[ord*2] +
352 convert.n2u[ord*2 + 1] * 256);
355 } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
356 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
358 c1 = ord < 0 || ord >= convert.n2u.Length ?
359 '\0' : (char)(convert.n2u[ord] +
360 convert.n2u[ord + 1] * 256);
379 last_byte_count = lastByte;
384 public override int GetChars(byte[] bytes, int byteIndex,
385 int byteCount, char[] chars, int charIndex)
387 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
393 int GetChars(byte[] bytes, int byteIndex,
394 int byteCount, char[] chars, int charIndex, bool refresh)
396 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
397 int origIndex = charIndex;
398 int lastByte = last_byte_conv;
400 while (byteCount-- > 0) {
401 int b = bytes[byteIndex++];
403 if (b <= 0x80 || b == 0xFF) { // ASCII
404 chars[charIndex++] = (char)b;
413 if (useUHC && lastByte < 0xa1) { // UHC Level 1
414 int ord = 8836 + (lastByte - 0x81) * 178;
416 if (b >= 0x41 && b <= 0x5A)
418 else if (b >= 0x61 && b <= 0x7A)
419 ord += b - 0x61 + 26;
420 else if (b >= 0x81 && b <= 0xFE)
421 ord += b - 0x81 + 52;
425 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
426 c1 = (char)(convert.n2u[ord*2] +
427 convert.n2u[ord*2 + 1] * 256);
430 } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2
431 int ord = 14532 + (lastByte - 0xA1) * 84;
433 if (b >= 0x41 && b <= 0x5A)
435 else if (b >= 0x61 && b <= 0x7A)
436 ord += b - 0x61 + 26;
437 else if (b >= 0x81 && b <= 0xA0)
438 ord += b - 0x81 + 52;
442 if (ord >= 0 && ord * 2 <= convert.n2u.Length)
443 c1 = (char)(convert.n2u[ord*2] +
444 convert.n2u[ord*2 + 1] * 256);
447 } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
448 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
450 c1 = ord < 0 || ord >= convert.n2u.Length ?
451 '\0' : (char)(convert.n2u[ord] +
452 convert.n2u[ord + 1] * 256);
457 chars[charIndex++] = '?';
459 chars[charIndex++] = c1;
465 chars[charIndex++] = '?';
469 last_byte_conv = lastByte;
471 return charIndex - origIndex;
477 internal class ENCuhc : CP949
483 internal class ENCeuc_kr: CP51949
485 public ENCeuc_kr() {}