Merge pull request #2333 from joelmartinez/docs-classic-fix
[mono.git] / mcs / class / I18N / Common / MonoEncoding.cs
index f36f71f86776124342c530f9fda2ee3906d400ea..2c736c600e1bb3b7f7a7624eed5ce23a1e0b170f 100644 (file)
@@ -32,16 +32,34 @@ namespace I18N.Common
                        get { return win_code_page != 0 ? win_code_page : base.WindowsCodePage; }
                }
 
-#if NET_2_0
-               [CLSCompliant (false)]
+               /// <summary>
+               /// GetBytes method used internally by state-full encoders/encodings.
+               /// </summary>
+               /// <param name="chars">The chars.</param>
+               /// <param name="charIndex">Index of the char.</param>
+               /// <param name="charCount">The char count.</param>
+               /// <param name="bytes">The bytes.</param>
+               /// <param name="byteIndex">Index of the byte.</param>
+               /// <param name="flush">if set to <c>true</c> [flush].</param>
+               /// <param name="encoding">The encoding class to use (or null if state-less).</param>
+               /// <returns></returns>
+               /// <remarks>
+               /// Only state-full encoders need to implement this method (ie. ISO-2022-JP)
+               /// </remarks>
+               protected unsafe virtual int GetBytesInternal(char *chars, int charCount,
+                               byte *bytes, int byteCount, bool flush, object state)
+               {
+                       throw new NotImplementedException("Statefull encoding is not implemented (yet?) by this encoding class.");
+               }
+
                public unsafe void HandleFallback (ref EncoderFallbackBuffer buffer,
                        char* chars, ref int charIndex, ref int charCount,
-                       byte* bytes, ref int byteIndex, ref int byteCount)
+                       byte* bytes, ref int byteIndex, ref int byteCount, object state)
                {
                        if (buffer == null)
                                buffer = EncoderFallback.CreateFallbackBuffer ();
-                       if (Char.IsSurrogate (chars [charIndex]) && charCount > 0 &&
-                               Char.IsSurrogate (chars [charIndex + 1])) {
+
+                       if (charCount > 1 && (Char.IsSurrogate (chars [charIndex]) && Char.IsSurrogate (chars [charIndex + 1]))) {
                                buffer.Fallback (chars [charIndex], chars [charIndex + 1], charIndex);
                                charIndex++;
                                charCount--;
@@ -52,11 +70,25 @@ namespace I18N.Common
                        int idx = 0;
                        while (buffer.Remaining > 0)
                                tmp [idx++] = buffer.GetNextChar ();
+
                        fixed (char* tmparr = tmp) {
-                               byteIndex += GetBytes (tmparr, tmp.Length, bytes + byteIndex, byteCount);
+                               var outbytes = bytes == null ? null : bytes + byteIndex;
+                               var len = state == null ?
+                                       GetBytes(tmparr, tmp.Length, outbytes, byteCount)
+                                       : GetBytesInternal(tmparr, tmp.Length, outbytes, byteCount, true, state);
+
+                               byteIndex += len;
+                               byteCount -= len;
                        }
                }
-#endif
+
+               public unsafe void HandleFallback (ref EncoderFallbackBuffer buffer,
+                       char* chars, ref int charIndex, ref int charCount,
+                       byte* bytes, ref int byteIndex, ref int byteCount)
+               {
+                       HandleFallback(ref buffer, chars, ref charIndex, ref charCount,
+                               bytes, ref byteIndex, ref byteCount, null);
+               }
 
                // Get the bytes that result from encoding a character buffer.
                public override int GetByteCount (
@@ -159,7 +191,6 @@ namespace I18N.Common
                        }
                }
 
-#if NET_2_0
                public unsafe override int GetByteCount (char* chars, int count)
 
                {
@@ -172,14 +203,18 @@ namespace I18N.Common
                {
                        return GetBytesImpl (chars, charCount, bytes, byteCount);
                }
-#endif
 
-               [CLSCompliant (false)]
+               //[CLSCompliant (false)]
                public unsafe abstract int GetByteCountImpl (char* chars, int charCount);
 
-               [CLSCompliant (false)]
+               //[CLSCompliant (false)]
                public unsafe abstract int GetBytesImpl (char* chars, int charCount,
                        byte* bytes, int byteCount);
+               
+               public override Encoder GetEncoder ()
+               {
+                       return new MonoEncodingDefaultEncoder (this);
+               }
        }
 
                public abstract class MonoEncoder : Encoder
@@ -251,22 +286,99 @@ namespace I18N.Common
 
                        public unsafe abstract int GetBytesImpl (char* chars, int charCount, byte* bytes, int byteCount, bool refresh);
 
-               #if NET_2_0
                        public unsafe override int GetBytes (char* chars, int charCount, byte* bytes, int byteCount, bool flush)
                        {
                                return GetBytesImpl (chars, charCount, bytes, byteCount, flush);
                        }
 
-                       //[CLSCompliant (false)]
                        public unsafe void HandleFallback (
                                char* chars, ref int charIndex, ref int charCount,
-                               byte* bytes, ref int byteIndex, ref int byteCount)
+                               byte* bytes, ref int byteIndex, ref int byteCount, object state)
                        {
                                EncoderFallbackBuffer buffer = FallbackBuffer;
                                encoding.HandleFallback (ref buffer,
                                        chars, ref charIndex, ref charCount,
-                                       bytes, ref byteIndex, ref byteCount);
+                                       bytes, ref byteIndex, ref byteCount, state);
                        }
