2009-12-09 Chris Toshok <toshok@ximian.com>
[mono-project.git] / mcs / class / corlib / System.Text / Encoding.cs
blob303b150a7304721c699be7d5bbc4154b1957f8e7
1 /*
2 * Encoding.cs - Implementation of the "System.Text.Encoding" class.
4 * Copyright (c) 2001, 2002 Southern Storm Software, Pty Ltd
5 * Copyright (c) 2002, Ximian, Inc.
6 * Copyright (c) 2003, 2004 Novell, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
27 namespace System.Text
30 using System;
31 using System.Reflection;
32 using System.Globalization;
33 using System.Security;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
37 [Serializable]
38 [ComVisible (true)]
39 public abstract class Encoding : ICloneable
41 // Code page used by this encoding.
42 internal int codePage;
43 internal int windows_code_page;
44 bool is_readonly = true;
46 // Constructor.
47 protected Encoding ()
51 #if ECMA_COMPAT
52 protected internal
53 #else
54 protected
55 #endif
56 Encoding (int codePage)
58 this.codePage = windows_code_page = codePage;
60 switch (codePage) {
61 default:
62 // MS has "InternalBestFit{Decoder|Encoder}Fallback
63 // here, but we dunno what they are for.
64 decoder_fallback = DecoderFallback.ReplacementFallback;
65 encoder_fallback = EncoderFallback.ReplacementFallback;
66 break;
67 case 20127: // ASCII
68 case 54936: // GB18030
69 decoder_fallback = DecoderFallback.ReplacementFallback;
70 encoder_fallback = EncoderFallback.ReplacementFallback;
71 break;
72 case 1200: // UTF16
73 case 1201: // UTF16
74 case 12000: // UTF32
75 case 12001: // UTF32
76 case 65000: // UTF7
77 case 65001: // UTF8
78 decoder_fallback = DecoderFallback.StandardSafeFallback;
79 encoder_fallback = EncoderFallback.StandardSafeFallback;
80 break;
84 // until we change the callers:
85 internal static string _ (string arg) {
86 return arg;
89 DecoderFallback decoder_fallback;
90 EncoderFallback encoder_fallback;
92 [ComVisible (false)]
93 public bool IsReadOnly {
94 get { return is_readonly; }
97 [ComVisible (false)]
98 public virtual bool IsSingleByte {
99 get { return false; }
102 [ComVisible (false)]
103 public DecoderFallback DecoderFallback {
104 get { return decoder_fallback; }
105 set {
106 if (IsReadOnly)
107 throw new InvalidOperationException ("This Encoding is readonly.");
108 if (value == null)
109 throw new ArgumentNullException ();
110 decoder_fallback = value;
114 [ComVisible (false)]
115 public EncoderFallback EncoderFallback {
116 get { return encoder_fallback; }
117 set {
118 if (IsReadOnly)
119 throw new InvalidOperationException ("This Encoding is readonly.");
120 if (value == null)
121 throw new ArgumentNullException ();
122 encoder_fallback = value;
126 internal void SetFallbackInternal (EncoderFallback e, DecoderFallback d)
128 if (e != null)
129 encoder_fallback = e;
130 if (d != null)
131 decoder_fallback = d;
134 // Convert between two encodings.
135 public static byte[] Convert (Encoding srcEncoding, Encoding dstEncoding,
136 byte[] bytes)
138 if (srcEncoding == null) {
139 throw new ArgumentNullException ("srcEncoding");
141 if (dstEncoding == null) {
142 throw new ArgumentNullException ("dstEncoding");
144 if (bytes == null) {
145 throw new ArgumentNullException ("bytes");
147 return dstEncoding.GetBytes (srcEncoding.GetChars (bytes, 0, bytes.Length));
149 public static byte[] Convert (Encoding srcEncoding, Encoding dstEncoding,
150 byte[] bytes, int index, int count)
152 if (srcEncoding == null) {
153 throw new ArgumentNullException ("srcEncoding");
155 if (dstEncoding == null) {
156 throw new ArgumentNullException ("dstEncoding");
158 if (bytes == null) {
159 throw new ArgumentNullException ("bytes");
161 if (index < 0 || index > bytes.Length) {
162 throw new ArgumentOutOfRangeException
163 ("index", _("ArgRange_Array"));
165 if (count < 0 || (bytes.Length - index) < count) {
166 throw new ArgumentOutOfRangeException
167 ("count", _("ArgRange_Array"));
169 return dstEncoding.GetBytes (srcEncoding.GetChars (bytes, index, count));
172 // Determine if two Encoding objects are equal.
173 public override bool Equals (Object value)
175 Encoding enc = (value as Encoding);
176 if (enc != null) {
177 return codePage == enc.codePage &&
178 DecoderFallback.Equals (enc.DecoderFallback) &&
179 EncoderFallback.Equals (enc.EncoderFallback);
180 } else {
181 return false;
185 // Get the number of characters needed to encode a character buffer.
186 public abstract int GetByteCount (char[] chars, int index, int count);
188 // Convenience wrappers for "GetByteCount".
189 public virtual int GetByteCount (String s)
191 if (s == null)
192 throw new ArgumentNullException ("s");
194 if (s.Length == 0)
195 return 0;
196 unsafe {
197 fixed (char* cptr = s) {
198 return GetByteCount (cptr, s.Length);
202 public virtual int GetByteCount (char[] chars)
204 if (chars != null) {
205 return GetByteCount (chars, 0, chars.Length);
206 } else {
207 throw new ArgumentNullException ("chars");
211 // Get the bytes that result from encoding a character buffer.
212 public abstract int GetBytes (char[] chars, int charIndex, int charCount,
213 byte[] bytes, int byteIndex);
215 // Convenience wrappers for "GetBytes".
216 public virtual int GetBytes (String s, int charIndex, int charCount,
217 byte[] bytes, int byteIndex)
219 if (s == null)
220 throw new ArgumentNullException ("s");
221 if (charIndex < 0 || charIndex > s.Length)
222 throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
223 if (charCount < 0 || charIndex > (s.Length - charCount))
224 throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
225 if (byteIndex < 0 || byteIndex > bytes.Length)
226 throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
228 if (charCount == 0 || bytes.Length == byteIndex)
229 return 0;
230 unsafe {
231 fixed (char* cptr = s) {
232 fixed (byte* bptr = bytes) {
233 return GetBytes (cptr + charIndex,
234 charCount,
235 bptr + byteIndex,
236 bytes.Length - byteIndex);
241 public virtual byte[] GetBytes (String s)
243 if (s == null)
244 throw new ArgumentNullException ("s");
246 if (s.Length == 0)
247 return new byte [0];
248 int byteCount = GetByteCount (s);
249 if (byteCount == 0)
250 return new byte [0];
251 unsafe {
252 fixed (char* cptr = s) {
253 byte [] bytes = new byte [byteCount];
254 fixed (byte* bptr = bytes) {
255 GetBytes (cptr, s.Length,
256 bptr, byteCount);
257 return bytes;
263 public virtual byte[] GetBytes (char[] chars, int index, int count)
265 int numBytes = GetByteCount (chars, index, count);
266 byte[] bytes = new byte [numBytes];
267 GetBytes (chars, index, count, bytes, 0);
268 return bytes;
270 public virtual byte[] GetBytes (char[] chars)
272 int numBytes = GetByteCount (chars, 0, chars.Length);
273 byte[] bytes = new byte [numBytes];
274 GetBytes (chars, 0, chars.Length, bytes, 0);
275 return bytes;
278 // Get the number of characters needed to decode a byte buffer.
279 public abstract int GetCharCount (byte[] bytes, int index, int count);
281 // Convenience wrappers for "GetCharCount".
282 public virtual int GetCharCount (byte[] bytes)
284 if (bytes == null) {
285 throw new ArgumentNullException ("bytes");
287 return GetCharCount (bytes, 0, bytes.Length);
290 // Get the characters that result from decoding a byte buffer.
291 public abstract int GetChars (byte[] bytes, int byteIndex, int byteCount,
292 char[] chars, int charIndex);
294 // Convenience wrappers for "GetChars".
295 public virtual char[] GetChars (byte[] bytes, int index, int count)
297 int numChars = GetCharCount (bytes, index, count);
298 char[] chars = new char [numChars];
299 GetChars (bytes, index, count, chars, 0);
300 return chars;
302 public virtual char[] GetChars (byte[] bytes)
304 if (bytes == null) {
305 throw new ArgumentNullException ("bytes");
307 int numChars = GetCharCount (bytes, 0, bytes.Length);
308 char[] chars = new char [numChars];
309 GetChars (bytes, 0, bytes.Length, chars, 0);
310 return chars;
313 // Get a decoder that forwards requests to this object.
314 public virtual Decoder GetDecoder ()
316 return new ForwardingDecoder (this);
319 // Get an encoder that forwards requests to this object.
320 public virtual Encoder GetEncoder ()
322 return new ForwardingEncoder (this);
325 // Loaded copy of the "I18N" assembly. We need to move
326 // this into a class in "System.Private" eventually.
327 private static Assembly i18nAssembly;
328 private static bool i18nDisabled;
330 // Invoke a specific method on the "I18N" manager object.
331 // Returns NULL if the method failed.
332 private static Object InvokeI18N (String name, params Object[] args)
334 lock (lockobj) {
335 // Bail out if we previously detected that there
336 // is insufficent engine support for I18N handling.
337 if (i18nDisabled) {
338 return null;
341 // Find or load the "I18N" assembly.
342 if (i18nAssembly == null) {
343 try {
344 try {
345 i18nAssembly = Assembly.Load (Consts.AssemblyI18N);
346 } catch (NotImplementedException) {
347 // Assembly loading unsupported by the engine.
348 i18nDisabled = true;
349 return null;
351 if (i18nAssembly == null) {
352 return null;
354 } catch (SystemException) {
355 return null;
359 // Find the "I18N.Common.Manager" class.
360 Type managerClass;
361 try {
362 managerClass = i18nAssembly.GetType ("I18N.Common.Manager");
363 } catch (NotImplementedException) {
364 // "GetType" is not supported by the engine.
365 i18nDisabled = true;
366 return null;
368 if (managerClass == null) {
369 return null;
372 // Get the value of the "PrimaryManager" property.
373 Object manager;
374 try {
375 manager = managerClass.InvokeMember
376 ("PrimaryManager",
377 BindingFlags.GetProperty |
378 BindingFlags.Static |
379 BindingFlags.Public,
380 null, null, null, null, null, null);
381 if (manager == null) {
382 return null;
384 } catch (MissingMethodException) {
385 return null;
386 } catch (SecurityException) {
387 return null;
388 } catch (NotImplementedException) {
389 // "InvokeMember" is not supported by the engine.
390 i18nDisabled = true;
391 return null;
394 // Invoke the requested method on the manager.
395 try {
396 return managerClass.InvokeMember
397 (name,
398 BindingFlags.InvokeMethod |
399 BindingFlags.Instance |
400 BindingFlags.Public,
401 null, manager, args, null, null, null);
402 } catch (MissingMethodException) {
403 return null;
404 } catch (SecurityException) {
405 return null;
410 // Get an encoder for a specific code page.
411 #if ECMA_COMPAT
412 private
413 #else
414 public
415 #endif
416 static Encoding GetEncoding (int codepage)
418 if (codepage < 0 || codepage > 0xffff)
419 throw new ArgumentOutOfRangeException ("codepage",
420 "Valid values are between 0 and 65535, inclusive.");
422 // Check for the builtin code pages first.
423 switch (codepage) {
424 case 0: return Default;
426 case ASCIIEncoding.ASCII_CODE_PAGE:
427 return ASCII;
429 case UTF7Encoding.UTF7_CODE_PAGE:
430 return UTF7;
432 case UTF8Encoding.UTF8_CODE_PAGE:
433 return UTF8;
435 case UTF32Encoding.UTF32_CODE_PAGE:
436 return UTF32;
438 case UTF32Encoding.BIG_UTF32_CODE_PAGE:
439 return BigEndianUTF32;
441 case UnicodeEncoding.UNICODE_CODE_PAGE:
442 return Unicode;
444 case UnicodeEncoding.BIG_UNICODE_CODE_PAGE:
445 return BigEndianUnicode;
447 #if !NET_2_1 || MONOTOUCH
448 case Latin1Encoding.ISOLATIN_CODE_PAGE:
449 return ISOLatin1;
450 #endif
451 default: break;
453 #if !NET_2_1 || MONOTOUCH
454 // Try to obtain a code page handler from the I18N handler.
455 Encoding enc = (Encoding)(InvokeI18N ("GetEncoding", codepage));
456 if (enc != null) {
457 enc.is_readonly = true;
458 return enc;
461 // Build a code page class name.
462 String cpName = "System.Text.CP" + codepage.ToString ();
464 // Look for a code page converter in this assembly.
465 Assembly assembly = Assembly.GetExecutingAssembly ();
466 Type type = assembly.GetType (cpName);
467 if (type != null) {
468 enc = (Encoding)(Activator.CreateInstance (type));
469 enc.is_readonly = true;
470 return enc;
473 // Look in any assembly, in case the application
474 // has provided its own code page handler.
475 type = Type.GetType (cpName);
476 if (type != null) {
477 enc = (Encoding)(Activator.CreateInstance (type));
478 enc.is_readonly = true;
479 return enc;
481 #endif // !NET_2_1
482 // We have no idea how to handle this code page.
483 throw new NotSupportedException
484 (String.Format ("CodePage {0} not supported", codepage.ToString ()));
487 #if !ECMA_COMPAT
489 [ComVisible (false)]
490 public virtual object Clone ()
492 Encoding e = (Encoding) MemberwiseClone ();
493 e.is_readonly = false;
494 return e;
497 #if !NET_2_1 || MONOTOUCH
499 public static Encoding GetEncoding (int codepage,
500 EncoderFallback encoderFallback, DecoderFallback decoderFallback)
502 if (encoderFallback == null)
503 throw new ArgumentNullException ("encoderFallback");
504 if (decoderFallback == null)
505 throw new ArgumentNullException ("decoderFallback");
507 Encoding e = GetEncoding (codepage).Clone () as Encoding;
508 e.is_readonly = false;
509 e.encoder_fallback = encoderFallback;
510 e.decoder_fallback = decoderFallback;
511 return e;
514 public static Encoding GetEncoding (string name,
515 EncoderFallback encoderFallback, DecoderFallback decoderFallback)
517 if (encoderFallback == null)
518 throw new ArgumentNullException ("encoderFallback");
519 if (decoderFallback == null)
520 throw new ArgumentNullException ("decoderFallback");
522 Encoding e = GetEncoding (name).Clone () as Encoding;
523 e.is_readonly = false;
524 e.encoder_fallback = encoderFallback;
525 e.decoder_fallback = decoderFallback;
526 return e;
529 #endif // !NET_2_1
531 static EncodingInfo [] encoding_infos;
533 // FIXME: As everyone would agree, this implementation is so *hacky*
534 // and could be very easily broken. But since there is a test for
535 // this method to make sure that this method always returns
536 // the same number and content of encoding infos, this won't
537 // matter practically.
538 public static EncodingInfo[] GetEncodings ()
540 if (encoding_infos == null) {
541 int [] codepages = new int [] {
542 37, 437, 500, 708,
543 850, 852, 855, 857, 858, 860, 861, 862, 863,
544 864, 865, 866, 869, 870, 874, 875,
545 932, 936, 949, 950,
546 1026, 1047, 1140, 1141, 1142, 1143, 1144,
547 1145, 1146, 1147, 1148, 1149,
548 1200, 1201, 1250, 1251, 1252, 1253, 1254,
549 1255, 1256, 1257, 1258,
550 10000, 10079, 12000, 12001,
551 20127, 20273, 20277, 20278, 20280, 20284,
552 20285, 20290, 20297, 20420, 20424, 20866,
553 20871, 21025, 21866, 28591, 28592, 28593,
554 28594, 28595, 28596, 28597, 28598, 28599,
555 28605, 38598,
556 50220, 50221, 50222, 51932, 51949, 54936,
557 57002, 57003, 57004, 57005, 57006, 57007,
558 57008, 57009, 57010, 57011,
559 65000, 65001};
561 encoding_infos = new EncodingInfo [codepages.Length];
562 for (int i = 0; i < codepages.Length; i++)
563 encoding_infos [i] = new EncodingInfo (codepages [i]);
565 return encoding_infos;
568 #if !NET_2_1 || MONOTOUCH
569 [ComVisible (false)]
570 public bool IsAlwaysNormalized ()
572 return IsAlwaysNormalized (NormalizationForm.FormC);
575 [ComVisible (false)]
576 public virtual bool IsAlwaysNormalized (NormalizationForm form)
578 // umm, ASCIIEncoding should have overriden this method, no?
579 return form == NormalizationForm.FormC && this is ASCIIEncoding;
581 #endif // NET_2_1
583 // Table of builtin web encoding names and the corresponding code pages.
584 private static readonly object[] encodings =
586 ASCIIEncoding.ASCII_CODE_PAGE,
587 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
588 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
589 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
591 UTF7Encoding.UTF7_CODE_PAGE,
592 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
593 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
594 "x_unicode_2_0_utf_7",
596 UTF8Encoding.UTF8_CODE_PAGE,
597 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
598 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
600 UnicodeEncoding.UNICODE_CODE_PAGE,
601 "utf_16", "UTF_16LE", "ucs_2", "unicode",
602 "iso_10646_ucs2",
604 UnicodeEncoding.BIG_UNICODE_CODE_PAGE,
605 "unicodefffe", "utf_16be",
607 UTF32Encoding.UTF32_CODE_PAGE,
608 "utf_32", "UTF_32LE", "ucs_4",
610 UTF32Encoding.BIG_UTF32_CODE_PAGE,
611 "UTF_32BE",
613 #if !NET_2_1 || MONOTOUCH
614 Latin1Encoding.ISOLATIN_CODE_PAGE,
615 "iso_8859_1", "latin1"
616 #endif // !NET_2_1
619 // Get an encoding object for a specific web encoding name.
620 public static Encoding GetEncoding (String name)
622 // Validate the parameters.
623 if (name == null) {
624 throw new ArgumentNullException ("name");
627 string converted = name.ToLowerInvariant ().Replace ('-', '_');
629 // Search the table for a name match.
630 int code = 0;
631 for (int i = 0; i < encodings.Length; ++i) {
632 object o = encodings [i];
634 if (o is int){
635 code = (int) o;
636 continue;
639 if (converted == ((string)encodings [i]))
640 return GetEncoding (code);
642 #if !NET_2_1 || MONOTOUCH
643 // Try to obtain a web encoding handler from the I18N handler.
644 Encoding enc = (Encoding)(InvokeI18N ("GetEncoding", name));
645 if (enc != null) {
646 return enc;
649 // Build a web encoding class name.
650 String encName = "System.Text.ENC" + converted;
653 // Look for a code page converter in this assembly.
654 Assembly assembly = Assembly.GetExecutingAssembly ();
655 Type type = assembly.GetType (encName);
656 if (type != null) {
657 return (Encoding)(Activator.CreateInstance (type));
660 // Look in any assembly, in case the application
661 // has provided its own code page handler.
662 type = Type.GetType (encName);
663 if (type != null) {
664 return (Encoding)(Activator.CreateInstance (type));
666 #endif
667 // We have no idea how to handle this encoding name.
668 throw new ArgumentException (String.Format ("Encoding name '{0}' not "
669 + "supported", name), "name");
672 #endif // !ECMA_COMPAT
674 // Get a hash code for this instance.
675 public override int GetHashCode ()
677 return DecoderFallback.GetHashCode () << 24 + EncoderFallback.GetHashCode () << 16 + codePage;
680 // Get the maximum number of bytes needed to encode a
681 // specified number of characters.
682 public abstract int GetMaxByteCount (int charCount);
684 // Get the maximum number of characters needed to decode a
685 // specified number of bytes.
686 public abstract int GetMaxCharCount (int byteCount);
688 // Get the identifying preamble for this encoding.
689 public virtual byte[] GetPreamble ()
691 return new byte [0];
694 // Decode a buffer of bytes into a string.
695 public virtual String GetString (byte[] bytes, int index, int count)
697 return new String (GetChars(bytes, index, count));
699 public virtual String GetString (byte[] bytes)
701 if (bytes == null)
702 throw new ArgumentNullException ("bytes");
704 return GetString (bytes, 0, bytes.Length);
707 #if !ECMA_COMPAT
709 internal string body_name;
710 internal string encoding_name;
711 internal string header_name;
712 internal bool is_mail_news_display;
713 internal bool is_mail_news_save;
714 internal bool is_browser_save = false;
715 internal bool is_browser_display = false;
716 internal string web_name;
718 // Get the mail body name for this encoding.
719 public virtual String BodyName
721 get {
722 return body_name;
726 // Get the code page represented by this object.
727 public virtual int CodePage
729 get {
730 return codePage;
734 // Get the human-readable name for this encoding.
735 public virtual String EncodingName
737 get {
738 return encoding_name;
742 // Get the mail agent header name for this encoding.
743 public virtual String HeaderName
745 get {
746 return header_name;
750 // Determine if this encoding can be displayed in a Web browser.
751 public virtual bool IsBrowserDisplay
753 get {
754 return is_browser_display;
758 // Determine if this encoding can be saved from a Web browser.
759 public virtual bool IsBrowserSave
761 get {
762 return is_browser_save;
766 // Determine if this encoding can be displayed in a mail/news agent.
767 public virtual bool IsMailNewsDisplay
769 get {
770 return is_mail_news_display;
774 // Determine if this encoding can be saved from a mail/news agent.
775 public virtual bool IsMailNewsSave
777 get {
778 return is_mail_news_save;
782 // Get the IANA-preferred Web name for this encoding.
783 public virtual String WebName
785 get {
786 return web_name;
790 // Get the Windows code page represented by this object.
791 public virtual int WindowsCodePage
793 get {
794 // We make no distinction between normal and
795 // Windows code pages in this implementation.
796 return windows_code_page;
800 #endif // !ECMA_COMPAT
802 // Storage for standard encoding objects.
803 static volatile Encoding asciiEncoding;
804 static volatile Encoding bigEndianEncoding;
805 static volatile Encoding defaultEncoding;
806 static volatile Encoding utf7Encoding;
807 static volatile Encoding utf8EncodingWithMarkers;
808 static volatile Encoding utf8EncodingWithoutMarkers;
809 static volatile Encoding unicodeEncoding;
810 static volatile Encoding isoLatin1Encoding;
811 static volatile Encoding utf8EncodingUnsafe;
812 static volatile Encoding utf32Encoding;
813 static volatile Encoding bigEndianUTF32Encoding;
815 static readonly object lockobj = new object ();
817 // Get the standard ASCII encoding object.
818 public static Encoding ASCII
820 get {
821 if (asciiEncoding == null) {
822 lock (lockobj) {
823 if (asciiEncoding == null) {
824 asciiEncoding = new ASCIIEncoding ();
825 // asciiEncoding.is_readonly = true;
830 return asciiEncoding;
834 // Get the standard big-endian Unicode encoding object.
835 public static Encoding BigEndianUnicode
837 get {
838 if (bigEndianEncoding == null) {
839 lock (lockobj) {
840 if (bigEndianEncoding == null) {
841 bigEndianEncoding = new UnicodeEncoding (true, true);
842 // bigEndianEncoding.is_readonly = true;
847 return bigEndianEncoding;
851 [MethodImpl (MethodImplOptions.InternalCall)]
852 extern internal static string InternalCodePage (ref int code_page);
854 // Get the default encoding object.
855 public static Encoding Default
857 get {
858 if (defaultEncoding == null) {
859 lock (lockobj) {
860 if (defaultEncoding == null) {
861 // See if the underlying system knows what
862 // code page handler we should be using.
863 int code_page = 1;
865 string code_page_name = InternalCodePage (ref code_page);
866 try {
867 if (code_page == -1)
868 defaultEncoding = GetEncoding (code_page_name);
869 else {
870 // map the codepage from internal to our numbers
871 code_page = code_page & 0x0fffffff;
872 switch (code_page){
873 case 1: code_page = ASCIIEncoding.ASCII_CODE_PAGE; break;
874 case 2: code_page = UTF7Encoding.UTF7_CODE_PAGE; break;
875 case 3: code_page = UTF8Encoding.UTF8_CODE_PAGE; break;
876 case 4: code_page = UnicodeEncoding.UNICODE_CODE_PAGE; break;
877 case 5: code_page = UnicodeEncoding.BIG_UNICODE_CODE_PAGE; break;
878 #if !NET_2_1 || MONOTOUCH
879 case 6: code_page = Latin1Encoding.ISOLATIN_CODE_PAGE; break;
880 #endif
882 defaultEncoding = GetEncoding (code_page);
884 } catch (NotSupportedException) {
885 #if NET_2_1 && !MONOTOUCH
886 defaultEncoding = UTF8;
887 #else
888 // code_page is not supported on underlying platform
889 defaultEncoding = UTF8Unmarked;
890 #endif
891 } catch (ArgumentException) {
892 // code_page_name is not a valid code page, or is
893 // not supported by underlying OS
894 #if NET_2_1 && !MONOTOUCH
895 defaultEncoding = UTF8;
896 #else
897 defaultEncoding = UTF8Unmarked;
898 #endif
900 defaultEncoding.is_readonly = true;
905 return defaultEncoding;
909 #if !NET_2_1 || MONOTOUCH
911 // Get the ISO Latin1 encoding object.
912 private static Encoding ISOLatin1
914 get {
915 if (isoLatin1Encoding == null) {
916 lock (lockobj) {
917 if (isoLatin1Encoding == null) {
918 isoLatin1Encoding = new Latin1Encoding ();
919 // isoLatin1Encoding.is_readonly = true;
924 return isoLatin1Encoding;
928 #endif
930 // Get the standard UTF-7 encoding object.
931 #if ECMA_COMPAT
932 private
933 #else
934 public
935 #endif
936 static Encoding UTF7
938 get {
939 if (utf7Encoding == null) {
940 lock (lockobj) {
941 if (utf7Encoding == null) {
942 utf7Encoding = new UTF7Encoding ();
943 // utf7Encoding.is_readonly = true;
948 return utf7Encoding;
952 // Get the standard UTF-8 encoding object.
953 public static Encoding UTF8
955 get {
956 if (utf8EncodingWithMarkers == null) {
957 lock (lockobj) {
958 if (utf8EncodingWithMarkers == null) {
959 utf8EncodingWithMarkers = new UTF8Encoding (true);
960 // utf8EncodingWithMarkers.is_readonly = true;
965 return utf8EncodingWithMarkers;
970 // Only internal, to be used by the class libraries: Unmarked and non-input-validating
972 internal static Encoding UTF8Unmarked {
973 get {
974 if (utf8EncodingWithoutMarkers == null) {
975 lock (lockobj){
976 if (utf8EncodingWithoutMarkers == null){
977 utf8EncodingWithoutMarkers = new UTF8Encoding (false, false);
978 // utf8EncodingWithoutMarkers.is_readonly = true;
983 return utf8EncodingWithoutMarkers;
988 // Only internal, to be used by the class libraries: Unmarked and non-input-validating
990 internal static Encoding UTF8UnmarkedUnsafe {
991 get {
992 if (utf8EncodingUnsafe == null) {
993 lock (lockobj){
994 if (utf8EncodingUnsafe == null){
995 utf8EncodingUnsafe = new UTF8Encoding (false, false);
996 utf8EncodingUnsafe.is_readonly = false;
997 utf8EncodingUnsafe.DecoderFallback = new DecoderReplacementFallback (String.Empty);
998 utf8EncodingUnsafe.is_readonly = true;
1003 return utf8EncodingUnsafe;
1007 // Get the standard little-endian Unicode encoding object.
1008 public static Encoding Unicode
1010 get {
1011 if (unicodeEncoding == null) {
1012 lock (lockobj) {
1013 if (unicodeEncoding == null) {
1014 unicodeEncoding = new UnicodeEncoding (false, true);
1015 // unicodeEncoding.is_readonly = true;
1020 return unicodeEncoding;
1024 // Get the standard little-endian UTF-32 encoding object.
1025 public static Encoding UTF32
1027 get {
1028 if (utf32Encoding == null) {
1029 lock (lockobj) {
1030 if (utf32Encoding == null) {
1031 utf32Encoding = new UTF32Encoding (false, true);
1032 // utf32Encoding.is_readonly = true;
1037 return utf32Encoding;
1041 // Get the standard big-endian UTF-32 encoding object.
1042 internal static Encoding BigEndianUTF32
1044 get {
1045 if (bigEndianUTF32Encoding == null) {
1046 lock (lockobj) {
1047 if (bigEndianUTF32Encoding == null) {
1048 bigEndianUTF32Encoding = new UTF32Encoding (true, true);
1049 // bigEndianUTF32Encoding.is_readonly = true;
1054 return bigEndianUTF32Encoding;
1058 // Forwarding decoder implementation.
1059 private sealed class ForwardingDecoder : Decoder
1061 private Encoding encoding;
1063 // Constructor.
1064 public ForwardingDecoder (Encoding enc)
1066 encoding = enc;
1067 DecoderFallback fallback = encoding.DecoderFallback;
1068 if (fallback != null)
1069 Fallback = fallback;
1072 // Override inherited methods.
1073 public override int GetCharCount (byte[] bytes, int index, int count)
1075 return encoding.GetCharCount (bytes, index, count);
1077 public override int GetChars (byte[] bytes, int byteIndex,
1078 int byteCount, char[] chars,
1079 int charIndex)
1081 return encoding.GetChars (bytes, byteIndex, byteCount, chars, charIndex);
1084 } // class ForwardingDecoder
1086 // Forwarding encoder implementation.
1087 private sealed class ForwardingEncoder : Encoder
1089 private Encoding encoding;
1091 // Constructor.
1092 public ForwardingEncoder (Encoding enc)
1094 encoding = enc;
1095 EncoderFallback fallback = encoding.EncoderFallback;
1096 if (fallback != null)
1097 Fallback = fallback;
1100 // Override inherited methods.
1101 public override int GetByteCount (char[] chars, int index, int count, bool flush)
1103 return encoding.GetByteCount (chars, index, count);
1105 public override int GetBytes (char[] chars, int charIndex,
1106 int charCount, byte[] bytes,
1107 int byteCount, bool flush)
1109 return encoding.GetBytes (chars, charIndex, charCount, bytes, byteCount);
1112 } // class ForwardingEncoder
1114 [CLSCompliantAttribute(false)]
1115 [ComVisible (false)]
1116 public unsafe virtual int GetByteCount (char *chars, int count)
1118 if (chars == null)
1119 throw new ArgumentNullException ("chars");
1120 if (count < 0)
1121 throw new ArgumentOutOfRangeException ("count");
1122 char [] c = new char [count];
1124 for (int p = 0; p < count; p++)
1125 c [p] = chars [p];
1127 return GetByteCount (c);
1130 [CLSCompliantAttribute(false)]
1131 [ComVisible (false)]
1132 public unsafe virtual int GetCharCount (byte *bytes, int count)
1134 if (bytes == null)
1135 throw new ArgumentNullException ("bytes");
1136 if (count < 0)
1137 throw new ArgumentOutOfRangeException ("count");
1139 byte [] ba = new byte [count];
1140 for (int i = 0; i < count; i++)
1141 ba [i] = bytes [i];
1142 return GetCharCount (ba, 0, count);
1145 [CLSCompliantAttribute(false)]
1146 [ComVisible (false)]
1147 public unsafe virtual int GetChars (byte *bytes, int byteCount, char *chars, int charCount)
1149 if (bytes == null)
1150 throw new ArgumentNullException ("bytes");
1151 if (chars == null)
1152 throw new ArgumentNullException ("chars");
1153 if (charCount < 0)
1154 throw new ArgumentOutOfRangeException ("charCount");
1155 if (byteCount < 0)
1156 throw new ArgumentOutOfRangeException ("byteCount");
1158 byte [] ba = new byte [byteCount];
1159 for (int i = 0; i < byteCount; i++)
1160 ba [i] = bytes [i];
1161 char [] ret = GetChars (ba, 0, byteCount);
1162 int top = ret.Length;
1164 if (top > charCount)
1165 throw new ArgumentException ("charCount is less than the number of characters produced", "charCount");
1167 for (int i = 0; i < top; i++)
1168 chars [i] = ret [i];
1169 return top;
1172 [CLSCompliantAttribute(false)]
1173 [ComVisible (false)]
1174 public unsafe virtual int GetBytes (char *chars, int charCount, byte *bytes, int byteCount)
1176 if (bytes == null)
1177 throw new ArgumentNullException ("bytes");
1178 if (chars == null)
1179 throw new ArgumentNullException ("chars");
1180 if (charCount < 0)
1181 throw new ArgumentOutOfRangeException ("charCount");
1182 if (byteCount < 0)
1183 throw new ArgumentOutOfRangeException ("byteCount");
1185 char [] c = new char [charCount];
1187 for (int i = 0; i < charCount; i++)
1188 c [i] = chars [i];
1190 byte [] b = GetBytes (c, 0, charCount);
1191 int top = b.Length;
1192 if (top > byteCount)
1193 throw new ArgumentException ("byteCount is less that the number of bytes produced", "byteCount");
1195 for (int i = 0; i < top; i++)
1196 bytes [i] = b [i];
1198 return b.Length;
1200 }; // class Encoding
1202 }; // namespace System.Text