[corlib] Enum from reference sources
authorMarek Safar <marek.safar@gmail.com>
Thu, 5 Mar 2015 13:36:41 +0000 (14:36 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 5 Mar 2015 13:37:09 +0000 (14:37 +0100)
external/referencesource
mcs/class/corlib/System/Enum.cs [deleted file]
mcs/class/corlib/System/Environment.cs
mcs/class/corlib/System/MonoType.cs
mcs/class/corlib/System/Type.cs
mcs/class/corlib/Test/System/EnumTest.cs
mcs/class/corlib/Test/System/TypeTest.cs
mcs/class/corlib/corlib.dll.sources
mono/metadata/appdomain.c
mono/metadata/icall-def.h
mono/metadata/icall.c

index 41a6d3d6a5432b964b6f8439b6375ffad6f2e6cb..4bb7900e7905930505b93124c2ab144936903ba4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 41a6d3d6a5432b964b6f8439b6375ffad6f2e6cb
+Subproject commit 4bb7900e7905930505b93124c2ab144936903ba4
diff --git a/mcs/class/corlib/System/Enum.cs b/mcs/class/corlib/System/Enum.cs
deleted file mode 100644 (file)
index c7df088..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-//
-// System.Enum.cs
-//
-// Authors:
-//   Miguel de Icaza (miguel@ximian.com)
-//   Nick Drochak (ndrochak@gol.com)
-//   Gonzalo Paniagua Javier (gonzalo@ximian.com)
-//   Marek Safar (marek.safar@gmail.com)
-//
-// (C) Ximian, Inc.  http://www.ximian.com
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Reflection;
-
-namespace System
-{
-       internal struct MonoEnumInfo
-       {
-               internal Type utype;
-               internal Array values;
-               internal string[] names;
-               internal Dictionary<string, int> name_hash;
-               [ThreadStatic]
-               static Dictionary<Type, MonoEnumInfo> cache;
-               static readonly Dictionary<Type, MonoEnumInfo> global_cache = new Dictionary<Type, MonoEnumInfo> ();
-               static object global_cache_monitor = new object ();
-               
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private static extern void get_enum_info (Type enumType, out MonoEnumInfo info);
-
-               //
-               // These comparers are needed because enumerations must be compared
-               // using unsigned values so that negative numbers can be looked up
-               // See bug: #371559
-               //
-               internal static SByteComparer  sbyte_comparer = new SByteComparer ();
-               internal static ShortComparer short_comparer = new ShortComparer ();
-               internal static IntComparer   int_comparer = new IntComparer ();
-               internal static LongComparer  long_comparer = new LongComparer ();
-               
-               internal class SByteComparer : IComparer, System.Collections.Generic.IComparer<sbyte>
-               {
-                       public int Compare (object x, object y)
-                       {
-                               sbyte ix = (sbyte) x;
-                               sbyte iy = (sbyte) y;
-                               
-                               return ((byte) ix) - ((byte) iy);
-                       }
-
-                       public int Compare (sbyte ix, sbyte iy)
-                       {
-                               return ((byte) ix) - ((byte) iy);
-                       }
-               }
-               
-               internal class ShortComparer : IComparer, System.Collections.Generic.IComparer<short>
-               {
-                       public int Compare (object x, object y)
-                       {
-                               short ix = (short) x;
-                               short iy = (short) y;
-                               
-                               return ((ushort) ix) - ((ushort) iy);
-                       }
-
-                       public int Compare (short ix, short iy)
-                       {
-                               return ((ushort) ix) - ((ushort) iy);
-                       }
-               }
-               
-               internal class IntComparer : IComparer, System.Collections.Generic.IComparer<int>
-                 {
-                       public int Compare (object x, object y)
-                       {
-                               int ix = (int) x;
-                               int iy = (int) y;
-
-                               if (ix == iy)
-                                       return 0;
-
-                               if (((uint) ix) < ((uint) iy))
-                                       return -1;
-                               return 1;
-                       }
-
-                       public int Compare (int ix, int iy)
-                       {
-                               if (ix == iy)
-                                       return 0;
-
-                               if (((uint) ix) < ((uint) iy))
-                                       return -1;
-                               return 1;
-                       }
-               }
-
-               internal class LongComparer : IComparer, System.Collections.Generic.IComparer<long>
-               {
-                       public int Compare (object x, object y)
-                       {
-                               long ix = (long) x;
-                               long iy = (long) y;
-                               
-                               if (ix == iy)
-                                       return 0;
-                               if (((ulong) ix) < ((ulong) iy))
-                                       return -1;
-                               return 1;
-                       }
-
-                       public int Compare (long ix, long iy)
-                       {
-                               if (ix == iy)
-                                       return 0;
-                               if (((ulong) ix) < ((ulong) iy))
-                                       return -1;
-                               return 1;
-                       }
-               }
-
-               private MonoEnumInfo (MonoEnumInfo other)
-               {
-                       utype = other.utype;
-                       values = other.values;
-                       names = other.names;
-                       name_hash = other.name_hash;
-               }
-               
-               internal static void GetInfo (Type enumType, out MonoEnumInfo info)
-               {
-                       var user_type = !(enumType is MonoType);
-
-                       if (user_type) {
-                               GetUserEnumInfo (enumType, out info);
-                       } else {
-                               /* First check the thread-local cache without locking */
-                               if (cache != null && cache.TryGetValue (enumType, out info)) {
-                                       return;
-                               }
-
-                               /* Threads could die, so keep a global cache too */
-                               lock (global_cache_monitor) {
-                                       if (global_cache.TryGetValue (enumType, out info)) {
-                                               if (cache == null)
-                                                       cache = new Dictionary<Type, MonoEnumInfo> ();
-
-                                               cache [enumType] = info;
-                                               return;
-                                       }
-                               }
-
-                               // TODO: return info with ulong values only to avoid all sorts of
-                               // Array trick and slow paths
-                               get_enum_info (enumType, out info);
-                       }
-
-                       SortEnums (info.utype, info.values, info.names);
-
-                       // User types can have unreliable/not-implemented GetHashCode
-                       if (user_type)
-                               return;
-                       
-                       if (info.names.Length > 50) {
-                               info.name_hash = new Dictionary<string, int> (info.names.Length);
-                               for (int i = 0; i <  info.names.Length; ++i)
-                                       info.name_hash [info.names [i]] = i;
-                       }
-                       MonoEnumInfo cached = new MonoEnumInfo (info);
-                       lock (global_cache_monitor) {
-                               global_cache [enumType] = cached;
-                       }
-               }
-
-               static void GetUserEnumInfo (Type type, out MonoEnumInfo mei)
-               {
-                       mei = new MonoEnumInfo ();
-                       mei.utype = typeof (UInt64);
-
-                       var fields = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
-                       mei.names = new string [fields.Length];
-                       var values = new UInt64 [fields.Length];
-                       mei.values = values;
-
-                       for (int i = 0; i < fields.Length; ++i) {
-                               mei.names [i] = fields [i].Name;
-                               values [i] = ToUInt64 (fields [i].GetRawConstantValue ());
-                       }
-               }
-
-               public static ulong ToUInt64 (object value)
-               {
-                       switch (Convert.GetTypeCode (value)) {
-                       case TypeCode.SByte:
-                       case TypeCode.Int16:
-                       case TypeCode.Int32:
-                       case TypeCode.Int64:
-                               return (UInt64) Convert.ToInt64 (value, CultureInfo.InvariantCulture);
-
-                       case TypeCode.Byte:
-                       case TypeCode.UInt16:
-                       case TypeCode.UInt32:
-                       case TypeCode.UInt64:
-                       case TypeCode.Boolean:
-                       case TypeCode.Char:
-                               return Convert.ToUInt64 (value, CultureInfo.InvariantCulture);
-
-                       default:
-                               throw new ArgumentException ("Value is not the enum or a valid enum underlying type", "value");
-                       }
-               }
-               
-               internal static void SortEnums (Type et, Array values, string[] names)
-               {
-                       IComparer ic;
-                       if (et == typeof (int))
-                               ic = int_comparer;
-                       else if (et == typeof (short))
-                               ic = short_comparer;
-                       else if (et == typeof (sbyte))
-                               ic = sbyte_comparer;
-                       else if (et == typeof (long))
-                               ic = long_comparer;
-                       else
-                               ic = null;
-                               
-                       Array.Sort (values, names, ic);
-               }
-       }
-
-       [Serializable]
-       [ComVisible (true)]
-       public abstract class Enum : ValueType, IComparable, IConvertible, IFormattable
-       {
-               protected Enum ()
-               {
-               }
-
-               // IConvertible methods Start -->
-               public TypeCode GetTypeCode ()
-               {
-                       return Type.GetTypeCode (GetUnderlyingType (this.GetType ()));
-               }
-
-               bool IConvertible.ToBoolean (IFormatProvider provider)
-               {
-                       return Convert.ToBoolean (Value, provider);
-               }
-
-               byte IConvertible.ToByte (IFormatProvider provider)
-               {
-                       return Convert.ToByte (Value, provider);
-               }
-
-               char IConvertible.ToChar (IFormatProvider provider)
-               {
-                       return Convert.ToChar (Value, provider);
-               }
-
-               DateTime IConvertible.ToDateTime (IFormatProvider provider)
-               {
-                       return Convert.ToDateTime (Value, provider);
-               }
-
-               decimal IConvertible.ToDecimal (IFormatProvider provider)
-               {       
-                       return Convert.ToDecimal (Value, provider);
-               }
-
-               double IConvertible.ToDouble (IFormatProvider provider)
-               {       
-                       return Convert.ToDouble (Value, provider);
-               }
-
-               short IConvertible.ToInt16 (IFormatProvider provider)
-               {
-                       return Convert.ToInt16 (Value, provider);
-               }
-
-               int IConvertible.ToInt32 (IFormatProvider provider)
-               {
-                       return Convert.ToInt32 (Value, provider);
-               }
-
-               long IConvertible.ToInt64 (IFormatProvider provider)
-               {
-                       return Convert.ToInt64 (Value, provider);
-               }
-
-               sbyte IConvertible.ToSByte (IFormatProvider provider)
-               {
-                       return Convert.ToSByte (Value, provider);
-               }
-
-               float IConvertible.ToSingle (IFormatProvider provider)
-               {
-                       return Convert.ToSingle (Value, provider);
-               }
-
-               object IConvertible.ToType (Type type, IFormatProvider provider)
-               {
-                       return Convert.DefaultToType ((IConvertible)this, type, provider);
-               }
-
-               ushort IConvertible.ToUInt16 (IFormatProvider provider)
-               {
-                       return Convert.ToUInt16 (Value, provider);
-               }
-
-               uint IConvertible.ToUInt32 (IFormatProvider provider)
-               {
-                       return Convert.ToUInt32 (Value, provider);
-               }
-
-               ulong IConvertible.ToUInt64 (IFormatProvider provider)
-               {
-                       return Convert.ToUInt64 (Value, provider);
-               }
-
-               // <-- End IConvertible methods
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern object get_value ();
-
-               // wrap the icall into a property so we don't hav to use the icall everywhere
-               private object Value {
-                       get { return get_value (); }
-               }
-
-               [ComVisible (true)]
-               public static Array GetValues (Type enumType)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-                       return (Array) info.values.Clone ();
-               }
-
-               [ComVisible (true)]
-               public static string[] GetNames (Type enumType)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.");
-
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-                       return (string []) info.names.Clone ();
-               }
-
-               //
-               // The faster, non-boxing version.   It must use the special MonoEnumInfo.xxx_comparers
-               // to ensure that we are perfoming bitwise compares, and not signed compares.
-               //
-               // It also tries to use the non-boxing version of the various Array.BinarySearch methods
-               //
-               static int FindPosition (Type underlyingEnumType, object value, Array values)
-               {
-                       switch (Type.GetTypeCode (underlyingEnumType)) {
-                       case TypeCode.SByte:
-                               sbyte [] sbyte_array = values as sbyte [];
-                               return Array.BinarySearch (sbyte_array, (sbyte) value,  MonoEnumInfo.sbyte_comparer);
-
-                       case TypeCode.Byte:
-                               byte [] byte_array = values as byte [];
-                               return Array.BinarySearch (byte_array, (byte) value);
-
-                       case TypeCode.Int16:
-                               short [] short_array = values as short [];
-                               return Array.BinarySearch (short_array, (short)value, MonoEnumInfo.short_comparer);
-
-                       case TypeCode.UInt16:
-                               ushort [] ushort_array = values as ushort [];
-                               return Array.BinarySearch (ushort_array, (ushort)value);
-               
-                       case TypeCode.Int32:
-                               int[] int_array = values as int[];
-                               return Array.BinarySearch (int_array, (int)value, MonoEnumInfo.int_comparer);
-
-                       case TypeCode.UInt32:
-                               uint[] uint_array = values as uint [];
-                               return Array.BinarySearch (uint_array, (uint)value);                    
-                       
-                       case TypeCode.Int64:
-                               long [] long_array = values as long [];
-                               return Array.BinarySearch (long_array, (long) value,  MonoEnumInfo.long_comparer);
-
-                       case TypeCode.UInt64:
-                               ulong [] ulong_array = values as ulong [];
-                               return Array.BinarySearch (ulong_array, (ulong) value);
-
-                       default:
-                               // This should never happen
-                               throw new NotSupportedException ("Unknown underlying enum type");
-                       }
-               }
-       
-               [ComVisible (true)]
-               public static string GetName (Type enumType, object value)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-                       if (value == null)
-                               throw new ArgumentNullException ("value");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-
-                       if (enumType is MonoType)
-                               value = ToObject (enumType, value);
-                       else
-                               value = MonoEnumInfo.ToUInt64 (value);
-
-                       int i = FindPosition (info.utype, value, info.values);
-                       return (i >= 0) ? info.names [i] : null;
-               }
-
-               [ComVisible (true)]
-               public static bool IsDefined (Type enumType, object value)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-                       if (value == null)
-                               throw new ArgumentNullException ("value");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-
-                       Type vType = value.GetType ();
-                       if (vType == typeof (String)) {
-                               return ((IList)(info.names)).Contains (value);
-                       }
-
-                       if ((vType == info.utype || !(enumType is MonoType)) || (vType == enumType)) {
-                               if (enumType is MonoType)
-                                       value = ToObject (enumType, value);
-                               else
-                                       value = MonoEnumInfo.ToUInt64 (value);
-
-                               MonoEnumInfo.GetInfo (enumType, out info);
-                               return FindPosition (info.utype, value, info.values) >= 0;
-                       }
-
-                       if (IsValidEnumType (info.utype))
-                               throw new ArgumentException("The value parameter is not the correct type. "
-                                       + "It must be type String or the same type as the underlying type "
-                                       + "of the Enum.");
-
-                       throw new InvalidOperationException ("Unknown enum type.");
-               }
-
-               static bool IsValidEnumType (Type type)
-               {
-                       return (type.IsPrimitive && type != typeof (double) && type != typeof (float));
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private static extern Type get_underlying_type (Type enumType);
-
-               [ComVisible (true)]
-               public static Type GetUnderlyingType (Type enumType)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-
-                       return get_underlying_type (enumType);
-               }
-
-               [ComVisible (true)]
-               public static object Parse (Type enumType, string value)
-               {
-                       // Note: Parameters are checked in the other overload
-                       return Parse (enumType, value, false);
-               }
-
-               private static int FindName (IDictionary<string, int> name_hash, string [] names, string name,  bool ignoreCase)
-               {
-                       if (!ignoreCase) {
-                               /* For enums with many values, use a hash table */
-                               if (name_hash != null) {
-                                       int val;
-                                       if (name_hash.TryGetValue (name, out val))
-                                               return val;
-                               } else {
-                                       for (int i = 0; i < names.Length; ++i) {
-                                               if (name == names [i])
-                                                       return i;
-                                       }
-                               }
-                       } else {
-                               for (int i = 0; i < names.Length; ++i) {
-                                       if (String.Compare (name, names [i], ignoreCase, CultureInfo.InvariantCulture) == 0)
-                                               return i;
-                               }
-                       }
-                       return -1;
-               }
-
-               // Helper function for dealing with [Flags]-style enums.
-               private static ulong GetValue (object value, TypeCode typeCode)
-               {
-                       switch (typeCode) {
-                       case TypeCode.Byte:
-                               return (byte) value;
-                       case TypeCode.SByte:
-                               return (byte) ((sbyte) value);
-                       case TypeCode.Int16:
-                               return (ushort) ((short) value);
-                       case TypeCode.Int32:
-                               return (uint) ((int) value);
-                       case TypeCode.Int64:
-                               return (ulong) ((long) value);
-                       case TypeCode.UInt16:
-                               return (ushort) value;
-                       case TypeCode.UInt32:
-                               return (uint) value;
-                       case TypeCode.UInt64:
-                               return (ulong) value;
-                       }
-                       throw new ArgumentException ("typeCode is not a valid type code for an Enum");
-               }
-
-               [ComVisible(true)]
-               public static object Parse (Type enumType, string value, bool ignoreCase)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-
-                       if (value == null)
-                               throw new ArgumentNullException ("value");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-
-                       value = value.Trim ();
-                       if (value.Length == 0)
-                               throw new ArgumentException ("An empty string is not considered a valid value.");
-
-                       object result;
-                       if (!Parse (enumType, value, ignoreCase, out result))
-                               throw new ArgumentException (String.Format ("The requested value '{0}' was not found.", value));
-
-                       return result;
-               }
-
-               static char [] split_char;
-
-               static bool Parse<TEnum> (Type enumType, string value, bool ignoreCase, out TEnum result)
-               {
-                       result = default (TEnum);
-
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-
-                       // is 'value' a named constant?
-                       int loc = FindName (info.name_hash, info.names, value, ignoreCase);
-                       if (loc >= 0) {
-                               result = (TEnum) info.values.GetValue (loc);
-                               return true;
-                       }
-
-                       TypeCode typeCode = ((Enum) info.values.GetValue (0)).GetTypeCode ();
-
-                       // is 'value' a list of named constants?
-                       if (value.IndexOf (',') != -1) {
-                               if (split_char == null)
-                                       split_char = new [] { ',' };
-                               string [] names = value.Split (split_char);
-                               ulong retVal = 0;
-                               for (int i = 0; i < names.Length; ++i) {
-                                       loc = FindName (info.name_hash, info.names, names [i].Trim (), ignoreCase);
-                                       if (loc < 0)
-                                               return false;
-
-                                       retVal |= GetValue (info.values.GetValue (loc), typeCode);
-                               }
-                               result = (TEnum) ToObject (enumType, retVal);
-                               return true;
-                       }
-
-                       // is 'value' a number?
-                       switch (typeCode) {
-                       case TypeCode.SByte:
-                               sbyte sb;
-                               if (!SByte.TryParse (value, out sb))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, sb);
-                               break;
-                       case TypeCode.Byte:
-                               byte b;
-                               if (!Byte.TryParse (value, out b))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, b);
-                               break;
-                       case TypeCode.Int16:
-                               short i16;
-                               if (!Int16.TryParse (value, out i16))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, i16);
-                               break;
-                       case TypeCode.UInt16:
-                               ushort u16;
-                               if (!UInt16.TryParse (value, out u16))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, u16);
-                               break;
-                       case TypeCode.Int32:
-                               int i32;
-                               if (!Int32.TryParse (value, out i32))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, i32);
-                               break;
-                       case TypeCode.UInt32:
-                               uint u32;
-                               if (!UInt32.TryParse (value, out u32))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, u32);
-                               break;
-                       case TypeCode.Int64:
-                               long i64;
-                               if (!Int64.TryParse (value, out i64))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, i64);
-                               break;
-                       case TypeCode.UInt64:
-                               ulong u64;
-                               if (!UInt64.TryParse (value, out u64))
-                                       return false;
-                               result = (TEnum) ToObject (enumType, u64);
-                               break;
-                       default:
-                               break;
-                       }
-
-                       return true;
-               }
-
-               public static bool TryParse<TEnum> (string value, out TEnum result) where TEnum : struct
-               {
-                       return TryParse (value, false, out result);
-               }
-
-               public static bool TryParse<TEnum> (string value, bool ignoreCase, out TEnum result) where TEnum : struct
-               {
-                       Type tenum_type = typeof (TEnum);
-                       if (!tenum_type.IsEnum)
-                               throw new ArgumentException("TEnum is not an Enum type.", "enumType");
-
-                       result = default (TEnum);
-
-                       if (value == null)
-                               return false;
-
-                       value = value.Trim ();
-                       if (value.Length == 0)
-                               return false;
-
-                       return Parse (tenum_type, value, ignoreCase, out result);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern int compare_value_to (object other);
-
-               /// <summary>
-               ///   Compares the enum value with another enum value of the same type.
-               /// </summary>
-               ///
-               /// <remarks/>
-               public int CompareTo (object target)
-               {
-                       Type thisType;
-
-                       if (target == null)
-                               return 1;
-
-                       thisType = this.GetType ();
-                       if (target.GetType() != thisType) {
-                               throw new ArgumentException (String.Format (
-                                       "Object must be the same type as the enum. The type passed in was {0}; the enum type was {1}.", 
-                                       target.GetType(), thisType));
-                       }
-
-                       return compare_value_to (target);
-               }
-
-               public override string ToString ()
-               {
-                       return Format (GetType (), Value, "G");
-               }
-
-               [Obsolete("Provider is ignored, just use ToString")]
-               public string ToString (IFormatProvider provider)
-               {
-                       return ToString ("G", provider);
-               }
-
-               public string ToString (String format)
-               {
-                       if (format == String.Empty || format == null)
-                               format = "G";
-                       
-                       return Format (this.GetType (), this.Value, format);
-               }
-
-               [Obsolete("Provider is ignored, just use ToString")]
-               public string ToString (String format, IFormatProvider provider)
-               {
-                       // provider is not used for Enums
-
-                       if (format == String.Empty || format == null) {
-                               format = "G";
-                       }
-                       return Format (this.GetType(), this.Value, format);
-               }
-
-               [ComVisible (true)]
-               public static object ToObject (Type enumType, byte value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               public static object ToObject (Type enumType, short value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               public static object ToObject (Type enumType, int value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               public static object ToObject (Type enumType, long value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public static extern object ToObject (Type enumType, object value);
-
-               [ComVisible (true)]
-               [CLSCompliant (false)]
-               public static object ToObject (Type enumType, sbyte value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               [CLSCompliant (false)]
-               public static object ToObject (Type enumType, ushort value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               [CLSCompliant (false)]
-               public static object ToObject (Type enumType, uint value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               [ComVisible (true)]
-               [CLSCompliant (false)]
-               public static object ToObject (Type enumType, ulong value)
-               {
-                       return ToObject (enumType, (object)value);
-               }
-
-               public override bool Equals (object obj)
-               {
-                       return DefaultEquals (this, obj);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern int get_hashcode ();
-
-               public override int GetHashCode ()
-               {
-                       return get_hashcode ();
-               }
-
-               private static string FormatSpecifier_X (Type enumType, object value, bool upper)
-               {
-                       switch (Type.GetTypeCode (enumType)) {
-                       case TypeCode.SByte:
-                               return NumberFormatter.NumberToString (upper ? "X2" : "x2", ((sbyte)value), null);
-                       case TypeCode.Byte:
-                               return NumberFormatter.NumberToString (upper ? "X2" : "x2", ((byte)value), null);
-                       case TypeCode.Int16:
-                               return NumberFormatter.NumberToString (upper ? "X4" : "x4", ((short)value), null);
-                       case TypeCode.UInt16:
-                               return NumberFormatter.NumberToString (upper ? "X4" : "x4", ((ushort)value), null);
-                       case TypeCode.Int32:
-                               return NumberFormatter.NumberToString (upper ? "X8" : "x8", ((int)value), null);
-                       case TypeCode.UInt32:
-                               return NumberFormatter.NumberToString (upper ? "X8" : "x8", ((uint)value), null);
-                       case TypeCode.Int64:
-                               return NumberFormatter.NumberToString (upper ? "X16" : "x16", ((long)value), null);
-                       case TypeCode.UInt64:
-                               return NumberFormatter.NumberToString (upper ? "X16" : "x16", ((ulong)value), null);
-                       default:
-                               throw new Exception ("Invalid type code for enumeration.");
-                       }
-               }
-
-               static string FormatFlags (Type enumType, object value)
-               {
-                       string retVal = String.Empty;
-                       MonoEnumInfo info;
-                       MonoEnumInfo.GetInfo (enumType, out info);
-                       string asString = value.ToString ();
-                       if (asString == "0") {
-                               retVal = GetName (enumType, value);
-                               if (retVal == null)
-                                       retVal = asString;
-                               return retVal;
-                       }
-                       // This is ugly, yes.  We need to handle the different integer
-                       // types for enums.  If someone else has a better idea, be my guest.
-                       switch (((Enum)info.values.GetValue (0)).GetTypeCode ()) {
-                       case TypeCode.SByte: {
-                               sbyte flags = (sbyte) value;
-                               sbyte enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (sbyte) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.Byte: {
-                               byte flags = (byte) value;
-                               byte enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (byte) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.Int16: {
-                               short flags = (short) value;
-                               short enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (short) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.Int32: {
-                               int flags = (int) value;
-                               int enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (int) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.UInt16: {
-                               ushort flags = (ushort) value;
-                               ushort enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (ushort) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.UInt32: {
-                               uint flags = (uint) value;
-                               uint enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (uint) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.Int64: {
-                               long flags = (long) value;
-                               long enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (long) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       case TypeCode.UInt64: {
-                               ulong flags = (ulong) value;
-                               ulong enumValue;
-                               for (int i = info.values.Length - 1; i >= 0; i--) {
-                                       enumValue = (ulong) info.values.GetValue (i);
-                                       if (enumValue == 0)
-                                               continue;
-
-                                       if ((flags & enumValue) == enumValue) {
-                                               retVal = info.names[i] + (retVal == String.Empty ? String.Empty : ", ") + retVal;
-                                               flags -= enumValue;
-                                       }
-                               }
-                               if (flags != 0) return asString;
-                               }
-                               break;
-                       }
-
-                       if (retVal == String.Empty)
-                               return asString;
-
-                       return retVal;
-               }
-
-               [ComVisible (true)]
-               public static string Format (Type enumType, object value, string format)
-               {
-                       if (enumType == null)
-                               throw new ArgumentNullException ("enumType");
-                       if (value == null)
-                               throw new ArgumentNullException ("value");
-                       if (format == null)
-                               throw new ArgumentNullException ("format");
-
-                       if (!enumType.IsEnum)
-                               throw new ArgumentException ("enumType is not an Enum type.", "enumType");
-                       
-                       Type vType = value.GetType();
-                       Type underlyingType = Enum.GetUnderlyingType (enumType);
-                       if (vType.IsEnum) {
-                               if (vType != enumType)
-                                       throw new ArgumentException (string.Format(
-                                               "Object must be the same type as the enum. The type" +
-                                               " passed in was {0}; the enum type was {1}.",
-                                               vType.FullName, enumType.FullName));
-                       } else if (vType != underlyingType) {
-                               throw new ArgumentException (string.Format (
-                                       "Enum underlying type and the object must be the same type" +
-                                       " or object. Type passed in was {0}; the enum underlying" +
-                                       " type was {1}.", vType.FullName, underlyingType.FullName));
-                       }
-
-                       if (format.Length == 1) {
-                               switch (format [0]) {
-                               case 'f':
-                               case 'F':
-                                       return FormatFlags (enumType, value);
-                               case 'g':
-                               case 'G':
-                                       if (!enumType.IsDefined (typeof(FlagsAttribute), false))
-                                               return GetName (enumType, value) ?? value.ToString ();
-                                       
-                                       goto case 'f';
-                               case 'X':
-                                       return FormatSpecifier_X (enumType, value, true);
-                               case 'x':
-                                       return FormatSpecifier_X (enumType, value, false);
-                               case 'D':
-                               case 'd':
-                                       if (vType.IsEnum)
-                                               value = ((Enum) value).Value;
-
-                                       return value.ToString ();
-                               }
-                       }               
-
-                       throw new FormatException ("Format String can be only \"G\",\"g\",\"X\"," + 
-                                       "\"x\",\"F\",\"f\",\"D\" or \"d\".");
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private static extern bool InternalHasFlag (Enum a, Enum b);
-
-               public bool HasFlag (Enum flag)
-               {
-                       if (flag == null)
-                               throw new ArgumentNullException ("flag");
-
-                       if (!this.GetType ().IsEquivalentTo (flag.GetType ()))
-                               throw new ArgumentException (Environment.GetResourceString ("Argument_EnumTypeDoesNotMatch", flag.GetType (), this.GetType ()));
-
-                       return InternalHasFlag (this, flag);
-               }
-       }
-}
index e356d68f252c954e9c1c910e7901f12766cf2627..998b127ae9cc158afcc2e22d6fa14c8c49eee628 100644 (file)
@@ -57,7 +57,7 @@ namespace System {
                 * of icalls, do not require an increment.
                 */
 #pragma warning disable 169
-               private const int mono_corlib_version = 118;
+               private const int mono_corlib_version = 119;
 #pragma warning restore 169
 
                [ComVisible (true)]
index 01be2cf36239877f3d24c42d4bcacd317c2ff2b7..70593e055c06e4f916780b4089a8ba872db9a709 100644 (file)
@@ -56,6 +56,8 @@ namespace System
                
        abstract class RuntimeType : TypeInfo
        {
+               private static readonly RuntimeType StringType = (RuntimeType)typeof(System.String);
+
                private static readonly RuntimeType DelegateType = (RuntimeType)typeof(System.Delegate);
 
                internal RuntimeAssembly GetRuntimeAssembly ()
@@ -712,7 +714,133 @@ namespace System
                        }
 
                        return ctor.InternalInvoke (null, null);
-               }        
+               }
+
+        #region Enums
+        public override string[] GetEnumNames()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            String[] ret = Enum.InternalGetNames(this);
+
+            // Make a copy since we can't hand out the same array since users can modify them
+            String[] retVal = new String[ret.Length];
+
+            Array.Copy(ret, retVal, ret.Length);
+
+            return retVal;
+        }
+
+        [SecuritySafeCritical]
+        public override Array GetEnumValues()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            // Get all of the values
+            ulong[] values = Enum.InternalGetValues(this);
+
+            // Create a generic Array
+            Array ret = Array.UnsafeCreateInstance(this, values.Length);
+
+            for (int i = 0; i < values.Length; i++)
+            {
+                Object val = Enum.ToObject(this, values[i]);
+                ret.SetValue(val, i);
+            }
+
+            return ret;
+        }
+
+        public override Type GetEnumUnderlyingType()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            return Enum.InternalGetUnderlyingType(this);
+        }
+
+        public override bool IsEnumDefined(object value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+            Contract.EndContractBlock();
+
+            // Check if both of them are of the same type
+            RuntimeType valueType = (RuntimeType)value.GetType();
+
+            // If the value is an Enum then we need to extract the underlying value from it
+            if (valueType.IsEnum)
+            {
+                if (!valueType.IsEquivalentTo(this))
+                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));
+
+                valueType = (RuntimeType)valueType.GetEnumUnderlyingType();
+            }
+
+            // If a string is passed in
+            if (valueType == RuntimeType.StringType)
+            {
+                // Get all of the Fields, calling GetHashEntry directly to avoid copying
+                string[] names = Enum.InternalGetNames(this);
+                if (Array.IndexOf(names, value) >= 0)
+                    return true;
+                else
+                    return false;
+            }
+
+            // If an enum or integer value is passed in
+            if (Type.IsIntegerType(valueType))
+            {
+                RuntimeType underlyingType = Enum.InternalGetUnderlyingType(this);
+                if (underlyingType != valueType)
+                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+
+                ulong[] ulValues = Enum.InternalGetValues(this);
+                ulong ulValue = Enum.ToUInt64(value);
+
+                return (Array.BinarySearch(ulValues, ulValue) >= 0);
+            }
+            else if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
+            {
+                // if at this point the value type is not an integer type, then its type doesn't match the enum type
+                // NetCF used to throw an argument exception in this case
+                throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), GetEnumUnderlyingType()));
+            }
+            else
+            {
+                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+            }
+        }
+
+        public override string GetEnumName(object value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+            Contract.EndContractBlock();
+
+            Type valueType = value.GetType();
+
+            if (!(valueType.IsEnum || IsIntegerType(valueType)))
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+
+            ulong[] ulValues = Enum.InternalGetValues(this);
+            ulong ulValue = Enum.ToUInt64(value);
+            int index = Array.BinarySearch(ulValues, ulValue);
+
+            if (index >= 0)
+            {
+                string[] names = Enum.InternalGetNames(this);
+                return names[index];
+            }
+
+            return null;
+        }
+        #endregion     
 
                internal abstract MonoCMethod GetDefaultConstructor ();
 
@@ -1453,11 +1581,25 @@ namespace System
                }
 
 
-               public override Array GetEnumValues () {
-                       if (!IsEnum)
-                               throw new ArgumentException ("Type is not an enumeration", "enumType");
+               public override Array GetEnumValues ()
+               {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            // Get all of the values
+            ulong[] values = Enum.InternalGetValues(this);
+
+            // Create a generic Array
+            Array ret = Array.UnsafeCreateInstance(this, values.Length);
+
+            for (int i = 0; i < values.Length; i++)
+            {
+                Object val = Enum.ToObject(this, values[i]);
+                ret.SetValue(val, i);
+            }
 
-                       return Enum.GetValues (this);
+            return ret;
                }
 
                static MethodBase CheckMethodSecurity (MethodBase mb)
index c90c1bee3aac1a4405b8efb6a7ffb33aa6bea487..9237fdece10d3b66a631d95e446f2f488a2d1d9f 100644 (file)
@@ -475,62 +475,10 @@ namespace System {
                        return !Object.ReferenceEquals (left, right);
                }
 
-               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
-               public virtual Type GetEnumUnderlyingType () {
-                       if (!IsEnum)
-                               throw new ArgumentException ("Type is not an enumeration", "enumType");
-
-                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
-
-                       if (fields == null || fields.Length != 1)
-                               throw new ArgumentException ("An enum must have exactly one instance field", "enumType");
-
-                       return fields [0].FieldType;
-               }
-
-               [MonoInternalNote ("Reimplement this in MonoType for bonus speed")]
-               public virtual string[] GetEnumNames () {
-                       if (!IsEnum)
-                               throw new ArgumentException ("Type is not an enumeration", "enumType");
-
-                       var fields = GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
-
-                       string [] names = new string [fields.Length];
-                       if (0 != names.Length) {
-                               for (int i = 0; i < fields.Length; ++i)
-                                       names [i] = fields [i].Name;
-                                       
-                               var et = GetEnumUnderlyingType ();
-                               var values = Array.CreateInstance (et, names.Length);
-                               for (int i = 0; i < fields.Length; ++i)
-                                       values.SetValue (fields [i].GetValue (null), i);
-                               MonoEnumInfo.SortEnums (et, values, names);
-                       }
-
-                       return names;
-               }
-
                static NotImplementedException CreateNIE () {
                        return new NotImplementedException ();
                }
 
-               public virtual Array GetEnumValues () {
-                       if (!IsEnum)
-                               throw new ArgumentException ("Type is not an enumeration", "enumType");
-
-                       throw CreateNIE ();
-               }
-
-               public virtual string GetEnumName (object value)
-               {
-                       return Enum.GetName (this, value);
-               }
-
-               public virtual bool IsEnumDefined (object value)
-               {
-                       return Enum.IsDefined (this, value);
-               }
-       
                public static Type GetType (string typeName, Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver)
                {
                        return GetType (typeName, assemblyResolver, typeResolver, false, false);
@@ -1644,6 +1592,214 @@ namespace System {
                        return rootElementType;
                }
 
+        #region Enum methods
+
+        // Default implementations of GetEnumNames, GetEnumValues, and GetEnumUnderlyingType
+        // Subclass of types can override these methods.
+
+        public virtual string[] GetEnumNames()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.Ensures(Contract.Result<String[]>() != null);
+
+            string[] names;
+            Array values;
+            GetEnumData(out names, out values);
+            return names;
+        }
+
+        // We don't support GetEnumValues in the default implementation because we cannot create an array of
+        // a non-runtime type. If there is strong need we can consider returning an object or int64 array.
+        public virtual Array GetEnumValues()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.Ensures(Contract.Result<Array>() != null);
+
+            throw new NotImplementedException();
+        }
+
+        // Returns the enum values as an object array.
+        private Array GetEnumRawConstantValues()
+        {
+            string[] names;
+            Array values;
+            GetEnumData(out names, out values);
+            return values;
+        }
+
+        // This will return enumValues and enumNames sorted by the values.
+        private void GetEnumData(out string[] enumNames, out Array enumValues)
+        {
+            Contract.Ensures(Contract.ValueAtReturn<String[]>(out enumNames) != null);
+            Contract.Ensures(Contract.ValueAtReturn<Array>(out enumValues) != null);
+
+            FieldInfo[] flds = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+            object[] values = new object[flds.Length];
+            string[] names = new string[flds.Length];
+
+            for (int i = 0; i < flds.Length; i++)
+            {
+                names[i] = flds[i].Name;
+                values[i] = flds[i].GetRawConstantValue();
+            }
+
+            // Insertion Sort these values in ascending order.
+            // We use this O(n^2) algorithm, but it turns out that most of the time the elements are already in sorted order and
+            // the common case performance will be faster than quick sorting this.
+            IComparer comparer = Comparer.Default;
+            for (int i = 1; i < values.Length; i++)
+            {
+                int j = i;
+                string tempStr = names[i];
+                object val = values[i];
+                bool exchanged = false;
+
+                // Since the elements are sorted we only need to do one comparision, we keep the check for j inside the loop.
+                while (comparer.Compare(values[j - 1], val) > 0)
+                {
+                    names[j] = names[j - 1];
+                    values[j] = values[j - 1];
+                    j--;
+                    exchanged = true;
+                    if (j == 0)
+                        break;
+                }
+
+                if (exchanged)
+                {
+                    names[j] = tempStr;
+                    values[j] = val;
+                }
+            }
+
+            enumNames = names;
+            enumValues = values;
+        }
+
+        public virtual Type GetEnumUnderlyingType()
+        {
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.Ensures(Contract.Result<Type>() != null);
+
+            FieldInfo[] fields = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+            if (fields == null || fields.Length != 1)
+                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnum"), "enumType");
+
+            return fields[0].FieldType;
+        }
+
+        public virtual bool IsEnumDefined(object value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            // Check if both of them are of the same type
+            Type valueType = value.GetType();
+
+            // If the value is an Enum then we need to extract the underlying value from it
+            if (valueType.IsEnum)
+            {
+                if (!valueType.IsEquivalentTo(this))
+                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));
+
+                valueType = valueType.GetEnumUnderlyingType();
+            }
+
+            // If a string is passed in
+            if (valueType == typeof(string))
+            {
+                string[] names = GetEnumNames();
+                if (Array.IndexOf(names, value) >= 0)
+                    return true;
+                else
+                    return false;
+            }
+
+            // If an enum or integer value is passed in
+            if (Type.IsIntegerType(valueType))
+            {
+                Type underlyingType = GetEnumUnderlyingType();
+                // We cannot compare the types directly because valueType is always a runtime type but underlyingType might not be.
+                if (underlyingType.GetTypeCodeImpl() != valueType.GetTypeCodeImpl())
+                    throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+
+                Array values = GetEnumRawConstantValues();
+                return (BinarySearch(values, value) >= 0);
+            }
+            else if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
+            {
+                // if at this point the value type is not an integer type, then its type doesn't match the enum type
+                // NetCF used to throw an argument exception in this case
+                throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), GetEnumUnderlyingType()));
+            }
+            else
+            {
+                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+            }
+        }
+
+        public virtual string GetEnumName(object value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            if (!IsEnum)
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+            Contract.EndContractBlock();
+
+            Type valueType = value.GetType();
+
+            if (!(valueType.IsEnum || Type.IsIntegerType(valueType)))
+                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+
+            Array values = GetEnumRawConstantValues();
+            int index = BinarySearch(values, value);
+
+            if (index >= 0)
+            {
+                string[] names = GetEnumNames();
+                return names[index];
+            }
+
+            return null;
+        }
+
+        // Convert everything to ulong then perform a binary search.
+        private static int BinarySearch(Array array, object value)
+        {
+            ulong[] ulArray = new ulong[array.Length];
+            for (int i = 0; i < array.Length; ++i)
+                ulArray[i] = Enum.ToUInt64(array.GetValue(i));
+
+            ulong ulValue = Enum.ToUInt64(value);
+
+            return Array.BinarySearch(ulArray, ulValue);
+        }
+
+        internal static bool IsIntegerType(Type t)
+        {
+            return (t == typeof(int) ||
+                    t == typeof(short) ||
+                    t == typeof(ushort) ||
+                    t == typeof(byte) ||
+                    t == typeof(sbyte) ||
+                    t == typeof(uint) ||
+                    t == typeof(long) ||
+                    t == typeof(ulong) ||
+                    t == typeof(char) ||
+                    t == typeof(bool));
+        }
+
+        #endregion             
+
 #if !MOBILE
                void _Type.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
                {
index 484c9374b8f4c7bd749b490fd0e9ba88d35a796f..c750ee11e3e70280f930dffdd2d4f94a7084748e 100644 (file)
@@ -201,22 +201,22 @@ namespace MonoTests.System
 
                        Assert.AreEqual ("00", TestingEnum4.This.ToString ("x"), "#B1");
                        Assert.AreEqual ("00", TestingEnum4.This.ToString ("X"), "#B2");
-                       Assert.AreEqual ("ff", TestingEnum4.Test.ToString ("x"), "#B3");
+                       Assert.AreEqual ("FF", TestingEnum4.Test.ToString ("x"), "#B3");
                        Assert.AreEqual ("FF", TestingEnum4.Test.ToString ("X"), "#B4");
 
                        Assert.AreEqual ("0000", TestingEnum5.This.ToString ("x"), "#C1");
                        Assert.AreEqual ("0000", TestingEnum5.This.ToString ("X"), "#C2");
-                       Assert.AreEqual ("7fff", TestingEnum5.Test.ToString ("x"), "#C3");
+                       Assert.AreEqual ("7FFF", TestingEnum5.Test.ToString ("x"), "#C3");
                        Assert.AreEqual ("7FFF", TestingEnum5.Test.ToString ("X"), "#C4");
 
                        Assert.AreEqual ("00000000", TestingEnum6.This.ToString ("x"), "#D1");
                        Assert.AreEqual ("00000000", TestingEnum6.This.ToString ("X"), "#D2");
-                       Assert.AreEqual ("7fffffff", TestingEnum6.Test.ToString ("x"), "#D3");
+                       Assert.AreEqual ("7FFFFFFF", TestingEnum6.Test.ToString ("x"), "#D3");
                        Assert.AreEqual ("7FFFFFFF", TestingEnum6.Test.ToString ("X"), "#D4");
 
                        Assert.AreEqual ("0000000000000000", TestingEnum3.This.ToString ("x"), "#E1");
                        Assert.AreEqual ("0000000000000000", TestingEnum3.This.ToString ("X"), "#E2");
-                       Assert.AreEqual ("ffffffffffffffff", TestingEnum3.Test.ToString ("x"), "#E3");
+                       Assert.AreEqual ("FFFFFFFFFFFFFFFF", TestingEnum3.Test.ToString ("x"), "#E3");
                        Assert.AreEqual ("FFFFFFFFFFFFFFFF", TestingEnum3.Test.ToString ("X"), "#E4");
                }
 
