[runtime] Default mobile_static AOT type to FullAOT
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlCustomFormatter.cs
1 //
2 // System.Xml.Serialization.XmlCustomFormatter.cs
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Collections;
34 using System.Text;
35 using System.Xml;
36 using System.Globalization;
37
38 namespace System.Xml.Serialization {
39         internal class XmlCustomFormatter {
40
41                 #region Methods
42
43                 internal static string FromByteArrayBase64 (byte[] value)
44                 {
45                         return value == null ? String.Empty : Convert.ToBase64String(value);
46                 }
47
48                 internal static string FromByteArrayHex (byte[] value)
49                 {
50                         if (value == null) return null;
51                         StringBuilder output = new StringBuilder ();
52                         foreach (byte val in value)
53                                 output.Append (val.ToString ("X2", CultureInfo.InvariantCulture));
54                         return output.ToString ();
55                 }
56
57                 internal static string FromChar (char value)
58                 {
59                         return ((int) value).ToString (CultureInfo.InvariantCulture);
60                 }
61
62                 internal static string FromDate (DateTime value)
63                 {
64                         return XmlConvert.ToString (value, "yyyy-MM-dd");
65                 }
66
67                 internal static string FromDateTime (DateTime value)
68                 {
69                         return XmlConvert.ToString (value, XmlDateTimeSerializationMode.RoundtripKind);
70                 }
71
72                 internal static string FromTime (DateTime value)
73                 {
74                         return XmlConvert.ToString (value, "HH:mm:ss.fffffffzzz");
75                 }
76
77                 internal static string FromEnum (long value, string[] values, long[] ids)
78                 {
79                         return FromEnum (value, values, ids, (string) null);
80                 }
81
82                 internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
83                 {
84                         StringBuilder sb = new StringBuilder();
85                         int length = ids.Length;
86                         long valueToProcess = value;
87                         int zeroValue = -1;
88
89                         for (int i = 0; i < length; i ++) {
90                                 if (ids[i] == 0) {
91                                         zeroValue = i;
92                                 } else {
93                                         if (valueToProcess == 0) {
94                                                 break;
95                                         }
96
97                                         if ((ids[i] & value) == ids[i]) {
98                                                 if (sb.Length != 0)
99                                                         sb.Append (' ');
100                                                 sb.Append (values[i]);
101                                                 valueToProcess &= ~ids[i];
102                                         }
103                                 }
104                         }
105
106                         if (valueToProcess != 0) {
107                                 if (typeName != null)
108                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
109                                                 "'{0}' is not a valid value for {1}.", value, typeName));
110                                 else
111                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
112                                                 "'{0}' is not a valid value.", value));
113                         }
114                         if (sb.Length == 0 && zeroValue != -1) {
115                                 sb.Append (values[zeroValue]);
116                         }
117                         return sb.ToString ();
118                 }
119
120                 internal static string FromXmlName (string name)
121                 {
122                         return XmlConvert.EncodeName (name);
123                 }
124
125                 internal static string FromXmlNCName (string ncName)
126                 {
127                         return XmlConvert.EncodeLocalName (ncName);
128                 }
129
130                 internal static string FromXmlNmToken (string nmToken)
131                 {
132                         return XmlConvert.EncodeNmToken (nmToken);
133                 }
134
135                 internal static string FromXmlNmTokens (string nmTokens)
136                 {
137                         string [] tokens = nmTokens.Split (' ');
138                         for (int i=0; i<tokens.Length; i++)
139                                 tokens [i] = FromXmlNmToken (tokens [i]);
140                         return String.Join (" ", tokens);
141                 }
142
143                 internal static byte[] ToByteArrayBase64 (string value)
144                 {
145                         return Convert.FromBase64String(value);
146                 }
147
148                 internal static char ToChar (string value)
149                 {
150                         return (char) XmlConvert.ToUInt16 (value);
151                 }
152
153                 internal static DateTime ToDate (string value)
154                 {
155                         return ToDateTime (value);
156                 }
157
158                 internal static DateTime ToDateTime (string value)
159                 {
160                         return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
161                 }
162
163                 internal static DateTime ToTime (string value)
164                 {
165                         return ToDateTime (value);
166                 }
167
168                 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
169                 {
170                         // Assuming that h contains map from value to Enumerated Name
171 /*
172                         You can try : 
173                                 return ToEnum ("One Two", h, "SomeType");
174                         where:
175                                 (1) no keys and values for h.
176                                 (2) string keys and long values.
177                         
178                         according to MSDN docs (for .NET 2.0) the hashtable "consists of the
179                         identifiers as keys and the constants as integral numbers"
180 */
181                         long enumValue = 0;
182                         string[] names = value.Split (' ');
183
184                         foreach (string name in names) {
185                                 object nameValue = values[name];
186                                 if (nameValue != null) {
187                                         enumValue |= (long) nameValue;
188                                 } else if (validate && name.Length != 0) {
189                                         throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
190                                 }
191                         }
192
193                         return enumValue;
194                 }
195
196                 internal static string ToXmlName (string value)
197                 {
198                         return XmlConvert.DecodeName (value);
199                 }
200
201                 internal static string ToXmlNCName (string value)
202                 {
203                         return ToXmlName (value);
204                 }
205
206                 internal static string ToXmlNmToken (string value)
207                 {
208                         return ToXmlName (value);
209                 }
210
211                 internal static string ToXmlNmTokens (string value)
212                 {
213                         return ToXmlName (value);
214                 }
215
216                 internal static string ToXmlString (TypeData type, object value)
217                 {
218                         if (value == null) return null;
219                         switch (type.XmlType)
220                         {
221                                 case "boolean": return XmlConvert.ToString ((bool)value);
222                                 case "unsignedByte": return XmlConvert.ToString ((byte)value);
223                                 case "char": return XmlConvert.ToString ((int)(char)value);
224                                 case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
225                                 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
226                                 case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
227                                 case "decimal": return XmlConvert.ToString ((decimal)value);
228                                 case "double": return XmlConvert.ToString ((double)value);
229                                 case "short": return XmlConvert.ToString ((Int16)value);
230                                 case "int": return XmlConvert.ToString ((Int32)value);
231                                 case "long": return XmlConvert.ToString ((Int64)value);
232                                 case "byte": return XmlConvert.ToString ((sbyte)value);
233                                 case "float": return XmlConvert.ToString ((Single)value);
234                                 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
235                                 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
236                                 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
237                                 case "guid": return XmlConvert.ToString ((Guid)value);
238                                 case "base64":
239                                 case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
240                                 case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
241                                 case "duration": return (string) value;
242                         default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
243                         }
244                 }
245
246                 internal static object FromXmlString (TypeData type, string value)
247                 {
248                         if (value == null) return null;
249
250                         switch (type.XmlType)
251                         {
252                                 case "boolean": return XmlConvert.ToBoolean (value);
253                                 case "unsignedByte": return XmlConvert.ToByte (value);
254                                 case "char": return (char)XmlConvert.ToInt32 (value);
255                                 case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
256                                 case "date": return XmlConvert.ToDateTime (value).Date;
257                                 case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
258                                 case "decimal": return XmlConvert.ToDecimal (value);
259                                 case "double": return XmlConvert.ToDouble (value);
260                                 case "short": return XmlConvert.ToInt16 (value);
261                                 case "int": return XmlConvert.ToInt32 (value);
262                                 case "long": return XmlConvert.ToInt64 (value);
263                                 case "byte": return XmlConvert.ToSByte (value);
264                                 case "float": return XmlConvert.ToSingle (value);
265                                 case "unsignedShort": return XmlConvert.ToUInt16 (value);
266                                 case "unsignedInt": return XmlConvert.ToUInt32 (value);
267                                 case "unsignedLong": return XmlConvert.ToUInt64 (value);
268                                 case "guid": return XmlConvert.ToGuid (value);
269                                 case "base64":
270                                 case "base64Binary": return Convert.FromBase64String (value);
271                                 case "hexBinary": return XmlConvert.FromBinHexString (value);
272                                 case "duration": return value;
273                                 default: 
274                                         if (type.Type != null)
275                                                 return Convert.ChangeType (value, type.Type, null);
276                                         else
277                                                 return value;
278                         }
279                 }
280
281                 internal static string GenerateToXmlString (TypeData type, string value)
282                 {
283                         if (type.NullableOverride)
284                                 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
285                         else
286                                 return GenerateToXmlStringCore (type, value);
287                 }
288
289                 static string GenerateToXmlStringCore (TypeData type, string value)
290                 {
291                         if (type.NullableOverride)
292                                 value = value + ".Value";
293                         switch (type.XmlType)
294                         {
295                                 case "boolean": return "(" + value + "?\"true\":\"false\")";
296                                 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
297                                 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
298                                 case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
299                                 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
300                                 case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
301                                 case "decimal": return "XmlConvert.ToString (" + value + ")";
302                                 case "double": return "XmlConvert.ToString (" + value + ")";
303                                 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
304                                 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
305                                 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
306                                 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
307                                 case "float": return "XmlConvert.ToString (" + value + ")";
308                                 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
309                                 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
310                                 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
311                                 case "guid": return "XmlConvert.ToString (" + value + ")";
312                                 case "base64":
313                                 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
314                                 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
315                                 case "duration": return value;
316                                 case "NMTOKEN":
317                                 case "Name":
318                                 case "NCName":
319                                 case "language":
320                                 case "ENTITY":
321                                 case "ID":
322                                 case "IDREF":
323                                 case "NOTATION":
324                                 case "token":
325                                 case "normalizedString":
326                                 case "string": return value;
327                                 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
328                         }
329                 }
330
331                 internal static string GenerateFromXmlString (TypeData type, string value)
332                 {
333                         if (type.NullableOverride)
334                                 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
335                         else
336                                 return GenerateFromXmlStringCore (type, value);
337                 }
338
339                 static string GenerateFromXmlStringCore (TypeData type, string value)
340                 {
341                         switch (type.XmlType)
342                         {
343                                 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
344                                 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
345                                 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
346                                 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
347                                 case "date": return "XmlConvert.ToDateTime (" + value + ").Date";
348                                 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
349                                 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
350                                 case "double": return "XmlConvert.ToDouble (" + value + ")";
351                                 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
352                                 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
353                                 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
354                                 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
355                                 case "float": return "XmlConvert.ToSingle (" + value + ")";
356                                 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
357                                 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
358                                 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
359                                 case "guid": return "XmlConvert.ToGuid (" + value + ")";
360                                 case "base64:":
361                                 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
362                                 case "hexBinary": return "FromBinHexString (" + value + ")";
363                                 case "duration": return value;
364                                 default: return value;
365                         }
366                 }
367
368                 #endregion // Methods
369         }
370 }