// // I18N.CJK.CP949 // // Author: // Hye-Shik Chang (perky@FreeBSD.org) // Atsushi Enomoto // using System; using System.Text; using I18N.Common; namespace I18N.CJK { [Serializable] internal class CP949 : KoreanEncoding { // Magic number used by Windows for the UHC code page. private const int UHC_CODE_PAGE = 949; // Constructor. public CP949 () : base (UHC_CODE_PAGE, true) { } // Get the mail body name for this encoding. public override String BodyName { get { return "ks_c_5601-1987"; } } // Get the human-readable name for this encoding. public override String EncodingName { get { return "Korean (UHC)"; } } // Get the mail agent header name for this encoding. public override String HeaderName { get { return "ks_c_5601-1987"; } } // Get the IANA-preferred Web name for this encoding. public override String WebName { get { return "ks_c_5601-1987"; } } /* // Get the Windows code page represented by this object. public override int WindowsCodePage { get { return UHC_PAGE; } } */ } [Serializable] internal class CP51949 : KoreanEncoding { // Magic number used by Windows for the euc-kr code page. private const int EUCKR_CODE_PAGE = 51949; // Constructor. public CP51949 () : base (EUCKR_CODE_PAGE, false) { } // Get the mail body name for this encoding. public override String BodyName { get { return "euc-kr"; } } // Get the human-readable name for this encoding. public override String EncodingName { get { return "Korean (EUC)"; } } // Get the mail agent header name for this encoding. public override String HeaderName { get { return "euc-kr"; } } // Get the IANA-preferred Web name for this encoding. public override String WebName { get { return "euc-kr"; } } /* // Get the Windows code page represented by this object. public override int WindowsCodePage { get { return UHC_PAGE; } } */ } [Serializable] internal class KoreanEncoding : DbcsEncoding { // Constructor. public KoreanEncoding (int codepage, bool useUHC) : base (codepage, 949) { this.useUHC = useUHC; } internal override DbcsConvert GetConvert () { return DbcsConvert.KS; } bool useUHC; // Get the bytes that result from encoding a character buffer. public unsafe override int GetByteCountImpl (char* chars, int count) { int index = 0; int length = 0; DbcsConvert convert = GetConvert (); // 00 00 - FF FF while (count-- > 0) { char c = chars[index++]; if (c <= 0x80 || c == 0xFF) { // ASCII length++; continue; } byte b1 = convert.u2n[((int)c) * 2]; byte b2 = convert.u2n[((int)c) * 2 + 1]; if (b1 == 0 && b2 == 0) { #if NET_2_0 // FIXME: handle fallback for GetByteCountImpl(). length++; #else length++; #endif } else length += 2; } return length; } // Get the bytes that result from encoding a character buffer. public unsafe override int GetBytesImpl (char* chars, int charCount, byte* bytes, int byteCount) { int charIndex = 0; int byteIndex = 0; DbcsConvert convert = GetConvert (); #if NET_2_0 EncoderFallbackBuffer buffer = null; #endif // 00 00 - FF FF int origIndex = byteIndex; while (charCount-- > 0) { char c = chars[charIndex++]; if (c <= 0x80 || c == 0xFF) { // ASCII bytes[byteIndex++] = (byte)c; continue; } byte b1 = convert.u2n[((int)c) * 2]; byte b2 = convert.u2n[((int)c) * 2 + 1]; if (b1 == 0 && b2 == 0) { #if NET_2_0 HandleFallback (ref buffer, chars, ref charIndex, ref charCount, bytes, ref byteIndex, ref byteCount); #else bytes[byteIndex++] = (byte)'?'; #endif } else { bytes[byteIndex++] = b1; bytes[byteIndex++] = b2; } } return byteIndex - origIndex; } // Get the characters that result from decoding a byte buffer. public override int GetCharCount (byte[] bytes, int index, int count) { return GetDecoder ().GetCharCount (bytes, index, count); } // Get the characters that result from decoding a byte buffer. public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex); } // Get a decoder that handles a rolling UHC state. public override Decoder GetDecoder() { return new KoreanDecoder (GetConvert (), useUHC); } // Decoder that handles a rolling UHC state. private sealed class KoreanDecoder : DbcsDecoder { // Constructor. public KoreanDecoder (DbcsConvert convert, bool useUHC) : base(convert) { this.useUHC = useUHC; } bool useUHC; int last_byte_count, last_byte_conv; public override int GetCharCount (byte[] bytes, int index, int count) { return GetCharCount (bytes, index, count, false); } #if NET_2_0 public override #endif int GetCharCount (byte [] bytes, int index, int count, bool refresh) { CheckRange (bytes, index, count); int lastByte = last_byte_count; last_byte_count = 0; int length = 0; while (count-- > 0) { int b = bytes[index++]; if (lastByte == 0) { if (b <= 0x80 || b == 0xFF) { // ASCII length++; continue; } else { lastByte = b; continue; } } char c1; if (useUHC && lastByte < 0xa1) { // UHC Level 1 int ord = 8836 + (lastByte - 0x81) * 178; if (b >= 0x41 && b <= 0x5A) ord += b - 0x41; else if (b >= 0x61 && b <= 0x7A) ord += b - 0x61 + 26; else if (b >= 0x81 && b <= 0xFE) ord += b - 0x81 + 52; else ord = -1; if (ord >= 0 && ord * 2 <= convert.n2u.Length) c1 = (char)(convert.n2u[ord*2] + convert.n2u[ord*2 + 1] * 256); else c1 = (char)0; } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2 int ord = 14532 + (lastByte - 0xA1) * 84; if (b >= 0x41 && b <= 0x5A) ord += b - 0x41; else if (b >= 0x61 && b <= 0x7A) ord += b - 0x61 + 26; else if (b >= 0x81 && b <= 0xA0) ord += b - 0x81 + 52; else ord = -1; if (ord >= 0 && ord * 2 <= convert.n2u.Length) c1 = (char)(convert.n2u[ord*2] + convert.n2u[ord*2 + 1] * 256); else c1 = (char)0; } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2; c1 = ord < 0 || ord >= convert.n2u.Length ? '\0' : (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256); } else c1 = (char)0; if (c1 == 0) // FIXME: fallback length++; else length++; lastByte = 0; } if (lastByte != 0) { if (refresh) { // FIXME: fallback length++; last_byte_count = 0; } else last_byte_count = lastByte; } return length; } public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false); } #if NET_2_0 public override #endif int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool refresh) { CheckRange (bytes, byteIndex, byteCount, chars, charIndex); int origIndex = charIndex; int lastByte = last_byte_conv; last_byte_conv = 0; while (byteCount-- > 0) { int b = bytes[byteIndex++]; if (lastByte == 0) { if (b <= 0x80 || b == 0xFF) { // ASCII chars[charIndex++] = (char)b; continue; } else { lastByte = b; continue; } } char c1; if (useUHC && lastByte < 0xa1) { // UHC Level 1 int ord = 8836 + (lastByte - 0x81) * 178; if (b >= 0x41 && b <= 0x5A) ord += b - 0x41; else if (b >= 0x61 && b <= 0x7A) ord += b - 0x61 + 26; else if (b >= 0x81 && b <= 0xFE) ord += b - 0x81 + 52; else ord = -1; if (ord >= 0 && ord * 2 <= convert.n2u.Length) c1 = (char)(convert.n2u[ord*2] + convert.n2u[ord*2 + 1] * 256); else c1 = (char)0; } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2 int ord = 14532 + (lastByte - 0xA1) * 84; if (b >= 0x41 && b <= 0x5A) ord += b - 0x41; else if (b >= 0x61 && b <= 0x7A) ord += b - 0x61 + 26; else if (b >= 0x81 && b <= 0xA0) ord += b - 0x81 + 52; else ord = -1; if (ord >= 0 && ord * 2 <= convert.n2u.Length) c1 = (char)(convert.n2u[ord*2] + convert.n2u[ord*2 + 1] * 256); else c1 = (char)0; } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001 int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2; c1 = ord < 0 || ord >= convert.n2u.Length ? '\0' : (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256); } else c1 = (char)0; if (c1 == 0) chars[charIndex++] = '?'; else chars[charIndex++] = c1; lastByte = 0; } if (lastByte != 0) { if (refresh) { chars[charIndex++] = '?'; last_byte_conv = 0; } else last_byte_conv = lastByte; } return charIndex - origIndex; } } } [Serializable] internal class ENCuhc : CP949 { public ENCuhc() {} } [Serializable] internal class ENCeuc_kr: CP51949 { public ENCeuc_kr() {} } } // ex: ts=8 sts=4 et