You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
@ -5,13 +5,11 @@
|
||||
// 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
|
||||
@ -38,6 +36,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System
|
||||
{
|
||||
@ -82,7 +81,7 @@ namespace System
|
||||
}
|
||||
|
||||
internal class ShortComparer : IComparer, System.Collections.Generic.IComparer<short>
|
||||
{
|
||||
{
|
||||
public int Compare (object x, object y)
|
||||
{
|
||||
short ix = (short) x;
|
||||
@ -157,26 +156,37 @@ namespace System
|
||||
|
||||
internal static void GetInfo (Type enumType, out MonoEnumInfo info)
|
||||
{
|
||||
/* First check the thread-local cache without locking */
|
||||
if (cache != null && cache.TryGetValue (enumType, out info)) {
|
||||
return;
|
||||
}
|
||||
var user_type = !(enumType is MonoType);
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
}
|
||||
|
||||
get_enum_info (enumType, out info);
|
||||
SortEnums (info.utype, info.values, info.names);
|
||||
|
||||
Type et = Enum.GetUnderlyingType (enumType);
|
||||
SortEnums (et, 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);
|
||||
@ -188,10 +198,48 @@ namespace System
|
||||
global_cache [enumType] = cached;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SortEnums (Type et, Array values, Array names)
|
||||
|
||||
static void GetUserEnumInfo (Type type, out MonoEnumInfo mei)
|
||||
{
|
||||
IComparer ic = null;
|
||||
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))
|
||||
@ -200,10 +248,12 @@ namespace System
|
||||
ic = sbyte_comparer;
|
||||
else if (et == typeof (long))
|
||||
ic = long_comparer;
|
||||
|
||||
else
|
||||
ic = null;
|
||||
|
||||
Array.Sort (values, names, ic);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[ComVisible (true)]
|
||||
@ -274,12 +324,9 @@ namespace System
|
||||
return Convert.ToSingle (Value, provider);
|
||||
}
|
||||
|
||||
object IConvertible.ToType (Type targetType, IFormatProvider provider)
|
||||
object IConvertible.ToType (Type type, IFormatProvider provider)
|
||||
{
|
||||
if (targetType == null)
|
||||
throw new ArgumentNullException ("targetType");
|
||||
|
||||
return Convert.ToType (this, targetType, provider, false);
|
||||
return Convert.DefaultToType ((IConvertible)this, type, provider);
|
||||
}
|
||||
|
||||
ushort IConvertible.ToUInt16 (IFormatProvider provider)
|
||||
@ -341,9 +388,9 @@ namespace System
|
||||
//
|
||||
// It also tries to use the non-boxing version of the various Array.BinarySearch methods
|
||||
//
|
||||
static int FindPosition (Type enumType, object value, Array values)
|
||||
static int FindPosition (Type underlyingEnumType, object value, Array values)
|
||||
{
|
||||
switch (Type.GetTypeCode (GetUnderlyingType (enumType))) {
|
||||
switch (Type.GetTypeCode (underlyingEnumType)) {
|
||||
case TypeCode.SByte:
|
||||
sbyte [] sbyte_array = values as sbyte [];
|
||||
return Array.BinarySearch (sbyte_array, (sbyte) value, MonoEnumInfo.sbyte_comparer);
|
||||
@ -394,10 +441,14 @@ namespace System
|
||||
throw new ArgumentException ("enumType is not an Enum type.", "enumType");
|
||||
|
||||
MonoEnumInfo info;
|
||||
value = ToObject (enumType, value);
|
||||
MonoEnumInfo.GetInfo (enumType, out info);
|
||||
|
||||
int i = FindPosition (enumType, value, info.values);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -416,18 +467,31 @@ namespace System
|
||||
MonoEnumInfo.GetInfo (enumType, out info);
|
||||
|
||||
Type vType = value.GetType ();
|
||||
if (vType == typeof(String)) {
|
||||
if (vType == typeof (String)) {
|
||||
return ((IList)(info.names)).Contains (value);
|
||||
} else if ((vType == info.utype) || (vType == enumType)) {
|
||||
value = ToObject (enumType, value);
|
||||
MonoEnumInfo.GetInfo (enumType, out info);
|
||||
}
|
||||
|
||||
return FindPosition (enumType, value, info.values) >= 0;
|
||||
} else {
|
||||
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)]
|
||||
@ -614,7 +678,6 @@ namespace System
|
||||
return true;
|
||||
}
|
||||
|
||||
#if NET_4_0
|
||||
public static bool TryParse<TEnum> (string value, out TEnum result) where TEnum : struct
|
||||
{
|
||||
return TryParse (value, false, out result);
|
||||
@ -637,7 +700,6 @@ namespace System
|
||||
|
||||
return Parse (tenum_type, value, ignoreCase, out result);
|
||||
}
|
||||
#endif
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
private extern int compare_value_to (object other);
|
||||
@ -994,15 +1056,18 @@ namespace System
|
||||
"\"x\",\"F\",\"f\",\"D\" or \"d\".");
|
||||
}
|
||||
|
||||
#if NET_4_0
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
private static extern bool InternalHasFlag (Enum a, Enum b);
|
||||
|
||||
public bool HasFlag (Enum flag)
|
||||
{
|
||||
var val = get_value ();
|
||||
ulong mvalue = GetValue (val, Type.GetTypeCode (val.GetType ()));
|
||||
ulong fvalue = GetValue (flag, Type.GetTypeCode (flag.GetType ()));
|
||||
if (flag == null)
|
||||
throw new ArgumentNullException ("flag");
|
||||
|
||||
return ((mvalue & fvalue) == fvalue);
|
||||
if (!this.GetType ().IsEquivalentTo (flag.GetType ()))
|
||||
throw new ArgumentException (Environment.GetResourceString ("Argument_EnumTypeDoesNotMatch", flag.GetType (), this.GetType ()));
|
||||
|
||||
return InternalHasFlag (this, flag);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user