Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 50 additions & 39 deletions src/mscorlib/src/System/Enum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ namespace System
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
#region Private Static Data Members
private static readonly char [] enumSeperatorCharArray = new char [] {','};
private const String enumSeperator = ", ";
#region Private Constants
private const char enumSeparatorChar = ',';
private const String enumSeparatorString = ", ";
#endregion

#region Private Static Methods
Expand Down Expand Up @@ -180,7 +180,7 @@ private static String InternalFlagsFormat(RuntimeType eT, Object value)
{
result -= values[index];
if (!firstTime)
retval.Insert(0, enumSeperator);
retval.Insert(0, enumSeparatorString);

retval.Insert(0, names[index]);
firstTime = false;
Expand Down Expand Up @@ -277,11 +277,6 @@ private struct EnumResult
internal object m_failureMessageFormatArgument;
internal Exception m_innerException;

internal void Init(bool canMethodThrow)
{
parsedEnum = 0;
canThrow = canMethodThrow;
}
internal void SetFailure(Exception unhandledException)
{
m_failure = ParseFailureKind.UnhandledException;
Expand Down Expand Up @@ -334,7 +329,6 @@ public static bool TryParse<TEnum>(String value, bool ignoreCase, out TEnum resu
{
result = default(TEnum);
EnumResult parseResult = new EnumResult();
parseResult.Init(false);
bool retValue;

if (retValue = TryParseEnum(typeof(TEnum), value, ignoreCase, ref parseResult))
Expand All @@ -351,8 +345,7 @@ public static Object Parse(Type enumType, String value)
[System.Runtime.InteropServices.ComVisible(true)]
public static Object Parse(Type enumType, String value, bool ignoreCase)
{
EnumResult parseResult = new EnumResult();
parseResult.Init(true);
EnumResult parseResult = new EnumResult() { canThrow = true };
if (TryParseEnum(enumType, value, ignoreCase, ref parseResult))
return parseResult.parsedEnum;
else
Expand All @@ -377,8 +370,16 @@ private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, r
return false;
}

value = value.Trim();
if (value.Length == 0) {
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;
}
Expand All @@ -387,13 +388,15 @@ private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, r
// values will have the first character as as number or a sign.
ulong result = 0;

if (Char.IsDigit(value[0]) || value[0] == '-' || value[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;
Expand All @@ -415,47 +418,55 @@ private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, r
}
}

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

// Find the field.Lets assume that these are always static classes because the class is
// an enum.
// 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;

for (int i = 0; i < values.Length; i++)

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

int valueIndex = 0;
while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma
{
values[i] = values[i].Trim(); // We need to remove whitespace characters
// 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;
}

bool success = false;
// 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;

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

ulong item = enumValues[j];

result |= item;
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
Expand Down