Merge pull request #1275 from ranma42/fix-lib64
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlCustomFormatter.cs
index dc3818bd360e7a528c2bad1ece3d9bf6c9bd7f31..dca5ac50d476444915e872aefbabc4c5fd4341a8 100644 (file)
@@ -42,7 +42,7 @@ namespace System.Xml.Serialization {
 
                internal static string FromByteArrayBase64 (byte[] value)
                {
-                       return Convert.ToBase64String(value);
+                       return value == null ? String.Empty : Convert.ToBase64String(value);
                }
 
                internal static string FromByteArrayHex (byte[] value)
@@ -66,7 +66,11 @@ namespace System.Xml.Serialization {
 
                internal static string FromDateTime (DateTime value)
                {
+#if NET_2_0
+                       return XmlConvert.ToString (value, XmlDateTimeSerializationMode.RoundtripKind);
+#else
                        return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.fffffffzzz");
+#endif
                }
 
                internal static string FromTime (DateTime value)
@@ -76,16 +80,49 @@ namespace System.Xml.Serialization {
 
                internal static string FromEnum (long value, string[] values, long[] ids)
                {
+                       return FromEnum (value, values, ids, (string) null);
+               }
+
+               internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
+               {
+                       StringBuilder sb = new StringBuilder();
                        int length = ids.Length;
+                       long valueToProcess = value;
+                       int zeroValue = -1;
 
                        for (int i = 0; i < length; i ++) {
-                               if (ids[i] == value) 
-                                       if (i >= values.Length)
-                                               return String.Empty;
-                                       else
-                                               return values[i].ToString ();
+                               if (ids[i] == 0) {
+                                       zeroValue = i;
+                               } else {
+                                       if (valueToProcess == 0) {
+                                               break;
+                                       }
+
+                                       if ((ids[i] & value) == ids[i]) {
+                                               if (sb.Length != 0)
+                                                       sb.Append (' ');
+                                               sb.Append (values[i]);
+                                               valueToProcess &= ~ids[i];
+                                       }
+                               }
                        }
-                       return String.Empty;
+
+                       if (valueToProcess != 0) {
+#if NET_2_0
+                               if (typeName != null)
+                                       throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
+                                               "'{0}' is not a valid value for {1}.", value, typeName));
+                               else
+                                       throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
+                                               "'{0}' is not a valid value.", value));
+#else
+                               return value.ToString ();
+#endif
+                       }
+                       if (sb.Length == 0 && zeroValue != -1) {
+                               sb.Append (values[zeroValue]);
+                       }
+                       return sb.ToString ();
                }
 
                internal static string FromXmlName (string name)
