[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); }
[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); }
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); } } }
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 } }
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); } } }