The Labs \ Source Viewer \ SSCLI \ System.Text \ UTF8Decoder

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. // The worker functions in this file was optimized for performance. If you make changes
  16. // you should use care to consider all of the interesting cases.
  17. // The code of all worker functions in this file is written twice: Once as as a slow loop, and the
  18. // second time as a fast loop. The slow loops handles all special cases, throws exceptions, etc.
  19. // The fast loops attempts to blaze through as fast as possible with optimistic range checks,
  20. // processing multiple characters at a time, and falling back to the slow loop for all special cases.
  21. // This define can be used to turn off the fast loops. Useful for finding whether
  22. // the problem is fastloop-specific.
  23. #define FASTLOOP
  24. namespace System.Text
  25. {
  26.     using System;
  27.     using System.Globalization;
  28.     using System.Runtime.Serialization;
  29.     using System.Security.Permissions;
  30.    
  31.     // Encodes text into and out of UTF-8. UTF-8 is a way of writing
  32.     // Unicode characters with variable numbers of bytes per character,
  33.     // optimized for the lower 127 ASCII characters. It's an efficient way
  34.     // of encoding US English in an internationalizable way.
  35.     //
  36.     // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
  37.     //
  38.     // The UTF-8 byte order mark is simply the Unicode byte order mark
  39.     // (0xFEFF) written in UTF-8 (0xEF 0xBB 0xBF). The byte order mark is
  40.     // used mostly to distinguish UTF-8 text from other encodings, and doesn't
  41.     // switch the byte orderings.
  42.    
  43.     [Serializable()]
  44.     [System.Runtime.InteropServices.ComVisible(true)]
  45.     public class UTF8Encoding : Encoding
  46.     {
  47. /*
  48.             bytes  bits    UTF-8 representation
  49.             -----  ----    -----------------------------------
  50.             1        7      0vvvvvvv
  51.             2      11      110vvvvv 10vvvvvv
  52.             3      16      1110vvvv 10vvvvvv 10vvvvvv
  53.             4      21      11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
  54.             -----  ----    -----------------------------------
  55.             Surrogate:
  56.             Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
  57.         */       
  58.        
  59.         private const int UTF8_CODEPAGE = 65001;
  60.        
  61.         // Yes, the idea of emitting U+FEFF as a UTF-8 identifier has made it into
  62.         // the standard.
  63.         private bool emitUTF8Identifier = false;
  64.        
  65.         private bool isThrowException = false;
  66.        
  67.        
  68.         public UTF8Encoding() : this(false)
  69.         {
  70.         }
  71.        
  72.        
  73.         public UTF8Encoding(bool encoderShouldEmitUTF8Identifier) : this(encoderShouldEmitUTF8Identifier, false)
  74.         {
  75.         }
  76.        
  77.        
  78.         public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes) : base(UTF8_CODEPAGE)
  79.         {
  80.             this.emitUTF8Identifier = encoderShouldEmitUTF8Identifier;
  81.             this.isThrowException = throwOnInvalidBytes;
  82.            
  83.             if (this.isThrowException)
  84.                 SetDefaultFallbacks();
  85.         }
  86.        
  87.         internal override void SetDefaultFallbacks()
  88.         {
  89.             // For UTF-X encodings, we use a replacement fallback with an empty string
  90.             if (this.isThrowException) {
  91.                 this.encoderFallback = EncoderFallback.ExceptionFallback;
  92.                 this.decoderFallback = DecoderFallback.ExceptionFallback;
  93.             }
  94.             else {
  95.                 this.encoderFallback = new EncoderReplacementFallback(String.Empty);
  96.                 this.decoderFallback = new DecoderReplacementFallback(String.Empty);
  97.             }
  98.         }
  99.        
  100.        
  101.         //
  102.         //
  103.        
  104.         //
  105.        
  106.         unsafe public override int GetByteCount(char[] chars, int index, int count)
  107.         {
  108.             // Validate input parameters
  109.             if (chars == null)
  110.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  111.            
  112.             if (index < 0 || count < 0)
  113.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  114.            
  115.             if (chars.Length - index < count)
  116.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  117.            
  118.             // If no input, return 0, avoid fixed empty array problem
  119.             if (chars.Length == 0)
  120.                 return 0;
  121.            
  122.             // Just call the pointer version
  123.             fixed (char* pChars = chars)
  124.                 return GetByteCount(pChars + index, count, null);
  125.         }
  126.        
  127.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  128.         // So if you fix this, fix the others. Currently those include:
  129.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  130.         // parent method is safe
  131.        
  132.         unsafe public override int GetByteCount(string chars)
  133.         {
  134.             // Validate input
  135.             if (chars == null)
  136.                 throw new ArgumentNullException("s");
  137.            
  138.             fixed (char* pChars = chars)
  139.                 return GetByteCount(pChars, chars.Length, null);
  140.         }
  141.        
  142.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  143.         // So if you fix this, fix the others. Currently those include:
  144.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  145.        
  146.         [CLSCompliant(false)]
  147.         [System.Runtime.InteropServices.ComVisible(false)]
  148.         unsafe public override int GetByteCount(char* chars, int count)
  149.         {
  150.             // Validate Parameters
  151.             if (chars == null)
  152.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  153.            
  154.             if (count < 0)
  155.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  156.            
  157.             // Call it with empty encoder
  158.             return GetByteCount(chars, count, null);
  159.         }
  160.        
  161.         // Parent method is safe.
  162.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  163.         // So if you fix this, fix the others. Currently those include:
  164.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  165.        
  166.         unsafe public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
  167.         {
  168.             if (s == null || bytes == null)
  169.                 throw new ArgumentNullException((s == null ? "s" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  170.            
  171.             if (charIndex < 0 || charCount < 0)
  172.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  173.            
  174.             if (s.Length - charIndex < charCount)
  175.                 throw new ArgumentOutOfRangeException("s", Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
  176.            
  177.             if (byteIndex < 0 || byteIndex > bytes.Length)
  178.                 throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  179.            
  180.             int byteCount = bytes.Length - byteIndex;
  181.            
  182.             // Fixed doesn't like 0 length arrays.
  183.             if (bytes.Length == 0)
  184.                 bytes = new byte[1];
  185.            
  186.             fixed (char* pChars = s)
  187.                 fixed (byte* pBytes = bytes)
  188.                     return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
  189.         }
  190.        
  191.         // Encodes a range of characters in a character array into a range of bytes
  192.         // in a byte array. An exception occurs if the byte array is not large
  193.         // enough to hold the complete encoding of the characters. The
  194.         // GetByteCount method can be used to determine the exact number of
  195.         // bytes that will be produced for a given range of characters.
  196.         // Alternatively, the GetMaxByteCount method can be used to
  197.         // determine the maximum number of bytes that will be produced for a given
  198.         // number of characters, regardless of the actual character values.
  199.         //
  200.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  201.         // So if you fix this, fix the others. Currently those include:
  202.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  203.         // parent method is safe
  204.        
  205.         unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
  206.         {
  207.             // Validate parameters
  208.             if (chars == null || bytes == null)
  209.                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  210.            
  211.             if (charIndex < 0 || charCount < 0)
  212.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  213.            
  214.             if (chars.Length - charIndex < charCount)
  215.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  216.            
  217.             if (byteIndex < 0 || byteIndex > bytes.Length)
  218.                 throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  219.            
  220.             // If nothing to encode return 0, avoid fixed problem
  221.             if (chars.Length == 0)
  222.                 return 0;
  223.            
  224.             // Just call pointer version
  225.             int byteCount = bytes.Length - byteIndex;
  226.            
  227.             // Fixed doesn't like 0 length arrays.
  228.             if (bytes.Length == 0)
  229.                 bytes = new byte[1];
  230.            
  231.             fixed (char* pChars = chars)
  232.                 fixed (byte* pBytes = bytes)
  233.                 // Remember that byteCount is # to decode, not size of array.
  234.                     return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
  235.         }
  236.        
  237.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  238.         // So if you fix this, fix the others. Currently those include:
  239.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  240.        
  241.         [CLSCompliant(false)]
  242.         [System.Runtime.InteropServices.ComVisible(false)]
  243.         unsafe public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
  244.         {
  245.             // Validate Parameters
  246.             if (bytes == null || chars == null)
  247.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  248.            
  249.             if (charCount < 0 || byteCount < 0)
  250.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  251.            
  252.             return GetBytes(chars, charCount, bytes, byteCount, null);
  253.         }
  254.        
  255.         // Returns the number of characters produced by decoding a range of bytes
  256.         // in a byte array.
  257.         //
  258.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  259.         // So if you fix this, fix the others. Currently those include:
  260.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  261.         // parent method is safe
  262.        
  263.         unsafe public override int GetCharCount(byte[] bytes, int index, int count)
  264.         {
  265.             // Validate Parameters
  266.             if (bytes == null)
  267.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  268.            
  269.             if (index < 0 || count < 0)
  270.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  271.            
  272.             if (bytes.Length - index < count)
  273.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  274.            
  275.             // If no input just return 0, fixed doesn't like 0 length arrays.
  276.             if (bytes.Length == 0)
  277.                 return 0;
  278.            
  279.             // Just call pointer version
  280.             fixed (byte* pBytes = bytes)
  281.                 return GetCharCount(pBytes + index, count, null);
  282.         }
  283.        
  284.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  285.         // So if you fix this, fix the others. Currently those include:
  286.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  287.        
  288.         [CLSCompliant(false)]
  289.         [System.Runtime.InteropServices.ComVisible(false)]
  290.         unsafe public override int GetCharCount(byte* bytes, int count)
  291.         {
  292.             // Validate Parameters
  293.             if (bytes == null)
  294.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  295.            
  296.             if (count < 0)
  297.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  298.            
  299.             return GetCharCount(bytes, count, null);
  300.         }
  301.        
  302.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  303.         // So if you fix this, fix the others. Currently those include:
  304.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  305.         // parent method is safe
  306.        
  307.         unsafe public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  308.         {
  309.             // Validate Parameters
  310.             if (bytes == null || chars == null)
  311.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  312.            
  313.             if (byteIndex < 0 || byteCount < 0)
  314.                 throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  315.            
  316.             if (bytes.Length - byteIndex < byteCount)
  317.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  318.            
  319.             if (charIndex < 0 || charIndex > chars.Length)
  320.                 throw new ArgumentOutOfRangeException("charIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  321.            
  322.             // If no input, return 0 & avoid fixed problem
  323.             if (bytes.Length == 0)
  324.                 return 0;
  325.            
  326.             // Just call pointer version
  327.             int charCount = chars.Length - charIndex;
  328.            
  329.             // Fixed doesn't like 0 length arrays.
  330.             if (chars.Length == 0)
  331.                 chars = new char[1];
  332.            
  333.             fixed (byte* pBytes = bytes)
  334.                 fixed (char* pChars = chars)
  335.                 // Remember that charCount is # to decode, not size of array
  336.                     return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
  337.         }
  338.        
  339.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  340.         // So if you fix this, fix the others. Currently those include:
  341.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  342.        
  343.         [CLSCompliant(false)]
  344.         [System.Runtime.InteropServices.ComVisible(false)]
  345.         unsafe public override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
  346.         {
  347.             // Validate Parameters
  348.             if (bytes == null || chars == null)
  349.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  350.            
  351.             if (charCount < 0 || byteCount < 0)
  352.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  353.            
  354.             return GetChars(bytes, byteCount, chars, charCount, null);
  355.         }
  356.        
  357.         // Returns a string containing the decoded representation of a range of
  358.         // bytes in a byte array.
  359.         //
  360.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  361.         // So if you fix this, fix the others. Currently those include:
  362.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  363.         // parent method is safe
  364.        
  365.         [System.Runtime.InteropServices.ComVisible(false)]
  366.         unsafe public override string GetString(byte[] bytes, int index, int count)
  367.         {
  368.             // Validate Parameters
  369.             if (bytes == null)
  370.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  371.            
  372.             if (index < 0 || count < 0)
  373.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  374.            
  375.             if (bytes.Length - index < count)
  376.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  377.            
  378.             // Avoid problems with empty input buffer
  379.             if (bytes.Length == 0)
  380.                 return String.Empty;
  381.            
  382.             fixed (byte* pBytes = bytes)
  383.                 return String.CreateStringFromEncoding(pBytes + index, count, this);
  384.         }
  385.        
  386.         //
  387.         // End of standard methods copied from EncodingNLS.cs
  388.         //
  389.        
  390.         // To simplify maintenance, the structure of GetByteCount and GetBytes should be
  391.         // kept the same as much as possible
  392.         unsafe internal override int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
  393.         {
  394.            
  395.             BCLDebug.Assert(chars != null, "[UTF8Encoding.GetByteCount]chars!=null");
  396.             BCLDebug.Assert(count >= 0, "[UTF8Encoding.GetByteCount]count >=0");
  397.            
  398.             EncoderFallbackBuffer fallbackBuffer = null;
  399.             char* pSrc = chars;
  400.             char* pEnd = pSrc + count;
  401.            
  402.             // Start by assuming we have as many as count
  403.             int byteCount = count;
  404.            
  405.             int ch = 0;
  406.            
  407.             if (baseEncoder != null) {
  408.                 UTF8Encoder encoder = (UTF8Encoder)baseEncoder;
  409.                 ch = encoder.surrogateChar;
  410.                
  411.                 // We mustn't have left over fallback data when counting
  412.                 if (encoder.InternalHasFallbackBuffer) {
  413.                     if ((fallbackBuffer = encoder.FallbackBuffer).Remaining > 0)
  414.                         throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", this.EncodingName, encoder.Fallback.GetType()));
  415.                    
  416.                     // Set our internal fallback interesting things.
  417.                     fallbackBuffer.InternalInitialize(chars, pEnd, encoder, false);
  418.                 }
  419.             }
  420.            
  421.             for (;;) {
  422.                 // SLOWLOOP: does all range checks, handles all special cases, but it is slow
  423.                 if (pSrc >= pEnd) {
  424.                    
  425.                     if (ch == 0) {
  426.                         // Unroll any fallback that happens at the end
  427.                         ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0;
  428.                         if (ch > 0) {
  429.                             byteCount++;
  430.                             goto ProcessChar;
  431.                         }
  432.                     }
  433.                     else {
  434.                         // Case of surrogates in the fallback.
  435.                         if (fallbackBuffer != null && fallbackBuffer.bFallingBack) {
  436.                             BCLDebug.Assert(ch >= 55296 && ch <= 56319, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
  437.                            
  438.                             ch = fallbackBuffer.InternalGetNextChar();
  439.                             byteCount++;
  440.                            
  441.                             if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  442.                                 ch = 65533;
  443.                                 byteCount++;
  444.                                 goto EncodeChar;
  445.                             }
  446.                             else if (ch > 0) {
  447.                                 goto ProcessChar;
  448.                             }
  449.                             else {
  450.                                 byteCount--;
  451.                                 // ignore last one.
  452.                                 break;
  453.                             }
  454.                         }
  455.                     }
  456.                    
  457.                     if (ch <= 0) {
  458.                         break;
  459.                     }
  460.                     if (baseEncoder != null && !baseEncoder.MustFlush) {
  461.                         break;
  462.                     }
  463.                    
  464.                     // attempt to encode the partial surrogate (will fallback or ignore it), it'll also subtract 1.
  465.                     byteCount++;
  466.                     goto EncodeChar;
  467.                 }
  468.                
  469.                 if (ch > 0) {
  470.                     BCLDebug.Assert(ch >= 55296 && ch <= 56319, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
  471.                    
  472.                     // use separate helper variables for local contexts so that the jit optimizations
  473.                     // won't get confused about the variable lifetimes
  474.                     int cha = *pSrc;
  475.                    
  476.                     // count the pending surrogate
  477.                     byteCount++;
  478.                    
  479.                     // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
  480.                     // if (IsLowSurrogate(cha)) {
  481.                     if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  482.                         // Don't need a real # because we're just counting, anything > 0x7ff ('cept surrogate) will do.
  483.                         ch = 65533;
  484.                         // ch = cha + (ch << 10) +
  485.                         // (0x10000
  486.                         // - CharUnicodeInfo.LOW_SURROGATE_START
  487.                         // - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) );
  488.                        
  489.                         // Use this next char
  490.                         pSrc++;
  491.                     }
  492.                     // else ch is still high surrogate and encoding will fail (so don't add count)
  493.                    
  494.                     // attempt to encode the surrogate or partial surrogate
  495.                     goto EncodeChar;
  496.                 }
  497.                
  498.                 // If we've used a fallback, then we have to check for it
  499.                 if (fallbackBuffer != null) {
  500.                     ch = fallbackBuffer.InternalGetNextChar();
  501.                     if (ch > 0) {
  502.                         // We have an extra byte we weren't expecting.
  503.                         byteCount++;
  504.                         goto ProcessChar;
  505.                     }
  506.                 }
  507.                
  508.                 // read next char. The JIT optimization seems to be getting confused when
  509.                 // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
  510.                 ch = *pSrc;
  511.                 pSrc++;
  512.                 ProcessChar:
  513.                
  514.                 // if (IsHighSurrogate(ch)) {
  515.                 if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) {
  516.                     // we will count this surrogate next time around
  517.                     byteCount--;
  518.                     continue;
  519.                 }
  520.                 EncodeChar:
  521.                 // either good char or partial surrogate
  522.                
  523.                 // throw exception on partial surrogate if necessary
  524.                 // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
  525.                 if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  526.                     // Lone surrogates aren't allowed
  527.                     // Have to make a fallback buffer if we don't have one
  528.                     if (fallbackBuffer == null) {
  529.                         // wait on fallbacks if we can
  530.                         // For fallback we may need a fallback buffer
  531.                         if (baseEncoder == null)
  532.                             fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
  533.                         else
  534.                             fallbackBuffer = baseEncoder.FallbackBuffer;
  535.                        
  536.                         // Set our internal fallback interesting things.
  537.                         fallbackBuffer.InternalInitialize(chars, chars + count, baseEncoder, false);
  538.                     }
  539.                    
  540.                     // Do our fallback. Actually we already know its a mixed up surrogate,
  541.                     // so the ref pSrc isn't gonna do anything.
  542.                     fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrc);
  543.                    
  544.                     // Ignore it if we don't throw (we had preallocated this ch)
  545.                     byteCount--;
  546.                     ch = 0;
  547.                     continue;
  548.                 }
  549.                
  550.                 // Count them
  551.                 if (ch > 127) {
  552.                     if (ch > 2047) {
  553.                         // the extra surrogate byte was compensated by the second surrogate character
  554.                         // (2 surrogates make 4 bytes. We've already counted 2 bytes, 1 per char)
  555.                         byteCount++;
  556.                     }
  557.                     byteCount++;
  558.                 }
  559.                
  560.                
  561.                 #if FASTLOOP
  562.                 // If still have fallback don't do fast loop
  563.                 if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0) {
  564.                     // We're reserving 1 byte for each char by default
  565.                     byteCount++;
  566.                     goto ProcessChar;
  567.                 }
  568.                
  569.                 int availableChars = PtrDiff(pEnd, pSrc);
  570.                
  571.                 // don't fall into the fast decoding loop if we don't have enough characters
  572.                 if (availableChars <= 13) {
  573.                     // try to get over the remainder of the ascii characters fast though
  574.                     char* pLocalEnd = pEnd;
  575.                     // hint to get pLocalEnd enregistered
  576.                     while (pSrc < pLocalEnd) {
  577.                         ch = *pSrc;
  578.                         pSrc++;
  579.                         if (ch > 127)
  580.                             goto ProcessChar;
  581.                     }
  582.                    
  583.                     // we are done
  584.                     break;
  585.                 }
  586.                
  587.                
  588.                 // To compute the upper bound, assume that all characters are ASCII characters at this point,
  589.                 // the boundary will be decreased for every non-ASCII character we encounter
  590.                 // Also, we need 3 + 4 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
  591.                 char* pStop = pSrc + availableChars - (3 + 4);
  592.                
  593.                 while (pSrc < pStop) {
  594.                     ch = *pSrc;
  595.                     pSrc++;
  596.                    
  597.                     // Not ASCII
  598.                     if (ch > 127) {
  599.                         // Not 2 Byte
  600.                         if (ch > 2047) {
  601.                             if ((ch & 63488) == 55296)
  602.                                 // See if its a Surrogate
  603.                                 goto LongCode;
  604.                             byteCount++;
  605.                         }
  606.                         byteCount++;
  607.                     }
  608.                    
  609.                     // get pSrc aligned
  610.                     if ((unchecked((int)pSrc) & 2) != 0) {
  611.                         ch = *pSrc;
  612.                         pSrc++;
  613.                         // Not ASCII
  614.                         if (ch > 127) {
  615.                             // Not 2 Byte
  616.                             if (ch > 2047) {
  617.                                 if ((ch & 63488) == 55296)
  618.                                     // See if its a Surrogate
  619.                                     goto LongCode;
  620.                                 byteCount++;
  621.                             }
  622.                             byteCount++;
  623.                         }
  624.                     }
  625.                    
  626.                     // Run 2 * 4 characters at a time!
  627.                     while (pSrc < pStop) {
  628.                         ch = *(int*)pSrc;
  629.                         int chc = *(int*)(pSrc + 2);
  630.                         // See if not ASCII
  631.                         if (((ch | chc) & unchecked((int)4286644096u)) != 0) {
  632.                             // See if not 2 Byte
  633.                             if (((ch | chc) & unchecked((int)4160813056u)) != 0) {
  634.                                 goto LongCodeWithMask;
  635.                             }
  636.                            
  637.                            
  638.                             if ((ch & unchecked((int)4286578688u)) != 0)
  639.                                 // Actually 0x07800780 is all we care about (4 bits)
  640.                                 byteCount++;
  641.                             if ((ch & unchecked((int)65408)) != 0)
  642.                                 byteCount++;
  643.                             if ((chc & unchecked((int)4286578688u)) != 0)
  644.                                 byteCount++;
  645.                             if ((chc & unchecked((int)65408)) != 0)
  646.                                 byteCount++;
  647.                         }
  648.                         pSrc += 4;
  649.                        
  650.                         ch = *(int*)pSrc;
  651.                         chc = *(int*)(pSrc + 2);
  652.                         // See if not ASCII
  653.                         if (((ch | chc) & unchecked((int)4286644096u)) != 0) {
  654.                             // See if not 2 Byte
  655.                             if (((ch | chc) & unchecked((int)4160813056u)) != 0) {
  656.                                 goto LongCodeWithMask;
  657.                             }
  658.                            
  659.                             if ((ch & unchecked((int)4286578688u)) != 0)
  660.                                 byteCount++;
  661.                             if ((ch & unchecked((int)65408)) != 0)
  662.                                 byteCount++;
  663.                             if ((chc & unchecked((int)4286578688u)) != 0)
  664.                                 byteCount++;
  665.                             if ((chc & unchecked((int)65408)) != 0)
  666.                                 byteCount++;
  667.                         }
  668.                         pSrc += 4;
  669.                     }
  670.                     break;
  671.                     LongCodeWithMask:
  672.                    
  673.                     #if BIGENDIAN
  674.                     // be careful about the sign extension
  675.                     ch = (int)(((uint)ch) >> 16);
  676.                     #else // BIGENDIAN
  677.                     ch = (char)ch;
  678.                     #endif // BIGENDIAN
  679.                     pSrc++;
  680.                    
  681.                     if (ch <= 127) {
  682.                         continue;
  683.                     }
  684.                     LongCode:
  685.                    
  686.                     // use separate helper variables for slow and fast loop so that the jit optimizations
  687.                     // won't get confused about the variable lifetimes
  688.                     if (ch > 2047) {
  689.                         // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
  690.                         if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  691.                             // 4 byte encoding - high surrogate + low surrogate
  692.                            
  693.                             int chd = *pSrc;
  694.                             // !IsHighSurrogate(ch) // low without high -> bad
  695.                             // !IsLowSurrogate(chd) // high not followed by low -> bad
  696.                             if (ch > CharUnicodeInfo.HIGH_SURROGATE_END || !InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  697.                                 // Back up and drop out to slow loop to figure out error
  698.                                 pSrc--;
  699.                                 break;
  700.                             }
  701.                             pSrc++;
  702.                            
  703.                             // byteCount - this byte is compensated by the second surrogate character
  704.                         }
  705.                         byteCount++;
  706.                     }
  707.                     byteCount++;
  708.                    
  709.                     // byteCount - the last byte is already included
  710.                 }
  711.                 #endif // FASTLOOP
  712.                
  713.                 // no pending char at this point
  714.                 ch = 0;
  715.             }
  716.            
  717.            
  718.             BCLDebug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[UTF8Encoding.GetByteCount]Expected Empty fallback buffer");
  719.            
  720.             return byteCount;
  721.         }
  722.        
  723.         // diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
  724.         // is good enough for us, and it tends to generate better code than the signed
  725.         // arithmetic generated by default
  726.         unsafe private static int PtrDiff(char* a, char* b)
  727.         {
  728.             return (int)(((uint)((byte*)a - (byte*)b)) >> 1);
  729.         }
  730.        
  731.         // byte* flavor just for parity
  732.         unsafe private static int PtrDiff(byte* a, byte* b)
  733.         {
  734.             return (int)(a - b);
  735.         }
  736.        
  737.         private static bool InRange(int ch, int start, int end)
  738.         {
  739.             return (uint)(ch - start) <= (uint)(end - start);
  740.         }
  741.        
  742.         // Our workhorse
  743.         // Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw
  744.         unsafe internal override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
  745.         {
  746.             BCLDebug.Assert(chars != null, "[UTF8Encoding.GetBytes]chars!=null");
  747.             BCLDebug.Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0");
  748.             BCLDebug.Assert(charCount >= 0, "[UTF8Encoding.GetBytes]charCount >=0");
  749.             BCLDebug.Assert(bytes != null, "[UTF8Encoding.GetBytes]bytes!=null");
  750.            
  751.             UTF8Encoder encoder = null;
  752.            
  753.             EncoderFallbackBuffer fallbackBuffer = null;
  754.             char* pSrc = chars;
  755.             byte* pTarget = bytes;
  756.            
  757.             char* pEnd = pSrc + charCount;
  758.             byte* pAllocatedBufferEnd = pTarget + byteCount;
  759.            
  760.             int ch = 0;
  761.            
  762.             // assume that JIT will enregister pSrc, pTarget and ch
  763.            
  764.             if (baseEncoder != null) {
  765.                 encoder = (UTF8Encoder)baseEncoder;
  766.                 ch = encoder.surrogateChar;
  767.                
  768.                 // We mustn't have left over fallback data when counting
  769.                 if (encoder.InternalHasFallbackBuffer) {
  770.                     // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
  771.                     fallbackBuffer = encoder.FallbackBuffer;
  772.                     if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
  773.                         throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", this.EncodingName, encoder.Fallback.GetType()));
  774.                    
  775.                     // Set our internal fallback interesting things.
  776.                     fallbackBuffer.InternalInitialize(chars, pEnd, encoder, true);
  777.                 }
  778.             }
  779.            
  780.             for (;;) {
  781.                 // SLOWLOOP: does all range checks, handles all special cases, but it is slow
  782.                
  783.                 if (pSrc >= pEnd) {
  784.                    
  785.                     if (ch == 0) {
  786.                         // Check if there's anthing left to get out of the fallback buffer
  787.                         ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0;
  788.                         if (ch > 0) {
  789.                             goto ProcessChar;
  790.                         }
  791.                     }
  792.                     else {
  793.                         // Case of leftover surrogates in the fallback buffer
  794.                         if (fallbackBuffer != null && fallbackBuffer.bFallingBack) {
  795.                             BCLDebug.Assert(ch >= 55296 && ch <= 56319, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
  796.                            
  797.                             int cha = ch;
  798.                            
  799.                             ch = fallbackBuffer.InternalGetNextChar();
  800.                            
  801.                             if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  802.                                 ch = ch + (cha << 10) + (65536 - CharUnicodeInfo.LOW_SURROGATE_START - (CharUnicodeInfo.HIGH_SURROGATE_START << 10));
  803.                                 goto EncodeChar;
  804.                             }
  805.                             else if (ch > 0) {
  806.                                 goto ProcessChar;
  807.                             }
  808.                             else {
  809.                                 break;
  810.                             }
  811.                         }
  812.                     }
  813.                    
  814.                     // attempt to encode the partial surrogate (will fail or ignore)
  815.                     if (ch > 0 && (encoder == null || encoder.MustFlush))
  816.                         goto EncodeChar;
  817.                    
  818.                     // We're done
  819.                     break;
  820.                 }
  821.                
  822.                 if (ch > 0) {
  823.                     // We have a high surrogate left over from a previous loop.
  824.                     BCLDebug.Assert(ch >= 55296 && ch <= 56319, "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
  825.                    
  826.                     // use separate helper variables for local contexts so that the jit optimizations
  827.                     // won't get confused about the variable lifetimes
  828.                     int cha = *pSrc;
  829.                    
  830.                     // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
  831.                     // if (IsLowSurrogate(cha)) {
  832.                     if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  833.                         ch = cha + (ch << 10) + (65536 - CharUnicodeInfo.LOW_SURROGATE_START - (CharUnicodeInfo.HIGH_SURROGATE_START << 10));
  834.                        
  835.                         pSrc++;
  836.                     }
  837.                     // else ch is still high surrogate and encoding will fail
  838.                    
  839.                     // attempt to encode the surrogate or partial surrogate
  840.                     goto EncodeChar;
  841.                 }
  842.                
  843.                 // If we've used a fallback, then we have to check for it
  844.                 if (fallbackBuffer != null) {
  845.                     ch = fallbackBuffer.InternalGetNextChar();
  846.                     if (ch > 0)
  847.                         goto ProcessChar;
  848.                 }
  849.                
  850.                 // read next char. The JIT optimization seems to be getting confused when
  851.                 // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
  852.                 ch = *pSrc;
  853.                 pSrc++;
  854.                 ProcessChar:
  855.                
  856.                 // if (IsHighSurrogate(ch)) {
  857.                 if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) {
  858.                     continue;
  859.                 }
  860.                 EncodeChar:
  861.                 // either good char or partial surrogate
  862.                
  863.                 // throw exception on partial surrogate if necessary
  864.                 // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
  865.                 if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  866.                     // Lone surrogates aren't allowed, we have to do fallback for them
  867.                     // Have to make a fallback buffer if we don't have one
  868.                     if (fallbackBuffer == null) {
  869.                         // wait on fallbacks if we can
  870.                         // For fallback we may need a fallback buffer
  871.                         if (baseEncoder == null)
  872.                             fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
  873.                         else
  874.                             fallbackBuffer = baseEncoder.FallbackBuffer;
  875.                        
  876.                         // Set our internal fallback interesting things.
  877.                         fallbackBuffer.InternalInitialize(chars, pEnd, baseEncoder, true);
  878.                     }
  879.                    
  880.                     // Do our fallback. Actually we already know its a mixed up surrogate,
  881.                     // so the ref pSrc isn't gonna do anything.
  882.                     fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrc);
  883.                    
  884.                     // Ignore it if we don't throw
  885.                     ch = 0;
  886.                     continue;
  887.                 }
  888.                
  889.                 // Count bytes needed
  890.                 int bytesNeeded = 1;
  891.                 if (ch > 127) {
  892.                     if (ch > 2047) {
  893.                         if (ch > 65535) {
  894.                             bytesNeeded++;
  895.                             // 4 bytes (surrogate pair)
  896.                         }
  897.                         bytesNeeded++;
  898.                         // 3 bytes (800-FFFF)
  899.                     }
  900.                     bytesNeeded++;
  901.                     // 2 bytes (80-7FF)
  902.                 }
  903.                
  904.                 if (pTarget > pAllocatedBufferEnd - bytesNeeded) {
  905.                     // Left over surrogate from last time will cause pSrc == chars, so we'll throw
  906.                     if (fallbackBuffer != null && fallbackBuffer.bFallingBack) {
  907.                         fallbackBuffer.MovePrevious();
  908.                         // Didn't use this fallback char
  909.                         if (ch > 65535)
  910.                             fallbackBuffer.MovePrevious();
  911.                         // Was surrogate, didn't use 2nd part either
  912.                     }
  913.                     else {
  914.                         pSrc--;
  915.                         // Didn't use this char
  916.                         if (ch > 65535)
  917.                             pSrc--;
  918.                         // Was surrogate, didn't use 2nd part either
  919.                     }
  920.                     BCLDebug.Assert(pSrc >= chars || pTarget == bytes, "[UTF8Encoding.GetBytes]Expected pSrc to be within buffer or to throw with insufficient room.");
  921.                     ThrowBytesOverflow(encoder, pTarget == bytes);
  922.                     // Throw if we must
  923.                     ch = 0;
  924.                     // Nothing left over (we backed up to start of pair if supplimentary)
  925.                     break;
  926.                 }
  927.                
  928.                 if (ch <= 127) {
  929.                     *pTarget = (byte)ch;
  930.                 }
  931.                 else {
  932.                     // use separate helper variables for local contexts so that the jit optimizations
  933.                     // won't get confused about the variable lifetimes
  934.                     int chb;
  935.                     if (ch <= 2047) {
  936.                         // 2 byte encoding
  937.                         chb = (byte)(unchecked((sbyte)192) | (ch >> 6));
  938.                     }
  939.                     else {
  940.                         if (ch <= 65535) {
  941.                             chb = (byte)(unchecked((sbyte)224) | (ch >> 12));
  942.                         }
  943.                         else {
  944.                             *pTarget = (byte)(unchecked((sbyte)240) | (ch >> 18));
  945.                             pTarget++;
  946.                            
  947.                             chb = unchecked((sbyte)128) | (ch >> 12) & 63;
  948.                         }
  949.                         *pTarget = (byte)chb;
  950.                         pTarget++;
  951.                        
  952.                         chb = unchecked((sbyte)128) | (ch >> 6) & 63;
  953.                     }
  954.                     *pTarget = (byte)chb;
  955.                     pTarget++;
  956.                    
  957.                     *pTarget = (byte)(unchecked((sbyte)128) | ch & 63);
  958.                 }
  959.                 pTarget++;
  960.                
  961.                
  962.                 #if FASTLOOP
  963.                 // If still have fallback don't do fast loop
  964.                 if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0)
  965.                     goto ProcessChar;
  966.                
  967.                 int availableChars = PtrDiff(pEnd, pSrc);
  968.                 int availableBytes = PtrDiff(pAllocatedBufferEnd, pTarget);
  969.                
  970.                 // don't fall into the fast decoding loop if we don't have enough characters
  971.                 // Note that if we don't have enough bytes, pStop will prevent us from entering the fast loop.
  972.                 if (availableChars <= 13) {
  973.                     // we are hoping for 1 byte per char
  974.                     if (availableBytes < availableChars) {
  975.                         // not enough output room. no pending bits at this point
  976.                         ch = 0;
  977.                         continue;
  978.                     }
  979.                    
  980.                     // try to get over the remainder of the ascii characters fast though
  981.                     char* pLocalEnd = pEnd;
  982.                     // hint to get pLocalEnd enregistered
  983.                     while (pSrc < pLocalEnd) {
  984.                         ch = *pSrc;
  985.                         pSrc++;
  986.                        
  987.                         // Not ASCII, need more than 1 byte per char
  988.                         if (ch > 127)
  989.                             goto ProcessChar;
  990.                        
  991.                         *pTarget = (byte)ch;
  992.                         pTarget++;
  993.                     }
  994.                     // we are done, let ch be 0 to clear encoder
  995.                     ch = 0;
  996.                     break;
  997.                 }
  998.                
  999.                 // we need at least 1 byte per character, but Convert might allow us to convert
  1000.                 // only part of the input, so try as much as we can. Reduce charCount if necessary
  1001.                 if (availableBytes < availableChars) {
  1002.                     availableChars = availableBytes;
  1003.                 }
  1004.                
  1005.                 // FASTLOOP:
  1006.                 // - optimistic range checks
  1007.                 // - fallbacks to the slow loop for all special cases, exception throwing, etc.
  1008.                
  1009.                 // To compute the upper bound, assume that all characters are ASCII characters at this point,
  1010.                 // the boundary will be decreased for every non-ASCII character we encounter
  1011.                 // Also, we need 5 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
  1012.                 // If there aren't enough bytes for the output, then pStop will be <= pSrc and will bypass the loop.
  1013.                 char* pStop = pSrc + availableChars - 5;
  1014.                
  1015.                 while (pSrc < pStop) {
  1016.                     ch = *pSrc;
  1017.                     pSrc++;
  1018.                    
  1019.                     if (ch > 127) {
  1020.                         goto LongCode;
  1021.                     }
  1022.                     *pTarget = (byte)ch;
  1023.                     pTarget++;
  1024.                    
  1025.                     // get pSrc aligned
  1026.                     if ((unchecked((int)pSrc) & 2) != 0) {
  1027.                         ch = *pSrc;
  1028.                         pSrc++;
  1029.                         if (ch > 127) {
  1030.                             goto LongCode;
  1031.                         }
  1032.                         *pTarget = (byte)ch;
  1033.                         pTarget++;
  1034.                     }
  1035.                    
  1036.                     // Run 4 characters at a time!
  1037.                     while (pSrc < pStop) {
  1038.                         ch = *(int*)pSrc;
  1039.                         int chc = *(int*)(pSrc + 2);
  1040.                         if (((ch | chc) & unchecked((int)4286644096u)) != 0) {
  1041.                             goto LongCodeWithMask;
  1042.                         }
  1043.                        
  1044.                         #if BIGENDIAN
  1045.                         *pTarget = (byte)(ch >> 16);
  1046.                         *(pTarget + 1) = (byte)ch;
  1047.                         pSrc += 4;
  1048.                         *(pTarget + 2) = (byte)(chc >> 16);
  1049.                         *(pTarget + 3) = (byte)chc;
  1050.                         pTarget += 4;
  1051.                         #else // BIGENDIAN
  1052.                         *pTarget = (byte)ch;
  1053.                         *(pTarget + 1) = (byte)(ch >> 16);
  1054.                         pSrc += 4;
  1055.                         *(pTarget + 2) = (byte)chc;
  1056.                         *(pTarget + 3) = (byte)(chc >> 16);
  1057.                         pTarget += 4;
  1058.                         #endif // BIGENDIAN
  1059.                     }
  1060.                     continue;
  1061.                     LongCodeWithMask:
  1062.                    
  1063.                     #if BIGENDIAN
  1064.                     // be careful about the sign extension
  1065.                     ch = (int)(((uint)ch) >> 16);
  1066.                     #else // BIGENDIAN
  1067.                     ch = (char)ch;
  1068.                     #endif // BIGENDIAN
  1069.                     pSrc++;
  1070.                    
  1071.                     if (ch > 127) {
  1072.                         goto LongCode;
  1073.                     }
  1074.                     *pTarget = (byte)ch;
  1075.                     pTarget++;
  1076.                     continue;
  1077.                     LongCode:
  1078.                    
  1079.                     // use separate helper variables for slow and fast loop so that the jit optimizations
  1080.                     // won't get confused about the variable lifetimes
  1081.                     int chd;
  1082.                     if (ch <= 2047) {
  1083.                         // 2 byte encoding
  1084.                         chd = unchecked((sbyte)192) | (ch >> 6);
  1085.                     }
  1086.                     else {
  1087.                         // if (!IsLowSurrogate(ch) && !IsHighSurrogate(ch))
  1088.                         if (!InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  1089.                             // 3 byte encoding
  1090.                             chd = unchecked((sbyte)224) | (ch >> 12);
  1091.                         }
  1092.                         else {
  1093.                             // 4 byte encoding - high surrogate + low surrogate
  1094.                             // if (!IsHighSurrogate(ch))
  1095.                             if (ch > CharUnicodeInfo.HIGH_SURROGATE_END) {
  1096.                                 // low without high -> bad, try again in slow loop
  1097.                                 pSrc -= 1;
  1098.                                 break;
  1099.                             }
  1100.                            
  1101.                             chd = *pSrc;
  1102.                             pSrc++;
  1103.                            
  1104.                             // if (!IsLowSurrogate(chd)) {
  1105.                             if (!InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
  1106.                                 // high not followed by low -> bad, try again in slow loop
  1107.                                 pSrc -= 2;
  1108.                                 break;
  1109.                             }
  1110.                            
  1111.                             ch = chd + (ch << 10) + (65536 - CharUnicodeInfo.LOW_SURROGATE_START - (CharUnicodeInfo.HIGH_SURROGATE_START << 10));
  1112.                            
  1113.                             *pTarget = (byte)(unchecked((sbyte)240) | (ch >> 18));
  1114.                             // pStop - this byte is compensated by the second surrogate character
  1115.                             // 2 input chars require 4 output bytes. 2 have been anticipated already
  1116.                             // and 2 more will be accounted for by the 2 pStop-- calls below.
  1117.                             pTarget++;
  1118.                            
  1119.                             chd = unchecked((sbyte)128) | (ch >> 12) & 63;
  1120.                         }
  1121.                         *pTarget = (byte)chd;
  1122.                         pStop--;
  1123.                         // 3 byte sequence for 1 char, so need pStop-- and the one below too.
  1124.                         pTarget++;
  1125.                        
  1126.                         chd = unchecked((sbyte)128) | (ch >> 6) & 63;
  1127.                     }
  1128.                     *pTarget = (byte)chd;
  1129.                     pStop--;
  1130.                     // 2 byte sequence for 1 char so need pStop--.
  1131.                     pTarget++;
  1132.                    
  1133.                     *pTarget = (byte)(unchecked((sbyte)128) | ch & 63);
  1134.                     // pStop - this byte is already included
  1135.                     pTarget++;
  1136.                 }
  1137.                
  1138.                 BCLDebug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd");
  1139.                
  1140.                 #endif // FASTLOOP
  1141.                
  1142.                 // no pending char at this point
  1143.                 ch = 0;
  1144.             }
  1145.            
  1146.             // Do we have to set the encoder bytes?
  1147.             if (encoder != null) {
  1148.                 BCLDebug.Assert(!encoder.MustFlush || ch == 0, "[UTF8Encoding.GetBytes] Expected no mustflush or 0 leftover ch " + ch.ToString("X2", CultureInfo.InvariantCulture));
  1149.                
  1150.                 encoder.surrogateChar = ch;
  1151.                 encoder.m_charsUsed = (int)(pSrc - chars);
  1152.             }
  1153.            
  1154.             BCLDebug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || baseEncoder == null || !baseEncoder.m_throwOnOverflow, "[UTF8Encoding.GetBytes]Expected empty fallback buffer if not converting");
  1155.            
  1156.             return (int)(pTarget - bytes);
  1157.         }
  1158.        
  1159.        
  1160.         // These are bitmasks used to maintain the state in the decoder. They occupy the higher bits
  1161.         // while the actual character is being built in the lower bits. They are shifted together
  1162.         // with the actual bits of the character.
  1163.        
  1164.         // bits 30 & 31 are used for pending bits fixup
  1165.         private const int FinalByte = 1 << 29;
  1166.         private const int SupplimentarySeq = 1 << 28;
  1167.         private const int ThreeByteSeq = 1 << 27;
  1168.        
  1169.         // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms.
  1170.         // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates.
  1171.         //
  1172.         // To simplify maintenance, the structure of GetCharCount and GetChars should be
  1173.         // kept the same as much as possible
  1174.         unsafe internal override int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
  1175.         {
  1176.             BCLDebug.Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0");
  1177.             BCLDebug.Assert(bytes != null, "[UTF8Encoding.GetCharCount]bytes!=null");
  1178.            
  1179.             // Initialize stuff
  1180.             byte* pSrc = bytes;
  1181.             byte* pEnd = pSrc + count;
  1182.            
  1183.             // Start by assuming we have as many as count, charCount always includes the adjustment
  1184.             // for the character being decoded
  1185.             int charCount = count;
  1186.             int ch = 0;
  1187.             DecoderFallbackBuffer fallback = null;
  1188.            
  1189.             if (baseDecoder != null) {
  1190.                 UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
  1191.                 ch = decoder.bits;
  1192.                 charCount -= (ch >> 30);
  1193.                 // Adjust char count for # of expected bytes and expected output chars.
  1194.                 // Shouldn't have anything in fallback buffer for GetCharCount
  1195.                 // (don't have to check m_throwOnOverflow for count)
  1196.                 BCLDebug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at start");
  1197.             }
  1198.            
  1199.             for (;;) {
  1200.                 // SLOWLOOP: does all range checks, handles all special cases, but it is slow
  1201.                
  1202.                 if (pSrc >= pEnd) {
  1203.                     break;
  1204.                 }
  1205.                
  1206.                 if (ch == 0) {
  1207.                     // no pending bits
  1208.                     goto ReadChar;
  1209.                 }
  1210.                
  1211.                 // read next byte. The JIT optimization seems to be getting confused when
  1212.                 // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
  1213.                 int cha = *pSrc;
  1214.                 pSrc++;
  1215.                
  1216.                 // we are expecting to see trailing bytes like 10vvvvvv
  1217.                 if ((cha & unchecked((sbyte)192)) != 128) {
  1218.                     // This can be a valid starting byte for another UTF8 byte sequence, so let's put
  1219.                     // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
  1220.                     pSrc--;
  1221.                     charCount += (ch >> 30);
  1222.                     goto InvalidByteSequence;
  1223.                 }
  1224.                
  1225.                 // fold in the new byte
  1226.                 ch = (ch << 6) | (cha & 63);
  1227.                
  1228.                 if ((ch & FinalByte) == 0) {
  1229.                     BCLDebug.Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, "[UTF8Encoding.GetChars]Invariant volation");
  1230.                    
  1231.                     if ((ch & SupplimentarySeq) != 0) {
  1232.                         if ((ch & (FinalByte >> 6)) != 0) {
  1233.                             // this is 3rd byte (of 4 byte supplimentary) - nothing to do
  1234.                             continue;
  1235.                         }
  1236.                        
  1237.                         // 2nd byte, check for non-shortest form of supplimentary char and the valid
  1238.                         // supplimentary characters in range 0x010000 - 0x10FFFF at the same time
  1239.                         if (!InRange(ch & 496, 16, 256)) {
  1240.                             goto InvalidByteSequence;
  1241.                         }
  1242.                     }
  1243.                     else {
  1244.                         // Must be 2nd byte of a 3-byte sequence
  1245.                         // check for non-shortest form of 3 byte seq
  1246.                         // non-shortest form
  1247.                         // illegal individually encoded surrogate
  1248.                         if ((ch & (31 << 5)) == 0 || (ch & (63488 >> 6)) == (55296 >> 6)) {
  1249.                             goto InvalidByteSequence;
  1250.                         }
  1251.                     }
  1252.                     continue;
  1253.                 }
  1254.                
  1255.                 // ready to punch
  1256.                
  1257.                 // adjust for surrogates in non-shortest form
  1258.                 if ((ch & (SupplimentarySeq | 2031616)) == SupplimentarySeq) {
  1259.                     charCount--;
  1260.                 }
  1261.                 goto EncodeChar;
  1262.                 InvalidByteSequence:
  1263.                
  1264.                 // this code fragment should be close to the gotos referencing it
  1265.                 // Have to do fallback for invalid bytes
  1266.                 if (fallback == null) {
  1267.                     if (baseDecoder == null)
  1268.                         fallback = this.decoderFallback.CreateFallbackBuffer();
  1269.                     else
  1270.                         fallback = baseDecoder.FallbackBuffer;
  1271.                     fallback.InternalInitialize(bytes, null);
  1272.                 }
  1273.                 charCount += FallbackInvalidByteSequence(pSrc, ch, fallback);
  1274.                
  1275.                 ch = 0;
  1276.                 continue;
  1277.                 ReadChar:
  1278.                
  1279.                 ch = *pSrc;
  1280.                 pSrc++;
  1281.                 ProcessChar:
  1282.                
  1283.                 if (ch > 127) {
  1284.                     // If its > 0x7F, its start of a new multi-byte sequence
  1285.                    
  1286.                     // Long sequence, so unreserve our char.
  1287.                     charCount--;
  1288.                    
  1289.                     // bit 6 has to be non-zero for start of multibyte chars.
  1290.                     if ((ch & 64) == 0) {
  1291.                         // Unexpected trail byte
  1292.                         goto InvalidByteSequence;
  1293.                     }
  1294.                    
  1295.                     // start a new long code
  1296.                     if ((ch & 32) != 0) {
  1297.                         if ((ch & 16) != 0) {
  1298.                             // 4 byte encoding - supplimentary character (2 surrogates)
  1299.                            
  1300.                             ch &= 15;
  1301.                            
  1302.                             // check that bit 4 is zero and the valid supplimentary character
  1303.                             // range 0x000000 - 0x10FFFF at the same time
  1304.                             if (ch > 4) {
  1305.                                 ch |= 240;
  1306.                                 goto InvalidByteSequence;
  1307.                             }
  1308.                            
  1309.                             // Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
  1310.                             // Final byte flag, count fix if we don't make final byte & supplimentary sequence flag.
  1311.                                 // Final byte is 3 more bytes from now
  1312.                                 // If it dies on next byte we'll need an extra char
  1313.                                 // If it dies on last byte we'll need to subtract a char
  1314.                             ch |= (FinalByte >> 3 * 6) | (1 << 30) | (3 << (30 - 2 * 6)) | (SupplimentarySeq) | (SupplimentarySeq >> 6) | (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6);
  1315.                            
  1316.                             // Our character count will be 2 characters for these 4 bytes, so subtract another char
  1317.                             charCount--;
  1318.                         }
  1319.                         else {
  1320.                             // 3 byte encoding
  1321.                             // Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
  1322.                             ch = (ch & 15) | ((FinalByte >> 2 * 6) | (1 << 30) | (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6));
  1323.                            
  1324.                             // We'll expect 1 character for these 3 bytes, so subtract another char.
  1325.                             charCount--;
  1326.                         }
  1327.                     }
  1328.                     else {
  1329.                         // 2 byte encoding
  1330.                        
  1331.                         ch &= 31;
  1332.                        
  1333.                         // check for non-shortest form
  1334.                         if (ch <= 1) {
  1335.                             ch |= 192;
  1336.                             goto InvalidByteSequence;
  1337.                         }
  1338.                        
  1339.                         // Add bit flags so we'll be flagged correctly
  1340.                         ch |= (FinalByte >> 6);
  1341.                     }
  1342.                     continue;
  1343.                 }
  1344.                 EncodeChar:
  1345.                
  1346.                
  1347.                 #if FASTLOOP
  1348.                 int availableBytes = PtrDiff(pEnd, pSrc);
  1349.                
  1350.                 // don't fall into the fast decoding loop if we don't have enough bytes
  1351.                 if (availableBytes <= 13) {
  1352.                     // try to get over the remainder of the ascii characters fast though
  1353.                     byte* pLocalEnd = pEnd;
  1354.                     // hint to get pLocalEnd enregistered
  1355.                     while (pSrc < pLocalEnd) {
  1356.                         ch = *pSrc;
  1357.                         pSrc++;
  1358.                        
  1359.                         if (ch > 127)
  1360.                             goto ProcessChar;
  1361.                     }
  1362.                     // we are done
  1363.                     ch = 0;
  1364.                     break;
  1365.                 }
  1366.                
  1367.                 // To compute the upper bound, assume that all characters are ASCII characters at this point,
  1368.                 // the boundary will be decreased for every non-ASCII character we encounter
  1369.                 // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
  1370.                 byte* pStop = pSrc + availableBytes - 7;
  1371.                
  1372.                 while (pSrc < pStop) {
  1373.                     ch = *pSrc;
  1374.                     pSrc++;
  1375.                    
  1376.                     if (ch > 127) {
  1377.                         goto LongCode;
  1378.                     }
  1379.                    
  1380.                     // get pSrc 2-byte aligned
  1381.                     if ((unchecked((int)pSrc) & 1) != 0) {
  1382.                         ch = *pSrc;
  1383.                         pSrc++;
  1384.                         if (ch > 127) {
  1385.                             goto LongCode;
  1386.                         }
  1387.                     }
  1388.                    
  1389.                     // get pSrc 4-byte aligned
  1390.                     if ((unchecked((int)pSrc) & 2) != 0) {
  1391.                         ch = *(ushort*)pSrc;
  1392.                         if ((ch & 32896) != 0) {
  1393.                             goto LongCodeWithMask16;
  1394.                         }
  1395.                         pSrc += 2;
  1396.                     }
  1397.                    
  1398.                     // Run 8 + 8 characters at a time!
  1399.                     while (pSrc < pStop) {
  1400.                         ch = *(int*)pSrc;
  1401.                         int chb = *(int*)(pSrc + 4);
  1402.                         if (((ch | chb) & unchecked((int)2155905152u)) != 0) {
  1403.                             goto LongCodeWithMask32;
  1404.                         }
  1405.                         pSrc += 8;
  1406.                        
  1407.                         // This is a really small loop - unroll it
  1408.                         if (pSrc >= pStop)
  1409.                             break;
  1410.                        
  1411.                         ch = *(int*)pSrc;
  1412.                         chb = *(int*)(pSrc + 4);
  1413.                         if (((ch | chb) & unchecked((int)2155905152u)) != 0) {
  1414.                             goto LongCodeWithMask32;
  1415.                         }
  1416.                         pSrc += 8;
  1417.                     }
  1418.                     break;
  1419.                     LongCodeWithMask32:
  1420.                    
  1421.                     #if BIGENDIAN
  1422.                     // be careful about the sign extension
  1423.                     ch = (int)(((uint)ch) >> 16);
  1424.                     LongCodeWithMask16:
  1425.                     ch = (int)(((uint)ch) >> 8);
  1426.                     LongCodeWithMask32:
  1427.                     LongCodeWithMask16:
  1428.                     #else // BIGENDIAN
  1429.                     ch &= 255;
  1430.                     #endif // BIGENDIAN
  1431.                     pSrc++;
  1432.                     if (ch <= 127) {
  1433.                         continue;
  1434.                     }
  1435.                     LongCode:
  1436.                    
  1437.                     int chc = *pSrc;
  1438.                     pSrc++;
  1439.                    
  1440.                     // bit 6 has to be zero
  1441.                     // we are expecting to see trailing bytes like 10vvvvvv
  1442.                     if ((ch & 64) == 0 || (chc & unchecked((sbyte)192)) != 128) {
  1443.                         goto BadLongCode;
  1444.                     }
  1445.                    
  1446.                     chc &= 63;
  1447.                    
  1448.                     // start a new long code
  1449.                     if ((ch & 32) != 0) {
  1450.                        
  1451.                         // fold the first two bytes together
  1452.                         chc |= (ch & 15) << 6;
  1453.                        
  1454.                         if ((ch & 16) != 0) {
  1455.                             // 4 byte encoding - surrogate
  1456.                             ch = *pSrc;
  1457.                             // check that bit 4 is zero, the non-shortest form of surrogate
  1458.                             // and the valid surrogate range 0x000000 - 0x10FFFF at the same time
  1459.                             // we are expecting to see trailing bytes like 10vvvvvv
  1460.                             if (!InRange(chc >> 4, 1, 16) || (ch & unchecked((sbyte)192)) != 128) {
  1461.                                 goto BadLongCode;
  1462.                             }
  1463.                            
  1464.                             chc = (chc << 6) | (ch & 63);
  1465.                            
  1466.                             ch = *(pSrc + 1);
  1467.                             // we are expecting to see trailing bytes like 10vvvvvv
  1468.                             if ((ch & unchecked((sbyte)192)) != 128) {
  1469.                                 goto BadLongCode;
  1470.                             }
  1471.                             pSrc += 2;
  1472.                            
  1473.                             // extra byte
  1474.                             charCount--;
  1475.                         }
  1476.                         else {
  1477.                             // 3 byte encoding
  1478.                             ch = *pSrc;
  1479.                             // check for non-shortest form of 3 byte seq
  1480.                             // Can't have surrogates here.
  1481.                             // we are expecting to see trailing bytes like 10vvvvvv
  1482.                             if ((chc & (31 << 5)) == 0 || (chc & (63488 >> 6)) == (55296 >> 6) || (ch & unchecked((sbyte)192)) != 128) {
  1483.                                 goto BadLongCode;
  1484.                             }
  1485.                             pSrc++;
  1486.                            
  1487.                             // extra byte
  1488.                             charCount--;
  1489.                         }
  1490.                     }
  1491.                     else {
  1492.                         // 2 byte encoding
  1493.                        
  1494.                         // check for non-shortest form
  1495.                         if ((ch & 30) == 0) {
  1496.                             goto BadLongCode;
  1497.                         }
  1498.                     }
  1499.                    
  1500.                     // extra byte
  1501.                     charCount--;
  1502.                 }
  1503.                 #endif // FASTLOOP
  1504.                
  1505.                 // no pending bits at this point
  1506.                 ch = 0;
  1507.                 continue;
  1508.                 BadLongCode:
  1509.                
  1510.                 pSrc -= 2;
  1511.                 ch = 0;
  1512.                 continue;
  1513.             }
  1514.            
  1515.             // May have a problem if we have to flush
  1516.             if (ch != 0) {
  1517.                 // We were already adjusting for these, so need to unadjust
  1518.                 charCount += (ch >> 30);
  1519.                 if (baseDecoder == null || baseDecoder.MustFlush) {
  1520.                     // Have to do fallback for invalid bytes
  1521.                     if (fallback == null) {
  1522.                         if (baseDecoder == null)
  1523.                             fallback = this.decoderFallback.CreateFallbackBuffer();
  1524.                         else
  1525.                             fallback = baseDecoder.FallbackBuffer;
  1526.                         fallback.InternalInitialize(bytes, null);
  1527.                     }
  1528.                     charCount += FallbackInvalidByteSequence(pSrc, ch, fallback);
  1529.                 }
  1530.             }
  1531.            
  1532.             // Shouldn't have anything in fallback buffer for GetCharCount
  1533.             // (don't have to check m_throwOnOverflow for count)
  1534.             BCLDebug.Assert(fallback == null || fallback.Remaining == 0, "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at end");
  1535.            
  1536.             return charCount;
  1537.         }
  1538.        
  1539.         //
  1540.         //
  1541.         unsafe internal override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
  1542.         {
  1543.             BCLDebug.Assert(chars != null, "[UTF8Encoding.GetChars]chars!=null");
  1544.             BCLDebug.Assert(byteCount >= 0, "[UTF8Encoding.GetChars]count >=0");
  1545.             BCLDebug.Assert(charCount >= 0, "[UTF8Encoding.GetChars]charCount >=0");
  1546.             BCLDebug.Assert(bytes != null, "[UTF8Encoding.GetChars]bytes!=null");
  1547.            
  1548.             byte* pSrc = bytes;
  1549.             char* pTarget = chars;
  1550.            
  1551.             byte* pEnd = pSrc + byteCount;
  1552.             char* pAllocatedBufferEnd = pTarget + charCount;
  1553.            
  1554.             int ch = 0;
  1555.            
  1556.             DecoderFallbackBuffer fallback = null;
  1557.             if (baseDecoder != null) {
  1558.                 UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
  1559.                 ch = decoder.bits;
  1560.                
  1561.                 // Shouldn't have anything in fallback buffer for GetChars
  1562.                 // (don't have to check m_throwOnOverflow for chars, we always use all or none so always should be empty)
  1563.                 BCLDebug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[UTF8Encoding.GetChars]Expected empty fallback buffer at start");
  1564.             }
  1565.            
  1566.             for (;;) {
  1567.                 // SLOWLOOP: does all range checks, handles all special cases, but it is slow
  1568.                
  1569.                 if (pSrc >= pEnd) {
  1570.                     break;
  1571.                 }
  1572.                
  1573.                 if (ch == 0) {
  1574.                     // no pending bits
  1575.                     goto ReadChar;
  1576.                 }
  1577.                
  1578.                 // read next byte. The JIT optimization seems to be getting confused when
  1579.                 // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
  1580.                 int cha = *pSrc;
  1581.                 pSrc++;
  1582.                
  1583.                 // we are expecting to see trailing bytes like 10vvvvvv
  1584.                 if ((cha & unchecked((sbyte)192)) != 128) {
  1585.                     // This can be a valid starting byte for another UTF8 byte sequence, so let's put
  1586.                     // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
  1587.                     pSrc--;
  1588.                     goto InvalidByteSequence;
  1589.                 }
  1590.                
  1591.                 // fold in the new byte
  1592.                 ch = (ch << 6) | (cha & 63);
  1593.                
  1594.                 if ((ch & FinalByte) == 0) {
  1595.                     // Not at last byte yet
  1596.                     BCLDebug.Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, "[UTF8Encoding.GetChars]Invariant volation");
  1597.                    
  1598.                     if ((ch & SupplimentarySeq) != 0) {
  1599.                         // Its a 4-byte supplimentary sequence
  1600.                         if ((ch & (FinalByte >> 6)) != 0) {
  1601.                             // this is 3rd byte of 4 byte sequence - nothing to do
  1602.                             continue;
  1603.                         }
  1604.                        
  1605.                         // 2nd byte of 4 bytes
  1606.                         // check for non-shortest form of surrogate and the valid surrogate
  1607.                         // range 0x000000 - 0x10FFFF at the same time
  1608.                         if (!InRange(ch & 496, 16, 256)) {
  1609.                             goto InvalidByteSequence;
  1610.                         }
  1611.                     }
  1612.                     else {
  1613.                         // Must be 2nd byte of a 3-byte sequence
  1614.                         // check for non-shortest form of 3 byte seq
  1615.                         // non-shortest form
  1616.                         // illegal individually encoded surrogate
  1617.                         if ((ch & (31 << 5)) == 0 || (ch & (63488 >> 6)) == (55296 >> 6)) {
  1618.                             goto InvalidByteSequence;
  1619.                         }
  1620.                     }
  1621.                     continue;
  1622.                 }
  1623.                
  1624.                 // ready to punch
  1625.                
  1626.                 // surrogate in shortest form?
  1627.                 // Might be possible to get rid of this? Already did non-shortest check for 4-byte sequence when reading 2nd byte?
  1628.                 if ((ch & (SupplimentarySeq | 2031616)) > SupplimentarySeq) {
  1629.                     // let the range check for the second char throw the exception
  1630.                     if (pTarget < pAllocatedBufferEnd) {
  1631.                         *pTarget = (char)(((ch >> 10) & 2047) + unchecked((short)((CharUnicodeInfo.HIGH_SURROGATE_START - (65536 >> 10)))));
  1632.                         pTarget++;
  1633.                        
  1634.                         ch = (ch & 1023) + unchecked((int)(CharUnicodeInfo.LOW_SURROGATE_START));
  1635.                     }
  1636.                 }
  1637.                
  1638.                 goto EncodeChar;
  1639.                 InvalidByteSequence:
  1640.                
  1641.                 // this code fragment should be close to the gotos referencing it
  1642.                 // Have to do fallback for invalid bytes
  1643.                 if (fallback == null) {
  1644.                     if (baseDecoder == null)
  1645.                         fallback = this.decoderFallback.CreateFallbackBuffer();
  1646.                     else
  1647.                         fallback = baseDecoder.FallbackBuffer;
  1648.                     fallback.InternalInitialize(bytes, pAllocatedBufferEnd);
  1649.                 }
  1650.                 // This'll back us up the appropriate # of bytes if we didn't get anywhere
  1651.                 if (!FallbackInvalidByteSequence(ref pSrc, ch, fallback, ref pTarget)) {
  1652.                     // Ran out of buffer space
  1653.                     // Need to throw an exception?
  1654.                     BCLDebug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer after fallback");
  1655.                     fallback.InternalReset();
  1656.                     ThrowCharsOverflow(baseDecoder, pTarget == chars);
  1657.                     ch = 0;
  1658.                     break;
  1659.                 }
  1660.                 BCLDebug.Assert(pSrc >= bytes, "[UTF8Encoding.GetChars]Expected invalid byte sequence to have remained within the byte array");
  1661.                 ch = 0;
  1662.                 continue;
  1663.                 ReadChar:
  1664.                
  1665.                 ch = *pSrc;
  1666.                 pSrc++;
  1667.                 ProcessChar:
  1668.                
  1669.                 if (ch > 127) {
  1670.                     // If its > 0x7F, its start of a new multi-byte sequence
  1671.                    
  1672.                     // bit 6 has to be non-zero
  1673.                     if ((ch & 64) == 0) {
  1674.                         goto InvalidByteSequence;
  1675.                     }
  1676.                    
  1677.                     // start a new long code
  1678.                     if ((ch & 32) != 0) {
  1679.                         if ((ch & 16) != 0) {
  1680.                             // 4 byte encoding - supplimentary character (2 surrogates)
  1681.                            
  1682.                             ch &= 15;
  1683.                            
  1684.                             // check that bit 4 is zero and the valid supplimentary character
  1685.                             // range 0x000000 - 0x10FFFF at the same time
  1686.                             if (ch > 4) {
  1687.                                 ch |= 240;
  1688.                                 goto InvalidByteSequence;
  1689.                             }
  1690.                            
  1691.                             ch |= (FinalByte >> 3 * 6) | (1 << 30) | (3 << (30 - 2 * 6)) | (SupplimentarySeq) | (SupplimentarySeq >> 6) | (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6);
  1692.                         }
  1693.                         else {
  1694.                             // 3 byte encoding
  1695.                             ch = (ch & 15) | ((FinalByte >> 2 * 6) | (1 << 30) | (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6));
  1696.                         }
  1697.                     }
  1698.                     else {
  1699.                         // 2 byte encoding
  1700.                        
  1701.                         ch &= 31;
  1702.                        
  1703.                         // check for non-shortest form
  1704.                         if (ch <= 1) {
  1705.                             ch |= 192;
  1706.                             goto InvalidByteSequence;
  1707.                         }
  1708.                        
  1709.                         ch |= (FinalByte >> 6);
  1710.                     }
  1711.                     continue;
  1712.                 }
  1713.                 EncodeChar:
  1714.                
  1715.                 // write the pending character
  1716.                 if (pTarget >= pAllocatedBufferEnd) {
  1717.                     // Fix chars so we make sure to throw if we didn't output anything
  1718.                     ch &= 2097151;
  1719.                     if (ch > 127) {
  1720.                         if (ch > 2047) {
  1721.                             if (ch >= CharUnicodeInfo.LOW_SURROGATE_START && ch <= CharUnicodeInfo.LOW_SURROGATE_END) {
  1722.                                 pSrc--;
  1723.                                 // It was 4 bytes
  1724.                                 pTarget--;
  1725.                                 // 1 was stored already, but we can't remember 1/2, so back up
  1726.                             }
  1727.                             else if (ch > 65535) {
  1728.                                 pSrc--;
  1729.                                 // It was 4 bytes, nothing was stored
  1730.                             }
  1731.                             pSrc--;
  1732.                             // It was at least 3 bytes
  1733.                         }
  1734.                         pSrc--;
  1735.                         // It was at least 2 bytes
  1736.                     }
  1737.                     pSrc--;
  1738.                    
  1739.                     // Throw that we don't have enough room (pSrc could be < chars if we had started to process
  1740.                     // a 4 byte sequence alredy)
  1741.                     BCLDebug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected pSrc to be within input buffer or throw due to no output]");
  1742.                     ThrowCharsOverflow(baseDecoder, pTarget == chars);
  1743.                    
  1744.                     // Don't store ch in decoder, we already backed up to its start
  1745.                     ch = 0;
  1746.                    
  1747.                     // Didn't throw, just use this buffer size.
  1748.                     break;
  1749.                 }
  1750.                 *pTarget = (char)ch;
  1751.                 pTarget++;
  1752.                
  1753.                 #if FASTLOOP
  1754.                 int availableChars = PtrDiff(pAllocatedBufferEnd, pTarget);
  1755.                 int availableBytes = PtrDiff(pEnd, pSrc);
  1756.                
  1757.                 // don't fall into the fast decoding loop if we don't have enough bytes
  1758.                 // Test for availableChars is done because pStop would be <= pTarget.
  1759.                 if (availableBytes <= 13) {
  1760.                     // we may need as many as 1 character per byte
  1761.                     if (availableChars < availableBytes) {
  1762.                         // not enough output room. no pending bits at this point
  1763.                         ch = 0;
  1764.                         continue;
  1765.                     }
  1766.                    
  1767.                     // try to get over the remainder of the ascii characters fast though
  1768.                     byte* pLocalEnd = pEnd;
  1769.                     // hint to get pLocalEnd enregistered
  1770.                     while (pSrc < pLocalEnd) {
  1771.                         ch = *pSrc;
  1772.                         pSrc++;
  1773.                        
  1774.                         if (ch > 127)
  1775.                             goto ProcessChar;
  1776.                        
  1777.                         *pTarget = (char)ch;
  1778.                         pTarget++;
  1779.                     }
  1780.                     // we are done
  1781.                     ch = 0;
  1782.                     break;
  1783.                 }
  1784.                
  1785.                 // we may need as many as 1 character per byte, so reduce the byte count if necessary.
  1786.                 // If availableChars is too small, pStop will be before pTarget and we won't do fast loop.
  1787.                 if (availableChars < availableBytes) {
  1788.                     availableBytes = availableChars;
  1789.                 }
  1790.                
  1791.                 // To compute the upper bound, assume that all characters are ASCII characters at this point,
  1792.                 // the boundary will be decreased for every non-ASCII character we encounter
  1793.                 // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
  1794.                 char* pStop = pTarget + availableBytes - 7;
  1795.                
  1796.                 while (pTarget < pStop) {
  1797.                     ch = *pSrc;
  1798.                     pSrc++;
  1799.                    
  1800.                     if (ch > 127) {
  1801.                         goto LongCode;
  1802.                     }
  1803.                     *pTarget = (char)ch;
  1804.                     pTarget++;
  1805.                    
  1806.                     // get pSrc to be 2-byte aligned
  1807.                     if ((unchecked((int)pSrc) & 1) != 0) {
  1808.                         ch = *pSrc;
  1809.                         pSrc++;
  1810.                         if (ch > 127) {
  1811.                             goto LongCode;
  1812.                         }
  1813.                         *pTarget = (char)ch;
  1814.                         pTarget++;
  1815.                     }
  1816.                    
  1817.                     // get pSrc to be 4-byte aligned
  1818.                     if ((unchecked((int)pSrc) & 2) != 0) {
  1819.                         ch = *(ushort*)pSrc;
  1820.                         if ((ch & 32896) != 0) {
  1821.                             goto LongCodeWithMask16;
  1822.                         }
  1823.                        
  1824.                         #if BIGENDIAN
  1825.                         *pTarget = (char)((ch >> 8) & 127);
  1826.                         pSrc += 2;
  1827.                         *(pTarget + 1) = (char)(ch & 127);
  1828.                         pTarget += 2;
  1829.                         #else // BIGENDIAN
  1830.                         *pTarget = (char)(ch & 127);
  1831.                         pSrc += 2;
  1832.                         *(pTarget + 1) = (char)((ch >> 8) & 127);
  1833.                         pTarget += 2;
  1834.                         #endif // BIGENDIAN
  1835.                     }
  1836.                    
  1837.                     // Run 8 characters at a time!
  1838.                     while (pTarget < pStop) {
  1839.                         ch = *(int*)pSrc;
  1840.                         int chb = *(int*)(pSrc + 4);
  1841.                         if (((ch | chb) & unchecked((int)2155905152u)) != 0) {
  1842.                             goto LongCodeWithMask32;
  1843.                         }
  1844.                        
  1845.                         #if BIGENDIAN
  1846.                         *pTarget = (char)((ch >> 24) & 127);
  1847.                         *(pTarget + 1) = (char)((ch >> 16) & 127);
  1848.                         *(pTarget + 2) = (char)((ch >> 8) & 127);
  1849.                         *(pTarget + 3) = (char)(ch & 127);
  1850.                         pSrc += 8;
  1851.                         *(pTarget + 4) = (char)((chb >> 24) & 127);
  1852.                         *(pTarget + 5) = (char)((chb >> 16) & 127);
  1853.                         *(pTarget + 6) = (char)((chb >> 8) & 127);
  1854.                         *(pTarget + 7) = (char)(chb & 127);
  1855.                         pTarget += 8;
  1856.                         #else // BIGENDIAN
  1857.                         *pTarget = (char)(ch & 127);
  1858.                         *(pTarget + 1) = (char)((ch >> 8) & 127);
  1859.                         *(pTarget + 2) = (char)((ch >> 16) & 127);
  1860.                         *(pTarget + 3) = (char)((ch >> 24) & 127);
  1861.                         pSrc += 8;
  1862.                         *(pTarget + 4) = (char)(chb & 127);
  1863.                         *(pTarget + 5) = (char)((chb >> 8) & 127);
  1864.                         *(pTarget + 6) = (char)((chb >> 16) & 127);
  1865.                         *(pTarget + 7) = (char)((chb >> 24) & 127);
  1866.                         pTarget += 8;
  1867.                         #endif // BIGENDIAN
  1868.                     }
  1869.                     break;
  1870.                     LongCodeWithMask32:
  1871.                    
  1872.                     #if BIGENDIAN
  1873.                     // be careful about the sign extension
  1874.                     ch = (int)(((uint)ch) >> 16);
  1875.                     LongCodeWithMask16:
  1876.                     ch = (int)(((uint)ch) >> 8);
  1877.                     LongCodeWithMask32:
  1878.                     LongCodeWithMask16:
  1879.                     #else // BIGENDIAN
  1880.                     ch &= 255;
  1881.                     #endif // BIGENDIAN
  1882.                     pSrc++;
  1883.                     if (ch <= 127) {
  1884.                         *pTarget = (char)ch;
  1885.                         pTarget++;
  1886.                         continue;
  1887.                     }
  1888.                     LongCode:
  1889.                    
  1890.                     int chc = *pSrc;
  1891.                     pSrc++;
  1892.                    
  1893.                     // bit 6 has to be zero
  1894.                     // we are expecting to see trailing bytes like 10vvvvvv
  1895.                     if ((ch & 64) == 0 || (chc & unchecked((sbyte)192)) != 128) {
  1896.                         goto BadLongCode;
  1897.                     }
  1898.                    
  1899.                     chc &= 63;
  1900.                    
  1901.                     // start a new long code
  1902.                     if ((ch & 32) != 0) {
  1903.                        
  1904.                         // fold the first two bytes together
  1905.                         chc |= (ch & 15) << 6;
  1906.                        
  1907.                         if ((ch & 16) != 0) {
  1908.                             // 4 byte encoding - surrogate
  1909.                             ch = *pSrc;
  1910.                             // check that bit 4 is zero, the non-shortest form of surrogate
  1911.                             // and the valid surrogate range 0x000000 - 0x10FFFF at the same time
  1912.                             // we are expecting to see trailing bytes like 10vvvvvv
  1913.                             if (!InRange(chc >> 4, 1, 16) || (ch & unchecked((sbyte)192)) != 128) {
  1914.                                 goto BadLongCode;
  1915.                             }
  1916.                            
  1917.                             chc = (chc << 6) | (ch & 63);
  1918.                            
  1919.                             ch = *(pSrc + 1);
  1920.                             // we are expecting to see trailing bytes like 10vvvvvv
  1921.                             if ((ch & unchecked((sbyte)192)) != 128) {
  1922.                                 goto BadLongCode;
  1923.                             }
  1924.                             pSrc += 2;
  1925.                            
  1926.                             ch = (chc << 6) | (ch & 63);
  1927.                            
  1928.                             *pTarget = (char)(((ch >> 10) & 2047) + unchecked((short)(CharUnicodeInfo.HIGH_SURROGATE_START - (65536 >> 10))));
  1929.                             pTarget++;
  1930.                            
  1931.                             ch = (ch & 1023) + unchecked((short)(CharUnicodeInfo.LOW_SURROGATE_START));
  1932.                            
  1933.                             // extra byte, we're already planning 2 chars for 2 of these bytes,
  1934.                             // but the big loop is testing the target against pStop, so we need
  1935.                             // to subtract 2 more or we risk overrunning the input. Subtract
  1936.                             // one here and one below.
  1937.                             pStop--;
  1938.                         }
  1939.                         else {
  1940.                             // 3 byte encoding
  1941.                             ch = *pSrc;
  1942.                             // check for non-shortest form of 3 byte seq
  1943.                             // Can't have surrogates here.
  1944.                             // we are expecting to see trailing bytes like 10vvvvvv
  1945.                             if ((chc & (31 << 5)) == 0 || (chc & (63488 >> 6)) == (55296 >> 6) || (ch & unchecked((sbyte)192)) != 128) {
  1946.                                 goto BadLongCode;
  1947.                             }
  1948.                             pSrc++;
  1949.                            
  1950.                             ch = (chc << 6) | (ch & 63);
  1951.                            
  1952.                             // extra byte, we're only expecting 1 char for each of these 3 bytes,
  1953.                             // but the loop is testing the target (not source) against pStop, so
  1954.                             // we need to subtract 2 more or we risk overrunning the input.
  1955.                             // Subtract 1 here and one more below
  1956.                             pStop--;
  1957.                         }
  1958.                     }
  1959.                     else {
  1960.                         // 2 byte encoding
  1961.                        
  1962.                         ch &= 31;
  1963.                        
  1964.                         // check for non-shortest form
  1965.                         if (ch <= 1) {
  1966.                             goto BadLongCode;
  1967.                         }
  1968.                         ch = (ch << 6) | chc;
  1969.                     }
  1970.                    
  1971.                     *pTarget = (char)ch;
  1972.                     pTarget++;
  1973.                    
  1974.                     // extra byte, we're only expecting 1 char for each of these 2 bytes,
  1975.                     // but the loop is testing the target (not source) against pStop.
  1976.                     // subtract an extra count from pStop so that we don't overrun the input.
  1977.                     pStop--;
  1978.                 }
  1979.                 #endif // FASTLOOP
  1980.                
  1981.                 BCLDebug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd");
  1982.                
  1983.                 // no pending bits at this point
  1984.                 ch = 0;
  1985.                 continue;
  1986.                 BadLongCode:
  1987.                
  1988.                 pSrc -= 2;
  1989.                 ch = 0;
  1990.                 continue;
  1991.             }
  1992.            
  1993.             if (ch != 0 && (baseDecoder == null || baseDecoder.MustFlush)) {
  1994.                 // Have to do fallback for invalid bytes
  1995.                 if (fallback == null) {
  1996.                     if (baseDecoder == null)
  1997.                         fallback = this.decoderFallback.CreateFallbackBuffer();
  1998.                     else
  1999.                         fallback = baseDecoder.FallbackBuffer;
  2000.                     fallback.InternalInitialize(bytes, pAllocatedBufferEnd);
  2001.                 }
  2002.                
  2003.                 // This'll back us up the appropriate # of bytes if we didn't get anywhere
  2004.                 if (!FallbackInvalidByteSequence(ref pSrc, ch, fallback, ref pTarget)) {
  2005.                     BCLDebug.Assert(pSrc >= bytes || pTarget == chars, "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer while flushing");
  2006.                    
  2007.                     // Ran out of buffer space
  2008.                     // Need to throw an exception?
  2009.                     fallback.InternalReset();
  2010.                     ThrowCharsOverflow(baseDecoder, pTarget == chars);
  2011.                 }
  2012.                 BCLDebug.Assert(pSrc >= bytes, "[UTF8Encoding.GetChars]Expected flushing invalid byte sequence to have remained within the byte array");
  2013.                 ch = 0;
  2014.             }
  2015.            
  2016.             if (baseDecoder != null) {
  2017.                 UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
  2018.                
  2019.                 // If we're storing flush data we expect all bits to be used or else
  2020.                 // we're stuck in the middle of a conversion
  2021.                 BCLDebug.Assert(!baseDecoder.MustFlush || ch == 0 || !baseDecoder.m_throwOnOverflow, "[UTF8Encoding.GetChars]Expected no must flush or no left over bits or no throw on overflow.");
  2022.                
  2023.                 // Remember our leftover bits.
  2024.                 decoder.bits = ch;
  2025.                
  2026.                 baseDecoder.m_bytesUsed = (int)(pSrc - bytes);
  2027.             }
  2028.            
  2029.             // Shouldn't have anything in fallback buffer for GetChars
  2030.             // (don't have to check m_throwOnOverflow for chars)
  2031.             BCLDebug.Assert(fallback == null || fallback.Remaining == 0, "[UTF8Encoding.GetChars]Expected empty fallback buffer at end");
  2032.            
  2033.             return PtrDiff(pTarget, chars);
  2034.         }
  2035.        
  2036.         // During GetChars we had an invalid byte sequence
  2037.         // pSrc is backed up to the start of the bad sequence if we didn't have room to
  2038.         // fall it back. Otherwise pSrc remains wher it is.
  2039.         unsafe private bool FallbackInvalidByteSequence(ref byte* pSrc, int ch, DecoderFallbackBuffer fallback, ref char* pTarget)
  2040.         {
  2041.             // Get our byte[]
  2042.             byte* pStart = pSrc;
  2043.             byte[] bytesUnknown = GetBytesUnknown(ref pStart, ch);
  2044.            
  2045.             // Do the actual fallback
  2046.             if (!fallback.InternalFallback(bytesUnknown, pSrc, ref pTarget)) {
  2047.                 // Oops, it failed, back up to pStart
  2048.                 pSrc = pStart;
  2049.                 return false;
  2050.             }
  2051.            
  2052.             // It worked
  2053.             return true;
  2054.         }
  2055.        
  2056.         // During GetCharCount we had an invalid byte sequence
  2057.         // pSrc is used to find the index that points to the invalid bytes,
  2058.         // however the byte[] contains the fallback bytes (in case the index is -1)
  2059.         unsafe private int FallbackInvalidByteSequence(byte* pSrc, int ch, DecoderFallbackBuffer fallback)
  2060.         {
  2061.             // Get our byte[]
  2062.             byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch);
  2063.            
  2064.             // Do the actual fallback
  2065.             int count = fallback.InternalFallback(bytesUnknown, pSrc);
  2066.            
  2067.             // # of fallback chars expected.
  2068.             // Note that we only get here for "long" sequences, and have already unreserved
  2069.             // the count that we prereserved for the input bytes
  2070.             return count;
  2071.         }
  2072.        
  2073.         // Note that some of these bytes may have come from a previous fallback, so we cannot
  2074.         // just decrement the pointer and use the values we read. In those cases we have
  2075.         // to regenerate the original values.
  2076.         unsafe private byte[] GetBytesUnknown(ref byte* pSrc, int ch)
  2077.         {
  2078.             // Get our byte[]
  2079.             byte[] bytesUnknown = null;
  2080.            
  2081.             // See if it was a plain char
  2082.             // (have to check >= 0 because we have all sorts of wierd bit flags)
  2083.             if (ch < 256 && ch >= 0) {
  2084.                 pSrc--;
  2085.                 bytesUnknown = new byte[] {unchecked((byte)ch)};
  2086.             }
  2087.             // See if its an unfinished 2 byte sequence
  2088.             else if ((ch & (SupplimentarySeq | ThreeByteSeq)) == 0) {
  2089.                 pSrc--;
  2090.                 bytesUnknown = new byte[] {unchecked((byte)((ch & 31) | 192))};
  2091.             }
  2092.             // So now we're either 2nd byte of 3 or 4 byte sequence or
  2093.             // we hit a non-trail byte or we ran out of space for 3rd byte of 4 byte sequence
  2094.             // 1st check if its a 4 byte sequence
  2095.             else if ((ch & SupplimentarySeq) != 0) {
  2096.                 // 3rd byte of 4 byte sequence?
  2097.                 if ((ch & (FinalByte >> 6)) != 0) {
  2098.                     // 3rd byte of 4 byte sequence
  2099.                     pSrc -= 3;
  2100.                     bytesUnknown = new byte[] {unchecked((byte)(((ch >> 12) & 7) | 240)), unchecked((byte)(((ch >> 6) & 63) | 128)), unchecked((byte)(((ch)&63) | 128))};
  2101.                 }
  2102.                 else if ((ch & (FinalByte >> 12)) != 0) {
  2103.                     // 2nd byte of a 4 byte sequence
  2104.                     pSrc -= 2;
  2105.                     bytesUnknown = new byte[] {unchecked((byte)(((ch >> 6) & 7) | 240)), unchecked((byte)(((ch)&63) | 128))};
  2106.                 }
  2107.                 else {
  2108.                     // 4th byte of a 4 byte sequence
  2109.                     pSrc--;
  2110.                     bytesUnknown = new byte[] {unchecked((byte)(((ch)&7) | 240))};
  2111.                 }
  2112.             }
  2113.             else {
  2114.                 // 2nd byte of 3 byte sequence?
  2115.                 if ((ch & (FinalByte >> 6)) != 0) {
  2116.                     // So its 2nd byte of a 3 byte sequence
  2117.                     pSrc -= 2;
  2118.                     bytesUnknown = new byte[] {unchecked((byte)(((ch >> 6) & 15) | 224)), unchecked((byte)(((ch)&63) | 128))};
  2119.                 }
  2120.                 else {
  2121.                     // 1st byte of a 3 byte sequence
  2122.                     pSrc--;
  2123.                     bytesUnknown = new byte[] {unchecked((byte)(((ch)&15) | 224))};
  2124.                 }
  2125.             }
  2126.            
  2127.             return bytesUnknown;
  2128.         }
  2129.        
  2130.        
  2131.         public override Decoder GetDecoder()
  2132.         {
  2133.             return new UTF8Decoder(this);
  2134.         }
  2135.        
  2136.        
  2137.         public override Encoder GetEncoder()
  2138.         {
  2139.             return new UTF8Encoder(this);
  2140.         }
  2141.        
  2142.        
  2143.         public override int GetMaxByteCount(int charCount)
  2144.         {
  2145.             if (charCount < 0)
  2146.                 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  2147.            
  2148.             // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
  2149.             long byteCount = (long)charCount + 1;
  2150.            
  2151.             if (EncoderFallback.MaxCharCount > 1)
  2152.                 byteCount *= EncoderFallback.MaxCharCount;
  2153.            
  2154.             // Max 3 bytes per char. (4 bytes per 2 chars for surrogates)
  2155.             byteCount *= 3;
  2156.            
  2157.             if (byteCount > 2147483647)
  2158.                 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
  2159.            
  2160.             return (int)byteCount;
  2161.         }
  2162.        
  2163.        
  2164.         public override int GetMaxCharCount(int byteCount)
  2165.         {
  2166.             if (byteCount < 0)
  2167.                 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  2168.            
  2169.             // Figure out our length, 1 char per input byte + 1 char if 1st byte is last byte of 4 byte surrogate pair
  2170.             long charCount = ((long)byteCount + 1);
  2171.            
  2172.             // Non-shortest form would fall back, so get max count from fallback.
  2173.             // So would 11... followed by 11..., so you could fall back every byte
  2174.             if (DecoderFallback.MaxCharCount > 1) {
  2175.                 charCount *= DecoderFallback.MaxCharCount;
  2176.             }
  2177.            
  2178.             if (charCount > 2147483647)
  2179.                 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
  2180.            
  2181.             return (int)charCount;
  2182.         }
  2183.        
  2184.        
  2185.         public override byte[] GetPreamble()
  2186.         {
  2187.             if (emitUTF8Identifier) {
  2188.                 // Allocate new array to prevent users from modifying it.
  2189.                 return new byte[3] {239, 187, 191};
  2190.             }
  2191.             else
  2192.                 return Encoding.emptyByteArray;
  2193.         }
  2194.        
  2195.        
  2196.         public override bool Equals(object value)
  2197.         {
  2198.             UTF8Encoding that = value as UTF8Encoding;
  2199.             if (that != null) {
  2200.                     // (isThrowException == that.isThrowException) && // Same as encoder/decoderfallbacks being exception
  2201.                 return (emitUTF8Identifier == that.emitUTF8Identifier) && (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback));
  2202.             }
  2203.             return (false);
  2204.         }
  2205.        
  2206.        
  2207.         public override int GetHashCode()
  2208.         {
  2209.             //Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
  2210.             return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() + UTF8_CODEPAGE + (emitUTF8Identifier ? 1 : 0);
  2211.         }
  2212.        
  2213.         [Serializable()]
  2214.         internal class UTF8Encoder : EncoderNLS, ISerializable
  2215.         {
  2216.             // We must save a high surrogate value until the next call, looking
  2217.             // for a low surrogate value.
  2218.             internal int surrogateChar;
  2219.            
  2220.             public UTF8Encoder(UTF8Encoding encoding) : base(encoding)
  2221.             {
  2222.                 // base calls reset
  2223.             }
  2224.            
  2225.             internal UTF8Encoder(SerializationInfo info, StreamingContext context)
  2226.             {
  2227.                 // Any info?
  2228.                 if (info == null)
  2229.                     throw new ArgumentNullException("info");
  2230.                
  2231.                 // Get common info
  2232.                 this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
  2233.                
  2234.                 // SurrogateChar happens to mean the same thing
  2235.                 this.surrogateChar = (int)info.GetValue("surrogateChar", typeof(int));
  2236.                
  2237.                 try {
  2238.                     this.m_fallback = (EncoderFallback)info.GetValue("m_fallback", typeof(EncoderFallback));
  2239.                 }
  2240.                 catch (SerializationException) {
  2241.                     this.m_fallback = null;
  2242.                 }
  2243.             }
  2244.            
  2245.             // ISerializable implementation, get data for this object
  2246.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  2247.             void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  2248.             {
  2249.                 // Any info?
  2250.                 if (info == null)
  2251.                     throw new ArgumentNullException("info");
  2252.                
  2253.                 info.AddValue("encoding", this.m_encoding);
  2254.                 info.AddValue("surrogateChar", this.surrogateChar);
  2255.                
  2256.                 info.AddValue("m_fallback", this.m_fallback);
  2257.                
  2258.                 info.AddValue("storedSurrogate", this.surrogateChar > 0 ? true : false);
  2259.                 info.AddValue("mustFlush", false);
  2260.             }
  2261.            
  2262.            
  2263.             public override void Reset()
  2264.             {
  2265.                 this.surrogateChar = 0;
  2266.                 if (m_fallbackBuffer != null)
  2267.                     m_fallbackBuffer.Reset();
  2268.             }
  2269.            
  2270.             // Anything left in our encoder?
  2271.             internal override bool HasState {
  2272.                 get { return (this.surrogateChar != 0); }
  2273.             }
  2274.         }
  2275.        
  2276.         [Serializable()]
  2277.         internal class UTF8Decoder : DecoderNLS, ISerializable
  2278.         {
  2279.             // We'll need to remember the previous information. See the comments around definition
  2280.             // of FinalByte for details.
  2281.             internal int bits;
  2282.            
  2283.             public UTF8Decoder(UTF8Encoding encoding) : base(encoding)
  2284.             {
  2285.                 // base calls reset
  2286.             }
  2287.            
  2288.             internal UTF8Decoder(SerializationInfo info, StreamingContext context)
  2289.             {
  2290.                 // Any info?
  2291.                 if (info == null)
  2292.                     throw new ArgumentNullException("info");
  2293.                
  2294.                 // Get common info
  2295.                 this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
  2296.                
  2297.                 try {
  2298.                     this.bits = (int)info.GetValue("wbits", typeof(int));
  2299.                     this.m_fallback = (DecoderFallback)info.GetValue("m_fallback", typeof(DecoderFallback));
  2300.                 }
  2301.                 catch (SerializationException) {
  2302.                     this.bits = 0;
  2303.                     this.m_fallback = null;
  2304.                 }
  2305.             }
  2306.            
  2307.             // ISerializable implementation, get data for this object
  2308.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  2309.             void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  2310.             {
  2311.                 // Any info?
  2312.                 if (info == null)
  2313.                     throw new ArgumentNullException("info");
  2314.                
  2315.                 info.AddValue("encoding", this.m_encoding);
  2316.                 info.AddValue("wbits", this.bits);
  2317.                 info.AddValue("m_fallback", this.m_fallback);
  2318.                
  2319.                 info.AddValue("bits", (int)0);
  2320.                 info.AddValue("trailCount", (int)0);
  2321.                 info.AddValue("isSurrogate", false);
  2322.                 info.AddValue("byteSequence", (int)0);
  2323.             }
  2324.            
  2325.             public override void Reset()
  2326.             {
  2327.                 this.bits = 0;
  2328.                 if (m_fallbackBuffer != null)
  2329.                     m_fallbackBuffer.Reset();
  2330.             }
  2331.            
  2332.             // Anything left in our decoder?
  2333.             internal override bool HasState {
  2334.                 get { return (this.bits != 0); }
  2335.             }
  2336.         }
  2337.     }
  2338. }

Developer Fusion