1 #region License
2 // Copyright (c) 2007 James Newton-King
3 //
4 // Permission is hereby granted, free of charge, to any person
5 // obtaining a copy of this software and associated documentation
6 // files (the "Software"), to deal in the Software without
7 // restriction, including without limitation the rights to use,
8 // copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following
11 // conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
24 #endregion
25 
26 using System;
27 using System.Collections.Generic;
28 using System.Globalization;
29 #if NET20
30 using Newtonsoft.Json.Utilities.LinqBridge;
31 #else
32 using System.Linq;
33 #endif
34 using System.Reflection;
35 
36 namespace Newtonsoft.Json.Utilities
37 {
38   internal static class EnumUtils
39   {
40     public static IList<T> GetFlagsValues<T>(T value) where T : struct
41     {
42       Type enumType = typeof(T);
43 
44       if (!enumType.IsDefined(typeof(FlagsAttribute), false))
45         throw new Exception("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, enumType));
46 
47       Type underlyingType = Enum.GetUnderlyingType(value.GetType());
48 
49       ulong num = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
50       EnumValues<ulong> enumNameValues = GetNamesAndValues<T>();
51       IList<T> selectedFlagsValues = new List<T>();
52 
53       foreach (EnumValue<ulong> enumNameValue in enumNameValues)
54       {
55         if ((num & enumNameValue.Value) == enumNameValue.Value && enumNameValue.Value != 0)
56           selectedFlagsValues.Add((T)Convert.ChangeType(enumNameValue.Value, underlyingType, CultureInfo.CurrentCulture));
57       }
58 
59       if (selectedFlagsValues.Count == 0 && enumNameValues.SingleOrDefault(v => v.Value == 0) != null)
selectedFlagsValues.AddNewtonsoft.Json.Utilities.EnumUtils.__anon160         selectedFlagsValues.Add(default(T));
61 
62       return selectedFlagsValues;
63     }
64 
65     /// <summary>
66     /// Gets a dictionary of the names and values of an Enum type.
67     /// </summary>
68     /// <returns></returns>
69     public static EnumValues<ulong> GetNamesAndValues<T>() where T : struct
70     {
71       return GetNamesAndValues<ulong>(typeof(T));
72     }
73 
74     /// <summary>
75     /// Gets a dictionary of the names and values of an Enum type.
76     /// </summary>
77     /// <param name="enumType">The enum type to get names and values for.</param>
78     /// <returns></returns>
79     public static EnumValues<TUnderlyingType> GetNamesAndValues<TUnderlyingType>(Type enumType) where TUnderlyingType : struct
80     {
81       if (enumType == null)
82         throw new ArgumentNullException("enumType");
83 
ValidationUtils.ArgumentTypeIsEnumNewtonsoft.Json.Utilities.EnumUtils.__anon384       ValidationUtils.ArgumentTypeIsEnum(enumType, "enumType");
85 
86       IList<object> enumValues = GetValues(enumType);
87       IList<string> enumNames = GetNames(enumType);
88 
89       EnumValues<TUnderlyingType> nameValues = new EnumValues<TUnderlyingType>();
90 
91       for (int i = 0; i < enumValues.Count; i++)
92       {
93         try
94         {
95           nameValues.Add(new EnumValue<TUnderlyingType>(enumNames[i], (TUnderlyingType)Convert.ChangeType(enumValues[i], typeof(TUnderlyingType), CultureInfo.CurrentCulture)));
96         }
97         catch (OverflowException e)
98         {
99           throw new Exception(
100             string.Format(CultureInfo.InvariantCulture, "Value from enum with the underlying type of {0} cannot be added to dictionary with a value type of {1}. Value was too large: {2}",
101               Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i], CultureInfo.InvariantCulture)), e);
102         }
103       }
104 
105       return nameValues;
106     }
107 
GetValues(Type enumType)108     public static IList<object> GetValues(Type enumType)
109     {
110       if (!enumType.IsEnum())
111         throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
112 
113       List<object> values = new List<object>();
114 
115       var fields = from field in enumType.GetFields()
116                    where field.IsLiteral
117                    select field;
118 
119       foreach (FieldInfo field in fields)
120       {
121         object value = field.GetValue(enumType);
122         values.Add(value);
123       }
124 
125       return values;
126     }
127 
GetNames(Type enumType)128     public static IList<string> GetNames(Type enumType)
129     {
130       if (!enumType.IsEnum())
131         throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
132 
133       List<string> values = new List<string>();
134 
135       var fields = from field in enumType.GetFields()
136                    where field.IsLiteral
137                    select field;
138 
139       foreach (FieldInfo field in fields)
140       {
141         values.Add(field.Name);
142       }
143 
144       return values;
145     }
146   }
147 }