Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Web.Services / System / Web / Services / Protocols / Scalars.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Scalars.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Web.Services.Protocols {
8
9     using System.Web.Services;
10     using System.Collections;
11     using System.Globalization;
12     using System.Reflection;
13     using System;
14     using System.Text;
15     using System.Threading;
16     
17     internal class ScalarFormatter {
18         private ScalarFormatter() { }
19
20         internal static string ToString(object value) {
21             if (value == null) 
22                 return string.Empty;
23             else if (value is string)
24                 return (string)value;
25             else if (value.GetType().IsEnum)
26                 return EnumToString(value);
27             else
28                 return (string)Convert.ToString(value, CultureInfo.InvariantCulture);
29         }
30
31         internal static object FromString(string value, Type type) {
32             try {
33                 if (type == typeof(string))
34                     return value;
35                 else if (type.IsEnum)
36                     return (object)EnumFromString(value, type);
37                 else
38                     return Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
39             }
40             catch (Exception e) {
41                 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
42                     throw;
43                 }
44                 throw new ArgumentException(Res.GetString(Res.WebChangeTypeFailed, value, type.FullName), "type", e);
45             }
46         }
47
48         static object EnumFromString(string value, Type type) {
49             return Enum.Parse(type, value);
50         }
51
52         static string EnumToString(object value) {
53             return Enum.Format(value.GetType(), value, "G");
54         }
55
56         // We support: whatever Convert supports, and Enums
57         internal static bool IsTypeSupported(Type type) {
58             if (type.IsEnum) return true;
59             return (
60                 type == typeof(int) ||
61                 type == typeof(string) ||
62                 type == typeof(long) ||
63                 type == typeof(byte) ||
64                 type == typeof(sbyte) ||
65                 type == typeof(short) ||
66                 type == typeof(bool) ||
67                 type == typeof(char) ||
68                 type == typeof(float) ||
69                 type == typeof(decimal) ||
70                 type == typeof(DateTime) ||
71                 type == typeof(UInt16) ||
72                 type == typeof(UInt32) ||
73                 type == typeof(UInt64) ||
74                 type == typeof(double));
75         }
76     }
77
78     internal class UrlEncoder {
79         private UrlEncoder() { }
80
81         private const int Max16BitUtf8SequenceLength = 4;
82
83         internal static string EscapeString(string s, Encoding e) {
84             return EscapeStringInternal(s, e == null ? new ASCIIEncoding() : e, false);
85         }
86
87         internal static string UrlEscapeString(string s, Encoding e) {
88             return EscapeStringInternal(s, e == null ? new ASCIIEncoding() : e, true);
89         }
90
91         private static string EscapeStringInternal(string s, Encoding e, bool escapeUriStuff) {
92             if (s == null) return null;
93             
94             byte[] bytes = e.GetBytes(s);
95             StringBuilder sb = new StringBuilder(bytes.Length);
96             for (int i = 0; i < bytes.Length; i++) {
97                 byte b = bytes[i];
98                 char c = (char)b;
99                 if (b > 0x7f || b < 0x20 || c == '%' || (escapeUriStuff && !IsSafe(c))) {
100                     HexEscape8(sb, c);
101                 }
102                 else {
103                     sb.Append(c);
104                 }
105             }
106             return sb.ToString();
107         }
108
109         /*
110         // [....]: adapted from UrlEscapeStringUnicode below
111         internal static string EscapeStringUnicode(string s) {
112             int l = s.Length;
113             StringBuilder sb = new StringBuilder(l);
114
115             for (int i = 0; i < l; i++) {
116                 char ch = s[i];
117                 if ((ch & 0xff80) == 0) {
118                     sb.Append(ch);
119                 }
120                 else {
121                     HexEscape16(sb, ch);
122                 }
123             }
124
125             return sb.ToString();
126         }
127         */
128
129         // [....]: copied from System.Web.HttpUtility
130         internal static string UrlEscapeStringUnicode(string s) {
131             int l = s.Length;
132             StringBuilder sb = new StringBuilder(l);
133
134             for (int i = 0; i < l; i++) {
135                 char ch = s[i];
136
137                 if (IsSafe(ch)) {
138                     sb.Append(ch);
139                 }
140                 else if (ch == ' ') {
141                     sb.Append('+');
142                 }
143                 else if ((ch & 0xff80) == 0) {  // 7 bit?
144                     HexEscape8(sb, ch);
145                 }
146                 else { // arbitrary Unicode?
147                     HexEscape16(sb, ch);
148                 }
149             }
150             return sb.ToString();
151         }
152
153         private static void HexEscape8(StringBuilder sb, char c) {
154             sb.Append('%');
155             sb.Append(HexUpperChars[(c >> 4) & 0xf]);
156             sb.Append(HexUpperChars[(c) & 0xf]);
157         }
158
159         private static void HexEscape16(StringBuilder sb, char c) {
160             sb.Append("%u");
161             sb.Append(HexUpperChars[(c >> 12) & 0xf]);
162             sb.Append(HexUpperChars[(c >> 8) & 0xf]);
163             sb.Append(HexUpperChars[(c >> 4) & 0xf]);
164             sb.Append(HexUpperChars[(c) & 0xf]);
165         }
166
167         private static bool IsSafe(char ch) {
168             if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
169                 return true;
170
171             switch (ch) {
172                 case '-':
173                 case '_':
174                 case '.':
175                 case '!':
176                 case '*':
177                 case '\'':
178                 case '(':
179                 case ')':
180                     return true;
181             }
182
183             return false;
184         }
185
186         internal static readonly char[] HexUpperChars = {
187             '0', '1', '2', '3', '4', '5', '6', '7',
188             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
189         };
190     }
191
192     internal class ContentType {
193         private ContentType() { }
194         internal const string TextBase = "text";
195         internal const string TextXml     = "text/xml";
196         internal const string TextPlain   = "text/plain";
197         internal const string TextHtml    = "text/html";
198
199         internal const string ApplicationBase = "application";
200         internal const string ApplicationXml = "application/xml";
201         internal const string ApplicationSoap = "application/soap+xml";
202         internal const string ApplicationOctetStream = "application/octet-stream";
203
204         internal const string ContentEncoding = "Content-Encoding";
205
206         // this returns the "base" part of the contentType/mimeType, e.g. the "text/xml" part w/o
207         // the ; CharSet=isoxxx part that sometimes follows.
208         internal static string GetBase(string contentType) {
209             int semi = contentType.IndexOf(';');
210             if (semi >= 0) return contentType.Substring(0, semi);
211             return contentType;
212         }
213
214         // this returns the "type" part of the contentType/mimeType without subtyape
215         internal static string GetMediaType(string contentType) {
216             string baseCT = GetBase(contentType);
217             int tmp = baseCT.IndexOf('/');
218             if (tmp >= 0) return baseCT.Substring(0, tmp);
219             return baseCT;
220         }
221
222         // grabs as follows (and case-insensitive): .*;\s*charset\s*=\s*[\s'"]*(.*)[\s'"]*
223         internal static string GetCharset(string contentType) {
224             return GetParameter(contentType, "charset");
225         }
226
227         internal static string GetAction(string contentType) {
228             return GetParameter(contentType, "action");
229         }
230
231         private static string GetParameter(string contentType, string paramName) {
232             string[] paramDecls = contentType.Split(new char[] { ';' });
233             for (int i = 1; i < paramDecls.Length; i++) {
234                 string paramDecl = paramDecls[i].TrimStart(null);
235                 if (String.Compare(paramDecl, 0, paramName, 0, paramName.Length, StringComparison.OrdinalIgnoreCase) == 0) {
236                     int equals = paramDecl.IndexOf('=', paramName.Length);
237                     if (equals >= 0) 
238                         return paramDecl.Substring(equals + 1).Trim(new char[] { ' ', '\'', '\"', '\t' });
239                 }
240             }
241             return null;
242         }
243
244         internal static bool MatchesBase(string contentType, string baseContentType) {
245             return string.Compare(GetBase(contentType), baseContentType, StringComparison.OrdinalIgnoreCase) == 0;
246         }
247
248         internal static bool IsApplication(string contentType) {
249             return string.Compare(GetMediaType(contentType), ApplicationBase, StringComparison.OrdinalIgnoreCase) == 0;
250         }
251
252         internal static bool IsSoap(string contentType) {
253             string type = GetBase(contentType);
254             return (String.Compare(type, ContentType.TextXml, StringComparison.OrdinalIgnoreCase) == 0) ||
255                    (String.Compare(type, ContentType.ApplicationSoap, StringComparison.OrdinalIgnoreCase) == 0);
256         }
257         
258         internal static bool IsXml(string contentType) {
259             string type = GetBase(contentType);
260             return (String.Compare(type, ContentType.TextXml, StringComparison.OrdinalIgnoreCase) == 0) ||
261                    (String.Compare(type, ContentType.ApplicationXml, StringComparison.OrdinalIgnoreCase) == 0);
262         }
263
264         internal static bool IsHtml(string contentType) {
265             string type = GetBase(contentType);
266             return String.Compare(type, ContentType.TextHtml, StringComparison.OrdinalIgnoreCase) == 0;
267         }
268
269         internal static string Compose(string contentType, Encoding encoding) {
270             return Compose(contentType, encoding, null);
271         }
272
273         internal static string Compose(string contentType, Encoding encoding, string action) {
274             if (encoding == null && action == null) return contentType;
275
276             StringBuilder sb = new StringBuilder(contentType);
277             if (encoding != null) {
278                 sb.Append("; charset=");
279                 sb.Append(encoding.WebName);
280             }
281             if (action != null) {
282                 sb.Append("; action=\"");
283                 sb.Append(action);
284                 sb.Append("\"");
285             }
286             return sb.ToString();
287         }
288     }
289
290     internal class MemberHelper {
291         private MemberHelper() { }
292         static object[] emptyObjectArray = new object[0];
293
294         internal static void SetValue(MemberInfo memberInfo, object target, object value) {
295             if (memberInfo is FieldInfo ) {
296                 ((FieldInfo)memberInfo).SetValue(target, value);
297             }
298             else {
299                 ((PropertyInfo)memberInfo).SetValue(target, value, emptyObjectArray);
300             }
301         }
302
303         internal static object GetValue(MemberInfo memberInfo, object target) {
304             if (memberInfo is FieldInfo) {
305                 return ((FieldInfo)memberInfo).GetValue(target);
306             }
307             else {
308                 return ((PropertyInfo)memberInfo).GetValue(target, emptyObjectArray);
309             }
310         }
311
312         internal static bool IsStatic(MemberInfo memberInfo) {
313             if (memberInfo is FieldInfo)
314                 return ((FieldInfo)memberInfo).IsStatic;
315             else
316                 return false;
317         }
318
319         internal static bool CanRead(MemberInfo memberInfo) {
320             if (memberInfo is FieldInfo)
321                 return true;
322             else
323                 return ((PropertyInfo)memberInfo).CanRead;
324         }
325
326         internal static bool CanWrite(MemberInfo memberInfo) {
327             if (memberInfo is FieldInfo)
328                 return true;
329             else
330                 return ((PropertyInfo)memberInfo).CanWrite;
331         }
332     }
333 }