Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / corlib / System.Text / EncodingHelper.cs
1 using System;
2 using System.Reflection;
3 using System.Runtime.CompilerServices;
4 using System.Runtime.InteropServices;
5 using System.Security;
6
7 namespace System.Text
8 {
9
10 internal static partial class EncodingHelper
11 {
12         //
13         // Only internal, to be used by the class libraries: Unmarked and non-input-validating
14         //
15         internal static Encoding UTF8Unmarked {
16                 get {
17                         if (utf8EncodingWithoutMarkers == null) {
18                                 lock (lockobj){
19                                         if (utf8EncodingWithoutMarkers == null){
20                                                 utf8EncodingWithoutMarkers = new UTF8Encoding (false, false);
21                                                 utf8EncodingWithoutMarkers.setReadOnly ();
22                                         }
23                                 }
24                         }
25
26                         return utf8EncodingWithoutMarkers;
27                 }
28         }
29         
30         //
31         // Only internal, to be used by the class libraries: Unmarked and non-input-validating
32         //
33         internal static Encoding UTF8UnmarkedUnsafe {
34                 get {
35                         if (utf8EncodingUnsafe == null) {
36                                 lock (lockobj){
37                                         if (utf8EncodingUnsafe == null){
38                                                 utf8EncodingUnsafe = new UTF8Encoding (false, false);
39                                                 utf8EncodingUnsafe.setReadOnly (false);
40                                                 utf8EncodingUnsafe.DecoderFallback = new DecoderReplacementFallback (String.Empty);
41                                                 utf8EncodingUnsafe.setReadOnly ();
42                                         }
43                                 }
44                         }
45
46                         return utf8EncodingUnsafe;
47                 }
48         }
49
50         // Get the standard big-endian UTF-32 encoding object.
51         internal static Encoding BigEndianUTF32
52         {
53                 get {
54                         if (bigEndianUTF32Encoding == null) {
55                                 lock (lockobj) {
56                                         if (bigEndianUTF32Encoding == null) {
57                                                 bigEndianUTF32Encoding = new UTF32Encoding (true, true);
58                                                 bigEndianUTF32Encoding.setReadOnly ();
59                                         }
60                                 }
61                         }
62
63                         return bigEndianUTF32Encoding;
64                 }
65         }
66         static volatile Encoding utf8EncodingWithoutMarkers;
67         static volatile Encoding utf8EncodingUnsafe;
68         static volatile Encoding bigEndianUTF32Encoding;
69         static readonly object lockobj = new object ();
70
71         [MethodImpl (MethodImplOptions.InternalCall)]
72         extern internal static string InternalCodePage (ref int code_page);
73
74 #if !MONOTOUCH
75         internal static Encoding GetDefaultEncoding ()
76         {
77                 Encoding enc = null;
78                                                 // See if the underlying system knows what
79                                                 // code page handler we should be using.
80                                                 int code_page = 1;
81                                                 
82                                                 string code_page_name = InternalCodePage (ref code_page);
83                                                 try {
84                                                         if (code_page == -1)
85                                                                 enc = Encoding.GetEncoding (code_page_name);
86                                                         else {
87                                                                 // map the codepage from internal to our numbers
88                                                                 code_page = code_page & 0x0fffffff;
89                                                                 switch (code_page){
90                                                                 case 1: code_page = 20127; break; // ASCIIEncoding.ASCII_CODE_PAGE
91                                                                 case 2: code_page = 65007; break; // UTF7Encoding.UTF7_CODE_PAGE
92                                                                 case 3: code_page = 65001; break; // UTF8Encoding.UTF8_CODE_PAGE
93                                                                 case 4: code_page = 1200; break; // UnicodeEncoding.UNICODE_CODE_PAGE
94                                                                 case 5: code_page = 1201; break; // UnicodeEncoding.BIG_UNICODE_CODE_PAGE
95                                                                 case 6: code_page = 1252; break; // Latin1Encoding.ISOLATIN_CODE_PAGE
96                                                                 }
97                                                                 enc = Encoding.GetEncoding (code_page);
98                                                         }
99                                                 } catch (NotSupportedException) {
100                                                         // code_page is not supported on underlying platform
101                                                         enc = EncodingHelper.UTF8Unmarked;
102                                                 } catch (ArgumentException) {
103                                                         // code_page_name is not a valid code page, or is 
104                                                         // not supported by underlying OS
105                                                         enc = EncodingHelper.UTF8Unmarked;
106                                                 }
107                 return enc;
108         }
109 #endif
110
111         // Loaded copy of the "I18N" assembly.  We need to move
112         // this into a class in "System.Private" eventually.
113         private static Assembly i18nAssembly;
114         private static bool i18nDisabled;
115
116         // Invoke a specific method on the "I18N" manager object.
117         // Returns NULL if the method failed.
118         internal static Object InvokeI18N (String name, params Object[] args)
119         {
120                 lock (lockobj) {
121                         // Bail out if we previously detected that there
122                         // is insufficent engine support for I18N handling.
123                         if (i18nDisabled) {
124                                 return null;
125                         }
126
127                         // Find or load the "I18N" assembly.
128                         if (i18nAssembly == null) {
129                                 try {
130                                         try {
131                                                 i18nAssembly = Assembly.Load (Consts.AssemblyI18N);
132                                         } catch (NotImplementedException) {
133                                                 // Assembly loading unsupported by the engine.
134                                                 i18nDisabled = true;
135                                                 return null;
136                                         }
137                                         if (i18nAssembly == null) {
138                                                 return null;
139                                         }
140                                 } catch (SystemException) {
141                                         return null;
142                                 }
143                         }
144
145                         // Find the "I18N.Common.Manager" class.
146                         Type managerClass;
147                         try {
148                                 managerClass = i18nAssembly.GetType ("I18N.Common.Manager");
149                         } catch (NotImplementedException) {
150                                 // "GetType" is not supported by the engine.
151                                 i18nDisabled = true;
152                                 return null;
153                         }
154                         if (managerClass == null) {
155                                 return null;
156                         }
157
158                         // Get the value of the "PrimaryManager" property.
159                         Object manager;
160                         try {
161                                 manager = managerClass.InvokeMember
162                                                 ("PrimaryManager",
163                                                  BindingFlags.GetProperty |
164                                                         BindingFlags.Static |
165                                                         BindingFlags.Public,
166                                                  null, null, null, null, null, null);
167                                 if (manager == null) {
168                                         return null;
169                                 }
170                         } catch (MissingMethodException) {
171                                 return null;
172                         } catch (SecurityException) {
173                                 return null;
174                         } catch (NotImplementedException) {
175                                 // "InvokeMember" is not supported by the engine.
176                                 i18nDisabled = true;
177                                 return null;
178                         }
179
180                         // Invoke the requested method on the manager.
181                         try {
182                                 return managerClass.InvokeMember
183                                                 (name,
184                                                  BindingFlags.InvokeMethod |
185                                                         BindingFlags.Instance |
186                                                         BindingFlags.Public,
187                                                  null, manager, args, null, null, null);
188                         } catch (MissingMethodException) {
189                                 return null;
190                         } catch (SecurityException) {
191                                 return null;
192                         }
193                 }
194         }
195 }
196
197 }