<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />

EnumUtils

static class EnumUtils
using Newtonsoft.Json.Utilities.LinqBridge; using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Text; namespace Newtonsoft.Json.Utilities { internal static class EnumUtils { private const char EnumSeparatorChar = ','; private const string EnumSeparatorString = ", "; private static readonly ThreadSafeStore<Type, EnumInfo> ValuesAndNamesPerEnum = new ThreadSafeStore<Type, EnumInfo>(InitializeValuesAndNames); private static EnumInfo InitializeValuesAndNames(Type enumType) { string[] names = Enum.GetNames(enumType); string[] array = new string[names.Length]; ulong[] array2 = new ulong[names.Length]; for (int i = 0; i < names.Length; i++) { string text = names[i]; FieldInfo field = enumType.GetField(text, BindingFlags.Static | BindingFlags.Public); array2[i] = ToUInt64(field.GetValue(null)); string text2 = array[i] = text; } return new EnumInfo(enumType.IsDefined(typeof(FlagsAttribute), false), array2, names, array); } public static IList<T> GetFlagsValues<T>(T value) where T : struct { Type typeFromHandle = typeof(T); if (!typeFromHandle.IsDefined(typeof(FlagsAttribute), false)) throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, typeFromHandle)); Type underlyingType = Enum.GetUnderlyingType(value.GetType()); ulong num = ToUInt64(value); EnumInfo enumValuesAndNames = GetEnumValuesAndNames(typeFromHandle); IList<T> list = new List<T>(); for (int i = 0; i < enumValuesAndNames.Values.Length; i++) { ulong num2 = enumValuesAndNames.Values[i]; if ((num & num2) == num2 && num2 != 0) ((ICollection<T>)list).Add((T)Convert.ChangeType(num2, underlyingType, CultureInfo.CurrentCulture)); } if (((ICollection<T>)list).Count == 0 && enumValuesAndNames.Values.Any((ulong v) => v == 0)) ((ICollection<T>)list).Add(default(T)); return list; } public static bool TryToString(Type enumType, object value, bool camelCaseText, out string name) { EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(enumType); ulong num = ToUInt64(value); if (!enumInfo.IsFlags) { int num2 = Array.BinarySearch(enumInfo.Values, num); if (num2 >= 0) { name = enumInfo.ResolvedNames[num2]; if (camelCaseText) name = StringUtils.ToCamelCase(name); return true; } name = null; return false; } name = InternalFlagsFormat(enumInfo, num, camelCaseText); return name != null; } private static string InternalFlagsFormat(EnumInfo entry, ulong result, bool camelCaseText) { string[] resolvedNames = entry.ResolvedNames; ulong[] values = entry.Values; int num = values.Length - 1; StringBuilder stringBuilder = new StringBuilder(); bool flag = true; ulong num2 = result; while (num >= 0 && (num != 0 || values[num] != 0)) { if ((result & values[num]) == values[num]) { result -= values[num]; if (!flag) stringBuilder.Insert(0, ", "); string text = resolvedNames[num]; stringBuilder.Insert(0, camelCaseText ? StringUtils.ToCamelCase(text) : text); flag = false; } num--; } string text2; if (result != 0) text2 = null; else if (num2 == 0) { if (values.Length != 0 && values[0] == 0) { text2 = resolvedNames[0]; if (camelCaseText) text2 = StringUtils.ToCamelCase(text2); } else text2 = null; } else { text2 = stringBuilder.ToString(); } return text2; } public static EnumInfo GetEnumValuesAndNames(Type enumType) { return ValuesAndNamesPerEnum.Get(enumType); } private static ulong ToUInt64(object value) { bool isEnum; switch (ConvertUtils.GetTypeCode(value.GetType(), out isEnum)) { case PrimitiveTypeCode.SByte: return (ulong)(sbyte)value; case PrimitiveTypeCode.Byte: return (byte)value; case PrimitiveTypeCode.Boolean: return Convert.ToByte((bool)value); case PrimitiveTypeCode.Int16: return (ulong)(short)value; case PrimitiveTypeCode.UInt16: return (ushort)value; case PrimitiveTypeCode.Char: return (char)value; case PrimitiveTypeCode.UInt32: return (uint)value; case PrimitiveTypeCode.Int32: return (ulong)(int)value; case PrimitiveTypeCode.UInt64: return (ulong)value; case PrimitiveTypeCode.Int64: return (ulong)(long)value; default: throw new InvalidOperationException("Unknown enum type."); } } public static object ParseEnum(Type enumType, string value, bool disallowNumber) { ValidationUtils.ArgumentNotNull(enumType, "enumType"); ValidationUtils.ArgumentNotNull(value, "value"); if (!enumType.IsEnum()) throw new ArgumentException("Type provided must be an Enum.", "enumType"); EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(enumType); string[] names = enumInfo.Names; string[] resolvedNames = enumInfo.ResolvedNames; ulong[] values = enumInfo.Values; int? nullable = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.Ordinal); if (nullable.HasValue) return Enum.ToObject(enumType, values[nullable.Value]); int num = -1; for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { num = i; break; } } if (num == -1) throw new ArgumentException("Must specify valid information for parsing in the string."); char c = value[num]; if (char.IsDigit(c) || c == '-' || c == '+') { Type underlyingType = Enum.GetUnderlyingType(enumType); value = value.Trim(); object obj = null; try { obj = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); } catch (FormatException) { } if (obj != null) { if (disallowNumber) throw new FormatException("Integer string '{0}' is not allowed.".FormatWith(CultureInfo.InvariantCulture, value)); return Enum.ToObject(enumType, obj); } } ulong num2 = 0; int num3; for (int j = num; j <= value.Length; j = num3 + 1) { num3 = value.IndexOf(',', j); if (num3 == -1) num3 = value.Length; int num4 = num3; for (; j < num3 && char.IsWhiteSpace(value[j]); j++) { } while (num4 > j && char.IsWhiteSpace(value[num4 - 1])) { num4--; } int valueSubstringLength = num4 - j; nullable = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.Ordinal); if (!nullable.HasValue) nullable = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.OrdinalIgnoreCase); if (!nullable.HasValue) { nullable = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.OrdinalIgnoreCase); if (nullable.HasValue) return Enum.ToObject(enumType, values[nullable.Value]); throw new ArgumentException("Requested value '{0}' was not found.".FormatWith(CultureInfo.InvariantCulture, value)); } num2 |= values[nullable.Value]; } return Enum.ToObject(enumType, num2); } private static int? MatchName(string value, string[] enumNames, string[] resolvedNames, int valueIndex, int valueSubstringLength, StringComparison comparison) { int? result = FindIndexByName(resolvedNames, value, valueIndex, valueSubstringLength, comparison); if (!result.HasValue) result = FindIndexByName(enumNames, value, valueIndex, valueSubstringLength, comparison); return result; } private static int? FindIndexByName(string[] enumNames, string value, int valueIndex, int valueSubstringLength, StringComparison comparison) { for (int i = 0; i < enumNames.Length; i++) { if (enumNames[i].Length == valueSubstringLength && string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0) return i; } return null; } } }