@@ -128,7 +165,11 @@ namespace System.Xml.Serialization {
 
                internal static DateTime ToDateTime (string value)
                {
+#if NET_2_0
+                       return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
+#else
                        return XmlConvert.ToDateTime (value);
+#endif
                }
 
                internal static DateTime ToTime (string value)
@@ -141,16 +182,27 @@ namespace System.Xml.Serialization {
                        // Assuming that h contains map from value to Enumerated Name
 /*
                        You can try : 
-                               return ToEnum ("Element", h, "XmlNodeType");
+                               return ToEnum ("One Two", h, "SomeType");
                        where:
                                (1) no keys and values for h.
-                               (2) string keys and Enum, Type, long, string value.
+                               (2) string keys and long values.
+                       
+                       according to MSDN docs (for .NET 2.0) the hashtable "consists of the
+                       identifiers as keys and the constants as integral numbers"
 */
-                       string memberName = (string) values [value];
-                       if (memberName == null)
-                               throw new InvalidOperationException (String.Format ("{0} is not a valid member of type {1}", value, typeName));
+                       long enumValue = 0;
+                       string[] names = value.Split (' ');
+
+                       foreach (string name in names) {
+                               object nameValue = values[name];
+                               if (nameValue != null) {
+                                       enumValue |= (long) nameValue;
+                               } else if (validate && name.Length != 0) {
+                                       throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
+                               }
+                       }
 
-                       return (long) Enum.Parse (Type.GetType (typeName), memberName);
+                       return enumValue;
                }
 
                internal static string ToXmlName (string value)
@@ -181,9 +233,15 @@ namespace System.Xml.Serialization {
                                case "boolean": return XmlConvert.ToString ((bool)value);
                                case "unsignedByte": return XmlConvert.ToString ((byte)value);
                                case "char": return XmlConvert.ToString ((int)(char)value);
+#if NET_2_0
+                               case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
+                               case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
+                               case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
+#else
                                case "dateTime": return XmlConvert.ToString ((DateTime)value);
                                case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
                                case "time": return ((DateTime)value).ToString("HH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
+#endif
                                case "decimal": return XmlConvert.ToString ((decimal)value);
                                case "double": return XmlConvert.ToString ((double)value);
                                case "short": return XmlConvert.ToString ((Int16)value);
@@ -196,8 +254,9 @@ namespace System.Xml.Serialization {
                                case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
                                case "guid": return XmlConvert.ToString ((Guid)value);
                                case "base64":
-                               case "base64Binary": return Convert.ToBase64String ((byte[])value);
-                               case "duration": return XmlConvert.ToString ((TimeSpan) value);
+                               case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
+                               case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
+                               case "duration": return (string) value;
                        default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
                        }
                }
@@ -211,9 +270,15 @@ namespace System.Xml.Serialization {
                                case "boolean": return XmlConvert.ToBoolean (value);
                                case "unsignedByte": return XmlConvert.ToByte (value);
                                case "char": return (char)XmlConvert.ToInt32 (value);
+#if NET_2_0
+                               case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
+                               case "date": return XmlConvert.ToDateTime (value).Date;
+                               case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
+#else
                                case "dateTime": return XmlConvert.ToDateTime (value);
-                               case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
+                               case "date": return XmlConvert.ToDateTime (value).Date;
                                case "time": return DateTime.ParseExact (value, "HH:mm:ss.fffffffzzz", null);
+#endif
                                case "decimal": return XmlConvert.ToDecimal (value);
                                case "double": return XmlConvert.ToDouble (value);
                                case "short": return XmlConvert.ToInt16 (value);
@@ -227,10 +292,11 @@ namespace System.Xml.Serialization {
                                case "guid": return XmlConvert.ToGuid (value);
                                case "base64":
                                case "base64Binary": return Convert.FromBase64String (value);
-                               case "duration": return XmlConvert.ToTimeSpan (value);
+                               case "hexBinary": return XmlConvert.FromBinHexString (value);
+                               case "duration": return value;
                                default: 
                                        if (type.Type != null)
-                                               return Convert.ChangeType (value, type.Type);
+                                               return Convert.ChangeType (value, type.Type, null);
                                        else
                                                return value;
                        }
@@ -238,14 +304,30 @@ namespace System.Xml.Serialization {
 
                internal static string GenerateToXmlString (TypeData type, string value)
                {
+                       if (type.NullableOverride)
+                               return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
+                       else
+                               return GenerateToXmlStringCore (type, value);
+               }
+
+               static string GenerateToXmlStringCore (TypeData type, string value)
+               {
+                       if (type.NullableOverride)
+                               value = value + ".Value";
                        switch (type.XmlType)
                        {
                                case "boolean": return "(" + value + "?\"true\":\"false\")";
                                case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
                                case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
+#if NET_2_0
+                               case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
+                               case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
+                               case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
+#else
                                case "dateTime": return value + ".ToString(\"yyyy-MM-ddTHH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
                                case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
                                case "time": return value + ".ToString(\"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
+#endif
                                case "decimal": return "XmlConvert.ToString (" + value + ")";
                                case "double": return "XmlConvert.ToString (" + value + ")";
                                case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
@@ -258,8 +340,9 @@ namespace System.Xml.Serialization {
                                case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
                                case "guid": return "XmlConvert.ToString (" + value + ")";
                                case "base64":
-                               case "base64Binary": return "Convert.ToBase64String (" + value + ")";
-                               case "duration": return "XmlConvert.ToString (" + value + ")";
+                               case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
+                               case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
+                               case "duration": return value;
                                case "NMTOKEN":
                                case "Name":
                                case "NCName":
@@ -276,15 +359,29 @@ namespace System.Xml.Serialization {
                }
 
                internal static string GenerateFromXmlString (TypeData type, string value)
+               {
+                       if (type.NullableOverride)
+                               return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
+                       else
+                               return GenerateFromXmlStringCore (type, value);
+               }
+
+               static string GenerateFromXmlStringCore (TypeData type, string value)
                {
                        switch (type.XmlType)
                        {
                                case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
                                case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
                                case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
+#if NET_2_0
+                               case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
+                               case "date": return "XmlConvert.ToDateTime (" + value + ").Date";
+                               case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
+#else
                                case "dateTime": return "XmlConvert.ToDateTime (" + value + ")";
-                               case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
+                               case "date": return "XmlConvert.ToDateTime (" + value + ").Date";
                                case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
+#endif
                                case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
                                case "double": return "XmlConvert.ToDouble (" + value + ")";
                                case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
@@ -298,7 +395,8 @@ namespace System.Xml.Serialization {
                                case "guid": return "XmlConvert.ToGuid (" + value + ")";
                                case "base64:":
                                case "base64Binary": return "Convert.FromBase64String (" + value + ")";
-                               case "duration": return "XmlConvert.ToTimeSpan (" + value + ")";
+                               case "hexBinary": return "FromBinHexString (" + value + ")";
+                               case "duration": return value;
                                default: return value;
                        }
                }