index 85c3542f0e152c8a7ae120185354895665c0b505..1979a74c7e5bcf4f00a4ff92549271f7c890b9be 100644 (file)
@@ -3758,7 +3758,7 @@ namespace MonoTests.System
                        try {
                                typeof (MyRealEnum).IsEnumDefined (typeof (MyRealEnum));
                                Assert.Fail ("#8");
-                       } catch (ArgumentException) { }
+                       } catch (InvalidOperationException) { }
 
                        Assert.IsTrue (typeof (MyRealEnum).IsEnumDefined ((short)0), "#9");
                        Assert.IsFalse (typeof (MyRealEnum).IsEnumDefined ((short)88), "#10");
index 78bff551cd67e705f378e0e88b3db2af882de6d4..944f07987f98f03c0e72ecc79ad085f0d5590444 100644 (file)
@@ -137,7 +137,6 @@ System/Double.cs
 System/DuplicateWaitObjectException.cs
 System/EmptyArray.cs
 System/EntryPointNotFoundException.cs
-System/Enum.cs
 System/Environment.cs
 System/EnvironmentVariableTarget.cs
 System/EventArgs.cs
@@ -1418,6 +1417,7 @@ ReferenceSources/ReflectionOnlyType.cs
 ../../../external/referencesource/mscorlib/system/defaultbinder.cs
 ../../../external/referencesource/mscorlib/system/dbnull.cs
 ../../../external/referencesource/mscorlib/system/empty.cs
