/* * Encoding.cs - Implementation of the "System.Text.Encoding" class. * * Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd * Copyright (c) 2002, Ximian, Inc. * Copyright (c) 2003, 2004 Novell, Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ namespace System.Text { using System; using System.Reflection; using System.Globalization; using System.Security; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [Serializable] #if NET_2_0 [ComVisible (true)] #endif public abstract class Encoding #if NET_2_0 : ICloneable #endif { // Code page used by this encoding. internal int codePage; internal int windows_code_page; bool is_readonly = true; // Constructor. protected Encoding () { } #if ECMA_COMPAT protected internal #else protected #endif Encoding (int codePage) { this.codePage = windows_code_page = codePage; #if NET_2_0 switch (codePage) { default: // MS has "InternalBestFit{Decoder|Encoder}Fallback // here, but we dunno what they are for. decoder_fallback = DecoderFallback.ReplacementFallback; encoder_fallback = EncoderFallback.ReplacementFallback; break; case 20127: // ASCII case 54936: // GB18030 decoder_fallback = DecoderFallback.ReplacementFallback; encoder_fallback = EncoderFallback.ReplacementFallback; break; case 1200: // UTF16 case 1201: // UTF16 case 12000: // UTF32 case 12001: // UTF32 case 65000: // UTF7 case 65001: // UTF8 decoder_fallback = new DecoderReplacementFallback (String.Empty); encoder_fallback = new EncoderReplacementFallback (String.Empty); break; } #endif } // until we change the callers: internal static string _ (string arg) { return arg; } #if NET_2_0 DecoderFallback decoder_fallback; EncoderFallback encoder_fallback; [ComVisible (false)] public bool IsReadOnly { get { return is_readonly; } } [ComVisible (false)] public virtual bool IsSingleByte { get { return false; } } [MonoTODO ("not used yet")] [ComVisible (false)] public DecoderFallback DecoderFallback { get { if (decoder_fallback == null) decoder_fallback = new DecoderReplacementFallback (String.Empty); return decoder_fallback; } set { if (IsReadOnly) throw new InvalidOperationException ("This Encoding is readonly."); if (value == null) throw new ArgumentNullException (); decoder_fallback = value; } } [MonoTODO ("not used yet")] [ComVisible (false)] public EncoderFallback EncoderFallback { get { if (encoder_fallback == null) encoder_fallback = new EncoderReplacementFallback (String.Empty); return encoder_fallback; } set { if (IsReadOnly) throw new InvalidOperationException ("This Encoding is readonly."); if (value == null) throw new ArgumentNullException (); encoder_fallback = value; } } internal void SetFallbackInternal (EncoderFallback e, DecoderFallback d) { if (e != null) encoder_fallback = e; if (d != null) decoder_fallback = d; } #endif // Convert between two encodings. public static byte[] Convert (Encoding srcEncoding, Encoding dstEncoding, byte[] bytes) { if (srcEncoding == null) { throw new ArgumentNullException ("srcEncoding"); } if (dstEncoding == null) { throw new ArgumentNullException ("dstEncoding"); } if (bytes == null) { throw new ArgumentNullException ("bytes"); } return dstEncoding.GetBytes (srcEncoding.GetChars (bytes, 0, bytes.Length)); } public static byte[] Convert (Encoding srcEncoding, Encoding dstEncoding, byte[] bytes, int index, int count) { if (srcEncoding == null) { throw new ArgumentNullException ("srcEncoding"); } if (dstEncoding == null) { throw new ArgumentNullException ("dstEncoding"); } if (bytes == null) { throw new ArgumentNullException ("bytes"); } if (index < 0 || index > bytes.Length) { throw new ArgumentOutOfRangeException ("index", _("ArgRange_Array")); } if (count < 0 || (bytes.Length - index) < count) { throw new ArgumentOutOfRangeException ("count", _("ArgRange_Array")); } return dstEncoding.GetBytes (srcEncoding.GetChars (bytes, index, count)); } // Determine if two Encoding objects are equal. public override bool Equals (Object obj) { Encoding enc = (obj as Encoding); if (enc != null) { #if NET_2_0 return codePage == enc.codePage && DecoderFallback.Equals (enc.DecoderFallback) && EncoderFallback.Equals (enc.EncoderFallback); #else return (codePage == enc.codePage); #endif } else { return false; } } // Get the number of characters needed to encode a character buffer. public abstract int GetByteCount (char[] chars, int index, int count); // Convenience wrappers for "GetByteCount". public virtual int GetByteCount (String s) { if (s == null) throw new ArgumentNullException ("s"); if (s.Length == 0) return 0; #if NET_2_0 unsafe { fixed (char* cptr = s) { return GetByteCount (cptr, s.Length); } } #else char[] chars = s.ToCharArray (); return GetByteCount (chars, 0, chars.Length); #endif } public virtual int GetByteCount (char[] chars) { if (chars != null) { return GetByteCount (chars, 0, chars.Length); } else { throw new ArgumentNullException ("chars"); } } // Get the bytes that result from encoding a character buffer. public abstract int GetBytes (char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex); // Convenience wrappers for "GetBytes". public virtual int GetBytes (String s, int charIndex, int charCount, byte[] bytes, int byteIndex) { if (s == null) throw new ArgumentNullException ("s"); #if NET_2_0 if (charIndex < 0 || charIndex > s.Length) throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array")); if (charCount < 0 || charIndex + charCount > s.Length) throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array")); if (byteIndex < 0 || byteIndex > bytes.Length) throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array")); if (charCount == 0 || bytes.Length == byteIndex) return 0; unsafe { fixed (char* cptr = s) { fixed (byte* bptr = bytes) { return GetBytes (cptr + charIndex, charCount, bptr + byteIndex, bytes.Length - byteIndex); } } } #else return GetBytes (s.ToCharArray(), charIndex, charCount, bytes, byteIndex); #endif } public virtual byte[] GetBytes (String s) { if (s == null) throw new ArgumentNullException ("s"); #if NET_2_0 if (s.Length == 0) return new byte [0]; int byteCount = GetByteCount (s); if (byteCount == 0) return new byte [0]; unsafe { fixed (char* cptr = s) { byte [] bytes = new byte [byteCount]; fixed (byte* bptr = bytes) { GetBytes (cptr, s.Length, bptr, byteCount); return bytes; } } } #else char[] chars = s.ToCharArray (); int numBytes = GetByteCount (chars, 0, chars.Length); byte[] bytes = new byte [numBytes]; GetBytes (chars, 0, chars.Length, bytes, 0); return bytes; #endif } public virtual byte[] GetBytes (char[] chars, int index, int count) { int numBytes = GetByteCount (chars, index, count); byte[] bytes = new byte [numBytes]; GetBytes (chars, index, count, bytes, 0); return bytes; } public virtual byte[] GetBytes (char[] chars) { int numBytes = GetByteCount (chars, 0, chars.Length); byte[] bytes = new byte [numBytes]; GetBytes (chars, 0, chars.Length, bytes, 0); return bytes; } // Get the number of characters needed to decode a byte buffer. public abstract int GetCharCount (byte[] bytes, int index, int count); // Convenience wrappers for "GetCharCount". public virtual int GetCharCount (byte[] bytes) { if (bytes == null) { throw new ArgumentNullException ("bytes"); } return GetCharCount (bytes, 0, bytes.Length); } // Get the characters that result from decoding a byte buffer. public abstract int GetChars (byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex); // Convenience wrappers for "GetChars". public virtual char[] GetChars (byte[] bytes, int index, int count) { int numChars = GetCharCount (bytes, index, count); char[] chars = new char [numChars]; GetChars (bytes, index, count, chars, 0); return chars; } public virtual char[] GetChars (byte[] bytes) { if (bytes == null) { throw new ArgumentNullException ("bytes"); } int numChars = GetCharCount (bytes, 0, bytes.Length); char[] chars = new char [numChars]; GetChars (bytes, 0, bytes.Length, chars, 0); return chars; } // Get a decoder that forwards requests to this object. public virtual Decoder GetDecoder () { return new ForwardingDecoder (this); } // Get an encoder that forwards requests to this object. public virtual Encoder GetEncoder () { return new ForwardingEncoder (this); } // Loaded copy of the "I18N" assembly. We need to move // this into a class in "System.Private" eventually. private static Assembly i18nAssembly; private static bool i18nDisabled; // Invoke a specific method on the "I18N" manager object. // Returns NULL if the method failed. private static Object InvokeI18N (String name, params Object[] args) { lock (lockobj) { // Bail out if we previously detected that there // is insufficent engine support for I18N handling. if (i18nDisabled) { return null; } // Find or load the "I18N" assembly. if (i18nAssembly == null) { try { try { i18nAssembly = Assembly.Load (Consts.AssemblyI18N); } catch (NotImplementedException) { // Assembly loading unsupported by the engine. i18nDisabled = true; return null; } if (i18nAssembly == null) { return null; } } catch (SystemException) { return null; } } // Find the "I18N.Common.Manager" class. Type managerClass; try { managerClass = i18nAssembly.GetType ("I18N.Common.Manager"); } catch (NotImplementedException) { // "GetType" is not supported by the engine. i18nDisabled = true; return null; } if (managerClass == null) { return null; } // Get the value of the "PrimaryManager" property. Object manager; try { manager = managerClass.InvokeMember ("PrimaryManager", BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public, null, null, null, null, null, null); if (manager == null) { return null; } } catch (MissingMethodException) { return null; } catch (SecurityException) { return null; } catch (NotImplementedException) { // "InvokeMember" is not supported by the engine. i18nDisabled = true; return null; } // Invoke the requested method on the manager. try { return managerClass.InvokeMember (name, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, manager, args, null, null, null); } catch (MissingMethodException) { return null; } catch (SecurityException) { return null; } } } // Get an encoder for a specific code page. #if ECMA_COMPAT private #else public #endif static Encoding GetEncoding (int codePage) { if (codePage < 0 || codePage > 0xffff) throw new ArgumentOutOfRangeException ("codepage", "Valid values are between 0 and 65535, inclusive."); // Check for the builtin code pages first. switch (codePage) { case 0: return Default; case ASCIIEncoding.ASCII_CODE_PAGE: return ASCII; case UTF7Encoding.UTF7_CODE_PAGE: return UTF7; case UTF8Encoding.UTF8_CODE_PAGE: return UTF8; #if NET_2_0 case UTF32Encoding.UTF32_CODE_PAGE: return UTF32; case UTF32Encoding.BIG_UTF32_CODE_PAGE: return BigEndianUTF32; #endif case UnicodeEncoding.UNICODE_CODE_PAGE: return Unicode; case UnicodeEncoding.BIG_UNICODE_CODE_PAGE: return BigEndianUnicode; case Latin1Encoding.ISOLATIN_CODE_PAGE: return ISOLatin1; default: break; } // Try to obtain a code page handler from the I18N handler. Encoding enc = (Encoding)(InvokeI18N ("GetEncoding", codePage)); if (enc != null) { enc.is_readonly = true; return enc; } // Build a code page class name. String cpName = "System.Text.CP" + codePage.ToString (); // Look for a code page converter in this assembly. Assembly assembly = Assembly.GetExecutingAssembly (); Type type = assembly.GetType (cpName); if (type != null) { enc = (Encoding)(Activator.CreateInstance (type)); enc.is_readonly = true; return enc; } // Look in any assembly, in case the application // has provided its own code page handler. type = Type.GetType (cpName); if (type != null) { enc = (Encoding)(Activator.CreateInstance (type)); enc.is_readonly = true; return enc; } // We have no idea how to handle this code page. throw new NotSupportedException (String.Format ("CodePage {0} not supported", codePage.ToString ())); } #if !ECMA_COMPAT #if NET_2_0 [ComVisible (false)] public virtual object Clone () { Encoding e = (Encoding) MemberwiseClone (); e.is_readonly = false; return e; } public static Encoding GetEncoding (int codePage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { if (encoderFallback == null) throw new ArgumentNullException ("encoderFallback"); if (decoderFallback == null) throw new ArgumentNullException ("decoderFallback"); Encoding e = GetEncoding (codePage).Clone () as Encoding; e.is_readonly = false; e.encoder_fallback = encoderFallback; e.decoder_fallback = decoderFallback; return e; } public static Encoding GetEncoding (string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { if (encoderFallback == null) throw new ArgumentNullException ("encoderFallback"); if (decoderFallback == null) throw new ArgumentNullException ("decoderFallback"); Encoding e = GetEncoding (name).Clone () as Encoding; e.is_readonly = false; e.encoder_fallback = encoderFallback; e.decoder_fallback = decoderFallback; return e; } static EncodingInfo [] encoding_infos; // FIXME: As everyone would agree, this implementation is so *hacky* // and could be very easily broken. But since there is a test for // this method to make sure that this method always returns // the same number and content of encoding infos, this won't // matter practically. public static EncodingInfo[] GetEncodings () { if (encoding_infos == null) { int [] codepages = new int [] { 37, 437, 500, 708, 850, 852, 855, 857, 858, 860, 861, 862, 863, 864, 865, 866, 869, 870, 874, 875, 932, 936, 949, 950, 1026, 1047, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1200, 1201, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000, 10079, 12000, 12001, 20127, 20273, 20277, 20278, 20280, 20284, 20285, 20290, 20297, 20420, 20424, 20866, 20871, 21025, 21866, 28591, 28592, 28593, 28594, 28595, 28596, 28597, 28598, 28599, 28605, 38598, 50220, 50221, 50222, 51932, 51949, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 65001}; encoding_infos = new EncodingInfo [codepages.Length]; for (int i = 0; i < codepages.Length; i++) encoding_infos [i] = new EncodingInfo (codepages [i]); } return encoding_infos; } public bool IsAlwaysNormalized () { return IsAlwaysNormalized (NormalizationForm.FormC); } public virtual bool IsAlwaysNormalized (NormalizationForm form) { // umm, ASCIIEncoding should have overriden this method, no? return form == NormalizationForm.FormC && this is ASCIIEncoding; } #endif // Table of builtin web encoding names and the corresponding code pages. private static readonly object[] encodings = { ASCIIEncoding.ASCII_CODE_PAGE, "ascii", "us_ascii", "us", "ansi_x3.4_1968", "ansi_x3.4_1986", "cp367", "csascii", "ibm367", "iso_ir_6", "iso646_us", "iso_646.irv:1991", UTF7Encoding.UTF7_CODE_PAGE, "utf_7", "csunicode11utf7", "unicode_1_1_utf_7", "unicode_2_0_utf_7", "x_unicode_1_1_utf_7", "x_unicode_2_0_utf_7", UTF8Encoding.UTF8_CODE_PAGE, "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8", "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8", UnicodeEncoding.UNICODE_CODE_PAGE, "utf_16", "UTF_16LE", "ucs_2", "unicode", "iso_10646_ucs2", UnicodeEncoding.BIG_UNICODE_CODE_PAGE, "unicodefffe", "utf_16be", #if NET_2_0 UTF32Encoding.UTF32_CODE_PAGE, "utf_32", "UTF_32LE", "ucs_4", UTF32Encoding.BIG_UTF32_CODE_PAGE, "UTF_32BE", #endif Latin1Encoding.ISOLATIN_CODE_PAGE, "iso_8859_1", "latin1" }; // Get an encoding object for a specific web encoding name. public static Encoding GetEncoding (String name) { // Validate the parameters. if (name == null) { throw new ArgumentNullException ("name"); } string converted = name.ToLowerInvariant ().Replace ('-', '_'); // Search the table for a name match. int code = 0; for (int i = 0; i < encodings.Length; ++i) { object o = encodings [i]; if (o is int){ code = (int) o; continue; } if (converted == ((string)encodings [i])) return GetEncoding (code); } // Try to obtain a web encoding handler from the I18N handler. Encoding enc = (Encoding)(InvokeI18N ("GetEncoding", name)); if (enc != null) { return enc; } // Build a web encoding class name. String encName = "System.Text.ENC" + converted; // Look for a code page converter in this assembly. Assembly assembly = Assembly.GetExecutingAssembly (); Type type = assembly.GetType (encName); if (type != null) { return (Encoding)(Activator.CreateInstance (type)); } // Look in any assembly, in case the application // has provided its own code page handler. type = Type.GetType (encName); if (type != null) { return (Encoding)(Activator.CreateInstance (type)); } // We have no idea how to handle this encoding name. throw new ArgumentException (String.Format ("Encoding name '{0}' not " + "supported", name), "name"); } #endif // !ECMA_COMPAT // Get a hash code for this instance. public override int GetHashCode () { #if NET_2_0 return DecoderFallback.GetHashCode () << 24 + EncoderFallback.GetHashCode () << 16 + codePage; #else return codePage; #endif } // Get the maximum number of bytes needed to encode a // specified number of characters. public abstract int GetMaxByteCount (int charCount); // Get the maximum number of characters needed to decode a // specified number of bytes. public abstract int GetMaxCharCount (int byteCount); // Get the identifying preamble for this encoding. public virtual byte[] GetPreamble () { return new byte [0]; } // Decode a buffer of bytes into a string. public virtual String GetString (byte[] bytes, int index, int count) { return new String (GetChars(bytes, index, count)); } public virtual String GetString (byte[] bytes) { if (bytes == null) throw new ArgumentNullException ("bytes"); return GetString (bytes, 0, bytes.Length); } #if !ECMA_COMPAT internal string body_name; internal string encoding_name; internal string header_name; internal bool is_mail_news_display; internal bool is_mail_news_save; internal bool is_browser_save = false; internal bool is_browser_display = false; internal string web_name; // Get the mail body name for this encoding. public virtual String BodyName { get { return body_name; } } // Get the code page represented by this object. public virtual int CodePage { get { return codePage; } } // Get the human-readable name for this encoding. public virtual String EncodingName { get { return encoding_name; } } // Get the mail agent header name for this encoding. public virtual String HeaderName { get { return header_name; } } // Determine if this encoding can be displayed in a Web browser. public virtual bool IsBrowserDisplay { get { return is_browser_display; } } // Determine if this encoding can be saved from a Web browser. public virtual bool IsBrowserSave { get { return is_browser_save; } } // Determine if this encoding can be displayed in a mail/news agent. public virtual bool IsMailNewsDisplay { get { return is_mail_news_display; } } // Determine if this encoding can be saved from a mail/news agent. public virtual bool IsMailNewsSave { get { return is_mail_news_save; } } // Get the IANA-preferred Web name for this encoding. public virtual String WebName { get { return web_name; } } // Get the Windows code page represented by this object. public virtual int WindowsCodePage { get { // We make no distinction between normal and // Windows code pages in this implementation. return windows_code_page; } } #endif // !ECMA_COMPAT // Storage for standard encoding objects. static volatile Encoding asciiEncoding; static volatile Encoding bigEndianEncoding; static volatile Encoding defaultEncoding; static volatile Encoding utf7Encoding; static volatile Encoding utf8EncodingWithMarkers; static volatile Encoding utf8EncodingWithoutMarkers; static volatile Encoding unicodeEncoding; static volatile Encoding isoLatin1Encoding; static volatile Encoding unixConsoleEncoding; #if NET_2_0 static volatile Encoding utf32Encoding; static volatile Encoding bigEndianUTF32Encoding; #endif static readonly object lockobj = new object (); // Get the standard ASCII encoding object. public static Encoding ASCII { get { if (asciiEncoding == null) { lock (lockobj) { if (asciiEncoding == null) { asciiEncoding = new ASCIIEncoding (); asciiEncoding.is_readonly = true; } } } return asciiEncoding; } } // Get the standard big-endian Unicode encoding object. public static Encoding BigEndianUnicode { get { if (bigEndianEncoding == null) { lock (lockobj) { if (bigEndianEncoding == null) { bigEndianEncoding = new UnicodeEncoding (true, true); bigEndianEncoding.is_readonly = true; } } } return bigEndianEncoding; } } [MethodImpl (MethodImplOptions.InternalCall)] extern internal static string InternalCodePage (ref int code_page); // Get the default encoding object. public static Encoding Default { get { if (defaultEncoding == null) { lock (lockobj) { if (defaultEncoding == null) { // See if the underlying system knows what // code page handler we should be using. int code_page = 1; string code_page_name = InternalCodePage (ref code_page); try { if (code_page == -1) defaultEncoding = GetEncoding (code_page_name); else { // map the codepage from internal to our numbers code_page = code_page & 0x0fffffff; switch (code_page){ case 1: code_page = ASCIIEncoding.ASCII_CODE_PAGE; break; case 2: code_page = UTF7Encoding.UTF7_CODE_PAGE; break; case 3: code_page = UTF8Encoding.UTF8_CODE_PAGE; break; case 4: code_page = UnicodeEncoding.UNICODE_CODE_PAGE; break; case 5: code_page = UnicodeEncoding.BIG_UNICODE_CODE_PAGE; break; case 6: code_page = Latin1Encoding.ISOLATIN_CODE_PAGE; break; } defaultEncoding = GetEncoding (code_page); } } catch (NotSupportedException) { // code_page is not supported on underlying platform defaultEncoding = UTF8Unmarked; } catch (ArgumentException) { // code_page_name is not a valid code page, or is // not supported by underlying OS defaultEncoding = UTF8Unmarked; } defaultEncoding.is_readonly = true; } } } return defaultEncoding; } } // Get the ISO Latin1 encoding object. private static Encoding ISOLatin1 { get { if (isoLatin1Encoding == null) { lock (lockobj) { if (isoLatin1Encoding == null) { isoLatin1Encoding = new Latin1Encoding (); isoLatin1Encoding.is_readonly = true; } } } return isoLatin1Encoding; } } // Get the standard UTF-7 encoding object. #if ECMA_COMPAT private #else public #endif static Encoding UTF7 { get { if (utf7Encoding == null) { lock (lockobj) { if (utf7Encoding == null) { utf7Encoding = new UTF7Encoding (); utf7Encoding.is_readonly = true; } } } return utf7Encoding; } } // Get the standard UTF-8 encoding object. public static Encoding UTF8 { get { if (utf8EncodingWithMarkers == null) { lock (lockobj) { if (utf8EncodingWithMarkers == null) { utf8EncodingWithMarkers = new UTF8Encoding (true); utf8EncodingWithMarkers.is_readonly = true; } } } return utf8EncodingWithMarkers; } } // // Only internal, to be used by the class libraries: Unmarked and non-input-validating // internal static Encoding UTF8Unmarked { get { if (utf8EncodingWithoutMarkers == null) { lock (lockobj){ if (utf8EncodingWithoutMarkers == null){ utf8EncodingWithoutMarkers = new UTF8Encoding (false, false); utf8EncodingWithoutMarkers.is_readonly = true; } } } return utf8EncodingWithoutMarkers; } } // Get the standard little-endian Unicode encoding object. public static Encoding Unicode { get { if (unicodeEncoding == null) { lock (lockobj) { if (unicodeEncoding == null) { unicodeEncoding = new UnicodeEncoding (false, true); unicodeEncoding.is_readonly = true; } } } return unicodeEncoding; } } #if NET_2_0 // Get the standard little-endian UTF-32 encoding object. public static Encoding UTF32 { get { if (utf32Encoding == null) { lock (lockobj) { if (utf32Encoding == null) { utf32Encoding = new UTF32Encoding (false, true); utf32Encoding.is_readonly = true; } } } return utf32Encoding; } } // Get the standard big-endian UTF-32 encoding object. internal static Encoding BigEndianUTF32 { get { if (bigEndianUTF32Encoding == null) { lock (lockobj) { if (bigEndianUTF32Encoding == null) { bigEndianUTF32Encoding = new UTF32Encoding (true, true); bigEndianUTF32Encoding.is_readonly = true; } } } return bigEndianUTF32Encoding; } } #endif // Forwarding decoder implementation. private sealed class ForwardingDecoder : Decoder { private Encoding encoding; // Constructor. public ForwardingDecoder (Encoding enc) { encoding = enc; #if NET_2_0 Fallback = encoding.DecoderFallback; #endif } // Override inherited methods. public override int GetCharCount (byte[] bytes, int index, int count) { return encoding.GetCharCount (bytes, index, count); } public override int GetChars (byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { return encoding.GetChars (bytes, byteIndex, byteCount, chars, charIndex); } } // class ForwardingDecoder // Forwarding encoder implementation. private sealed class ForwardingEncoder : Encoder { private Encoding encoding; // Constructor. public ForwardingEncoder (Encoding enc) { encoding = enc; #if NET_2_0 Fallback = encoding.EncoderFallback; #endif } // Override inherited methods. public override int GetByteCount (char[] chars, int index, int count, bool flush) { return encoding.GetByteCount (chars, index, count); } public override int GetBytes (char[] chars, int charIndex, int charCount, byte[] bytes, int byteCount, bool flush) { return encoding.GetBytes (chars, charIndex, charCount, bytes, byteCount); } } // class ForwardingEncoder #if NET_2_0 [CLSCompliantAttribute(false)] [ComVisible (false)] public unsafe virtual int GetByteCount (char *chars, int count) { if (chars == null) throw new ArgumentNullException ("chars"); if (count < 0) throw new ArgumentOutOfRangeException ("count"); char [] c = new char [count]; for (int p = 0; p < count; p++) c [p] = chars [p]; return GetByteCount (c); } [CLSCompliantAttribute(false)] [ComVisible (false)] public unsafe virtual int GetCharCount (byte *bytes, int count) { if (bytes == null) throw new ArgumentNullException ("bytes"); if (count < 0) throw new ArgumentOutOfRangeException ("count"); byte [] ba = new byte [count]; for (int i = 0; i < count; i++) ba [i] = bytes [i]; return GetCharCount (ba, 0, count); } [CLSCompliantAttribute(false)] [ComVisible (false)] public unsafe virtual int GetChars (byte *bytes, int byteCount, char *chars, int charCount) { if (bytes == null) throw new ArgumentNullException ("bytes"); if (chars == null) throw new ArgumentNullException ("chars"); if (charCount < 0) throw new ArgumentOutOfRangeException ("charCount"); if (byteCount < 0) throw new ArgumentOutOfRangeException ("byteCount"); byte [] ba = new byte [byteCount]; for (int i = 0; i < byteCount; i++) ba [i] = bytes [i]; char [] ret = GetChars (ba, 0, byteCount); int top = ret.Length; if (top > charCount) throw new ArgumentException ("charCount is less than the number of characters produced", "charCount"); for (int i = 0; i < top; i++) chars [i] = ret [i]; return top; } [CLSCompliantAttribute(false)] [ComVisible (false)] public unsafe virtual int GetBytes (char *chars, int charCount, byte *bytes, int byteCount) { if (bytes == null) throw new ArgumentNullException ("bytes"); if (chars == null) throw new ArgumentNullException ("chars"); if (charCount < 0) throw new ArgumentOutOfRangeException ("charCount"); if (byteCount < 0) throw new ArgumentOutOfRangeException ("byteCount"); char [] c = new char [charCount]; for (int i = 0; i < charCount; i++) c [i] = chars [i]; byte [] b = GetBytes (c, 0, charCount); int top = b.Length; if (top > byteCount) throw new ArgumentException ("byteCount is less that the number of bytes produced", "byteCount"); for (int i = 0; i < top; i++) bytes [i] = b [i]; return b.Length; } #endif }; // class Encoding }; // namespace System.Text