예제 #1
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static ValuesAndNames GetCachedValuesAndNames(RuntimeType enumType, bool getNames)
        {
            ValuesAndNames entry = enumType.GenericCache as ValuesAndNames;

            if (entry == null || (getNames && entry.Names == null))
            {
                ulong[]  values = null;
                String[] names  = null;

#if MONO
                if (!GetEnumValuesAndNames(enumType, out values, out names))
                {
                    Array.Sort(values, names, System.Collections.Generic.Comparer <ulong> .Default);
                }
#else
                GetEnumValuesAndNames(
                    enumType.GetTypeHandleInternal(),
                    JitHelpers.GetObjectHandleOnStack(ref values),
                    JitHelpers.GetObjectHandleOnStack(ref names),
                    getNames);
#endif
                entry = new ValuesAndNames(values, names);
                enumType.GenericCache = entry;
            }

            return(entry);
        }
예제 #2
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static ValuesAndNames GetCachedValuesAndNames(RuntimeType enumType, bool getNames)
        {
            ValuesAndNames entry = enumType.GenericCache as ValuesAndNames;

            if (entry == null || (getNames && entry.Names == null))
            {
                ulong[]  values = null;
                String[] names  = null;

                GetEnumValuesAndNames(
                    enumType.GetTypeHandleInternal(),
                    JitHelpers.GetObjectHandleOnStack(ref values),
                    JitHelpers.GetObjectHandleOnStack(ref names),
                    getNames);

                entry = new ValuesAndNames(values, names);
                enumType.GenericCache = entry;
            }

            return(entry);
        }
예제 #3
0
        private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult)
        {
            if (enumType == null)
            {
                throw new ArgumentNullException("enumType");
            }
            Contract.EndContractBlock();

            RuntimeType rtType = enumType as RuntimeType;

            if (rtType == null)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            }

            if (!enumType.IsEnum)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            }

            if (value == null)
            {
                parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value");
                return(false);
            }

            int firstNonWhitespaceIndex = -1;

            for (int i = 0; i < value.Length; i++)
            {
                if (!Char.IsWhiteSpace(value[i]))
                {
                    firstNonWhitespaceIndex = i;
                    break;
                }
            }
            if (firstNonWhitespaceIndex == -1)
            {
                parseResult.SetFailure(ParseFailureKind.Argument, "Arg_MustContainEnumInfo", null);
                return(false);
            }

            // We have 2 code paths here. One if they are values else if they are Strings.
            // values will have the first character as as number or a sign.
            ulong result = 0;

            char firstNonWhitespaceChar = value[firstNonWhitespaceIndex];

            if (Char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '-' || firstNonWhitespaceChar == '+')
            {
                Type   underlyingType = GetUnderlyingType(enumType);
                Object temp;

                try
                {
                    value = value.Trim();
                    temp  = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
                    parseResult.parsedEnum = ToObject(enumType, temp);
                    return(true);
                }
                catch (FormatException)
                { // We need to Parse this as a String instead. There are cases
                  // when you tlbimp enums that can have values of the form "3D".
                  // Don't fix this code.
                }
                catch (Exception ex)
                {
                    if (parseResult.canThrow)
                    {
                        throw;
                    }
                    else
                    {
                        parseResult.SetFailure(ex);
                        return(false);
                    }
                }
            }

            // Find the field. Let's assume that these are always static classes
            // because the class is an enum.
            ValuesAndNames entry = GetCachedValuesAndNames(rtType, true);

            String[] enumNames  = entry.Names;
            ulong[]  enumValues = entry.Values;

            StringComparison comparison = ignoreCase ?
                                          StringComparison.OrdinalIgnoreCase :
                                          StringComparison.Ordinal;

            int valueIndex = firstNonWhitespaceIndex;

            while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma
            {
                // Find the next separator, if there is one, otherwise the end of the string.
                int endIndex = value.IndexOf(enumSeparatorChar, valueIndex);
                if (endIndex == -1)
                {
                    endIndex = value.Length;
                }

                // Shift the starting and ending indices to eliminate whitespace
                int endIndexNoWhitespace = endIndex;
                while (valueIndex < endIndex && Char.IsWhiteSpace(value[valueIndex]))
                {
                    valueIndex++;
                }
                while (endIndexNoWhitespace > valueIndex && Char.IsWhiteSpace(value[endIndexNoWhitespace - 1]))
                {
                    endIndexNoWhitespace--;
                }
                int valueSubstringLength = endIndexNoWhitespace - valueIndex;

                // Try to match this substring against each enum name
                bool success = false;
                for (int i = 0; i < enumNames.Length; i++)
                {
                    if (enumNames[i].Length == valueSubstringLength &&
                        string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0)
                    {
                        result |= enumValues[i];
                        success = true;
                        break;
                    }
                }

                // If we couldn't find a match, throw an argument exception.
                if (!success)
                {
                    // Not found, throw an argument exception.
                    parseResult.SetFailure(ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
                    return(false);
                }

                // Move our pointer to the ending index to go again.
                valueIndex = endIndex + 1;
            }

            try
            {
                parseResult.parsedEnum = ToObject(enumType, result);
                return(true);
            }
            catch (Exception ex)
            {
                if (parseResult.canThrow)
                {
                    throw;
                }
                else
                {
                    parseResult.SetFailure(ex);
                    return(false);
                }
            }
        }
