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

  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. //
  16. // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
  17. //
  18. namespace System.Text
  19. {
  20.    
  21.     using System;
  22.     using System.Globalization;
  23.     // Encodes text into and out of UTF-32. UTF-32 is a way of writing
  24.     // Unicode characters with a single storage unit (32 bits) per character,
  25.     //
  26.     // The UTF-32 byte order mark is simply the Unicode byte order mark
  27.     // (0x00FEFF) written in UTF-32 (0x0000FEFF or 0xFFFE0000). The byte order
  28.     // mark is used mostly to distinguish UTF-32 text from other encodings, and doesn't
  29.     // switch the byte orderings.
  30.    
  31.     [Serializable()]
  32.     public sealed class UTF32Encoding : Encoding
  33.     {
  34. /*
  35.             words  bits    UTF-32 representation
  36.             -----  ----    -----------------------------------
  37.             1      16      00000000 00000000 xxxxxxxx xxxxxxxx
  38.             2      21      00000000 000xxxxx hhhhhhll llllllll
  39.             -----  ----    -----------------------------------
  40.             Surrogate:
  41.             Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
  42.         */       
  43.        
  44.         //
  45.         private bool emitUTF32ByteOrderMark = false;
  46.         private bool isThrowException = false;
  47.         private bool bigEndian = false;
  48.        
  49.        
  50.         public UTF32Encoding() : this(false, true, false)
  51.         {
  52.         }
  53.        
  54.        
  55.         public UTF32Encoding(bool bigEndian, bool byteOrderMark) : this(bigEndian, byteOrderMark, false)
  56.         {
  57.         }
  58.        
  59.        
  60.         public UTF32Encoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidCharacters) : base(bigEndian ? 12001 : 12000)
  61.         {
  62.             this.bigEndian = bigEndian;
  63.             this.emitUTF32ByteOrderMark = byteOrderMark;
  64.             this.isThrowException = throwOnInvalidCharacters;
  65.            
  66.             if (this.isThrowException)
  67.                 SetDefaultFallbacks();
  68.         }
  69.        
  70.         internal override void SetDefaultFallbacks()
  71.         {
  72.             // For UTF-X encodings, we use a replacement fallback with an empty string
  73.             if (this.isThrowException) {
  74.                 this.encoderFallback = EncoderFallback.ExceptionFallback;
  75.                 this.decoderFallback = DecoderFallback.ExceptionFallback;
  76.             }
  77.             else {
  78.                 this.encoderFallback = new EncoderReplacementFallback(String.Empty);
  79.                 this.decoderFallback = new DecoderReplacementFallback(String.Empty);
  80.             }
  81.         }
  82.        
  83.        
  84.         //
  85.        
  86.         //
  87.        
  88.         unsafe public override int GetByteCount(char[] chars, int index, int count)
  89.         {
  90.             // Validate input parameters
  91.             if (chars == null)
  92.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  93.            
  94.             if (index < 0 || count < 0)
  95.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  96.            
  97.             if (chars.Length - index < count)
  98.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  99.            
  100.             // If no input, return 0, avoid fixed empty array problem
  101.             if (chars.Length == 0)
  102.                 return 0;
  103.            
  104.             // Just call the pointer version
  105.             fixed (char* pChars = chars)
  106.                 return GetByteCount(pChars + index, count, null);
  107.         }
  108.        
  109.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  110.         // So if you fix this, fix the others. Currently those include:
  111.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  112.         // parent method is safe
  113.        
  114.         unsafe public override int GetByteCount(string s)
  115.         {
  116.             // Validate input
  117.             if (s == null)
  118.                 throw new ArgumentNullException("s");
  119.            
  120.             fixed (char* pChars = s)
  121.                 return GetByteCount(pChars, s.Length, null);
  122.         }
  123.        
  124.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  125.         // So if you fix this, fix the others. Currently those include:
  126.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  127.        
  128.         [CLSCompliant(false)]
  129.         unsafe public override int GetByteCount(char* chars, int count)
  130.         {
  131.             // Validate Parameters
  132.             if (chars == null)
  133.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  134.            
  135.             if (count < 0)
  136.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  137.            
  138.             // Call it with empty encoder
  139.             return GetByteCount(chars, count, null);
  140.         }
  141.        
  142.         // Parent method is safe.
  143.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  144.         // So if you fix this, fix the others. Currently those include:
  145.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  146.        
  147.         unsafe public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
  148.         {
  149.             if (s == null || bytes == null)
  150.                 throw new ArgumentNullException((s == null ? "s" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  151.            
  152.             if (charIndex < 0 || charCount < 0)
  153.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  154.            
  155.             if (s.Length - charIndex < charCount)
  156.                 throw new ArgumentOutOfRangeException("s", Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
  157.            
  158.             if (byteIndex < 0 || byteIndex > bytes.Length)
  159.                 throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  160.            
  161.             int byteCount = bytes.Length - byteIndex;
  162.            
  163.             // Fix our input array if 0 length because fixed doesn't like 0 length arrays
  164.             if (bytes.Length == 0)
  165.                 bytes = new byte[1];
  166.            
  167.             fixed (char* pChars = s)
  168.                 fixed (byte* pBytes = bytes)
  169.                     return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
  170.         }
  171.        
  172.         // Encodes a range of characters in a character array into a range of bytes
  173.         // in a byte array. An exception occurs if the byte array is not large
  174.         // enough to hold the complete encoding of the characters. The
  175.         // GetByteCount method can be used to determine the exact number of
  176.         // bytes that will be produced for a given range of characters.
  177.         // Alternatively, the GetMaxByteCount method can be used to
  178.         // determine the maximum number of bytes that will be produced for a given
  179.         // number of characters, regardless of the actual character values.
  180.         //
  181.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  182.         // So if you fix this, fix the others. Currently those include:
  183.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  184.         // parent method is safe
  185.        
  186.         unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
  187.         {
  188.             // Validate parameters
  189.             if (chars == null || bytes == null)
  190.                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  191.            
  192.             if (charIndex < 0 || charCount < 0)
  193.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  194.            
  195.             if (chars.Length - charIndex < charCount)
  196.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  197.            
  198.             if (byteIndex < 0 || byteIndex > bytes.Length)
  199.                 throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  200.            
  201.             // If nothing to encode return 0, avoid fixed problem
  202.             if (chars.Length == 0)
  203.                 return 0;
  204.            
  205.             // Just call pointer version
  206.             int byteCount = bytes.Length - byteIndex;
  207.            
  208.             // Fix our input array if 0 length because fixed doesn't like 0 length arrays
  209.             if (bytes.Length == 0)
  210.                 bytes = new byte[1];
  211.            
  212.             fixed (char* pChars = chars)
  213.                 fixed (byte* pBytes = bytes)
  214.                 // Remember that byteCount is # to decode, not size of array.
  215.                     return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null);
  216.         }
  217.        
  218.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  219.         // So if you fix this, fix the others. Currently those include:
  220.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  221.        
  222.         [CLSCompliant(false)]
  223.         unsafe public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
  224.         {
  225.             // Validate Parameters
  226.             if (bytes == null || chars == null)
  227.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  228.            
  229.             if (charCount < 0 || byteCount < 0)
  230.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  231.            
  232.             return GetBytes(chars, charCount, bytes, byteCount, null);
  233.         }
  234.        
  235.         // Returns the number of characters produced by decoding a range of bytes
  236.         // in a byte array.
  237.         //
  238.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  239.         // So if you fix this, fix the others. Currently those include:
  240.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  241.         // parent method is safe
  242.        
  243.         unsafe public override int GetCharCount(byte[] bytes, int index, int count)
  244.         {
  245.             // Validate Parameters
  246.             if (bytes == null)
  247.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  248.            
  249.             if (index < 0 || count < 0)
  250.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  251.            
  252.             if (bytes.Length - index < count)
  253.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  254.            
  255.             // If no input just return 0, fixed doesn't like 0 length arrays.
  256.             if (bytes.Length == 0)
  257.                 return 0;
  258.            
  259.             // Just call pointer version
  260.             fixed (byte* pBytes = bytes)
  261.                 return GetCharCount(pBytes + index, count, null);
  262.         }
  263.        
  264.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  265.         // So if you fix this, fix the others. Currently those include:
  266.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  267.        
  268.         [CLSCompliant(false)]
  269.         unsafe public override int GetCharCount(byte* bytes, int count)
  270.         {
  271.             // Validate Parameters
  272.             if (bytes == null)
  273.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  274.            
  275.             if (count < 0)
  276.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  277.            
  278.             return GetCharCount(bytes, count, null);
  279.         }
  280.        
  281.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  282.         // So if you fix this, fix the others. Currently those include:
  283.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  284.         // parent method is safe
  285.        
  286.         unsafe public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  287.         {
  288.             // Validate Parameters
  289.             if (bytes == null || chars == null)
  290.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  291.            
  292.             if (byteIndex < 0 || byteCount < 0)
  293.                 throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  294.            
  295.             if (bytes.Length - byteIndex < byteCount)
  296.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  297.            
  298.             if (charIndex < 0 || charIndex > chars.Length)
  299.                 throw new ArgumentOutOfRangeException("charIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  300.            
  301.             // If no input, return 0 & avoid fixed problem
  302.             if (bytes.Length == 0)
  303.                 return 0;
  304.            
  305.             // Just call pointer version
  306.             int charCount = chars.Length - charIndex;
  307.            
  308.             // Fix our input array if 0 length because fixed doesn't like 0 length arrays
  309.             if (chars.Length == 0)
  310.                 chars = new char[1];
  311.            
  312.             fixed (byte* pBytes = bytes)
  313.                 fixed (char* pChars = chars)
  314.                 // Remember that charCount is # to decode, not size of array
  315.                     return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null);
  316.         }
  317.        
  318.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  319.         // So if you fix this, fix the others. Currently those include:
  320.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  321.        
  322.         [CLSCompliant(false)]
  323.         unsafe public override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
  324.         {
  325.             // Validate Parameters
  326.             if (bytes == null || chars == null)
  327.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  328.            
  329.             if (charCount < 0 || byteCount < 0)
  330.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  331.            
  332.             return GetChars(bytes, byteCount, chars, charCount, null);
  333.         }
  334.        
  335.         // Returns a string containing the decoded representation of a range of
  336.         // bytes in a byte array.
  337.         //
  338.         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
  339.         // So if you fix this, fix the others. Currently those include:
  340.         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
  341.         // parent method is safe
  342.        
  343.         unsafe public override string GetString(byte[] bytes, int index, int count)
  344.         {
  345.             // Validate Parameters
  346.             if (bytes == null)
  347.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  348.            
  349.             if (index < 0 || count < 0)
  350.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  351.            
  352.             if (bytes.Length - index < count)
  353.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  354.            
  355.             // Avoid problems with empty input buffer
  356.             if (bytes.Length == 0)
  357.                 return String.Empty;
  358.            
  359.             fixed (byte* pBytes = bytes)
  360.                 return String.CreateStringFromEncoding(pBytes + index, count, this);
  361.         }
  362.        
  363.         //
  364.         // End of standard methods copied from EncodingNLS.cs
  365.         //
  366.        
  367.         unsafe internal override int GetByteCount(char* chars, int count, EncoderNLS encoder)
  368.         {
  369.             BCLDebug.Assert(chars != null, "[UTF32Encoding.GetByteCount]chars!=null");
  370.             BCLDebug.Assert(count >= 0, "[UTF32Encoding.GetByteCount]count >=0");
  371.            
  372.             char* end = chars + count;
  373.             char* charStart = chars;
  374.             int byteCount = 0;
  375.            
  376.             char highSurrogate = '\0';
  377.            
  378.             // For fallback we may need a fallback buffer
  379.             EncoderFallbackBuffer fallbackBuffer = null;
  380.             if (encoder != null) {
  381.                 highSurrogate = encoder.charLeftOver;
  382.                 fallbackBuffer = encoder.FallbackBuffer;
  383.                
  384.                 // We mustn't have left over fallback data when counting
  385.                 if (fallbackBuffer.Remaining > 0)
  386.                     throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", this.EncodingName, encoder.Fallback.GetType()));
  387.             }
  388.             else {
  389.                 fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
  390.             }
  391.            
  392.             // Set our internal fallback interesting things.
  393.             fallbackBuffer.InternalInitialize(charStart, end, encoder, false);
  394.            
  395.             char ch;
  396.             TryAgain:
  397.            
  398.             while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < end) {
  399.                 // First unwind any fallback
  400.                 if (ch == 0) {
  401.                     // No fallback, just get next char
  402.                     ch = *chars;
  403.                     chars++;
  404.                 }
  405.                
  406.                 // Do we need a low surrogate?
  407.                 if (highSurrogate != '\0') {
  408.                     //
  409.                     // In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
  410.                     //
  411.                     if (Char.IsLowSurrogate(ch)) {
  412.                         // They're all legal
  413.                         highSurrogate = '\0';
  414.                        
  415.                         //
  416.                         // One surrogate pair will be translated into 4 bytes UTF32.
  417.                         //
  418.                        
  419.                         byteCount += 4;
  420.                         continue;
  421.                     }
  422.                    
  423.                     // We are missing our low surrogate, decrement chars and fallback the high surrogate
  424.                     // The high surrogate may have come from the encoder, but nothing else did.
  425.                     BCLDebug.Assert(chars > charStart, "[UTF32Encoding.GetByteCount]Expected chars to have advanced if no low surrogate");
  426.                     chars--;
  427.                    
  428.                     // Do the fallback
  429.                     fallbackBuffer.InternalFallback(highSurrogate, ref chars);
  430.                    
  431.                     // We're going to fallback the old high surrogate.
  432.                     highSurrogate = '\0';
  433.                     continue;
  434.                    
  435.                 }
  436.                
  437.                 // Do we have another high surrogate?
  438.                 if (Char.IsHighSurrogate(ch)) {
  439.                     //
  440.                     // We'll have a high surrogate to check next time.
  441.                     //
  442.                     highSurrogate = ch;
  443.                     continue;
  444.                 }
  445.                
  446.                 // Check for illegal characters
  447.                 if (Char.IsLowSurrogate(ch)) {
  448.                     // We have a leading low surrogate, do the fallback
  449.                     fallbackBuffer.InternalFallback(ch, ref chars);
  450.                    
  451.                     // Try again with fallback buffer
  452.                     continue;
  453.                 }
  454.                
  455.                 // We get to add the character (4 bytes UTF32)
  456.                 byteCount += 4;
  457.             }
  458.            
  459.             // May have to do our last surrogate
  460.             if ((encoder == null || encoder.MustFlush) && highSurrogate > 0) {
  461.                 // We have to do the fallback for the lonely high surrogate
  462.                 fallbackBuffer.InternalFallback(highSurrogate, ref chars);
  463.                 highSurrogate = (char)0;
  464.                 goto TryAgain;
  465.             }
  466.            
  467.             // Check for overflows.
  468.             if (byteCount < 0)
  469.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
  470.            
  471.             // Shouldn't have anything in fallback buffer for GetByteCount
  472.             // (don't have to check m_throwOnOverflow for count)
  473.             BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetByteCount]Expected empty fallback buffer at end");
  474.            
  475.             // Return our count
  476.             return byteCount;
  477.         }
  478.        
  479.         unsafe internal override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
  480.         {
  481.             BCLDebug.Assert(chars != null, "[UTF32Encoding.GetBytes]chars!=null");
  482.             BCLDebug.Assert(bytes != null, "[UTF32Encoding.GetBytes]bytes!=null");
  483.             BCLDebug.Assert(byteCount >= 0, "[UTF32Encoding.GetBytes]byteCount >=0");
  484.             BCLDebug.Assert(charCount >= 0, "[UTF32Encoding.GetBytes]charCount >=0");
  485.            
  486.             char* charStart = chars;
  487.             char* charEnd = chars + charCount;
  488.             byte* byteStart = bytes;
  489.             byte* byteEnd = bytes + byteCount;
  490.            
  491.             char highSurrogate = '\0';
  492.            
  493.             // For fallback we may need a fallback buffer
  494.             EncoderFallbackBuffer fallbackBuffer = null;
  495.             if (encoder != null) {
  496.                 highSurrogate = encoder.charLeftOver;
  497.                 fallbackBuffer = encoder.FallbackBuffer;
  498.                
  499.                 // We mustn't have left over fallback data when not converting
  500.                 if (encoder.m_throwOnOverflow && fallbackBuffer.Remaining > 0)
  501.                     throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", this.EncodingName, encoder.Fallback.GetType()));
  502.             }
  503.             else {
  504.                 fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
  505.             }
  506.            
  507.             // Set our internal fallback interesting things.
  508.             fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
  509.            
  510.             char ch;
  511.             TryAgain:
  512.            
  513.             while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < charEnd) {
  514.                 // First unwind any fallback
  515.                 if (ch == 0) {
  516.                     // No fallback, just get next char
  517.                     ch = *chars;
  518.                     chars++;
  519.                 }
  520.                
  521.                 // Do we need a low surrogate?
  522.                 if (highSurrogate != '\0') {
  523.                     //
  524.                     // In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
  525.                     //
  526.                     if (Char.IsLowSurrogate(ch)) {
  527.                         // Is it a legal one?
  528.                         uint iTemp = GetSurrogate(highSurrogate, ch);
  529.                         highSurrogate = '\0';
  530.                        
  531.                         //
  532.                         // One surrogate pair will be translated into 4 bytes UTF32.
  533.                         //
  534.                         if (bytes + 3 >= byteEnd) {
  535.                             // Don't have 4 bytes
  536.                             if (fallbackBuffer.bFallingBack) {
  537.                                 fallbackBuffer.MovePrevious();
  538.                                 // Aren't using these 2 fallback chars
  539.                                 fallbackBuffer.MovePrevious();
  540.                             }
  541.                             else {
  542.                                 // If we don't have enough room, then either we should've advanced a while
  543.                                 // or we should have bytes==byteStart and throw below
  544.                                 BCLDebug.Assert(chars > charStart + 1 || bytes == byteStart, "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair");
  545.                                 chars -= 2;
  546.                                 // Aren't using those 2 chars
  547.                             }
  548.                             ThrowBytesOverflow(encoder, bytes == byteStart);
  549.                             // Throw maybe (if no bytes written)
  550.                             highSurrogate = (char)0;
  551.                             // Nothing left over (we backed up to start of pair if supplimentary)
  552.                             break;
  553.                         }
  554.                        
  555.                         if (bigEndian) {
  556.                             *(bytes++) = (byte)(0);
  557.                             *(bytes++) = (byte)(iTemp >> 16);
  558.                             // Implies & 0xFF, which isn't needed cause high are all 0
  559.                             *(bytes++) = (byte)(iTemp >> 8);
  560.                             // Implies & 0xFF
  561.                             *(bytes++) = (byte)(iTemp);
  562.                             // Implies & 0xFF
  563.                         }
  564.                         else {
  565.                             *(bytes++) = (byte)(iTemp);
  566.                             // Implies & 0xFF
  567.                             *(bytes++) = (byte)(iTemp >> 8);
  568.                             // Implies & 0xFF
  569.                             *(bytes++) = (byte)(iTemp >> 16);
  570.                             // Implies & 0xFF, which isn't needed cause high are all 0
  571.                             *(bytes++) = (byte)(0);
  572.                         }
  573.                         continue;
  574.                     }
  575.                    
  576.                     // We are missing our low surrogate, decrement chars and fallback the high surrogate
  577.                     // The high surrogate may have come from the encoder, but nothing else did.
  578.                     BCLDebug.Assert(chars > charStart, "[UTF32Encoding.GetBytes]Expected chars to have advanced if no low surrogate");
  579.                     chars--;
  580.                    
  581.                     // Do the fallback
  582.                     fallbackBuffer.InternalFallback(highSurrogate, ref chars);
  583.                    
  584.                     // We're going to fallback the old high surrogate.
  585.                     highSurrogate = '\0';
  586.                     continue;
  587.                 }
  588.                
  589.                 // Do we have another high surrogate?, if so remember it
  590.                 if (Char.IsHighSurrogate(ch)) {
  591.                     //
  592.                     // We'll have a high surrogate to check next time.
  593.                     //
  594.                     highSurrogate = ch;
  595.                     continue;
  596.                 }
  597.                
  598.                 // Check for illegal characters (low surrogate)
  599.                 if (Char.IsLowSurrogate(ch)) {
  600.                     // We have a leading low surrogate, do the fallback
  601.                     fallbackBuffer.InternalFallback(ch, ref chars);
  602.                    
  603.                     // Try again with fallback buffer
  604.                     continue;
  605.                 }
  606.                
  607.                 // We get to add the character, yippee.
  608.                 if (bytes + 3 >= byteEnd) {
  609.                     // Don't have 4 bytes
  610.                     if (fallbackBuffer.bFallingBack)
  611.                         fallbackBuffer.MovePrevious();
  612.                     // Aren't using this fallback char
  613.                     else {
  614.                         // Must've advanced already
  615.                         BCLDebug.Assert(chars > charStart, "[UTF32Encoding.GetBytes]Expected chars to have advanced if normal character");
  616.                         chars--;
  617.                         // Aren't using this char
  618.                     }
  619.                     ThrowBytesOverflow(encoder, bytes == byteStart);
  620.                     // Throw maybe (if no bytes written)
  621.                     break;
  622.                     // Didn't throw, stop
  623.                 }
  624.                
  625.                 if (bigEndian) {
  626.                     *(bytes++) = (byte)(0);
  627.                     *(bytes++) = (byte)(0);
  628.                     *(bytes++) = (byte)((uint)ch >> 8);
  629.                     // Implies & 0xFF
  630.                     *(bytes++) = (byte)(ch);
  631.                     // Implies & 0xFF
  632.                 }
  633.                 else {
  634.                     *(bytes++) = (byte)(ch);
  635.                     // Implies & 0xFF
  636.                     *(bytes++) = (byte)((uint)ch >> 8);
  637.                     // Implies & 0xFF
  638.                     *(bytes++) = (byte)(0);
  639.                     *(bytes++) = (byte)(0);
  640.                 }
  641.             }
  642.            
  643.             // May have to do our last surrogate
  644.             if ((encoder == null || encoder.MustFlush) && highSurrogate > 0) {
  645.                 // We have to do the fallback for the lonely high surrogate
  646.                 fallbackBuffer.InternalFallback(highSurrogate, ref chars);
  647.                 highSurrogate = (char)0;
  648.                 goto TryAgain;
  649.             }
  650.            
  651.             // Fix our encoder if we have one
  652.             BCLDebug.Assert(highSurrogate == 0 || (encoder != null && !encoder.MustFlush), "[UTF32Encoding.GetBytes]Expected encoder to be flushed.");
  653.            
  654.             if (encoder != null) {
  655.                 // Remember our left over surrogate (or 0 if flushing)
  656.                 encoder.charLeftOver = highSurrogate;
  657.                
  658.                 // Need # chars used
  659.                 encoder.m_charsUsed = (int)(chars - charStart);
  660.             }
  661.            
  662.             // return the new length
  663.             return (int)(bytes - byteStart);
  664.         }
  665.        
  666.         unsafe internal override int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
  667.         {
  668.             BCLDebug.Assert(bytes != null, "[UTF32Encoding.GetCharCount]bytes!=null");
  669.             BCLDebug.Assert(count >= 0, "[UTF32Encoding.GetCharCount]count >=0");
  670.            
  671.             UTF32Decoder decoder = (UTF32Decoder)baseDecoder;
  672.            
  673.             // None so far!
  674.             int charCount = 0;
  675.             byte* end = bytes + count;
  676.             byte* byteStart = bytes;
  677.            
  678.             // Set up decoder
  679.             int readCount = 0;
  680.             uint iChar = 0;
  681.            
  682.             // For fallback we may need a fallback buffer
  683.             DecoderFallbackBuffer fallbackBuffer = null;
  684.            
  685.             // See if there's anything in our decoder
  686.             if (decoder != null) {
  687.                 readCount = decoder.readByteCount;
  688.                 iChar = (uint)decoder.iChar;
  689.                 fallbackBuffer = decoder.FallbackBuffer;
  690.                
  691.                 // Shouldn't have anything in fallback buffer for GetCharCount
  692.                 // (don't have to check m_throwOnOverflow for chars or count)
  693.                 BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at start");
  694.             }
  695.             else {
  696.                 fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
  697.             }
  698.            
  699.             // Set our internal fallback interesting things.
  700.             fallbackBuffer.InternalInitialize(byteStart, null);
  701.            
  702.             // Loop through our input, 4 characters at a time!
  703.             while (bytes < end && charCount >= 0) {
  704.                 // Get our next character
  705.                 if (bigEndian) {
  706.                     // Scoot left and add it to the bottom
  707.                     iChar <<= 8;
  708.                     iChar += *(bytes++);
  709.                 }
  710.                 else {
  711.                     // Scoot right and add it to the top
  712.                     iChar >>= 8;
  713.                     iChar += (uint)(*(bytes++)) << 24;
  714.                 }
  715.                
  716.                 readCount++;
  717.                
  718.                 // See if we have all the bytes yet
  719.                 if (readCount < 4)
  720.                     continue;
  721.                
  722.                 // Have the bytes
  723.                 readCount = 0;
  724.                
  725.                 // See if its valid to encode
  726.                 if (iChar > 1114111 || (iChar >= 55296 && iChar <= 57343)) {
  727.                     // Need to fall back these 4 bytes
  728.                     byte[] fallbackBytes;
  729.                     if (this.bigEndian) {
  730.                         fallbackBytes = new byte[] {unchecked((byte)(iChar >> 24)), unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar))};
  731.                     }
  732.                     else {
  733.                         fallbackBytes = new byte[] {unchecked((byte)(iChar)), unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 24))};
  734.                     }
  735.                    
  736.                     charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
  737.                    
  738.                     // Ignore the illegal character
  739.                     iChar = 0;
  740.                     continue;
  741.                 }
  742.                
  743.                 // Ok, we have something we can add to our output
  744.                 if (iChar >= 65536) {
  745.                     // Surrogates take 2
  746.                     charCount++;
  747.                 }
  748.                
  749.                 // Add the rest of the surrogate or our normal character
  750.                 charCount++;
  751.                
  752.                 // iChar is back to 0
  753.                 iChar = 0;
  754.             }
  755.            
  756.             // See if we have something left over that has to be decoded
  757.             if (readCount > 0 && (decoder == null || decoder.MustFlush)) {
  758.                 // Oops, there's something left over with no place to go.
  759.                 byte[] fallbackBytes = new byte[readCount];
  760.                 if (this.bigEndian) {
  761.                     while (readCount > 0) {
  762.                         fallbackBytes[--readCount] = unchecked((byte)iChar);
  763.                         iChar >>= 8;
  764.                     }
  765.                 }
  766.                 else {
  767.                     while (readCount > 0) {
  768.                         fallbackBytes[--readCount] = unchecked((byte)(iChar >> 24));
  769.                         iChar <<= 8;
  770.                     }
  771.                 }
  772.                
  773.                 charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
  774.             }
  775.            
  776.             // Check for overflows.
  777.             if (charCount < 0)
  778.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
  779.            
  780.             // Shouldn't have anything in fallback buffer for GetCharCount
  781.             // (don't have to check m_throwOnOverflow for chars or count)
  782.             BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at end");
  783.            
  784.             // Return our count
  785.             return charCount;
  786.         }
  787.        
  788.         unsafe internal override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
  789.         {
  790.             BCLDebug.Assert(chars != null, "[UTF32Encoding.GetChars]chars!=null");
  791.             BCLDebug.Assert(bytes != null, "[UTF32Encoding.GetChars]bytes!=null");
  792.             BCLDebug.Assert(byteCount >= 0, "[UTF32Encoding.GetChars]byteCount >=0");
  793.             BCLDebug.Assert(charCount >= 0, "[UTF32Encoding.GetChars]charCount >=0");
  794.            
  795.             UTF32Decoder decoder = (UTF32Decoder)baseDecoder;
  796.            
  797.             // None so far!
  798.             char* charStart = chars;
  799.             char* charEnd = chars + charCount;
  800.            
  801.             byte* byteStart = bytes;
  802.             byte* byteEnd = bytes + byteCount;
  803.            
  804.             // See if there's anything in our decoder (but don't clear it yet)
  805.             int readCount = 0;
  806.             uint iChar = 0;
  807.            
  808.             // For fallback we may need a fallback buffer
  809.             DecoderFallbackBuffer fallbackBuffer = null;
  810.            
  811.             // See if there's anything in our decoder
  812.             if (decoder != null) {
  813.                 readCount = decoder.readByteCount;
  814.                 iChar = (uint)decoder.iChar;
  815.                 fallbackBuffer = baseDecoder.FallbackBuffer;
  816.                
  817.                 // Shouldn't have anything in fallback buffer for GetChars
  818.                 // (don't have to check m_throwOnOverflow for chars)
  819.                 BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetChars]Expected empty fallback buffer at start");
  820.             }
  821.             else {
  822.                 fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
  823.             }
  824.            
  825.             // Set our internal fallback interesting things.
  826.             fallbackBuffer.InternalInitialize(bytes, chars + charCount);
  827.            
  828.             // Loop through our input, 4 characters at a time!
  829.             while (bytes < byteEnd) {
  830.                 // Get our next character
  831.                 if (bigEndian) {
  832.                     // Scoot left and add it to the bottom
  833.                     iChar <<= 8;
  834.                     iChar += *(bytes++);
  835.                 }
  836.                 else {
  837.                     // Scoot right and add it to the top
  838.                     iChar >>= 8;
  839.                     iChar += (uint)(*(bytes++)) << 24;
  840.                 }
  841.                
  842.                 readCount++;
  843.                
  844.                 // See if we have all the bytes yet
  845.                 if (readCount < 4)
  846.                     continue;
  847.                
  848.                 // Have the bytes
  849.                 readCount = 0;
  850.                
  851.                 // See if its valid to encode
  852.                 if (iChar > 1114111 || (iChar >= 55296 && iChar <= 57343)) {
  853.                     // Need to fall back these 4 bytes
  854.                     byte[] fallbackBytes;
  855.                     if (this.bigEndian) {
  856.                         fallbackBytes = new byte[] {unchecked((byte)(iChar >> 24)), unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar))};
  857.                     }
  858.                     else {
  859.                         fallbackBytes = new byte[] {unchecked((byte)(iChar)), unchecked((byte)(iChar >> 8)), unchecked((byte)(iChar >> 16)), unchecked((byte)(iChar >> 24))};
  860.                     }
  861.                    
  862.                     // Chars won't be updated unless this works.
  863.                     if (!fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref chars)) {
  864.                         // Couldn't fallback, throw or wait til next time
  865.                         // We either read enough bytes for bytes-=4 to work, or we're
  866.                         // going to throw in ThrowCharsOverflow because chars == charStart
  867.                         BCLDebug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (bad surrogate)");
  868.                         bytes -= 4;
  869.                         // get back to where we were
  870.                         iChar = 0;
  871.                         // Remembering nothing
  872.                         fallbackBuffer.InternalReset();
  873.                         ThrowCharsOverflow(decoder, chars == charStart);
  874.                         // Might throw, if no chars output
  875.                         break;
  876.                         // Stop here, didn't throw
  877.                     }
  878.                    
  879.                     // Ignore the illegal character
  880.                     iChar = 0;
  881.                     continue;
  882.                 }
  883.                
  884.                
  885.                 // Ok, we have something we can add to our output
  886.                 if (iChar >= 65536) {
  887.                     // Surrogates take 2
  888.                     if (chars >= charEnd - 1) {
  889.                         // Throwing or stopping
  890.                         // We either read enough bytes for bytes-=4 to work, or we're
  891.                         // going to throw in ThrowCharsOverflow because chars == charStart
  892.                         BCLDebug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (surrogate)");
  893.                         bytes -= 4;
  894.                         // get back to where we were
  895.                         iChar = 0;
  896.                         // Remembering nothing
  897.                         ThrowCharsOverflow(decoder, chars == charStart);
  898.                         // Might throw, if no chars output
  899.                         break;
  900.                         // Stop here, didn't throw
  901.                     }
  902.                    
  903.                     *(chars++) = GetHighSurrogate(iChar);
  904.                     iChar = GetLowSurrogate(iChar);
  905.                 }
  906.                 // Bounds check for normal character
  907.                 else if (chars >= charEnd) {
  908.                     // Throwing or stopping
  909.                     // We either read enough bytes for bytes-=4 to work, or we're
  910.                     // going to throw in ThrowCharsOverflow because chars == charStart
  911.                     BCLDebug.Assert(bytes >= byteStart + 4 || chars == charStart, "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (normal char)");
  912.                     bytes -= 4;
  913.                     // get back to where we were
  914.                     iChar = 0;
  915.                     // Remembering nothing
  916.                     ThrowCharsOverflow(decoder, chars == charStart);
  917.                     // Might throw, if no chars output
  918.                     break;
  919.                     // Stop here, didn't throw
  920.                 }
  921.                
  922.                 // Add the rest of the surrogate or our normal character
  923.                 *(chars++) = (char)iChar;
  924.                
  925.                 // iChar is back to 0
  926.                 iChar = 0;
  927.             }
  928.            
  929.             // See if we have something left over that has to be decoded
  930.             if (readCount > 0 && (decoder == null || decoder.MustFlush)) {
  931.                 // Oops, there's something left over with no place to go.
  932.                 byte[] fallbackBytes = new byte[readCount];
  933.                 int tempCount = readCount;
  934.                 if (this.bigEndian) {
  935.                     while (tempCount > 0) {
  936.                         fallbackBytes[--tempCount] = unchecked((byte)iChar);
  937.                         iChar >>= 8;
  938.                     }
  939.                 }
  940.                 else {
  941.                     while (tempCount > 0) {
  942.                         fallbackBytes[--tempCount] = unchecked((byte)(iChar >> 24));
  943.                         iChar <<= 8;
  944.                     }
  945.                 }
  946.                
  947.                 if (!fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref chars)) {
  948.                     // Couldn't fallback.
  949.                     fallbackBuffer.InternalReset();
  950.                     ThrowCharsOverflow(decoder, chars == charStart);
  951.                     // Might throw, if no chars output
  952.                     // Stop here, didn't throw, backed up, so still nothing in buffer
  953.                 }
  954.                 else {
  955.                     // Don't clear our decoder unless we could fall it back.
  956.                     // If we caught the if above, then we're a convert() and will catch this next time.
  957.                     readCount = 0;
  958.                     iChar = 0;
  959.                 }
  960.             }
  961.            
  962.             // Remember any left over stuff, clearing buffer as well for MustFlush
  963.             if (decoder != null) {
  964.                 decoder.iChar = (int)iChar;
  965.                 decoder.readByteCount = readCount;
  966.                 decoder.m_bytesUsed = (int)(bytes - byteStart);
  967.             }
  968.            
  969.             // Shouldn't have anything in fallback buffer for GetChars
  970.             // (don't have to check m_throwOnOverflow for chars)
  971.             BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[UTF32Encoding.GetChars]Expected empty fallback buffer at end");
  972.            
  973.             // Return our count
  974.             return (int)(chars - charStart);
  975.         }
  976.        
  977.        
  978.         private uint GetSurrogate(char cHigh, char cLow)
  979.         {
  980.             return (((uint)cHigh - 55296) * 1024) + ((uint)cLow - 56320) + 65536;
  981.         }
  982.        
  983.         private char GetHighSurrogate(uint iChar)
  984.         {
  985.             return (char)((iChar - 65536) / 1024 + 55296);
  986.         }
  987.        
  988.         private char GetLowSurrogate(uint iChar)
  989.         {
  990.             return (char)((iChar - 65536) % 1024 + 56320);
  991.         }
  992.        
  993.        
  994.         public override Decoder GetDecoder()
  995.         {
  996.             return new UTF32Decoder(this);
  997.         }
  998.        
  999.        
  1000.         public override Encoder GetEncoder()
  1001.         {
  1002.             return new EncoderNLS(this);
  1003.         }
  1004.        
  1005.        
  1006.         public override int GetMaxByteCount(int charCount)
  1007.         {
  1008.             if (charCount < 0)
  1009.                 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  1010.            
  1011.             // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
  1012.             long byteCount = (long)charCount + 1;
  1013.            
  1014.             if (EncoderFallback.MaxCharCount > 1)
  1015.                 byteCount *= EncoderFallback.MaxCharCount;
  1016.            
  1017.             // 4 bytes per char
  1018.             byteCount *= 4;
  1019.            
  1020.             if (byteCount > 2147483647)
  1021.                 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
  1022.            
  1023.             return (int)byteCount;
  1024.         }
  1025.        
  1026.        
  1027.         public override int GetMaxCharCount(int byteCount)
  1028.         {
  1029.             if (byteCount < 0)
  1030.                 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  1031.            
  1032.             // A supplementary character becomes 2 surrogate characters, so 4 input bytes becomes 2 chars,
  1033.             // plus we may have 1 surrogate char left over if the decoder has 3 bytes in it already for a non-bmp char.
  1034.             // Have to add another one because 1/2 == 0, but 3 bytes left over could be 2 char surrogate pair
  1035.             int charCount = (byteCount / 2) + 2;
  1036.            
  1037.             if (DecoderFallback.MaxCharCount > 2) {
  1038.                 // Multiply time fallback size
  1039.                 charCount *= DecoderFallback.MaxCharCount;
  1040.                
  1041.                 // We were already figuring 2 chars per 4 bytes, but fallback will be different #
  1042.                 charCount /= 2;
  1043.             }
  1044.            
  1045.             if (charCount > 2147483647)
  1046.                 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
  1047.            
  1048.             return (int)charCount;
  1049.         }
  1050.        
  1051.        
  1052.         public override byte[] GetPreamble()
  1053.         {
  1054.             if (emitUTF32ByteOrderMark) {
  1055.                 // Allocate new array to prevent users from modifying it.
  1056.                 if (bigEndian) {
  1057.                     return new byte[4] {0, 0, 254, 255};
  1058.                 }
  1059.                 else {
  1060.                     return new byte[4] {255, 254, 0, 0};
  1061.                     // 00 00 FE FF
  1062.                 }
  1063.             }
  1064.             else
  1065.                 return Encoding.emptyByteArray;
  1066.         }
  1067.        
  1068.        
  1069.         public override bool Equals(object value)
  1070.         {
  1071.             UTF32Encoding that = value as UTF32Encoding;
  1072.             if (that != null) {
  1073.                     // (isThrowException == that.isThrowException) && // same as encoder/decoderfallback being exceptions
  1074.                 return (emitUTF32ByteOrderMark == that.emitUTF32ByteOrderMark) && (bigEndian == that.bigEndian) && (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback));
  1075.             }
  1076.             return (false);
  1077.         }
  1078.        
  1079.        
  1080.         public override int GetHashCode()
  1081.         {
  1082.             //Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
  1083.             return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() + CodePage + (emitUTF32ByteOrderMark ? 4 : 0) + (bigEndian ? 8 : 0);
  1084.         }
  1085.        
  1086.         [Serializable()]
  1087.         internal class UTF32Decoder : DecoderNLS
  1088.         {
  1089.             // Need a place to store any extra bytes we may have sucked up
  1090.             internal int iChar = 0;
  1091.             internal int readByteCount = 0;
  1092.            
  1093.             public UTF32Decoder(UTF32Encoding encoding) : base(encoding)
  1094.             {
  1095.                 // base calls reset
  1096.             }
  1097.            
  1098.             public override void Reset()
  1099.             {
  1100.                 this.iChar = 0;
  1101.                 this.readByteCount = 0;
  1102.                 if (m_fallbackBuffer != null)
  1103.                     m_fallbackBuffer.Reset();
  1104.             }
  1105.            
  1106.             // Anything left in our decoder?
  1107.             internal override bool HasState {
  1108. // ReadByteCount is our flag. (iChar==0 doesn't mean much).
  1109.                 get { return (this.readByteCount != 0); }
  1110.             }
  1111.         }
  1112.     }
  1113. }

Developer Fusion