+../../../external/referencesource/mscorlib/system/enum.cs
 ../../../external/referencesource/mscorlib/system/guid.cs
 ../../../external/referencesource/mscorlib/system/int16.cs
 ../../../external/referencesource/mscorlib/system/int32.cs
index 1467445061a7e86b3b4062ce908fb74d79c0389c..411f73a476cc0053053744a7a63a0a521be46fb8 100644 (file)
@@ -78,7 +78,7 @@
  * Changes which are already detected at runtime, like the addition
  * of icalls, do not require an increment.
  */
-#define MONO_CORLIB_VERSION 118
+#define MONO_CORLIB_VERSION 119
 
 typedef struct
 {
index 41f4fac450f868922315ae6068f91f585604f6dd..219b701fd95178d5f43314466b61250650725c0f 100644 (file)
@@ -219,13 +219,14 @@ ICALL(STOPWATCH_1, "GetTimestamp", mono_100ns_ticks)
 ICALL_TYPE(DOUBLE, "System.Double", DOUBLE_1)
 ICALL(DOUBLE_1, "ParseImpl",    mono_double_ParseImpl)
 
-ICALL_TYPE(ENUM, "System.Enum", ENUM_6)
-ICALL(ENUM_6, "InternalHasFlag", ves_icall_System_Enum_InternalHasFlag)
-ICALL(ENUM_1, "ToObject", ves_icall_System_Enum_ToObject)
-ICALL(ENUM_2, "compare_value_to", ves_icall_System_Enum_compare_value_to)
-ICALL(ENUM_3, "get_hashcode", ves_icall_System_Enum_get_hashcode)
-ICALL(ENUM_4, "get_underlying_type", ves_icall_System_Enum_get_underlying_type)
-ICALL(ENUM_5, "get_value", ves_icall_System_Enum_get_value)
+ICALL_TYPE(ENUM, "System.Enum", ENUM_1)
+ICALL(ENUM_1, "GetEnumValuesAndNames", ves_icall_System_Enum_GetEnumValuesAndNames)
+ICALL(ENUM_2, "InternalBoxEnum", ves_icall_System_Enum_ToObject)
+ICALL(ENUM_3, "InternalCompareTo", ves_icall_System_Enum_compare_value_to)
+ICALL(ENUM_4, "InternalGetUnderlyingType", ves_icall_System_Enum_get_underlying_type)
+ICALL(ENUM_5, "InternalHasFlag", ves_icall_System_Enum_InternalHasFlag)
+ICALL(ENUM_6, "get_hashcode", ves_icall_System_Enum_get_hashcode)
+ICALL(ENUM_7, "get_value", ves_icall_System_Enum_get_value)
 
 ICALL_TYPE(ENV, "System.Environment", ENV_1)
 ICALL(ENV_1, "Exit", ves_icall_System_Environment_Exit)
@@ -397,9 +398,6 @@ ICALL(MCATTR_1, "GetCustomAttributesDataInternal", mono_reflection_get_custom_at
 ICALL(MCATTR_2, "GetCustomAttributesInternal", custom_attrs_get_by_type)
 ICALL(MCATTR_3, "IsDefinedInternal", custom_attrs_defined_internal)
 
-ICALL_TYPE(MENUM, "System.MonoEnumInfo", MENUM_1)
-ICALL(MENUM_1, "get_enum_info", ves_icall_get_enum_info)
-
 ICALL_TYPE(MTYPE, "System.MonoType", MTYPE_1)
 ICALL(MTYPE_1, "GetArrayRank", ves_icall_MonoType_GetArrayRank)
 ICALL(MTYPE_2, "GetConstructors", ves_icall_Type_GetConstructors_internal)
index b39ed3e7ba9db564ffb070606c52cf087ad30d7d..b94dc2bc8fa32a1e77466e7169269f0eeea1f1c2 100644 (file)
@@ -2954,7 +2954,7 @@ ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoA
 #endif
 
 static guint64
-read_enum_value (char *mem, int type)
+read_enum_value (const char *mem, int type)
 {
        switch (type) {
        case MONO_TYPE_BOOLEAN:
@@ -3016,43 +3016,22 @@ write_enum_value (char *mem, int type, guint64 value)
 }
 
 ICALL_EXPORT MonoObject *
-ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
+ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
 {
        MonoDomain *domain; 
-       MonoClass *enumc, *objc;
+       MonoClass *enumc;
        MonoObject *res;
        MonoType *etype;
-       guint64 val;
-       
-       MONO_CHECK_ARG_NULL (enumType, NULL);
-       MONO_CHECK_ARG_NULL (value, NULL);
 
        domain = mono_object_domain (enumType); 
        enumc = mono_class_from_mono_type (enumType->type);
 
        mono_class_init_or_throw (enumc);
 
-       objc = value->vtable->klass;
-
-       if (!enumc->enumtype) {
-               mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
-               return NULL;
-       }
-       if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8))) {
-               mono_set_pending_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
-               return NULL;
-       }
-
        etype = mono_class_enum_basetype (enumc);
-       if (!etype) {
-               /* MS throws this for typebuilders */
-               mono_set_pending_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
-               return NULL;
-       }
 
        res = mono_object_new (domain, enumc);
-       val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
-       write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
+       write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
 
        return res;
 }