-               #endif
+
+/*                     public unsafe void HandleFallback(
+                               char* chars, ref int charIndex, ref int charCount,
+                               byte* bytes, ref int byteIndex, ref int byteCount)
+                       {
+                               HandleFallback(chars, ref charIndex, ref charCount,
+                                       bytes, ref byteIndex, ref byteCount, null);
+                       }*/
                }
+
+       public class MonoEncodingDefaultEncoder : ReferenceSourceDefaultEncoder
+       {
+               public MonoEncodingDefaultEncoder (Encoding encoding)
+                       : base (encoding)
+               {
+               }
+
+               [CLSCompliant (false)]
+               [ComVisible (false)]
+               public unsafe override void Convert (
+                       char* chars, int charCount,
+                       byte* bytes, int byteCount, bool flush,
+                       out int charsUsed, out int bytesUsed, out bool completed)
+               {
+                       CheckArguments (chars, charCount, bytes, byteCount);
+
+                       charsUsed = charCount;
+                       while (true) {
+                               bytesUsed = GetByteCount (chars, charsUsed, flush);
+                               if (bytesUsed <= byteCount)
+                                       break;
+                               flush = false;
+                               charsUsed >>= 1;
+                       }
+                       completed = charsUsed == charCount;
+                       bytesUsed = GetBytes (chars, charsUsed, bytes, byteCount, flush);
+               }
+
+               [ComVisible (false)]
+               public override void Convert (
+                       char [] chars, int charIndex, int charCount,
+                       byte [] bytes, int byteIndex, int byteCount, bool flush,
+                       out int charsUsed, out int bytesUsed, out bool completed)
+               {
+                       if (chars == null)
+                               throw new ArgumentNullException ("chars");
+                       if (bytes == null)
+                               throw new ArgumentNullException ("bytes");
+                       if (charIndex < 0)
+                               throw new ArgumentOutOfRangeException ("charIndex");
+                       if (charCount < 0 || chars.Length < charIndex + charCount)
+                               throw new ArgumentOutOfRangeException ("charCount");
+                       if (byteIndex < 0)
+                               throw new ArgumentOutOfRangeException ("byteIndex");
+                       if (byteCount < 0 || bytes.Length < byteIndex + byteCount)
+                               throw new ArgumentOutOfRangeException ("byteCount");
+
+                       charsUsed = charCount;
+                       while (true) {
+                               bytesUsed = GetByteCount (chars, charIndex, charsUsed, flush);
+                               if (bytesUsed <= byteCount)
+                                       break;
+                               flush = false;
+                               charsUsed >>= 1;
+                       }
+                       completed = charsUsed == charCount;
+                       bytesUsed = GetBytes (chars, charIndex, charsUsed, bytes, byteIndex, flush);
+               }
+
+               unsafe void CheckArguments (char* chars, int charCount, byte* bytes, int byteCount)
+               {
+                       if (chars == null)
+                               throw new ArgumentNullException ("chars");
+                       if (bytes == null)
+                               throw new ArgumentNullException ("bytes");
+                       if (charCount < 0)
+                               throw new ArgumentOutOfRangeException ("charCount");
+                       if (byteCount < 0)
+                               throw new ArgumentOutOfRangeException ("byteCount");
+               }
+       }
 }