[msvc] Update csproj files (#4846)
[mono.git] / mcs / class / I18N / CJK / CP950.cs
index 785b9cb412825ae9c99b434afad42c0a47cc4576..8e2420ca14c516256d55d92bef0c84820b7d2a1e 100644 (file)
@@ -3,6 +3,7 @@
 //
 // Author:
 //   Alan Tam Siu Lung (Tam@SiuLung.com)
+//   Atsushi Enomoto  <atsushi@ximian.com>
 //
 
 using System;
@@ -11,6 +12,7 @@ using I18N.Common;
 
 namespace I18N.CJK
 {
+       [Serializable]
        internal class CP950 : DbcsEncoding
        {
                // Magic number used by Windows for the Big5 code page.
@@ -18,18 +20,53 @@ namespace I18N.CJK
                
                // Constructor.
                public CP950() : base(BIG5_CODE_PAGE) {
-                       convert = Big5Convert.Convert;
                }
-               
+
+               internal override DbcsConvert GetConvert ()
+               {
+                       return DbcsConvert.Big5;
+               }
+
+#if !DISABLE_UNSAFE
                // Get the bytes that result from encoding a character buffer.
-               public override int GetBytes(char[] chars, int charIndex, int charCount,
-                                            byte[] bytes, int byteIndex)
+               public unsafe override int GetByteCountImpl (char* chars, int count)
                {
-                       // 00 00 - FF FF
-                       base.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
+                       DbcsConvert convert = GetConvert ();
+                       int index = 0;
+                       int length = 0;
+
+                       while (count-- > 0) {
+                               char c = chars[index++];
+                               if (c <= 0x80 || c == 0xFF) { // ASCII
+                                       length++;
+                                       continue;
+                               }
+                               byte b1 = convert.u2n[((int)c) * 2 + 1];
+                               byte b2 = convert.u2n[((int)c) * 2];
+                               if (b1 == 0 && b2 == 0) {
+                                       // FIXME: handle fallback for GetByteCountImpl().
+                                       length++;
+                               }
+                               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)
+               {
+                       DbcsConvert convert = GetConvert ();
+                       int charIndex = 0;
+                       int byteIndex = 0;
+                       int end = charCount;
+                       EncoderFallbackBuffer buffer = null;
+
                        int origIndex = byteIndex;
-                       while (charCount-- > 0) {
-                               char c = chars[charIndex++];
+                       for (int i = charIndex; i < end; i++, charCount--) 
+                       {
+                               char c = chars[i];
                                if (c <= 0x80 || c == 0xFF) { // ASCII
                                        bytes[byteIndex++] = (byte)c;
                                        continue;
@@ -37,7 +74,9 @@ namespace I18N.CJK
                                byte b1 = convert.u2n[((int)c) * 2 + 1];
                                byte b2 = convert.u2n[((int)c) * 2];
                                if (b1 == 0 && b2 == 0) {
-                                       bytes[byteIndex++] = (byte)'?';
+                                       HandleFallback (ref buffer, chars,
+                                               ref i, ref charCount,
+                                               bytes, ref byteIndex, ref byteCount, null);
                                } else {
                                        bytes[byteIndex++] = b1;
                                        bytes[byteIndex++] = b2;
@@ -45,11 +84,74 @@ namespace I18N.CJK
                        }
                        return byteIndex - origIndex;
                }
-               
+#else
+               // Get the bytes that result from encoding a character buffer.
+               public override int GetByteCount(char[] chars, int index, int count)
+               {
+                       DbcsConvert convert = GetConvert();
+                       int length = 0;
+
+                       while (count-- > 0)
+                       {
+                               char c = chars[index++];
+                               if (c <= 0x80 || c == 0xFF)
+                               { // ASCII
+                                       length++;
+                                       continue;
+                               }
+                               byte b1 = convert.u2n[((int)c) * 2 + 1];
+                               byte b2 = convert.u2n[((int)c) * 2];
+                               if (b1 == 0 && b2 == 0)
+                               {
+                                       // FIXME: handle fallback for GetByteCountImpl().
+                                       length++;
+                               }
+                               else
+                                       length += 2;
+                       }
+                       return length;
+               }
+
+               // Get the bytes that result from encoding a character buffer.
+               public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+               {
+                       int byteCount = bytes.Length;
+                       int end = charIndex + charCount;
+
+                       DbcsConvert convert = GetConvert();
+                       EncoderFallbackBuffer buffer = null;
+
+                       int origIndex = byteIndex;
+                       for (int i = charIndex; i < end; i++, charCount--)
+                       {
+                               char c = chars[i];
+                               if (c <= 0x80 || c == 0xFF)
+                               { // ASCII
+                                       bytes[byteIndex++] = (byte)c;
+                                       continue;
+                               }
+                               byte b1 = convert.u2n[((int)c) * 2 + 1];
+                               byte b2 = convert.u2n[((int)c) * 2];
+                               if (b1 == 0 && b2 == 0)
+                               {
+                                       HandleFallback (ref buffer, chars, ref i, ref charCount,
+                                               bytes, ref byteIndex, ref byteCount, null);
+                               }
+                               else
+                               {
+                                       bytes[byteIndex++] = b1;
+                                       bytes[byteIndex++] = b2;
+                               }
+                       }
+                       return byteIndex - origIndex;
+               }
+#endif
                // Get the characters that result from decoding a byte buffer.
                public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
                                             char[] chars, int charIndex)
                {
+                       /*
+                       DbcsConvert convert = GetConvert ();
                        // A1 40 - FA FF
                        base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
                        int origIndex = charIndex;
@@ -59,29 +161,38 @@ namespace I18N.CJK
                                if (lastByte == 0) {
                                        if (b <= 0x80 || b == 0xFF) { // ASCII
                                                chars[charIndex++] = (char)b;
-                                               continue;
                                        } else if (b < 0xA1 || b >= 0xFA) {
-                                               continue;
+                                               // incorrect first byte.
+                                               chars[charIndex++] = '?';
+                                               byteCount--; // cut one more byte.
                                        } else {
                                                lastByte = b;
-                                               continue;
                                        }
+                                       continue;
                                }
                                int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
-                               char c1 = (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+                               char c1 = ord < 0 || ord > convert.n2u.Length ?
+                                       '\0' :
+                                       (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
                                if (c1 == 0)
                                        chars[charIndex++] = '?';
                                else
                                        chars[charIndex++] = c1;
                                lastByte = 0;
                        }
+                       if (lastByte != 0)
+                               chars[charIndex++] = '?';
+
                        return charIndex - origIndex;
+                       */
+
+                       return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
                }
                
                // Get a decoder that handles a rolling Big5 state.
                public override Decoder GetDecoder()
                {
-                       return new CP950Decoder(convert);
+                       return new CP950Decoder(GetConvert ());
                }
                
                // Get the mail body name for this encoding.
@@ -121,39 +232,109 @@ namespace I18N.CJK
                {
                        // Constructor.
                        public CP950Decoder(DbcsConvert convert) : base(convert) {}
-                       
+                       int last_byte_count, last_byte_conv;
+
+                       public override int GetCharCount (byte[] bytes, int index, int count)
+                       {
+                               return GetCharCount (bytes, index, count, false);
+                       }
+
+                       public override
+                       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++;
+                                               } else if (b < 0xA1 || b >= 0xFA) {
+                                                       // incorrect first byte.
+                                                       length++;
+                                                       count--; // cut one more byte.
+                                               } else {
+                                                       lastByte = b;
+                                               }
+                                               continue;
+                                       }
+                                       int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
+                                       char c1 = ord < 0 || ord > convert.n2u.Length ?
+                                               '\0' :
+                                               (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+                                       if (c1 == 0)
+                                               // FIXME: fallback
+                                               length++;
+                                       else
+                                               length++;
+                                       lastByte = 0;
+                               }
+
+                               if (lastByte != 0) {
+                                       if (refresh)
+                                               // FIXME: fallback
+                                               length++;
+                                       else
+                                               last_byte_count = lastByte;
+                               }
+                               return length;
+                       }
+
                        public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
                                                     char[] chars, int charIndex)
                        {
-                               base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
+                               return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
+                       }
+
+                       public override
+                       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 if (b < 0xA1 || b >= 0xFA) {
-                                                       continue;
+                                                       // incorrect first byte.
+                                                       chars[charIndex++] = '?';
+                                                       byteCount--; // cut one more byte.
                                                } else {
                                                        lastByte = b;
-                                                       continue;
                                                }
+                                               continue;
                                        }
                                        int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
-                                       char c1 = (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
-                                       if (c1 == 0) {
+                                       char c1 = ord < 0 || ord > convert.n2u.Length ?
+                                               '\0' :
+                                               (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+                                       if (c1 == 0)
                                                chars[charIndex++] = '?';
-                                       } else {
+                                       else
                                                chars[charIndex++] = c1;
-                                       }
                                        lastByte = 0;
                                }
+
+                               if (lastByte != 0) {
+                                       if (refresh)
+                                               chars [charIndex++] = '?';
+                                       else
+                                               last_byte_conv = lastByte;
+                               }
                                return charIndex - origIndex;
                        }
                }
        }
        
+       [Serializable]
        internal class ENCbig5 : CP950
        {
                public ENCbig5() {}