@@ -3105,8 +3084,7 @@ ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
 
        etype = mono_class_enum_basetype (klass);
        if (!etype) {
-               /* MS throws this for typebuilders */
-               mono_set_pending_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
+               mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
                return NULL;
        }
 
@@ -3121,6 +3099,12 @@ ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
        MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
        g_assert (basetype);
 
+       if (other == NULL)
+               return 1;
+
+       if (this->vtable->klass != other->vtable->klass)
+               return 2;
+
 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
                ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
                ENUM_TYPE other = *((ENUM_TYPE*)odata); \
@@ -3147,11 +3131,10 @@ ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
                        COMPARE_ENUM_VALUES (guint64);
                case MONO_TYPE_I8:
                        COMPARE_ENUM_VALUES (gint64);
-               default:
-                       g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
        }
 #undef COMPARE_ENUM_VALUES
-       return 0;
+       /* indicates that the enum was of an unsupported unerlying type */
+       return 3;
 }
 
 ICALL_EXPORT int
@@ -3187,21 +3170,30 @@ ves_icall_System_Enum_get_hashcode (MonoObject *this)
        return 0;
 }
 
-ICALL_EXPORT void
-ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
+ICALL_EXPORT MonoBoolean
+ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
 {
        MonoDomain *domain = mono_object_domain (type); 
        MonoClass *enumc = mono_class_from_mono_type (type->type);
        guint j = 0, nvalues, crow;
        gpointer iter;
        MonoClassField *field;
+       int base_type;
+       guint64 field_value, previous_value = 0;
+       gboolean sorted = TRUE;
 
        mono_class_init_or_throw (enumc);
 
-       MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
+       if (!enumc->enumtype) {
+               mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
+               return TRUE;
+       }
+
+       base_type = mono_class_enum_basetype (enumc)->type;
+
        nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
-       MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
-       MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
+       *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
+       *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
 
        crow = -1;
        iter = NULL;
@@ -3209,40 +3201,29 @@ ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
                const char *p;
                int len;
                MonoTypeEnum def_type;
-               
+
                if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
                        continue;
                if (strcmp ("value__", mono_field_get_name (field)) == 0)
                        continue;
                if (mono_field_is_deleted (field))
                        continue;
-               mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
+               mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
 
                p = mono_class_get_field_default_value (field, &def_type);
                len = mono_metadata_decode_blob_size (p, &p);
-               switch (mono_class_enum_basetype (enumc)->type) {
-               case MONO_TYPE_U1:
-               case MONO_TYPE_I1:
-                       mono_array_set (info->values, gchar, j, *p);
-                       break;
-               case MONO_TYPE_CHAR:
-               case MONO_TYPE_U2:
-               case MONO_TYPE_I2:
-                       mono_array_set (info->values, gint16, j, read16 (p));
-                       break;
-               case MONO_TYPE_U4:
-               case MONO_TYPE_I4:
-                       mono_array_set (info->values, gint32, j, read32 (p));
-                       break;
-               case MONO_TYPE_U8:
-               case MONO_TYPE_I8:
-                       mono_array_set (info->values, gint64, j, read64 (p));
-                       break;
-               default:
-                       g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
-               }
+
+               field_value = read_enum_value (p, base_type);
+               mono_array_set (*values, guint64, j, field_value);
+
+               if (previous_value > field_value)
+                       sorted = FALSE;
+
+               previous_value = field_value;
                ++j;
        }
+
+       return sorted;
 }
 
 enum {