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