2006-01-20 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / I18N / CJK / CP949.cs
1 //
2 // I18N.CJK.CP949
3 //
4 // Author:
5 //   Hye-Shik Chang (perky@FreeBSD.org)
6 //
7
8 using System;
9 using System.Text;
10 using I18N.Common;
11
12 namespace I18N.CJK
13 {
14     [Serializable]
15     internal class CP949 : KoreanEncoding
16     {
17         // Magic number used by Windows for the UHC code page.
18         private const int UHC_CODE_PAGE = 949;
19
20         // Constructor.
21         public CP949 () : base (UHC_CODE_PAGE, true)
22         {
23         }
24
25         // Get the mail body name for this encoding.
26         public override String BodyName
27         {
28             get { return "ks_c_5601-1987"; }
29         }
30
31         // Get the human-readable name for this encoding.
32         public override String EncodingName
33         {
34             get { return "Korean (UHC)"; }
35         }
36
37         // Get the mail agent header name for this encoding.
38         public override String HeaderName
39         {
40             get { return "ks_c_5601-1987"; }
41         }
42
43         // Get the IANA-preferred Web name for this encoding.
44         public override String WebName
45         {
46             get { return "ks_c_5601-1987"; }
47         }
48
49         /*
50         // Get the Windows code page represented by this object.
51         public override int WindowsCodePage
52         {
53             get { return UHC_PAGE; }
54         }
55         */
56     }
57
58     [Serializable]
59     internal class CP51949 : KoreanEncoding
60     {
61         // Magic number used by Windows for the euc-kr code page.
62         private const int EUCKR_CODE_PAGE = 51949;
63
64         // Constructor.
65         public CP51949 () : base (EUCKR_CODE_PAGE, false)
66         {
67         }
68
69         // Get the mail body name for this encoding.
70         public override String BodyName
71         {
72             get { return "euc-kr"; }
73         }
74
75         // Get the human-readable name for this encoding.
76         public override String EncodingName
77         {
78             get { return "Korean (EUC)"; }
79         }
80
81         // Get the mail agent header name for this encoding.
82         public override String HeaderName
83         {
84             get { return "euc-kr"; }
85         }
86
87         // Get the IANA-preferred Web name for this encoding.
88         public override String WebName
89         {
90             get { return "euc-kr"; }
91         }
92
93         /*
94         // Get the Windows code page represented by this object.
95         public override int WindowsCodePage
96         {
97             get { return UHC_PAGE; }
98         }
99         */
100
101     }
102
103     [Serializable]
104     internal class KoreanEncoding : DbcsEncoding
105     {
106         // Constructor.
107         public KoreanEncoding (int codepage, bool useUHC) : base (codepage) {
108             this.useUHC = useUHC;
109         }
110
111         internal override DbcsConvert GetConvert ()
112         {
113                 return KSConvert.Convert;
114         }
115
116         bool useUHC;
117
118         // Get the bytes that result from encoding a character buffer.
119         public unsafe override int GetBytesImpl (char* chars, int charCount,
120                          byte* bytes, int byteCount)
121         {
122             int charIndex = 0;
123             int byteIndex = 0;
124             DbcsConvert convert = GetConvert ();
125 #if NET_2_0
126             EncoderFallbackBuffer buffer = null;
127 #endif
128
129             // 00 00 - FF FF
130             int origIndex = byteIndex;
131             while (charCount-- > 0) {
132                 char c = chars[charIndex++];
133                 if (c <= 0x80 || c == 0xFF) { // ASCII
134                     bytes[byteIndex++] = (byte)c;
135                     continue;
136                 }
137                 byte b1 = convert.u2n[((int)c) * 2];
138                 byte b2 = convert.u2n[((int)c) * 2 + 1];
139                 if (b1 == 0 && b2 == 0) {
140 #if NET_2_0
141                     HandleFallback (ref buffer, chars, ref charIndex, ref charCount,
142                         bytes, ref byteIndex, ref byteCount);
143 #else
144                     bytes[byteIndex++] = (byte)'?';
145 #endif
146                 } else {
147                     bytes[byteIndex++] = b1;
148                     bytes[byteIndex++] = b2;
149                 }
150             }
151             return byteIndex - origIndex;
152         }
153
154         // Get the characters that result from decoding a byte buffer.
155         public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
156                          char[] chars, int charIndex)
157         {
158             DbcsConvert convert = GetConvert ();
159             base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
160             int origIndex = charIndex;
161             int lastByte = 0;
162
163             while (byteCount-- > 0) {
164                 int b = bytes[byteIndex++];
165                 if (lastByte == 0) {
166                     if (b <= 0x80 || b == 0xFF) { // ASCII
167                         chars[charIndex++] = (char)b;
168                         continue;
169                     } else {
170                         lastByte = b;
171                         continue;
172                     }
173                 }
174
175                 char c1;
176                 if (useUHC && lastByte < 0xa1) { // UHC Level 1
177                     int ord = 8836 + (lastByte - 0x81) * 178;
178
179                     if (b >= 0x41 && b <= 0x5A)
180                         ord += b - 0x41;
181                     else if (b >= 0x61 && b <= 0x7A)
182                         ord += b - 0x61 + 26;
183                     else if (b >= 0x81 && b <= 0xFE)
184                         ord += b - 0x81 + 52;
185                     else
186                         ord = -1;
187
188                       if (ord >= 0 && ord * 2 <= convert.n2u.Length)
189                         c1 = (char)(convert.n2u[ord*2] +
190                                     convert.n2u[ord*2 + 1] * 256);
191                     else
192                         c1 = (char)0;
193                 } else if (useUHC && lastByte <= 0xC6 && b < 0xa1) { // UHC Level 2
194                     int ord = 14532 + (lastByte - 0xA1) * 84;
195
196                     if (b >= 0x41 && b <= 0x5A)
197                         ord += b - 0x41;
198                     else if (b >= 0x61 && b <= 0x7A)
199                         ord += b - 0x61 + 26;
200                     else if (b >= 0x81 && b <= 0xA0)
201                         ord += b - 0x81 + 52;
202                     else
203                         ord = -1;
204
205                     if (ord >= 0 && ord * 2 < convert.n2u.Length)
206                         c1 = (char)(convert.n2u[ord*2] +
207                                     convert.n2u[ord*2 + 1] * 256);
208                     else
209                         c1 = (char)0;
210                 } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
211                     int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
212
213                     c1 = ord < 0 || ord >= convert.n2u.Length ?
214                         '\0' : (char)(convert.n2u[ord] +
215                                 convert.n2u[ord + 1] * 256);
216                 } else
217                     c1 = (char)0;
218
219                 if (c1 == 0)
220                     chars[charIndex++] = '?';
221                 else
222                     chars[charIndex++] = c1;
223                 lastByte = 0;
224             }
225             return charIndex - origIndex;
226         }
227
228         // Get a decoder that handles a rolling UHC state.
229         public override Decoder GetDecoder()
230         {
231             return new KoreanDecoder (GetConvert (), useUHC);
232         }
233
234         // Decoder that handles a rolling UHC state.
235         private sealed class KoreanDecoder : DbcsDecoder
236         {
237             // Constructor.
238             public KoreanDecoder (DbcsConvert convert, bool useUHC)
239                 : base(convert)
240             {
241                 this.useUHC = useUHC;
242             }
243             bool useUHC;
244
245             public override int GetChars(byte[] bytes, int byteIndex,
246                                 int byteCount, char[] chars, int charIndex)
247             {
248                 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
249                 int origIndex = charIndex;
250                 while (byteCount-- > 0) {
251                     int b = bytes[byteIndex++];
252                     if (lastByte == 0) {
253                         if (b <= 0x80 || b == 0xFF) { // ASCII
254                             chars[charIndex++] = (char)b;
255                             continue;
256                         } else {
257                             lastByte = b;
258                             continue;
259                         }
260                     }
261
262                     char c1;
263                     if (useUHC && lastByte < 0xa1) { // UHC Level 1
264                         int ord = 8836 + (lastByte - 0x81) * 178;
265
266                         if (b >= 0x41 && b <= 0x5A)
267                             ord += b - 0x41;
268                         else if (b >= 0x61 && b <= 0x7A)
269                             ord += b - 0x61 + 26;
270                         else if (b >= 0x81 && b <= 0xFE)
271                             ord += b - 0x81 + 52;
272                         else
273                             ord = -1;
274
275                         if (ord >= 0 && ord * 2 <= convert.n2u.Length)
276                             c1 = (char)(convert.n2u[ord*2] +
277                                         convert.n2u[ord*2 + 1] * 256);
278                         else
279                             c1 = (char)0;
280                     } else if (useUHC && lastByte <= 0xC6 && b < 0xA1) { // UHC Level 2
281                         int ord = 14532 + (lastByte - 0xA1) * 84;
282
283                         if (b >= 0x41 && b <= 0x5A)
284                             ord += b - 0x41;
285                         else if (b >= 0x61 && b <= 0x7A)
286                             ord += b - 0x61 + 26;
287                         else if (b >= 0x81 && b <= 0xA0)
288                             ord += b - 0x81 + 52;
289                         else
290                             ord = -1;
291
292                         if (ord >= 0 && ord * 2 <= convert.n2u.Length)
293                             c1 = (char)(convert.n2u[ord*2] +
294                                         convert.n2u[ord*2 + 1] * 256);
295                         else
296                             c1 = (char)0;
297                     } else if (b >= 0xA1 && b <= 0xFE) { // KS X 1001
298                         int ord = ((lastByte - 0xA1) * 94 + b - 0xA1) * 2;
299
300                         c1 = ord < 0 || ord >= convert.n2u.Length ?
301                             '\0' : (char)(convert.n2u[ord] +
302                                     convert.n2u[ord + 1] * 256);
303                     } else
304                         c1 = (char)0;
305
306                     if (c1 == 0)
307                         chars[charIndex++] = '?';
308                     else
309                         chars[charIndex++] = c1;
310                     lastByte = 0;
311                 }
312                 return charIndex - origIndex;
313             }
314         }
315     }
316
317     [Serializable]
318     internal class ENCuhc : CP949
319     {
320         public ENCuhc() {}
321     }
322
323     [Serializable]
324     internal class ENCeuc_kr: CP51949
325     {
326         public ENCeuc_kr() {}
327     }
328 }
329
330 // ex: ts=8 sts=4 et