예제 #4
0
        private static String InternalFlagsFormat(RuntimeType eT, Object value)
        {
            Contract.Requires(eT != null);
            Contract.Requires(value != null);
            ulong result = ToUInt64(value);

            // These values are sorted by value. Don't change this
            ValuesAndNames entry = GetCachedValuesAndNames(eT, true);

            String[] names  = entry.Names;
            ulong[]  values = entry.Values;
            Contract.Assert(names.Length == values.Length);

            int           index      = values.Length - 1;
            StringBuilder retval     = new StringBuilder();
            bool          firstTime  = true;
            ulong         saveResult = result;

            // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied
            // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of
            // items in an enum are sufficiently small and not worth the optimization.
            while (index >= 0)
            {
                if ((index == 0) && (values[index] == 0))
                {
                    break;
                }

                if ((result & values[index]) == values[index])
                {
                    result -= values[index];
                    if (!firstTime)
                    {
                        retval.Insert(0, enumSeparatorString);
                    }

                    retval.Insert(0, names[index]);
                    firstTime = false;
                }

                index--;
            }

            // We were unable to represent this number as a bitwise or of valid flags
            if (result != 0)
            {
                return(value.ToString());
            }

            // For the case when we have zero
            if (saveResult == 0)
            {
                if (values.Length > 0 && values[0] == 0)
                {
                    return(names[0]); // Zero was one of the enum values.
                }
                else
                {
                    return("0");
                }
            }
            else
            {
                return(retval.ToString()); // Return the string representation
            }
        }
예제 #5
0
        private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult)
        {
            if (enumType == null)
            {
                throw new ArgumentNullException("enumType");
            }
            Contract.EndContractBlock();

            RuntimeType rtType = enumType as RuntimeType;

            if (rtType == null)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
            }

            if (!enumType.IsEnum)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
            }

            if (value == null)
            {
                parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value");
                return(false);
            }

            value = value.Trim();
            if (value.Length == 0)
            {
                parseResult.SetFailure(ParseFailureKind.Argument, "Arg_MustContainEnumInfo", null);
                return(false);
            }

            // We have 2 code paths here. One if they are values else if they are Strings.
            // values will have the first character as as number or a sign.
            ulong result = 0;

            if (Char.IsDigit(value[0]) || value[0] == '-' || value[0] == '+')
            {
                Type   underlyingType = GetUnderlyingType(enumType);
                Object temp;

                try
                {
                    temp = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
                    parseResult.parsedEnum = ToObject(enumType, temp);
                    return(true);
                }
                catch (FormatException)
                { // We need to Parse this as a String instead. There are cases
                  // when you tlbimp enums that can have values of the form "3D".
                  // Don't fix this code.
                }
                catch (Exception ex)
                {
                    if (parseResult.canThrow)
                    {
                        throw;
                    }
                    else
                    {
                        parseResult.SetFailure(ex);
                        return(false);
                    }
                }
            }

            String[] values = value.Split(enumSeperatorCharArray);

            // Find the field.Lets assume that these are always static classes because the class is
            //  an enum.
            ValuesAndNames entry = GetCachedValuesAndNames(rtType, true);

            String[] enumNames  = entry.Names;
            ulong[]  enumValues = entry.Values;

            for (int i = 0; i < values.Length; i++)
            {
                values[i] = values[i].Trim(); // We need to remove whitespace characters

                bool success = false;

                for (int j = 0; j < enumNames.Length; j++)
                {
                    if (ignoreCase)
                    {
                        if (String.Compare(enumNames[j], values[i], StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (!enumNames[j].Equals(values[i]))
                        {
                            continue;
                        }
                    }

                    ulong item = enumValues[j];

                    result |= item;
                    success = true;
                    break;
                }

                if (!success)
                {
                    // Not found, throw an argument exception.
                    parseResult.SetFailure(ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
                    return(false);
                }
            }

            try
            {
                parseResult.parsedEnum = ToObject(enumType, result);
                return(true);
            }
            catch (Exception ex)
            {
                if (parseResult.canThrow)
                {
                    throw;
                }
                else
                {
                    parseResult.SetFailure(ex);
                    return(false);
                }
            }
        }