Switch to compiler-tester
[mono.git] / mcs / class / I18N / CJK / CP932.cs
1 /*
2  * CP932.cs - Japanese (Shift-JIS) code page.
3  *
4  * Copyright (c) 2002  Southern Storm Software, Pty Ltd
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 namespace I18N.CJK
26 {
27
28 using System;
29 using System.Text;
30 using I18N.Common;
31
32 public unsafe class CP932 : Encoding
33 {
34         // Magic number used by Windows for the Shift-JIS code page.
35         private const int SHIFTJIS_CODE_PAGE = 932;
36
37         // Internal state.
38         private JISConvert convert;
39
40         // Constructor.
41         public CP932() : base(SHIFTJIS_CODE_PAGE)
42                         {
43                                 // Load the JIS conversion tables.
44                                 convert = JISConvert.Convert;
45                         }
46
47         // Get the number of bytes needed to encode a character buffer.
48         public override int GetByteCount(char[] chars, int index, int count)
49                         {
50                                 // Validate the parameters.
51                                 if(chars == null)
52                                 {
53                                         throw new ArgumentNullException("chars");
54                                 }
55                                 if(index < 0 || index > chars.Length)
56                                 {
57                                         throw new ArgumentOutOfRangeException
58                                                 ("index", Strings.GetString("ArgRange_Array"));
59                                 }
60                                 if(count < 0 || count > (chars.Length - index))
61                                 {
62                                         throw new ArgumentOutOfRangeException
63                                                 ("count", Strings.GetString("ArgRange_Array"));
64                                 }
65
66                                 // Determine the length of the final output.
67                                 int length = 0;
68                                 int ch, value;
69 #if __PNET__
70                                 byte *cjkToJis = convert.cjkToJis;
71                                 byte *extraToJis = convert.extraToJis;
72 #else
73                                 byte[] cjkToJis = convert.cjkToJis;
74                                 byte[] extraToJis = convert.extraToJis;
75 #endif
76                                 while(count > 0)
77                                 {
78                                         ch = chars[index++];
79                                         --count;
80                                         ++length;
81                                         if(ch < 0x0080)
82                                         {
83                                                 // Character maps to itself.
84                                                 continue;
85                                         }
86                                         else if(ch < 0x0100)
87                                         {
88                                                 // Check for special Latin 1 characters that
89                                                 // can be mapped to double-byte code points.
90                                                 if(ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
91                                                    ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
92                                                    ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
93                                                    ch == 0x00D7 || ch == 0x00F7)
94                                                 {
95                                                         ++length;
96                                                 }
97                                         }
98                                         else if(ch >= 0x0391 && ch <= 0x0451)
99                                         {
100                                                 // Greek subset characters.
101                                                 ++length;
102                                         }
103                                         else if(ch >= 0x2010 && ch <= 0x9FA5)
104                                         {
105                                                 // This range contains the bulk of the CJK set.
106                                                 value = (ch - 0x2010) * 2;
107                                                 value = ((int)(cjkToJis[value])) |
108                                                                 (((int)(cjkToJis[value + 1])) << 8);
109                                                 if(value >= 0x0100)
110                                                 {
111                                                         ++length;
112                                                 }
113                                         }
114                                         else if(ch >= 0xFF01 && ch <= 0xFFEF)
115                                         {
116                                                 // This range contains extra characters,
117                                                 // including half-width katakana.
118                                                 value = (ch - 0xFF01) * 2;
119                                                 value = ((int)(extraToJis[value])) |
120                                                                 (((int)(extraToJis[value + 1])) << 8);
121                                                 if(value >= 0x0100)
122                                                 {
123                                                         ++length;
124                                                 }
125                                         }
126                                 }
127
128                                 // Return the length to the caller.
129                                 return length;
130                         }
131
132         // Get the bytes that result from encoding a character buffer.
133         public override int GetBytes(char[] chars, int charIndex, int charCount,
134                                                                  byte[] bytes, int byteIndex)
135                         {
136                                 // Validate the parameters.
137                                 if(chars == null)
138                                 {
139                                         throw new ArgumentNullException("chars");
140                                 }
141                                 if(bytes == null)
142                                 {
143                                         throw new ArgumentNullException("bytes");
144                                 }
145                                 if(charIndex < 0 || charIndex > chars.Length)
146                                 {
147                                         throw new ArgumentOutOfRangeException
148                                                 ("charIndex", Strings.GetString("ArgRange_Array"));
149                                 }
150                                 if(charCount < 0 || charCount > (chars.Length - charIndex))
151                                 {
152                                         throw new ArgumentOutOfRangeException
153                                                 ("charCount", Strings.GetString("ArgRange_Array"));
154                                 }
155                                 if(byteIndex < 0 || byteIndex > bytes.Length)
156                                 {
157                                         throw new ArgumentOutOfRangeException
158                                                 ("byteIndex", Strings.GetString("ArgRange_Array"));
159                                 }
160
161                                 // Convert the characters into their byte form.
162                                 int posn = byteIndex;
163                                 int byteLength = bytes.Length;
164                                 int ch, value;
165 #if __PNET__
166                                 byte *cjkToJis = convert.cjkToJis;
167                                 byte *greekToJis = convert.greekToJis;
168                                 byte *extraToJis = convert.extraToJis;
169 #else
170                                 byte[] cjkToJis = convert.cjkToJis;
171                                 byte[] greekToJis = convert.greekToJis;
172                                 byte[] extraToJis = convert.extraToJis;
173 #endif
174                                 while(charCount > 0)
175                                 {
176                                         ch = chars[charIndex++];
177                                         --charCount;
178                                         if(posn >= byteLength)
179                                         {
180                                                 throw new ArgumentException
181                                                         (Strings.GetString("Arg_InsufficientSpace"),
182                                                          "bytes");
183                                         }
184                                         if(ch < 0x0080)
185                                         {
186                                                 // Character maps to itself.
187                                                 bytes[posn++] = (byte)ch;
188                                                 continue;
189                                         }
190                                         else if(ch < 0x0100)
191                                         {
192                                                 // Check for special Latin 1 characters that
193                                                 // can be mapped to double-byte code points.
194                                                 if(ch == 0x00A2 || ch == 0x00A3 || ch == 0x00A7 ||
195                                                    ch == 0x00A8 || ch == 0x00AC || ch == 0x00B0 ||
196                                                    ch == 0x00B1 || ch == 0x00B4 || ch == 0x00B6 ||
197                                                    ch == 0x00D7 || ch == 0x00F7)
198                                                 {
199                                                         if((posn + 1) >= byteLength)
200                                                         {
201                                                                 throw new ArgumentException
202                                                                         (Strings.GetString
203                                                                                 ("Arg_InsufficientSpace"), "bytes");
204                                                         }
205                                                         switch(ch)
206                                                         {
207                                                                 case 0x00A2:
208                                                                         bytes[posn++] = (byte)0x81;
209                                                                         bytes[posn++] = (byte)0x91;
210                                                                         break;
211
212                                                                 case 0x00A3:
213                                                                         bytes[posn++] = (byte)0x81;
214                                                                         bytes[posn++] = (byte)0x92;
215                                                                         break;
216
217                                                                 case 0x00A7:
218                                                                         bytes[posn++] = (byte)0x81;
219                                                                         bytes[posn++] = (byte)0x98;
220                                                                         break;
221
222                                                                 case 0x00A8:
223                                                                         bytes[posn++] = (byte)0x81;
224                                                                         bytes[posn++] = (byte)0x4E;
225                                                                         break;
226
227                                                                 case 0x00AC:
228                                                                         bytes[posn++] = (byte)0x81;
229                                                                         bytes[posn++] = (byte)0xCA;
230                                                                         break;
231
232                                                                 case 0x00B0:
233                                                                         bytes[posn++] = (byte)0x81;
234                                                                         bytes[posn++] = (byte)0x8B;
235                                                                         break;
236
237                                                                 case 0x00B1:
238                                                                         bytes[posn++] = (byte)0x81;
239                                                                         bytes[posn++] = (byte)0x7D;
240                                                                         break;
241
242                                                                 case 0x00B4:
243                                                                         bytes[posn++] = (byte)0x81;
244                                                                         bytes[posn++] = (byte)0x4C;
245                                                                         break;
246
247                                                                 case 0x00B6:
248                                                                         bytes[posn++] = (byte)0x81;
249                                                                         bytes[posn++] = (byte)0xF7;
250                                                                         break;
251
252                                                                 case 0x00D7:
253                                                                         bytes[posn++] = (byte)0x81;
254                                                                         bytes[posn++] = (byte)0x7E;
255                                                                         break;
256
257                                                                 case 0x00F7:
258                                                                         bytes[posn++] = (byte)0x81;
259                                                                         bytes[posn++] = (byte)0x80;
260                                                                         break;
261                                                         }
262                                                 }
263                                                 else if(ch == 0x00A5)
264                                                 {
265                                                         // Yen sign.
266                                                         bytes[posn++] = (byte)0x5C;
267                                                 }
268                                                 else
269                                                 {
270                                                         // Invalid character.
271                                                         bytes[posn++] = (byte)'?';
272                                                 }
273                                                 continue;
274                                         }
275                                         else if(ch >= 0x0391 && ch <= 0x0451)
276                                         {
277                                                 // Greek subset characters.
278                                                 value = (ch - 0x0391) * 2;
279                                                 value = ((int)(greekToJis[value])) |
280                                                                 (((int)(greekToJis[value + 1])) << 8);
281                                         }
282                                         else if(ch >= 0x2010 && ch <= 0x9FA5)
283                                         {
284                                                 // This range contains the bulk of the CJK set.
285                                                 value = (ch - 0x2010) * 2;
286                                                 value = ((int)(cjkToJis[value])) |
287                                                                 (((int)(cjkToJis[value + 1])) << 8);
288                                         }
289                                         else if(ch >= 0xE000 && ch <= 0xE757)
290                                         {
291                                                 // PrivateUse
292                                                 int diff = ch - 0xE000;
293                                                 value = ((int) (diff / 0xBC) << 8)
294                                                         + (diff % 0xBC)
295                                                         + 0xF040;
296                                                 if (value % 0x100 >= 0x7F)
297                                                         value++;
298                                         }
299                                         else if(ch >= 0xFF01 && ch <= 0xFF60)
300                                         {
301                                                 value = ch - 0xFF00 + 0x20;
302                                         }
303                                         else if(ch >= 0xFF60 && ch <= 0xFFA0)
304                                         {
305                                                 value = ch - 0xFF60 + 0xA0;
306                                         }
307                                         else
308                                         {
309                                                 // Invalid character.
310                                                 value = 0;
311                                         }
312                                         if(value == 0)
313                                         {
314                                                 bytes[posn++] = (byte)'?';
315                                         }
316                                         else if(value < 0x0100)
317                                         {
318                                                 bytes[posn++] = (byte)value;
319                                         }
320                                         else if((posn + 1) >= byteLength)
321                                         {
322                                                 throw new ArgumentException
323                                                         (Strings.GetString("Arg_InsufficientSpace"),
324                                                          "bytes");
325                                         }
326                                         else if(value < 0x8000)
327                                         {
328                                                 // JIS X 0208 character.
329                                                 value -= 0x0100;
330                                                 ch = (value / 0xBC);
331                                                 value = (value % 0xBC) + 0x40;
332                                                 if(value >= 0x7F)
333                                                 {
334                                                         ++value;
335                                                 }
336                                                 if(ch < (0x9F - 0x80))
337                                                 {
338                                                         bytes[posn++] = (byte)(ch + 0x81);
339                                                 }
340                                                 else
341                                                 {
342                                                         bytes[posn++] = (byte)(ch - (0x9F - 0x80) + 0xE0);
343                                                 }
344                                                 bytes[posn++] = (byte)value;
345                                         }
346                                         else if (value >= 0xF040 && value <= 0xF9FC)
347                                         {
348                                                 // PrivateUse
349                                                 bytes[posn++] = (byte) (value / 0x100);
350                                                 bytes[posn++] = (byte) (value % 0x100);
351                                         }
352                                         else
353                                         {
354                                                 // JIS X 0212 character, which Shift-JIS doesn't
355                                                 // support, but we've already allocated two slots.
356                                                 bytes[posn++] = (byte)'?';
357                                                 bytes[posn++] = (byte)'?';
358                                         }
359                                 }
360
361                                 // Return the final length to the caller.
362                                 return posn - byteIndex;
363                         }
364
365         // Get the number of characters needed to decode a byte buffer.
366         public override int GetCharCount(byte[] bytes, int index, int count)
367                         {
368                                 // Validate the parameters.
369                                 if(bytes == null)
370                                 {
371                                         throw new ArgumentNullException("bytes");
372                                 }
373                                 if(index < 0 || index > bytes.Length)
374                                 {
375                                         throw new ArgumentOutOfRangeException
376                                                 ("index", Strings.GetString("ArgRange_Array"));
377                                 }
378                                 if(count < 0 || count > (bytes.Length - index))
379                                 {
380                                         throw new ArgumentOutOfRangeException
381                                                 ("count", Strings.GetString("ArgRange_Array"));
382                                 }
383
384                                 // Determine the total length of the converted string.
385                                 int length = 0;
386                                 int byteval;
387                                 while(count > 0)
388                                 {
389                                         byteval = bytes[index++];
390                                         --count;
391                                         ++length;
392                                         if(byteval < 0x80)
393                                         {
394                                                 // Ordinary ASCII/Latin1 character, or the
395                                                 // single-byte Yen or overline signs.
396                                                 continue;
397                                         }
398                                         else if(byteval >= 0xA1 && byteval <= 0xDF)
399                                         {
400                                                 // Half-width katakana.
401                                                 continue;
402                                         }
403                                         else if(byteval < 0x81 ||
404                                                 (byteval > 0x9F && byteval < 0xE0) ||
405                                                         byteval > 0xEF)
406                                         {
407                                                 // Invalid first byte.
408                                                 continue;
409                                         }
410                                         if(count == 0)
411                                         {
412                                                 // Missing second byte.
413                                                 continue;
414                                         }
415                                         ++index;
416                                         --count;
417                                 }
418
419                                 // Return the total length.
420                                 return length;
421                         }
422
423         // Get the characters that result from decoding a byte buffer.
424         public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
425                                                                  char[] chars, int charIndex)
426                         {
427                                 // Validate the parameters.
428                                 if(bytes == null)
429                                 {
430                                         throw new ArgumentNullException("bytes");
431                                 }
432                                 if(chars == null)
433                                 {
434                                         throw new ArgumentNullException("chars");
435                                 }
436                                 if(byteIndex < 0 || byteIndex > bytes.Length)
437                                 {
438                                         throw new ArgumentOutOfRangeException
439                                                 ("byteIndex", Strings.GetString("ArgRange_Array"));
440                                 }
441                                 if(byteCount < 0 || byteCount > (bytes.Length - byteIndex))
442                                 {
443                                         throw new ArgumentOutOfRangeException
444                                                 ("byteCount", Strings.GetString("ArgRange_Array"));
445                                 }
446                                 if(charIndex < 0 || charIndex > chars.Length)
447                                 {
448                                         throw new ArgumentOutOfRangeException
449                                                 ("charIndex", Strings.GetString("ArgRange_Array"));
450                                 }
451
452                                 // Determine the total length of the converted string.
453                                 int charLength = chars.Length;
454                                 int posn = charIndex;
455                                 int length = 0;
456                                 int byteval, value;
457 #if __PNET__
458                                 byte *table = convert.jisx0208ToUnicode;
459 #else
460                                 byte[] table = convert.jisx0208ToUnicode;
461 #endif
462                                 while(byteCount > 0)
463                                 {
464                                         byteval = bytes[byteIndex++];
465                                         --byteCount;
466                                         ++length;
467                                         if(posn >= charLength)
468                                         {
469                                                 throw new ArgumentException
470                                                         (Strings.GetString("Arg_InsufficientSpace"),
471                                                          "chars");
472                                         }
473                                         if(byteval == 0x5C)
474                                         {
475                                                 // Yen sign.
476                                                 chars[posn++] = '\u00A5';
477                                                 continue;
478                                         }
479                                         else if(byteval == 0x7E)
480                                         {
481                                                 // Overline symbol.
482                                                 chars[posn++] = '\u203E';
483                                                 continue;
484                                         }
485                                         else if(byteval < 0x80)
486                                         {
487                                                 // Ordinary ASCII/Latin1 character.
488                                                 chars[posn++] = (char)byteval;
489                                                 continue;
490                                         }
491                                         else if(byteval >= 0xA1 && byteval <= 0xDF)
492                                         {
493                                                 // Half-width katakana.
494                                                 chars[posn++] = (char)(byteval - 0xA1 + 0xFF61);
495                                                 continue;
496                                         }
497                                         else if(byteval >= 0x81 && byteval <= 0x9F)
498                                         {
499                                                 value = (byteval - 0x81) * 0xBC;
500                                         }
501                                         else if(byteval >= 0xE0 && byteval <= 0xEF)
502                                         {
503                                                 value = (byteval - 0xE0 + (0xA0 - 0x81)) * 0xBC;
504                                         }
505                                         else
506                                         {
507                                                 // Invalid first byte.
508                                                 chars[posn++] = '?';
509                                                 continue;
510                                         }
511                                         if(byteCount == 0)
512                                         {
513                                                 // Missing second byte.
514                                                 chars[posn++] = '?';
515                                                 continue;
516                                         }
517                                         byteval = bytes[byteIndex++];
518                                         --byteCount;
519                                         if(byteval >= 0x40 && byteval <= 0x7E)
520                                         {
521                                                 value += (byteval - 0x40);
522                                         }
523                                         else if(byteval >= 0x80 && byteval <= 0xFC)
524                                         {
525                                                 value += (byteval - 0x80 + 0x3F);
526                                         }
527                                         else
528                                         {
529                                                 // Invalid second byte.
530                                                 chars[posn++] = '?';
531                                                 continue;
532                                         }
533                                         value *= 2;
534                                         value = ((int)(table[value])) |
535                                                         (((int)(table[value + 1])) << 8);
536                                         if(value != 0)
537                                         {
538                                                 chars[posn++] = (char)value;
539                                         }
540                                         else
541                                         {
542                                                 chars[posn++] = '?';
543                                         }
544                                 }
545
546                                 // Return the total length.
547                                 return posn - charIndex;
548                         }
549
550         // Get the maximum number of bytes needed to encode a
551         // specified number of characters.
552         public override int GetMaxByteCount(int charCount)
553                         {
554                                 if(charCount < 0)
555                                 {
556                                         throw new ArgumentOutOfRangeException
557                                                 ("charCount",
558                                                  Strings.GetString("ArgRange_NonNegative"));
559                                 }
560                                 return charCount * 2;
561                         }
562
563         // Get the maximum number of characters needed to decode a
564         // specified number of bytes.
565         public override int GetMaxCharCount(int byteCount)
566                         {
567                                 if(byteCount < 0)
568                                 {
569                                         throw new ArgumentOutOfRangeException
570                                                 ("byteCount",
571                                                  Strings.GetString("ArgRange_NonNegative"));
572                                 }
573                                 return byteCount;
574                         }
575
576         // Get a decoder that handles a rolling Shift-JIS state.
577         public override Decoder GetDecoder()
578                         {
579                                 return new CP932Decoder(convert);
580                         }
581
582 #if !ECMA_COMPAT
583
584         // Get the mail body name for this encoding.
585         public override String BodyName
586                         {
587                                 get
588                                 {
589                                         return "iso-2022-jp";
590                                 }
591                         }
592
593         // Get the human-readable name for this encoding.
594         public override String EncodingName
595                         {
596                                 get
597                                 {
598                                         return "Japanese (Shift-JIS)";
599                                 }
600                         }
601
602         // Get the mail agent header name for this encoding.
603         public override String HeaderName
604                         {
605                                 get
606                                 {
607                                         return "iso-2022-jp";
608                                 }
609                         }
610
611         // Determine if this encoding can be displayed in a Web browser.
612         public override bool IsBrowserDisplay
613                         {
614                                 get
615                                 {
616                                         return true;
617                                 }
618                         }
619
620         // Determine if this encoding can be saved from a Web browser.
621         public override bool IsBrowserSave
622                         {
623                                 get
624                                 {
625                                         return true;
626                                 }
627                         }
628
629         // Determine if this encoding can be displayed in a mail/news agent.
630         public override bool IsMailNewsDisplay
631                         {
632                                 get
633                                 {
634                                         return true;
635                                 }
636                         }
637
638         // Determine if this encoding can be saved from a mail/news agent.
639         public override bool IsMailNewsSave
640                         {
641                                 get
642                                 {
643                                         return true;
644                                 }
645                         }
646
647         // Get the IANA-preferred Web name for this encoding.
648         public override String WebName
649                         {
650                                 get
651                                 {
652                                         return "shift_jis";
653                                 }
654                         }
655
656         // Get the Windows code page represented by this object.
657         public override int WindowsCodePage
658                         {
659                                 get
660                                 {
661                                         return SHIFTJIS_CODE_PAGE;
662                                 }
663                         }
664
665 #endif // !ECMA_COMPAT
666
667         // Decoder that handles a rolling Shift-JIS state.
668         private sealed class CP932Decoder : Decoder
669         {
670                 private JISConvert convert;
671                 private int lastByte;
672
673                 // Constructor.
674                 public CP932Decoder(JISConvert convert)
675                                 {
676                                         this.convert = convert;
677                                         this.lastByte = 0;
678                                 }
679
680                 // Override inherited methods.
681                 public override int GetCharCount(byte[] bytes, int index, int count)
682                                 {
683                                         // Validate the parameters.
684                                         if(bytes == null)
685                                         {
686                                                 throw new ArgumentNullException("bytes");
687                                         }
688                                         if(index < 0 || index > bytes.Length)
689                                         {
690                                                 throw new ArgumentOutOfRangeException
691                                                         ("index", Strings.GetString("ArgRange_Array"));
692                                         }
693                                         if(count < 0 || count > (bytes.Length - index))
694                                         {
695                                                 throw new ArgumentOutOfRangeException
696                                                         ("count", Strings.GetString("ArgRange_Array"));
697                                         }
698
699                                         // Determine the total length of the converted string.
700                                         int length = 0;
701                                         int byteval;
702                                         int last = lastByte;
703                                         while(count > 0)
704                                         {
705                                                 byteval = bytes[index++];
706                                                 --count;
707                                                 if(last == 0)
708                                                 {
709                                                         if((byteval >= 0x81 && byteval <= 0x9F) ||
710                                                            (byteval >= 0xE0 && byteval <= 0xEF))
711                                                         {
712                                                                 // First byte in a double-byte sequence.
713                                                                 last = byteval;
714                                                         }
715                                                         ++length;
716                                                 }
717                                                 else
718                                                 {
719                                                         // Second byte in a double-byte sequence.
720                                                         last = 0;
721                                                 }
722                                         }
723         
724                                         // Return the total length.
725                                         return length;
726                                 }
727                 public override int GetChars(byte[] bytes, int byteIndex,
728                                                                          int byteCount, char[] chars,
729                                                                          int charIndex)
730                                 {
731                                         // Validate the parameters.
732                                         if(bytes == null)
733                                         {
734                                                 throw new ArgumentNullException("bytes");
735                                         }
736                                         if(chars == null)
737                                         {
738                                                 throw new ArgumentNullException("chars");
739                                         }
740                                         if(byteIndex < 0 || byteIndex > bytes.Length)
741                                         {
742                                                 throw new ArgumentOutOfRangeException
743                                                         ("byteIndex", Strings.GetString("ArgRange_Array"));
744                                         }
745                                         if(byteCount < 0 || byteCount > (bytes.Length - byteIndex))
746                                         {
747                                                 throw new ArgumentOutOfRangeException
748                                                         ("byteCount", Strings.GetString("ArgRange_Array"));
749                                         }
750                                         if(charIndex < 0 || charIndex > chars.Length)
751                                         {
752                                                 throw new ArgumentOutOfRangeException
753                                                         ("charIndex", Strings.GetString("ArgRange_Array"));
754                                         }
755
756                                         // Decode the bytes in the buffer.
757                                         int posn = charIndex;
758                                         int charLength = chars.Length;
759                                         int byteval, value;
760                                         int last = lastByte;
761 #if __PNET__
762                                         byte *table = convert.jisx0208ToUnicode;
763 #else
764                                         byte[] table = convert.jisx0208ToUnicode;
765 #endif
766                                         while(byteCount > 0)
767                                         {
768                                                 byteval = bytes[byteIndex++];
769                                                 --byteCount;
770                                                 if(last == 0)
771                                                 {
772                                                         if(posn >= charLength)
773                                                         {
774                                                                 throw new ArgumentException
775                                                                         (Strings.GetString
776                                                                                 ("Arg_InsufficientSpace"), "chars");
777                                                         }
778                                                         if((byteval >= 0x81 && byteval <= 0x9F) ||
779                                                            (byteval >= 0xE0 && byteval <= 0xEF))
780                                                         {
781                                                                 // First byte in a double-byte sequence.
782                                                                 last = byteval;
783                                                         }
784                                                         else if(byteval == 0x5C)
785                                                         {
786                                                                 // Yen sign.
787                                                                 chars[posn++] ='\u00A5';
788                                                         }
789                                                         else if(byteval == 0x7E)
790                                                         {
791                                                                 // Overline symbol.
792                                                                 chars[posn++] ='\u203E';
793                                                         }
794                                                         else if(byteval < 0x80)
795                                                         {
796                                                                 // Ordinary ASCII/Latin1 character.
797                                                                 chars[posn++] = (char)byteval;
798                                                         }
799                                                         else if(byteval >= 0xA1 && byteval <= 0xDF)
800                                                         {
801                                                                 // Half-width katakana character.
802                                                                 chars[posn++] = (char)(byteval - 0xA1 + 0xFF61);
803                                                         }
804                                                         else
805                                                         {
806                                                                 // Invalid first byte.
807                                                                 chars[posn++] = '?';
808                                                         }
809                                                 }
810                                                 else
811                                                 {
812                                                         // Second byte in a double-byte sequence.
813                                                         if(last >= 0x81 && last <= 0x9F)
814                                                         {
815                                                                 value = (last - 0x81) * 0xBC;
816                                                         }
817                                                         else if (last >= 0xF0 && last <= 0xFC && byteval <= 0xFC)
818                                                         {
819                                                                 // PrivateUse
820                                                                 value = 0xE000 + (last - 0xF0) * 0xBC + byteval;
821                                                                 if (byteval > 0x7F)
822                                                                         value--;
823                                                         }
824                                                         else
825                                                         {
826                                                                 value = (last - 0xE0 + (0xA0 - 0x81)) * 0xBC;
827                                                         }
828                                                         last = 0;
829                                                         if(byteval >= 0x40 && byteval <= 0x7E)
830                                                         {
831                                                                 value += (byteval - 0x40);
832                                                         }
833                                                         else if(byteval >= 0x80 && byteval <= 0xFC)
834                                                         {
835                                                                 value += (byteval - 0x80 + 0x3F);
836                                                         }
837                                                         else
838                                                         {
839                                                                 // Invalid second byte.
840                                                                 chars[posn++] = '?';
841                                                                 continue;
842                                                         }
843                                                         value *= 2;
844                                                         value = ((int)(table[value])) |
845                                                                         (((int)(table[value + 1])) << 8);
846                                                         if(value != 0)
847                                                         {
848                                                                 chars[posn++] = (char)value;
849                                                         }
850                                                         else
851                                                         {
852                                                                 chars[posn++] = '?';
853                                                         }
854                                                 }
855                                         }
856                                         lastByte = last;
857
858                                         // Return the final length to the caller.
859                                         return posn - charIndex;
860                                 }
861
862         } // class CP932Decoder
863
864 }; // class CP932
865
866 public class ENCshift_jis : CP932
867 {
868         public ENCshift_jis() : base() {}
869
870 }; // class ENCshift_jis
871
872 }; // namespace I18N.CJK