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

  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. namespace System.Text
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Runtime.Remoting;
  20.     using System.Runtime.Serialization;
  21.     using System.Globalization;
  22.     using System.Security.Permissions;
  23.     using System.Threading;
  24.     using System.Text;
  25.     using Win32Native = Microsoft.Win32.Win32Native;
  26.    
  27.     // This abstract base class represents a character encoding. The class provides
  28.     // methods to convert arrays and strings of Unicode characters to and from
  29.     // arrays of bytes. A number of Encoding implementations are provided in
  30.     // the System.Text package, including:
  31.     //
  32.     // ASCIIEncoding, which encodes Unicode characters as single 7-bit
  33.     // ASCII characters. This encoding only supports character values between 0x00
  34.     // and 0x7F.
  35.     // BaseCodePageEncoding, which encapsulates a Windows code page. Any
  36.     // installed code page can be accessed through this encoding, and conversions
  37.     // are performed using the WideCharToMultiByte and
  38.     // MultiByteToWideChar Windows API functions.
  39.     // UnicodeEncoding, which encodes each Unicode character as two
  40.     // consecutive bytes. Both little-endian (code page 1200) and big-endian (code
  41.     // page 1201) encodings are recognized.
  42.     // UTF7Encoding, which encodes Unicode characters using the UTF-7
  43.     // encoding (UTF-7 stands for UCS Transformation Format, 7-bit form). This
  44.     // encoding supports all Unicode character values, and can also be accessed
  45.     // as code page 65000.
  46.     // UTF8Encoding, which encodes Unicode characters using the UTF-8
  47.     // encoding (UTF-8 stands for UCS Transformation Format, 8-bit form). This
  48.     // encoding supports all Unicode character values, and can also be accessed
  49.     // as code page 65001.
  50.     // UTF32Encoding, both 12000 (little endian) & 12001 (big endian)
  51.     //
  52.     // In addition to directly instantiating Encoding objects, an
  53.     // application can use the ForCodePage, GetASCII,
  54.     // GetDefault, GetUnicode, GetUTF7, and GetUTF8
  55.     // methods in this class to obtain encodings.
  56.     //
  57.     // Through an encoding, the GetBytes method is used to convert arrays
  58.     // of characters to arrays of bytes, and the GetChars method is used to
  59.     // convert arrays of bytes to arrays of characters. The GetBytes and
  60.     // GetChars methods maintain no state between conversions, and are
  61.     // generally intended for conversions of complete blocks of bytes and
  62.     // characters in one operation. When the data to be converted is only available
  63.     // in sequential blocks (such as data read from a stream) or when the amount of
  64.     // data is so large that it needs to be divided into smaller blocks, an
  65.     // application may choose to use a Decoder or an Encoder to
  66.     // perform the conversion. Decoders and encoders allow sequential blocks of
  67.     // data to be converted and they maintain the state required to support
  68.     // conversions of data that spans adjacent blocks. Decoders and encoders are
  69.     // obtained using the GetDecoder and GetEncoder methods.
  70.     //
  71.     // The core GetBytes and GetChars methods require the caller
  72.     // to provide the destination buffer and ensure that the buffer is large enough
  73.     // to hold the entire result of the conversion. When using these methods,
  74.     // either directly on an Encoding object or on an associated
  75.     // Decoder or Encoder, an application can use one of two methods
  76.     // to allocate destination buffers.
  77.     //
  78.     // The GetByteCount and GetCharCount methods can be used to
  79.     // compute the exact size of the result of a particular conversion, and an
  80.     // appropriately sized buffer for that conversion can then be allocated.
  81.     // The GetMaxByteCount and GetMaxCharCount methods can be
  82.     // be used to compute the maximum possible size of a conversion of a given
  83.     // number of bytes or characters, and a buffer of that size can then be reused
  84.     // for multiple conversions.
  85.     //
  86.     // The first method generally uses less memory, whereas the second method
  87.     // generally executes faster.
  88.     //
  89.    
  90.     [System.Runtime.InteropServices.ComVisible(true)]
  91.     [Serializable()]
  92.     public abstract class Encoding : ICloneable
  93.     {
  94.         private static Encoding defaultEncoding;
  95.         private static Encoding unicodeEncoding;
  96.         private static Encoding bigEndianUnicode;
  97.         private static Encoding utf7Encoding;
  98.         private static Encoding utf8Encoding;
  99.         private static Encoding utf32Encoding;
  100.         private static Encoding asciiEncoding;
  101.         private static Encoding latin1Encoding;
  102.         private static Hashtable encodings;
  103.        
  104.         //
  105.         // The following values are from mlang.idl. These values
  106.         // should be in sync with those in mlang.idl.
  107.         //
  108.         private const int MIMECONTF_MAILNEWS = 1;
  109.         private const int MIMECONTF_BROWSER = 2;
  110.         private const int MIMECONTF_SAVABLE_MAILNEWS = 256;
  111.         private const int MIMECONTF_SAVABLE_BROWSER = 512;
  112.        
  113.         // Special Case Code Pages
  114.         private const int CodePageDefault = 0;
  115.         private const int CodePageNoOEM = 1;
  116.         // OEM Code page not supported
  117.         private const int CodePageNoMac = 2;
  118.         // MAC code page not supported
  119.         private const int CodePageNoThread = 3;
  120.         // Thread code page not supported
  121.         private const int CodePageNoSymbol = 42;
  122.         // Symbol code page not supported
  123.         private const int CodePageUnicode = 1200;
  124.         // Unicode
  125.         private const int CodePageBigEndian = 1201;
  126.         // Big Endian Unicode
  127.         private const int CodePageWindows1252 = 1252;
  128.         // Windows 1252 code page
  129.         // 20936 has same code page as 10008, so we'll special case it
  130.         private const int CodePageMacGB2312 = 10008;
  131.         private const int CodePageGB2312 = 20936;
  132.         private const int CodePageMacKorean = 10003;
  133.         private const int CodePageDLLKorean = 20949;
  134.        
  135.         // ISO 2022 Code Pages
  136.         private const int ISO2022JP = 50220;
  137.         private const int ISO2022JPESC = 50221;
  138.         private const int ISO2022JPSISO = 50222;
  139.         private const int ISOKorean = 50225;
  140.         private const int ISOSimplifiedCN = 50227;
  141.         private const int EUCJP = 51932;
  142.         private const int ChineseHZ = 52936;
  143.         // HZ has ~}~{~~ sequences
  144.         // 51936 is the same as 936
  145.         private const int DuplicateEUCCN = 51936;
  146.         private const int EUCCN = 936;
  147.        
  148.         private const int EUCKR = 51949;
  149.        
  150.         // Latin 1 & ASCII Code Pages
  151.         internal const int CodePageASCII = 20127;
  152.         // ASCII
  153.         internal const int ISO_8859_1 = 28591;
  154.         // Latin1
  155.         // ISCII
  156.         private const int ISCIIAssemese = 57006;
  157.         private const int ISCIIBengali = 57003;
  158.         private const int ISCIIDevanagari = 57002;
  159.         private const int ISCIIGujarathi = 57010;
  160.         private const int ISCIIKannada = 57008;
  161.         private const int ISCIIMalayalam = 57009;
  162.         private const int ISCIIOriya = 57007;
  163.         private const int ISCIIPanjabi = 57011;
  164.         private const int ISCIITamil = 57004;
  165.         private const int ISCIITelugu = 57005;
  166.        
  167.         // GB18030
  168.         private const int GB18030 = 54936;
  169.        
  170.         // Other
  171.         private const int ISO_8859_8I = 38598;
  172.         private const int ISO_8859_8_Visual = 28598;
  173.        
  174.         // 50229 is currently unsupported // "Chinese Traditional (ISO-2022)"
  175.         private const int ENC50229 = 50229;
  176.        
  177.         // Special code pages
  178.         private const int CodePageUTF7 = 65000;
  179.         private const int CodePageUTF8 = 65001;
  180.         private const int CodePageUTF32 = 12000;
  181.         private const int CodePageUTF32BE = 12001;
  182.        
  183.         internal int m_codePage = 0;
  184.        
  185.         internal CodePageDataItem dataItem = null;
  186.        
  187.         [NonSerialized()]
  188.         internal bool m_deserializedFromEverett = false;
  189.        
  190.         // Because of encoders we may be read only
  191.         [OptionalField(VersionAdded = 2)]
  192.         private bool m_isReadOnly = true;
  193.        
  194.         // Encoding (encoder) fallback
  195.         [OptionalField(VersionAdded = 2)]
  196.         internal EncoderFallback encoderFallback = null;
  197.         [OptionalField(VersionAdded = 2)]
  198.         internal DecoderFallback decoderFallback = null;
  199.        
  200.         // Useful for Encodings whose GetPreamble method must return an
  201.         // empty byte array.
  202.         static internal readonly byte[] emptyByteArray = new byte[0];
  203.        
  204.        
  205.         protected Encoding() : this(0)
  206.         {
  207.         }
  208.        
  209.        
  210.         protected Encoding(int codePage)
  211.         {
  212.             // Validate code page
  213.             if (codePage < 0) {
  214.                 throw new ArgumentOutOfRangeException("codePage");
  215.             }
  216.            
  217.             // Remember code page
  218.             m_codePage = codePage;
  219.            
  220.             // Use default encoder/decoder fallbacks
  221.             this.SetDefaultFallbacks();
  222.         }
  223.        
  224.         // Default fallback that we'll use.
  225.         internal virtual void SetDefaultFallbacks()
  226.         {
  227.             // For UTF-X encodings, we use a replacement fallback with an empty string,
  228.             // For ASCII we use "?" replacement fallback, etc.
  229.             this.encoderFallback = new InternalEncoderBestFitFallback(this);
  230.             this.decoderFallback = new InternalDecoderBestFitFallback(this);
  231.         }
  232.        
  233.        
  234.         #region Serialization
  235.         internal void OnDeserializing()
  236.         {
  237.             encoderFallback = null;
  238.             decoderFallback = null;
  239.             m_isReadOnly = true;
  240.         }
  241.        
  242.         internal void OnDeserialized()
  243.         {
  244.             if (encoderFallback == null || decoderFallback == null) {
  245.                 m_deserializedFromEverett = true;
  246.                 SetDefaultFallbacks();
  247.             }
  248.         }
  249.        
  250.         [OnDeserializing()]
  251.         private void OnDeserializing(StreamingContext ctx)
  252.         {
  253.             OnDeserializing();
  254.         }
  255.        
  256.        
  257.         [OnDeserialized()]
  258.         private void OnDeserialized(StreamingContext ctx)
  259.         {
  260.             OnDeserialized();
  261.         }
  262.        
  263.         [OnSerializing()]
  264.         private void OnSerializing(StreamingContext ctx)
  265.         {
  266.             // to be consistent with SerializeEncoding
  267.             dataItem = null;
  268.         }
  269.        
  270.         // the following two methods are used for the inherited classes which implemented ISerializable
  271.         // Deserialization Helper
  272.         internal void DeserializeEncoding(SerializationInfo info, StreamingContext context)
  273.         {
  274.             // Any info?
  275.             if (info == null)
  276.                 throw new ArgumentNullException("info");
  277.            
  278.             // All versions have a code page
  279.             this.m_codePage = (int)info.GetValue("m_codePage", typeof(int));
  280.            
  281.             this.dataItem = null;
  282.            
  283.             // See if we have a code page
  284.             try {
  285.                
  286.                 this.m_isReadOnly = (bool)info.GetValue("m_isReadOnly", typeof(bool));
  287.                
  288.                 this.encoderFallback = (EncoderFallback)info.GetValue("encoderFallback", typeof(EncoderFallback));
  289.                 this.decoderFallback = (DecoderFallback)info.GetValue("decoderFallback", typeof(DecoderFallback));
  290.             }
  291.             catch (SerializationException) {
  292.                 this.m_deserializedFromEverett = true;
  293.                
  294.                 // May as well be read only
  295.                 this.m_isReadOnly = true;
  296.                 SetDefaultFallbacks();
  297.             }
  298.         }
  299.        
  300.         // Serialization Helper
  301.         internal void SerializeEncoding(SerializationInfo info, StreamingContext context)
  302.         {
  303.             // Any Info?
  304.             if (info == null)
  305.                 throw new ArgumentNullException("info");
  306.            
  307.             info.AddValue("m_isReadOnly", this.m_isReadOnly);
  308.             info.AddValue("encoderFallback", this.EncoderFallback);
  309.             info.AddValue("decoderFallback", this.DecoderFallback);
  310.            
  311.             info.AddValue("m_codePage", this.m_codePage);
  312.            
  313.             info.AddValue("dataItem", (CodePageDataItem)null);
  314.            
  315.             info.AddValue("Encoding+m_codePage", this.m_codePage);
  316.             info.AddValue("Encoding+dataItem", (CodePageDataItem)null);
  317.         }
  318.        
  319.         #endregion Serialization
  320.        
  321.         // Converts a byte array from one encoding to another. The bytes in the
  322.         // bytes array are converted from srcEncoding to
  323.         // dstEncoding, and the returned value is a new byte array
  324.         // containing the result of the conversion.
  325.         //
  326.        
  327.         public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding, byte[] bytes)
  328.         {
  329.             if (bytes == null)
  330.                 throw new ArgumentNullException("bytes");
  331.             return Convert(srcEncoding, dstEncoding, bytes, 0, bytes.Length);
  332.         }
  333.        
  334.         // Converts a range of bytes in a byte array from one encoding to another.
  335.         // This method converts count bytes from bytes starting at
  336.         // index index from srcEncoding to dstEncoding, and
  337.         // returns a new byte array containing the result of the conversion.
  338.         //
  339.        
  340.         public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding, byte[] bytes, int index, int count)
  341.         {
  342.             if (srcEncoding == null || dstEncoding == null) {
  343.                 throw new ArgumentNullException((srcEncoding == null ? "srcEncoding" : "dstEncoding"), Environment.GetResourceString("ArgumentNull_Array"));
  344.             }
  345.             if (bytes == null) {
  346.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  347.             }
  348.             return dstEncoding.GetBytes(srcEncoding.GetChars(bytes, index, count));
  349.         }
  350.        
  351.         // Private object for locking instead of locking on a public type for SQL reliability work.
  352.         private static object s_InternalSyncObject;
  353.         private static object InternalSyncObject {
  354.             get {
  355.                 if (s_InternalSyncObject == null) {
  356.                     object o = new object();
  357.                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
  358.                 }
  359.                 return s_InternalSyncObject;
  360.             }
  361.         }
  362.        
  363.        
  364.         public static Encoding GetEncoding(int codepage)
  365.         {
  366.             //
  367.             // NOTE: If you add a new encoding that can be get by codepage, be sure to
  368.             // add the corresponding item in EncodingTable.
  369.             // Otherwise, the code below will throw exception when trying to call
  370.             // EncodingTable.GetDataItem().
  371.             //
  372.             if (codepage < 0 || codepage > 65535) {
  373.                 throw new ArgumentOutOfRangeException("codepage", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, 65535));
  374.             }
  375.            
  376.             // Our Encoding
  377.             Encoding result = null;
  378.            
  379.             // See if we have a hash table with our encoding in it already.
  380.             if (encodings != null)
  381.                 result = (Encoding)encodings[codepage];
  382.            
  383.             if (result == null) {
  384.                 // Don't conflict with ourselves
  385.                 lock (InternalSyncObject) {
  386.                     // Need a new hash table
  387.                     if (encodings == null)
  388.                         encodings = new Hashtable();
  389.                    
  390.                     // Double check that we don't have one in the table (in case another thread beat us here)
  391.                     if ((result = (Encoding)encodings[codepage]) != null)
  392.                         return result;
  393.                    
  394.                     // Special case the commonly used Encoding classes here, then call
  395.                     // GetEncodingRare to avoid loading classes like MLangCodePageEncoding
  396.                     // and ASCIIEncoding. ASP.NET uses UTF-8 & ISO-8859-1.
  397.                     switch (codepage) {
  398.                         case CodePageDefault:
  399.                             // 0, default code page
  400.                             result = Encoding.Default;
  401.                             break;
  402.                         case CodePageUnicode:
  403.                             // 1200, Unicode
  404.                             result = Unicode;
  405.                             break;
  406.                         case CodePageBigEndian:
  407.                             // 1201, big endian unicode
  408.                             result = BigEndianUnicode;
  409.                             break;
  410.                         case CodePageWindows1252:
  411.                             // 1252, Windows
  412.                             result = new SBCSCodePageEncoding(codepage);
  413.                             break;
  414.                         case CodePageUTF8:
  415.                             // 65001, UTF8
  416.                             result = UTF8;
  417.                             break;
  418.                         case CodePageNoOEM:
  419.                         case CodePageNoMac:
  420.                         case CodePageNoThread:
  421.                         case CodePageNoSymbol:
  422.                            
  423.                             // These are (hopefully) not very common, but also shouldn't slow us down much and make default
  424.                             // case able to handle more code pages by calling GetEncodingCodePage
  425.                             // 1
  426.                             // 2
  427.                             // 3
  428.                             // 42
  429.                             // Win32 also allows the following special code page values. We won't allow them except in the
  430.                             // CP_ACP case.
  431.                             // #define CP_ACP 0 // default to ANSI code page
  432.                             // #define CP_OEMCP 1 // default to OEM code page
  433.                             // #define CP_MACCP 2 // default to MAC code page
  434.                             // #define CP_THREAD_ACP 3 // current thread's ANSI code page
  435.                             // #define CP_SYMBOL 42 // SYMBOL translations
  436.                             throw new ArgumentException(Environment.GetResourceString("Argument_CodepageNotSupported", codepage), "codepage");
  437.                             break;
  438.                         case CodePageASCII:
  439.                            
  440.                             // Have to do ASCII and Latin 1 first so they don't get loaded as code pages
  441.                             // 20127
  442.                             result = ASCII;
  443.                             break;
  444.                         case ISO_8859_1:
  445.                             // 28591
  446.                             result = Latin1;
  447.                             break;
  448.                         default:
  449.                            
  450.                             {
  451.                                 // 1st assume its a code page.
  452.                                 result = GetEncodingCodePage(codepage);
  453.                                 if (result == null)
  454.                                     result = GetEncodingRare(codepage);
  455.                                 break;
  456.                             }
  457.                             break;
  458.                     }
  459.                     encodings.Add(codepage, result);
  460.                 }
  461.                
  462.             }
  463.             return result;
  464.         }
  465.        
  466.        
  467.         public static Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
  468.         {
  469.             // Get the default encoding (which is cached and read only)
  470.             Encoding baseEncoding = GetEncoding(codepage);
  471.            
  472.             // Clone it and set the fallback
  473.             Encoding fallbackEncoding = (Encoding)baseEncoding.Clone();
  474.             fallbackEncoding.EncoderFallback = encoderFallback;
  475.             fallbackEncoding.DecoderFallback = decoderFallback;
  476.            
  477.             return fallbackEncoding;
  478.         }
  479.        
  480.         private static Encoding GetEncodingRare(int codepage)
  481.         {
  482.             BCLDebug.Assert(codepage != 0 && codepage != 1200 && codepage != 1201 && codepage != 65001, "[Encoding.GetEncodingRare]This code page (" + codepage + ") isn't supported by GetEncodingRare!");
  483.             Encoding result;
  484.             switch (codepage) {
  485.                 case CodePageUTF7:
  486.                     // 65000
  487.                     result = UTF7;
  488.                     break;
  489.                 case CodePageUTF32:
  490.                     // 12000
  491.                     result = UTF32;
  492.                     break;
  493.                 case CodePageUTF32BE:
  494.                     // 12001
  495.                     result = new UTF32Encoding(true, true);
  496.                     break;
  497.                 case ISCIIAssemese:
  498.                 case ISCIIBengali:
  499.                 case ISCIIDevanagari:
  500.                 case ISCIIGujarathi:
  501.                 case ISCIIKannada:
  502.                 case ISCIIMalayalam:
  503.                 case ISCIIOriya:
  504.                 case ISCIIPanjabi:
  505.                 case ISCIITamil:
  506.                 case ISCIITelugu:
  507.                     result = new ISCIIEncoding(codepage);
  508.                     break;
  509.                 case CodePageMacGB2312:
  510.                     // GB2312-80 uses same code page for 20936 and mac 10008
  511.                     // case CodePageGB2312:
  512.                     // result = new DBCSCodePageEncoding(codepage, EUCCN);
  513.                     result = new DBCSCodePageEncoding(CodePageMacGB2312, CodePageGB2312);
  514.                     break;
  515.                 case CodePageMacKorean:
  516.                    
  517.                     // Mac Korean 10003 and 20949 are the same
  518.                     result = new DBCSCodePageEncoding(CodePageMacKorean, CodePageDLLKorean);
  519.                     break;
  520.                 case GB18030:
  521.                     // GB18030 Code Pages
  522.                     result = new GB18030Encoding();
  523.                     break;
  524.                 case ISOKorean:
  525.                 case ChineseHZ:
  526.                 case ISO2022JP:
  527.                 case ISO2022JPESC:
  528.                 case ISO2022JPSISO:
  529.                     // ISO2022 Code Pages
  530.                     // case ISOSimplifiedCN
  531.                     // JIS JP, full-width Katakana mode (no half-width Katakana)
  532.                     // JIS JP, esc sequence to do Katakana.
  533.                     // JIS JP with Shift In/ Shift Out Katakana support
  534.                     result = new ISO2022Encoding(codepage);
  535.                     break;
  536.                 case DuplicateEUCCN:
  537.                 case ISOSimplifiedCN:
  538.                     result = new DBCSCodePageEncoding(codepage, EUCCN);
  539.                     // Just maps to 936
  540.                     break;
  541.                 case EUCJP:
  542.                     result = new EUCJPEncoding();
  543.                     break;
  544.                 case EUCKR:
  545.                     result = new DBCSCodePageEncoding(codepage, CodePageDLLKorean);
  546.                     // Maps to 20949
  547.                     break;
  548.                 case ENC50229:
  549.                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_CodePage50229"));
  550.                     break;
  551.                 case ISO_8859_8I:
  552.                     result = new SBCSCodePageEncoding(codepage, ISO_8859_8_Visual);
  553.                     // Hebrew maps to a different code page
  554.                     break;
  555.                 default:
  556.                     // Not found, already tried codepage table code pages in GetEncoding()
  557.                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_NoCodepageData", codepage));
  558.                     break;
  559.             }
  560.             return result;
  561.         }
  562.        
  563.         private static Encoding GetEncodingCodePage(int CodePage)
  564.         {
  565.             // Single Byte or Double Byte Code Page? (0 if not found)
  566.             int i = BaseCodePageEncoding.GetCodePageByteSize(CodePage);
  567.             if (i == 1)
  568.                 return new SBCSCodePageEncoding(CodePage);
  569.             else if (i == 2)
  570.                 return new DBCSCodePageEncoding(CodePage);
  571.            
  572.             // Return null if we didn't find one.
  573.             return null;
  574.         }
  575.        
  576.         // Returns an Encoding object for a given name or a given code page value.
  577.         //
  578.        
  579.         public static Encoding GetEncoding(string name)
  580.         {
  581.             //
  582.             // NOTE: If you add a new encoding that can be requested by name, be sure to
  583.             // add the corresponding item in EncodingTable.
  584.             // Otherwise, the code below will throw exception when trying to call
  585.             // EncodingTable.GetCodePageFromName().
  586.             //
  587.             return (GetEncoding(EncodingTable.GetCodePageFromName(name)));
  588.         }
  589.        
  590.         // Returns an Encoding object for a given name or a given code page value.
  591.         //
  592.        
  593.         public static Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
  594.         {
  595.             //
  596.             // NOTE: If you add a new encoding that can be requested by name, be sure to
  597.             // add the corresponding item in EncodingTable.
  598.             // Otherwise, the code below will throw exception when trying to call
  599.             // EncodingTable.GetCodePageFromName().
  600.             //
  601.             return (GetEncoding(EncodingTable.GetCodePageFromName(name), encoderFallback, decoderFallback));
  602.         }
  603.        
  604.         // Return a list of all EncodingInfo objects describing all of our encodings
  605.        
  606.         public static EncodingInfo[] GetEncodings()
  607.         {
  608.             return EncodingTable.GetEncodings();
  609.         }
  610.        
  611.        
  612.         public virtual byte[] GetPreamble()
  613.         {
  614.             return emptyByteArray;
  615.         }
  616.        
  617.         private void GetDataItem()
  618.         {
  619.             if (dataItem == null) {
  620.                 dataItem = EncodingTable.GetCodePageDataItem(m_codePage);
  621.                 if (dataItem == null) {
  622.                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_NoCodepageData", m_codePage));
  623.                 }
  624.             }
  625.         }
  626.        
  627.         // Returns the name for this encoding that can be used with mail agent body tags.
  628.         // If the encoding may not be used, the string is empty.
  629.        
  630.         public virtual string BodyName {
  631.             get {
  632.                 if (dataItem == null) {
  633.                     GetDataItem();
  634.                 }
  635.                 return (dataItem.BodyName);
  636.             }
  637.         }
  638.        
  639.         // Returns the human-readable description of the encoding ( e.g. Hebrew (DOS)).
  640.        
  641.         public virtual string EncodingName {
  642.             get { return (Environment.GetResourceString("Globalization.cp_" + m_codePage)); }
  643.         }
  644.        
  645.         // Returns the name for this encoding that can be used with mail agent header
  646.         // tags. If the encoding may not be used, the string is empty.
  647.        
  648.         public virtual string HeaderName {
  649.             get {
  650.                 if (dataItem == null) {
  651.                     GetDataItem();
  652.                 }
  653.                 return (dataItem.HeaderName);
  654.             }
  655.         }
  656.        
  657.         // Returns the array of IANA-registered names for this encoding. If there is an
  658.         // IANA preferred name, it is the first name in the array.
  659.        
  660.         public virtual string WebName {
  661.             get {
  662.                 if (dataItem == null) {
  663.                     GetDataItem();
  664.                 }
  665.                 return (dataItem.WebName);
  666.             }
  667.         }
  668.        
  669.         // Returns the windows code page that most closely corresponds to this encoding.
  670.        
  671.         public virtual int WindowsCodePage {
  672.             get {
  673.                 if (dataItem == null) {
  674.                     GetDataItem();
  675.                 }
  676.                 return (dataItem.UIFamilyCodePage);
  677.             }
  678.         }
  679.        
  680.        
  681.         // True if and only if the encoding is used for display by browsers clients.
  682.        
  683.         public virtual bool IsBrowserDisplay {
  684.             get {
  685.                 if (dataItem == null) {
  686.                     GetDataItem();
  687.                 }
  688.                 return ((dataItem.Flags & MIMECONTF_BROWSER) != 0);
  689.             }
  690.         }
  691.        
  692.         // True if and only if the encoding is used for saving by browsers clients.
  693.        
  694.         public virtual bool IsBrowserSave {
  695.             get {
  696.                 if (dataItem == null) {
  697.                     GetDataItem();
  698.                 }
  699.                 return ((dataItem.Flags & MIMECONTF_SAVABLE_BROWSER) != 0);
  700.             }
  701.         }
  702.        
  703.         // True if and only if the encoding is used for display by mail and news clients.
  704.        
  705.         public virtual bool IsMailNewsDisplay {
  706.             get {
  707.                 if (dataItem == null) {
  708.                     GetDataItem();
  709.                 }
  710.                 return ((dataItem.Flags & MIMECONTF_MAILNEWS) != 0);
  711.             }
  712.         }
  713.        
  714.        
  715.         // True if and only if the encoding is used for saving documents by mail and
  716.         // news clients
  717.        
  718.         public virtual bool IsMailNewsSave {
  719.             get {
  720.                 if (dataItem == null) {
  721.                     GetDataItem();
  722.                 }
  723.                 return ((dataItem.Flags & MIMECONTF_SAVABLE_MAILNEWS) != 0);
  724.             }
  725.         }
  726.        
  727.         // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
  728.        
  729.         [System.Runtime.InteropServices.ComVisible(false)]
  730.         public virtual bool IsSingleByte {
  731.             get { return false; }
  732.         }
  733.        
  734.        
  735.         [System.Runtime.InteropServices.ComVisible(false)]
  736.         public EncoderFallback EncoderFallback {
  737.             get { return encoderFallback; }
  738.            
  739.             set {
  740.                 if (this.IsReadOnly)
  741.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
  742.                
  743.                 if (value == null)
  744.                     throw new ArgumentNullException("value");
  745.                
  746.                 encoderFallback = value;
  747.             }
  748.         }
  749.        
  750.        
  751.         [System.Runtime.InteropServices.ComVisible(false)]
  752.         public DecoderFallback DecoderFallback {
  753.             get { return decoderFallback; }
  754.            
  755.             set {
  756.                 if (this.IsReadOnly)
  757.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
  758.                
  759.                 if (value == null)
  760.                     throw new ArgumentNullException("value");
  761.                
  762.                 decoderFallback = value;
  763.             }
  764.         }
  765.        
  766.        
  767.         [System.Runtime.InteropServices.ComVisible(false)]
  768.         public virtual object Clone()
  769.         {
  770.             Encoding newEncoding = (Encoding)this.MemberwiseClone();
  771.            
  772.             // New one should be readable
  773.             newEncoding.m_isReadOnly = false;
  774.             return newEncoding;
  775.         }
  776.        
  777.        
  778.         [System.Runtime.InteropServices.ComVisible(false)]
  779.         public bool IsReadOnly {
  780.             get { return (m_isReadOnly); }
  781.         }
  782.        
  783.         // Returns an encoding for the ASCII character set. The returned encoding
  784.         // will be an instance of the ASCIIEncoding class.
  785.         //
  786.        
  787.         public static Encoding ASCII {
  788.             get {
  789.                 if (asciiEncoding == null)
  790.                     asciiEncoding = new ASCIIEncoding();
  791.                 return asciiEncoding;
  792.             }
  793.         }
  794.        
  795.         // Returns an encoding for the Latin1 character set. The returned encoding
  796.         // will be an instance of the Latin1Encoding class.
  797.         //
  798.         // This is for our optimizations
  799.         private static Encoding Latin1 {
  800.             get {
  801.                 if (latin1Encoding == null)
  802.                     latin1Encoding = new Latin1Encoding();
  803.                 return latin1Encoding;
  804.             }
  805.         }
  806.        
  807.         // Returns the number of bytes required to encode the given character
  808.         // array.
  809.         //
  810.        
  811.         public virtual int GetByteCount(char[] chars)
  812.         {
  813.             if (chars == null) {
  814.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  815.             }
  816.            
  817.             return GetByteCount(chars, 0, chars.Length);
  818.         }
  819.        
  820.        
  821.         public virtual int GetByteCount(string s)
  822.         {
  823.             if (s == null)
  824.                 throw new ArgumentNullException("s");
  825.            
  826.             char[] chars = s.ToCharArray();
  827.             return GetByteCount(chars, 0, chars.Length);
  828.            
  829.         }
  830.        
  831.         // Returns the number of bytes required to encode a range of characters in
  832.         // a character array.
  833.         //
  834.        
  835.         public abstract int GetByteCount(char[] chars, int index, int count);
  836.        
  837.        
  838.         [CLSCompliant(false)]
  839.         [System.Runtime.InteropServices.ComVisible(false)]
  840.         unsafe public virtual int GetByteCount(char* chars, int count)
  841.         {
  842.             // Validate input parameters
  843.             if (chars == null)
  844.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  845.            
  846.             if (count < 0)
  847.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  848.            
  849.             char[] arrChar = new char[count];
  850.             int index;
  851.            
  852.             for (index = 0; index < count; index++)
  853.                 arrChar[index] = chars[index];
  854.            
  855.             return GetByteCount(arrChar, 0, count);
  856.         }
  857.        
  858.         // For NLS Encodings, workhorse takes an encoder (may be null)
  859.         // Always validate parameters before calling internal version, which will only assert.
  860.         unsafe internal virtual int GetByteCount(char* chars, int count, EncoderNLS encoder)
  861.         {
  862.             return GetByteCount(chars, count);
  863.         }
  864.        
  865.         // Returns a byte array containing the encoded representation of the given
  866.         // character array.
  867.         //
  868.        
  869.         public virtual byte[] GetBytes(char[] chars)
  870.         {
  871.             if (chars == null) {
  872.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  873.             }
  874.             return GetBytes(chars, 0, chars.Length);
  875.         }
  876.        
  877.         // Returns a byte array containing the encoded representation of a range
  878.         // of characters in a character array.
  879.         //
  880.        
  881.         public virtual byte[] GetBytes(char[] chars, int index, int count)
  882.         {
  883.             byte[] result = new byte[GetByteCount(chars, index, count)];
  884.             GetBytes(chars, index, count, result, 0);
  885.             return result;
  886.         }
  887.        
  888.         // Encodes a range of characters in a character array into a range of bytes
  889.         // in a byte array. An exception occurs if the byte array is not large
  890.         // enough to hold the complete encoding of the characters. The
  891.         // GetByteCount method can be used to determine the exact number of
  892.         // bytes that will be produced for a given range of characters.
  893.         // Alternatively, the GetMaxByteCount method can be used to
  894.         // determine the maximum number of bytes that will be produced for a given
  895.         // number of characters, regardless of the actual character values.
  896.         //
  897.        
  898.         public abstract int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex);
  899.        
  900.         // Returns a byte array containing the encoded representation of the given
  901.         // string.
  902.         //
  903.        
  904.         public virtual byte[] GetBytes(string s)
  905.         {
  906.             if (s == null)
  907.                 throw new ArgumentNullException("s", Environment.GetResourceString("ArgumentNull_String"));
  908.            
  909.             char[] chars = s.ToCharArray();
  910.             return GetBytes(chars, 0, chars.Length);
  911.         }
  912.        
  913.        
  914.         public virtual int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
  915.         {
  916.             if (s == null)
  917.                 throw new ArgumentNullException("s");
  918.             return GetBytes(s.ToCharArray(), charIndex, charCount, bytes, byteIndex);
  919.         }
  920.        
  921.         // This is our internal workhorse
  922.         // Always validate parameters before calling internal version, which will only assert.
  923.         unsafe internal virtual int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
  924.         {
  925.             return GetBytes(chars, charCount, bytes, byteCount);
  926.         }
  927.        
  928.         //
  929.         //
  930.         //
  931.        
  932.         [CLSCompliant(false)]
  933.         [System.Runtime.InteropServices.ComVisible(false)]
  934.         unsafe public virtual int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
  935.         {
  936.             // Validate input parameters
  937.             if (bytes == null || chars == null)
  938.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  939.            
  940.             if (charCount < 0 || byteCount < 0)
  941.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  942.            
  943.             // Get the char array to convert
  944.             char[] arrChar = new char[charCount];
  945.            
  946.             int index;
  947.             for (index = 0; index < charCount; index++)
  948.                 arrChar[index] = chars[index];
  949.            
  950.             // Get the byte array to fill
  951.             byte[] arrByte = new byte[byteCount];
  952.            
  953.             // Do the work
  954.             int result = GetBytes(arrChar, 0, charCount, arrByte, 0);
  955.            
  956.             // The only way this could fail is a bug in GetBytes
  957.             BCLDebug.Assert(result <= byteCount, "[Encoding.GetBytes]Returned more bytes than we have space for");
  958.            
  959.             // Copy the byte array
  960.             // WARNING: We MUST make sure that we don't copy too many bytes. We can't
  961.             // rely on result because it could be a 3rd party implimentation. We need
  962.             // to make sure we never copy more than byteCount bytes no matter the value
  963.             // of result
  964.             if (result < byteCount)
  965.                 byteCount = result;
  966.            
  967.             // Copy the data, don't overrun our array!
  968.             for (index = 0; index < byteCount; index++)
  969.                 bytes[index] = arrByte[index];
  970.            
  971.             return byteCount;
  972.         }
  973.        
  974.         // Returns the number of characters produced by decoding the given byte
  975.         // array.
  976.         //
  977.        
  978.         public virtual int GetCharCount(byte[] bytes)
  979.         {
  980.             if (bytes == null) {
  981.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  982.             }
  983.             return GetCharCount(bytes, 0, bytes.Length);
  984.         }
  985.        
  986.         // Returns the number of characters produced by decoding a range of bytes
  987.         // in a byte array.
  988.         //
  989.        
  990.         public abstract int GetCharCount(byte[] bytes, int index, int count);
  991.        
  992.         // We expect this to be the workhorse for NLS Encodings, but for existing
  993.         // ones we need a working (if slow) default implimentation)
  994.        
  995.         [CLSCompliant(false)]
  996.         [System.Runtime.InteropServices.ComVisible(false)]
  997.         unsafe public virtual int GetCharCount(byte* bytes, int count)
  998.         {
  999.             // Validate input parameters
  1000.             if (bytes == null)
  1001.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  1002.            
  1003.             if (count < 0)
  1004.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  1005.            
  1006.             byte[] arrbyte = new byte[count];
  1007.             int index;
  1008.            
  1009.             for (index = 0; index < count; index++)
  1010.                 arrbyte[index] = bytes[index];
  1011.            
  1012.             return GetCharCount(arrbyte, 0, count);
  1013.         }
  1014.        
  1015.         // This is our internal workhorse
  1016.         // Always validate parameters before calling internal version, which will only assert.
  1017.         unsafe internal virtual int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
  1018.         {
  1019.             return GetCharCount(bytes, count);
  1020.         }
  1021.        
  1022.         // Returns a character array containing the decoded representation of a
  1023.         // given byte array.
  1024.         //
  1025.        
  1026.         public virtual char[] GetChars(byte[] bytes)
  1027.         {
  1028.             if (bytes == null) {
  1029.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  1030.             }
  1031.             return GetChars(bytes, 0, bytes.Length);
  1032.         }
  1033.        
  1034.         // Returns a character array containing the decoded representation of a
  1035.         // range of bytes in a byte array.
  1036.         //
  1037.        
  1038.         public virtual char[] GetChars(byte[] bytes, int index, int count)
  1039.         {
  1040.             char[] result = new char[GetCharCount(bytes, index, count)];
  1041.             GetChars(bytes, index, count, result, 0);
  1042.             return result;
  1043.         }
  1044.        
  1045.         // Decodes a range of bytes in a byte array into a range of characters in a
  1046.         // character array. An exception occurs if the character array is not large
  1047.         // enough to hold the complete decoding of the bytes. The
  1048.         // GetCharCount method can be used to determine the exact number of
  1049.         // characters that will be produced for a given range of bytes.
  1050.         // Alternatively, the GetMaxCharCount method can be used to
  1051.         // determine the maximum number of characterss that will be produced for a
  1052.         // given number of bytes, regardless of the actual byte values.
  1053.         //
  1054.        
  1055.         public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex);
  1056.        
  1057.        
  1058.         //
  1059.         //
  1060.         //
  1061.        
  1062.         [CLSCompliant(false)]
  1063.         [System.Runtime.InteropServices.ComVisible(false)]
  1064.         unsafe public virtual int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
  1065.         {
  1066.             // Validate input parameters
  1067.             if (chars == null || bytes == null)
  1068.                 throw new ArgumentNullException(chars == null ? "chars" : "bytes", Environment.GetResourceString("ArgumentNull_Array"));
  1069.            
  1070.             if (byteCount < 0 || charCount < 0)
  1071.                 throw new ArgumentOutOfRangeException((byteCount < 0 ? "byteCount" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  1072.            
  1073.             // Get the byte array to convert
  1074.             byte[] arrByte = new byte[byteCount];
  1075.            
  1076.             int index;
  1077.             for (index = 0; index < byteCount; index++)
  1078.                 arrByte[index] = bytes[index];
  1079.            
  1080.             // Get the char array to fill
  1081.             char[] arrChar = new char[charCount];
  1082.            
  1083.             // Do the work
  1084.             int result = GetChars(arrByte, 0, byteCount, arrChar, 0);
  1085.            
  1086.             // The only way this could fail is a bug in GetChars
  1087.             BCLDebug.Assert(result <= charCount, "[Encoding.GetChars]Returned more chars than we have space for");
  1088.            
  1089.             // Copy the char array
  1090.             // WARNING: We MUST make sure that we don't copy too many chars. We can't
  1091.             // rely on result because it could be a 3rd party implimentation. We need
  1092.             // to make sure we never copy more than charCount chars no matter the value
  1093.             // of result
  1094.             if (result < charCount)
  1095.                 charCount = result;
  1096.            
  1097.             // Copy the data, don't overrun our array!
  1098.             for (index = 0; index < charCount; index++)
  1099.                 chars[index] = arrChar[index];
  1100.            
  1101.             return charCount;
  1102.         }
  1103.        
  1104.        
  1105.         // This is our internal workhorse
  1106.         // Always validate parameters before calling internal version, which will only assert.
  1107.         unsafe internal virtual int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder)
  1108.         {
  1109.             return GetChars(bytes, byteCount, chars, charCount);
  1110.         }
  1111.        
  1112.         // Returns the code page identifier of this encoding. The returned value is
  1113.         // an integer between 0 and 65535 if the encoding has a code page
  1114.         // identifier, or -1 if the encoding does not represent a code page.
  1115.         //
  1116.        
  1117.         public virtual int CodePage {
  1118.             get { return m_codePage; }
  1119.         }
  1120.        
  1121.         // IsAlwaysNormalized
  1122.         // Returns true if the encoding is always normalized for the specified encoding form
  1123.        
  1124.         [System.Runtime.InteropServices.ComVisible(false)]
  1125.         public bool IsAlwaysNormalized()
  1126.         {
  1127.             return this.IsAlwaysNormalized(NormalizationForm.FormC);
  1128.         }
  1129.        
  1130.        
  1131.         [System.Runtime.InteropServices.ComVisible(false)]
  1132.         public virtual bool IsAlwaysNormalized(NormalizationForm form)
  1133.         {
  1134.             // Assume false unless the encoding knows otherwise
  1135.             return false;
  1136.         }
  1137.        
  1138.         // Returns a Decoder object for this encoding. The returned object
  1139.         // can be used to decode a sequence of bytes into a sequence of characters.
  1140.         // Contrary to the GetChars family of methods, a Decoder can
  1141.         // convert partial sequences of bytes into partial sequences of characters
  1142.         // by maintaining the appropriate state between the conversions.
  1143.         //
  1144.         // This default implementation returns a Decoder that simply
  1145.         // forwards calls to the GetCharCount and GetChars methods to
  1146.         // the corresponding methods of this encoding. Encodings that require state
  1147.         // to be maintained between successive conversions should override this
  1148.         // method and return an instance of an appropriate Decoder
  1149.         // implementation.
  1150.         //
  1151.        
  1152.         public virtual Decoder GetDecoder()
  1153.         {
  1154.             return new DefaultDecoder(this);
  1155.         }
  1156.        
  1157.         private static Encoding CreateDefaultEncoding()
  1158.         {
  1159.             Encoding enc;
  1160.             int codePage = Win32Native.GetACP();
  1161.            
  1162.             // For US English, we can save some startup working set by not calling
  1163.             // GetEncoding(int codePage) since JITting GetEncoding will force us to load
  1164.             // all the Encoding classes for ASCII, UTF7 & UTF8, & UnicodeEncoding.
  1165.             if (codePage == 1252)
  1166.                 enc = new SBCSCodePageEncoding(codePage);
  1167.             else
  1168.                 enc = GetEncoding(codePage);
  1169.            
  1170.             return (enc);
  1171.         }
  1172.        
  1173.         // Returns an encoding for the system's current ANSI code page.
  1174.         //
  1175.        
  1176.         public static Encoding Default {
  1177.             get {
  1178.                 if (defaultEncoding == null) {
  1179.                     defaultEncoding = CreateDefaultEncoding();
  1180.                 }
  1181.                 return defaultEncoding;
  1182.             }
  1183.         }
  1184.        
  1185.         // Returns an Encoder object for this encoding. The returned object
  1186.         // can be used to encode a sequence of characters into a sequence of bytes.
  1187.         // Contrary to the GetBytes family of methods, an Encoder can
  1188.         // convert partial sequences of characters into partial sequences of bytes
  1189.         // by maintaining the appropriate state between the conversions.
  1190.         //
  1191.         // This default implementation returns an Encoder that simply
  1192.         // forwards calls to the GetByteCount and GetBytes methods to
  1193.         // the corresponding methods of this encoding. Encodings that require state
  1194.         // to be maintained between successive conversions should override this
  1195.         // method and return an instance of an appropriate Encoder
  1196.         // implementation.
  1197.         //
  1198.        
  1199.         public virtual Encoder GetEncoder()
  1200.         {
  1201.             return new DefaultEncoder(this);
  1202.         }
  1203.        
  1204.         // Returns the maximum number of bytes required to encode a given number of
  1205.         // characters. This method can be used to determine an appropriate buffer
  1206.         // size for byte arrays passed to the GetBytes method of this
  1207.         // encoding or the GetBytes method of an Encoder for this
  1208.         // encoding. All encodings must guarantee that no buffer overflow
  1209.         // exceptions will occur if buffers are sized according to the results of
  1210.         // this method.
  1211.         //
  1212.         // WARNING: If you're using something besides the default replacement encoder fallback,
  1213.         // then you could have more bytes than this returned from an actual call to GetBytes().
  1214.         //
  1215.        
  1216.         public abstract int GetMaxByteCount(int charCount);
  1217.        
  1218.         // Returns the maximum number of characters produced by decoding a given
  1219.         // number of bytes. This method can be used to determine an appropriate
  1220.         // buffer size for character arrays passed to the GetChars method of
  1221.         // this encoding or the GetChars method of a Decoder for this
  1222.         // encoding. All encodings must guarantee that no buffer overflow
  1223.         // exceptions will occur if buffers are sized according to the results of
  1224.         // this method.
  1225.         //
  1226.        
  1227.         public abstract int GetMaxCharCount(int byteCount);
  1228.        
  1229.         // Returns a string containing the decoded representation of a given byte
  1230.         // array.
  1231.         //
  1232.        
  1233.         public virtual string GetString(byte[] bytes)
  1234.         {
  1235.             if (bytes == null)
  1236.                 throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
  1237.            
  1238.             return GetString(bytes, 0, bytes.Length);
  1239.         }
  1240.        
  1241.         // Returns a string containing the decoded representation of a range of
  1242.         // bytes in a byte array.
  1243.         //
  1244.         // Internally we override this for performance
  1245.         //
  1246.        
  1247.         public virtual string GetString(byte[] bytes, int index, int count)
  1248.         {
  1249.             return new string(GetChars(bytes, index, count));
  1250.         }
  1251.        
  1252.         // Returns an encoding for Unicode format. The returned encoding will be
  1253.         // an instance of the UnicodeEncoding class.
  1254.         //
  1255.         // It will use little endian byte order, but will detect
  1256.         // input in big endian if it finds a byte order mark per Unicode 2.0.
  1257.         //
  1258.        
  1259.         public static Encoding Unicode {
  1260.             get {
  1261.                 if (unicodeEncoding == null)
  1262.                     unicodeEncoding = new UnicodeEncoding(false, true);
  1263.                 return unicodeEncoding;
  1264.             }
  1265.         }
  1266.        
  1267.         // Returns an encoding for Unicode format. The returned encoding will be
  1268.         // an instance of the UnicodeEncoding class.
  1269.         //
  1270.         // It will use big endian byte order, but will detect
  1271.         // input in little endian if it finds a byte order mark per Unicode 2.0.
  1272.         //
  1273.        
  1274.         public static Encoding BigEndianUnicode {
  1275.             get {
  1276.                 if (bigEndianUnicode == null)
  1277.                     bigEndianUnicode = new UnicodeEncoding(true, true);
  1278.                 return bigEndianUnicode;
  1279.             }
  1280.         }
  1281.        
  1282.         // Returns an encoding for the UTF-7 format. The returned encoding will be
  1283.         // an instance of the UTF7Encoding class.
  1284.         //
  1285.        
  1286.         public static Encoding UTF7 {
  1287.             get {
  1288.                 if (utf7Encoding == null)
  1289.                     utf7Encoding = new UTF7Encoding();
  1290.                 return utf7Encoding;
  1291.             }
  1292.         }
  1293.        
  1294.         // Returns an encoding for the UTF-8 format. The returned encoding will be
  1295.         // an instance of the UTF8Encoding class.
  1296.         //
  1297.        
  1298.         public static Encoding UTF8 {
  1299.             get {
  1300.                 if (utf8Encoding == null)
  1301.                     utf8Encoding = new UTF8Encoding(true);
  1302.                 return utf8Encoding;
  1303.             }
  1304.         }
  1305.        
  1306.         // Returns an encoding for the UTF-32 format. The returned encoding will be
  1307.         // an instance of the UTF32Encoding class.
  1308.         //
  1309.        
  1310.         public static Encoding UTF32 {
  1311.             get {
  1312.                 if (utf32Encoding == null)
  1313.                     utf32Encoding = new UTF32Encoding(false, true);
  1314.                 return utf32Encoding;
  1315.             }
  1316.         }
  1317.        
  1318.        
  1319.         public override bool Equals(object value)
  1320.         {
  1321.             Encoding that = value as Encoding;
  1322.             if (that != null)
  1323.                 return (m_codePage == that.m_codePage) && (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback));
  1324.             return (false);
  1325.         }
  1326.        
  1327.        
  1328.         public override int GetHashCode()
  1329.         {
  1330.             return m_codePage + this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode();
  1331.         }
  1332.        
  1333.         internal virtual char[] GetBestFitUnicodeToBytesData()
  1334.         {
  1335.             // Normally we don't have any best fit data.
  1336.             return new char[0];
  1337.         }
  1338.        
  1339.         internal virtual char[] GetBestFitBytesToUnicodeData()
  1340.         {
  1341.             // Normally we don't have any best fit data.
  1342.             return new char[0];
  1343.         }
  1344.        
  1345.         internal void ThrowBytesOverflow()
  1346.         {
  1347.             throw new ArgumentException(Environment.GetResourceString("Argument_EncodingConversionOverflowBytes", EncodingName, EncoderFallback.GetType()), "bytes");
  1348.         }
  1349.        
  1350.         internal void ThrowBytesOverflow(EncoderNLS encoder, bool nothingEncoded)
  1351.         {
  1352.             if (encoder == null || encoder.m_throwOnOverflow || nothingEncoded) {
  1353.                 if (encoder != null && encoder.InternalHasFallbackBuffer)
  1354.                     encoder.FallbackBuffer.InternalReset();
  1355.                 ThrowBytesOverflow();
  1356.             }
  1357.            
  1358.             // If we didn't throw, we are in convert and have to remember our flushing
  1359.             encoder.ClearMustFlush();
  1360.         }
  1361.        
  1362.         internal void ThrowCharsOverflow()
  1363.         {
  1364.             throw new ArgumentException(Environment.GetResourceString("Argument_EncodingConversionOverflowChars", EncodingName, DecoderFallback.GetType()), "chars");
  1365.         }
  1366.        
  1367.         internal void ThrowCharsOverflow(DecoderNLS decoder, bool nothingDecoded)
  1368.         {
  1369.             if (decoder == null || decoder.m_throwOnOverflow || nothingDecoded) {
  1370.                 if (decoder != null && decoder.InternalHasFallbackBuffer)
  1371.                     decoder.FallbackBuffer.InternalReset();
  1372.                
  1373.                 ThrowCharsOverflow();
  1374.             }
  1375.            
  1376.             // If we didn't throw, we are in convert and have to remember our flushing
  1377.             decoder.ClearMustFlush();
  1378.         }
  1379.        
  1380.         [Serializable()]
  1381.         internal class DefaultEncoder : Encoder, ISerializable, IObjectReference
  1382.         {
  1383.             private Encoding m_encoding;
  1384.            
  1385.             [NonSerialized()]
  1386.             internal char charLeftOver;
  1387.            
  1388.             public DefaultEncoder(Encoding encoding)
  1389.             {
  1390.                 m_encoding = encoding;
  1391.             }
  1392.            
  1393.             internal DefaultEncoder(SerializationInfo info, StreamingContext context)
  1394.             {
  1395.                 if (info == null)
  1396.                     throw new ArgumentNullException("info");
  1397.                
  1398.                 // All we have is our encoding
  1399.                 this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
  1400.                
  1401.                 try {
  1402.                     this.m_fallback = (EncoderFallback)info.GetValue("m_fallback", typeof(EncoderFallback));
  1403.                     this.charLeftOver = (char)info.GetValue("charLeftOver", typeof(char));
  1404.                 }
  1405.                 catch (SerializationException) {
  1406.                 }
  1407.             }
  1408.            
  1409.             // Just get it from GetEncoding
  1410.             public object GetRealObject(StreamingContext context)
  1411.             {
  1412.                 Encoder encoder = m_encoding.GetEncoder();
  1413.                 if (m_fallback != null)
  1414.                     encoder.m_fallback = m_fallback;
  1415.                 if (charLeftOver != (char)0) {
  1416.                     EncoderNLS encoderNls = encoder as EncoderNLS;
  1417.                     if (encoderNls != null)
  1418.                         encoderNls.charLeftOver = charLeftOver;
  1419.                 }
  1420.                 return encoder;
  1421.             }
  1422.            
  1423.             // ISerializable implementation, get data for this object
  1424.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  1425.             void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  1426.             {
  1427.                 // Any info?
  1428.                 if (info == null)
  1429.                     throw new ArgumentNullException("info");
  1430.                
  1431.                 // All we have is our encoding
  1432.                 info.AddValue("encoding", this.m_encoding);
  1433.             }
  1434.            
  1435.             // Returns the number of bytes the next call to GetBytes will
  1436.             // produce if presented with the given range of characters and the given
  1437.             // value of the flush parameter. The returned value takes into
  1438.             // account the state in which the encoder was left following the last call
  1439.             // to GetBytes. The state of the encoder is not affected by a call
  1440.             // to this method.
  1441.             //
  1442.            
  1443.             public override int GetByteCount(char[] chars, int index, int count, bool flush)
  1444.             {
  1445.                 return m_encoding.GetByteCount(chars, index, count);
  1446.             }
  1447.            
  1448.             unsafe public override int GetByteCount(char* chars, int count, bool flush)
  1449.             {
  1450.                 return m_encoding.GetByteCount(chars, count);
  1451.             }
  1452.            
  1453.             // Encodes a range of characters in a character array into a range of bytes
  1454.             // in a byte array. The method encodes charCount characters from
  1455.             // chars starting at index charIndex, storing the resulting
  1456.             // bytes in bytes starting at index byteIndex. The encoding
  1457.             // takes into account the state in which the encoder was left following the
  1458.             // last call to this method. The flush parameter indicates whether
  1459.             // the encoder should flush any shift-states and partial characters at the
  1460.             // end of the conversion. To ensure correct termination of a sequence of
  1461.             // blocks of encoded bytes, the last call to GetBytes should specify
  1462.             // a value of true for the flush parameter.
  1463.             //
  1464.             // An exception occurs if the byte array is not large enough to hold the
  1465.             // complete encoding of the characters. The GetByteCount method can
  1466.             // be used to determine the exact number of bytes that will be produced for
  1467.             // a given range of characters. Alternatively, the GetMaxByteCount
  1468.             // method of the Encoding that produced this encoder can be used to
  1469.             // determine the maximum number of bytes that will be produced for a given
  1470.             // number of characters, regardless of the actual character values.
  1471.             //
  1472.            
  1473.             public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush)
  1474.             {
  1475.                 return m_encoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
  1476.             }
  1477.            
  1478.             unsafe public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush)
  1479.             {
  1480.                 return m_encoding.GetBytes(chars, charCount, bytes, byteCount);
  1481.             }
  1482.         }
  1483.        
  1484.         [Serializable()]
  1485.         internal class DefaultDecoder : Decoder, ISerializable, IObjectReference
  1486.         {
  1487.             private Encoding m_encoding;
  1488.            
  1489.             public DefaultDecoder(Encoding encoding)
  1490.             {
  1491.                 m_encoding = encoding;
  1492.             }
  1493.            
  1494.             internal DefaultDecoder(SerializationInfo info, StreamingContext context)
  1495.             {
  1496.                 // Any info?
  1497.                 if (info == null)
  1498.                     throw new ArgumentNullException("info");
  1499.                
  1500.                 // All we have is our encoding
  1501.                 this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
  1502.                
  1503.                 try {
  1504.                     this.m_fallback = (DecoderFallback)info.GetValue("m_fallback", typeof(DecoderFallback));
  1505.                 }
  1506.                 catch (SerializationException) {
  1507.                     m_fallback = null;
  1508.                 }
  1509.             }
  1510.            
  1511.             // Just get it from GetEncoding
  1512.             public object GetRealObject(StreamingContext context)
  1513.             {
  1514.                 Decoder decoder = m_encoding.GetDecoder();
  1515.                 if (m_fallback != null)
  1516.                     decoder.m_fallback = m_fallback;
  1517.                
  1518.                 return decoder;
  1519.             }
  1520.            
  1521.             // ISerializable implementation, get data for this object
  1522.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  1523.             void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  1524.             {
  1525.                 // Any info?
  1526.                 if (info == null)
  1527.                     throw new ArgumentNullException("info");
  1528.                
  1529.                 // All we have is our encoding
  1530.                 info.AddValue("encoding", this.m_encoding);
  1531.             }
  1532.            
  1533.             // Returns the number of characters the next call to GetChars will
  1534.             // produce if presented with the given range of bytes. The returned value
  1535.             // takes into account the state in which the decoder was left following the
  1536.             // last call to GetChars. The state of the decoder is not affected
  1537.             // by a call to this method.
  1538.             //
  1539.            
  1540.             public override int GetCharCount(byte[] bytes, int index, int count)
  1541.             {
  1542.                 return GetCharCount(bytes, index, count, false);
  1543.             }
  1544.            
  1545.             public override int GetCharCount(byte[] bytes, int index, int count, bool flush)
  1546.             {
  1547.                 return m_encoding.GetCharCount(bytes, index, count);
  1548.             }
  1549.            
  1550.             unsafe public override int GetCharCount(byte* bytes, int count, bool flush)
  1551.             {
  1552.                 // By default just call the encoding version, no flush by default
  1553.                 return m_encoding.GetCharCount(bytes, count);
  1554.             }
  1555.            
  1556.             // Decodes a range of bytes in a byte array into a range of characters
  1557.             // in a character array. The method decodes byteCount bytes from
  1558.             // bytes starting at index byteIndex, storing the resulting
  1559.             // characters in chars starting at index charIndex. The
  1560.             // decoding takes into account the state in which the decoder was left
  1561.             // following the last call to this method.
  1562.             //
  1563.             // An exception occurs if the character array is not large enough to
  1564.             // hold the complete decoding of the bytes. The GetCharCount method
  1565.             // can be used to determine the exact number of characters that will be
  1566.             // produced for a given range of bytes. Alternatively, the
  1567.             // GetMaxCharCount method of the Encoding that produced this
  1568.             // decoder can be used to determine the maximum number of characters that
  1569.             // will be produced for a given number of bytes, regardless of the actual
  1570.             // byte values.
  1571.             //
  1572.            
  1573.             public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
  1574.             {
  1575.                 return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false);
  1576.             }
  1577.            
  1578.             public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush)
  1579.             {
  1580.                 return m_encoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
  1581.             }
  1582.            
  1583.             unsafe public override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, bool flush)
  1584.             {
  1585.                 // By default just call the encoding's version
  1586.                 return m_encoding.GetChars(bytes, byteCount, chars, charCount);
  1587.             }
  1588.         }
  1589.        
  1590.         internal class EncodingCharBuffer
  1591.         {
  1592.             unsafe char* chars;
  1593.             unsafe char* charStart;
  1594.             unsafe char* charEnd;
  1595.             int charCountResult = 0;
  1596.             Encoding enc;
  1597.             DecoderNLS decoder;
  1598.             unsafe byte* byteStart;
  1599.             unsafe byte* byteEnd;
  1600.             unsafe byte* bytes;
  1601.             DecoderFallbackBuffer fallbackBuffer;
  1602.            
  1603.             unsafe internal EncodingCharBuffer(Encoding enc, DecoderNLS decoder, char* charStart, int charCount, byte* byteStart, int byteCount)
  1604.             {
  1605.                 this.enc = enc;
  1606.                 this.decoder = decoder;
  1607.                
  1608.                 this.chars = charStart;
  1609.                 this.charStart = charStart;
  1610.                 this.charEnd = charStart + charCount;
  1611.                
  1612.                 this.byteStart = byteStart;
  1613.                 this.bytes = byteStart;
  1614.                 this.byteEnd = byteStart + byteCount;
  1615.                
  1616.                 if (this.decoder == null)
  1617.                     this.fallbackBuffer = enc.DecoderFallback.CreateFallbackBuffer();
  1618.                 else
  1619.                     this.fallbackBuffer = this.decoder.FallbackBuffer;
  1620.                
  1621.                 // If we're getting chars or getting char count we don't expect to have
  1622.                 // to remember fallbacks between calls (so it should be empty)
  1623.                 BCLDebug.Assert(fallbackBuffer.Remaining == 0, "[Encoding.EncodingCharBuffer.EncodingCharBuffer]Expected empty fallback buffer for getchars/charcount");
  1624.                 fallbackBuffer.InternalInitialize(bytes, charEnd);
  1625.             }
  1626.            
  1627.             unsafe internal bool AddChar(char ch, int numBytes)
  1628.             {
  1629.                 if (chars != null) {
  1630.                     if (chars >= charEnd) {
  1631.                         // Throw maybe
  1632.                         bytes -= numBytes;
  1633.                         // Didn't encode these bytes
  1634.                         enc.ThrowCharsOverflow(decoder, bytes <= byteStart);
  1635.                         // Throw?
  1636.                         return false;
  1637.                         // No throw, but no store either
  1638.                     }
  1639.                    
  1640.                     *(chars++) = ch;
  1641.                 }
  1642.                 charCountResult++;
  1643.                 return true;
  1644.             }
  1645.            
  1646.             unsafe internal bool AddChar(char ch)
  1647.             {
  1648.                 return AddChar(ch, 1);
  1649.             }
  1650.            
  1651.            
  1652.             unsafe internal bool AddChar(char ch1, char ch2, int numBytes)
  1653.             {
  1654.                 // Need room for 2 chars
  1655.                 if (chars >= charEnd - 1) {
  1656.                     // Throw maybe
  1657.                     bytes -= numBytes;
  1658.                     // Didn't encode these bytes
  1659.                     enc.ThrowCharsOverflow(decoder, bytes <= byteStart);
  1660.                     // Throw?
  1661.                     return false;
  1662.                     // No throw, but no store either
  1663.                 }
  1664.                 return AddChar(ch1, numBytes) && AddChar(ch2, numBytes);
  1665.             }
  1666.            
  1667.             unsafe internal void AdjustBytes(int count)
  1668.             {
  1669.                 bytes += count;
  1670.             }
  1671.            
  1672.             unsafe internal bool MoreData {
  1673.                 get { return bytes < byteEnd; }
  1674.             }
  1675.            
  1676.             // Do we have count more bytes?
  1677.             unsafe internal bool EvenMoreData(int count)
  1678.             {
  1679.                 return (bytes <= byteEnd - count);
  1680.             }
  1681.            
  1682.             // GetNextByte shouldn't be called unless the caller's already checked more data or even more data,
  1683.             // but we'll double check just to make sure.
  1684.             unsafe internal byte GetNextByte()
  1685.             {
  1686.                 BCLDebug.Assert(bytes < byteEnd, "[EncodingCharBuffer.GetNextByte]Expected more date");
  1687.                 if (bytes >= byteEnd)
  1688.                     return 0;
  1689.                 return *(bytes++);
  1690.             }
  1691.            
  1692.             unsafe internal int BytesUsed {
  1693.                 get { return (int)(bytes - byteStart); }
  1694.             }
  1695.            
  1696.             unsafe internal bool Fallback(byte fallbackByte)
  1697.             {
  1698.                 // Build our buffer
  1699.                 byte[] byteBuffer = new byte[] {fallbackByte};
  1700.                
  1701.                 // Do the fallback and add the data.
  1702.                 return Fallback(byteBuffer);
  1703.             }
  1704.            
  1705.             unsafe internal bool Fallback(byte byte1, byte byte2)
  1706.             {
  1707.                 // Build our buffer
  1708.                 byte[] byteBuffer = new byte[] {byte1, byte2};
  1709.                
  1710.                 // Do the fallback and add the data.
  1711.                 return Fallback(byteBuffer);
  1712.             }
  1713.            
  1714.             unsafe internal bool Fallback(byte byte1, byte byte2, byte byte3, byte byte4)
  1715.             {
  1716.                 // Build our buffer
  1717.                 byte[] byteBuffer = new byte[] {byte1, byte2, byte3, byte4};
  1718.                
  1719.                 // Do the fallback and add the data.
  1720.                 return Fallback(byteBuffer);
  1721.             }
  1722.            
  1723.             unsafe internal bool Fallback(byte[] byteBuffer)
  1724.             {
  1725.                 // Do the fallback and add the data.
  1726.                 if (chars != null) {
  1727.                     char* pTemp = chars;
  1728.                     if (fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars) == false) {
  1729.                         // Throw maybe
  1730.                         bytes -= byteBuffer.Length;
  1731.                         // Didn't use how many ever bytes we're falling back
  1732.                         fallbackBuffer.InternalReset();
  1733.                         // We didn't use this fallback.
  1734.                         enc.ThrowCharsOverflow(decoder, chars == charStart);
  1735.                         // Throw?
  1736.                         return false;
  1737.                         // No throw, but no store either
  1738.                     }
  1739.                     charCountResult += unchecked((int)(chars - pTemp));
  1740.                 }
  1741.                 else {
  1742.                     charCountResult += fallbackBuffer.InternalFallback(byteBuffer, bytes);
  1743.                 }
  1744.                
  1745.                 return true;
  1746.             }
  1747.            
  1748.             unsafe internal int Count {
  1749.                 get { return charCountResult; }
  1750.             }
  1751.         }
  1752.        
  1753.         internal class EncodingByteBuffer
  1754.         {
  1755.             unsafe byte* bytes;
  1756.             unsafe byte* byteStart;
  1757.             unsafe byte* byteEnd;
  1758.             unsafe char* chars;
  1759.             unsafe char* charStart;
  1760.             unsafe char* charEnd;
  1761.             int byteCountResult = 0;
  1762.             Encoding enc;
  1763.             EncoderNLS encoder;
  1764.             internal EncoderFallbackBuffer fallbackBuffer;
  1765.            
  1766.             unsafe internal EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder, byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount)
  1767.             {
  1768.                 this.enc = inEncoding;
  1769.                 this.encoder = inEncoder;
  1770.                
  1771.                 this.charStart = inCharStart;
  1772.                 this.chars = inCharStart;
  1773.                 this.charEnd = inCharStart + inCharCount;
  1774.                
  1775.                 this.bytes = inByteStart;
  1776.                 this.byteStart = inByteStart;
  1777.                 this.byteEnd = inByteStart + inByteCount;
  1778.                
  1779.                 if (this.encoder == null)
  1780.                     this.fallbackBuffer = enc.EncoderFallback.CreateFallbackBuffer();
  1781.                 else {
  1782.                     this.fallbackBuffer = this.encoder.FallbackBuffer;
  1783.                     // If we're not converting we must not have data in our fallback buffer
  1784.                     if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer && this.fallbackBuffer.Remaining > 0)
  1785.                         throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", encoder.Encoding.EncodingName, encoder.Fallback.GetType()));
  1786.                 }
  1787.                 fallbackBuffer.InternalInitialize(chars, charEnd, encoder, bytes != null);
  1788.             }
  1789.            
  1790.             unsafe internal bool AddByte(byte b, int moreBytesExpected)
  1791.             {
  1792.                 BCLDebug.Assert(moreBytesExpected >= 0, "[EncodingByteBuffer.AddByte]expected non-negative moreBytesExpected");
  1793.                 if (bytes != null) {
  1794.                     if (bytes >= byteEnd - moreBytesExpected) {
  1795.                         // Throw maybe. Check which buffer to back up (only matters if Converting)
  1796.                         this.MovePrevious(true);
  1797.                         // Throw if necessary
  1798.                         return false;
  1799.                         // No throw, but no store either
  1800.                     }
  1801.                    
  1802.                     *(bytes++) = b;
  1803.                 }
  1804.                 byteCountResult++;
  1805.                 return true;
  1806.             }
  1807.            
  1808.             unsafe internal bool AddByte(byte b1)
  1809.             {
  1810.                 return (AddByte(b1, 0));
  1811.             }
  1812.            
  1813.             unsafe internal bool AddByte(byte b1, byte b2)
  1814.             {
  1815.                 return (AddByte(b1, b2, 0));
  1816.             }
  1817.            
  1818.             unsafe internal bool AddByte(byte b1, byte b2, int moreBytesExpected)
  1819.             {
  1820.                 return (AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected));
  1821.             }
  1822.            
  1823.             unsafe internal bool AddByte(byte b1, byte b2, byte b3)
  1824.             {
  1825.                 return AddByte(b1, b2, b3, (int)0);
  1826.             }
  1827.            
  1828.             unsafe internal bool AddByte(byte b1, byte b2, byte b3, int moreBytesExpected)
  1829.             {
  1830.                 return (AddByte(b1, 2 + moreBytesExpected) && AddByte(b2, 1 + moreBytesExpected) && AddByte(b3, moreBytesExpected));
  1831.             }
  1832.            
  1833.             unsafe internal bool AddByte(byte b1, byte b2, byte b3, byte b4)
  1834.             {
  1835.                 return (AddByte(b1, 3) && AddByte(b2, 2) && AddByte(b3, 1) && AddByte(b4, 0));
  1836.             }
  1837.            
  1838.             unsafe internal void MovePrevious(bool bThrow)
  1839.             {
  1840.                 if (fallbackBuffer.bFallingBack)
  1841.                     fallbackBuffer.MovePrevious();
  1842.                 // don't use last fallback
  1843.                 else {
  1844.                     BCLDebug.Assert(chars > charStart || ((bThrow == true) && (bytes == byteStart)), "[EncodingByteBuffer.MovePrevious]expected previous data or throw");
  1845.                     if (chars > charStart)
  1846.                         chars--;
  1847.                     // don't use last char
  1848.                 }
  1849.                
  1850.                 if (bThrow)
  1851.                     enc.ThrowBytesOverflow(encoder, bytes == byteStart);
  1852.                 // Throw? (and reset fallback if not converting)
  1853.             }
  1854.            
  1855.             unsafe internal bool Fallback(char charFallback)
  1856.             {
  1857.                 // Do the fallback
  1858.                 return fallbackBuffer.InternalFallback(charFallback, ref chars);
  1859.             }
  1860.            
  1861.             unsafe internal bool MoreData {
  1862. // See if fallbackBuffer is not empty or if there's data left in chars buffer.
  1863.                 get { return ((fallbackBuffer.Remaining > 0) || (chars < charEnd)); }
  1864.             }
  1865.            
  1866.             unsafe internal char GetNextChar()
  1867.             {
  1868.                 // See if there's something in our fallback buffer
  1869.                 char cReturn = fallbackBuffer.InternalGetNextChar();
  1870.                
  1871.                 // Nothing in the fallback buffer, return our normal data.
  1872.                 if (cReturn == 0) {
  1873.                     if (chars < charEnd)
  1874.                         cReturn = *(chars++);
  1875.                 }
  1876.                
  1877.                 return cReturn;
  1878.             }
  1879.            
  1880.             unsafe internal int CharsUsed {
  1881.                 get { return (int)(chars - charStart); }
  1882.             }
  1883.            
  1884.             unsafe internal int Count {
  1885.                 get { return byteCountResult; }
  1886.             }
  1887.         }
  1888.     }
  1889. }

Developer Fusion