Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Utilities\EnumUtils.cs

Symbol Coverage: 52.75% (48 of 91)

Branch Coverage: 50.88% (29 of 57)

Cyclomatic Complexity Avg: 2.47 Max:9

Code Lines: 81


L V Source
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
using System.Linq;
30
using System.Reflection;
31

  
32
namespace Newtonsoft.Json.Utilities
33
{
34
  internal static class EnumUtils
35
  {
36
    /// <summary>
37
    /// Parses the specified enum member name, returning it's value.
38
    /// </summary>
39
    /// <param name="enumMemberName">Name of the enum member.</param>
40
    /// <returns></returns>
41
    public static T Parse<T>(string enumMemberName) where T : struct
42
    {
43
 0
      return Parse<T>(enumMemberName, false);
44
 0
    }
45

  
46
    /// <summary>
47
    /// Parses the specified enum member name, returning it's value.
48
    /// </summary>
49
    /// <param name="enumMemberName">Name of the enum member.</param>
50
    /// <param name="ignoreCase">If set to <c>true</c> ignore case.</param>
51
    /// <returns></returns>
52
    public static T Parse<T>(string enumMemberName, bool ignoreCase) where T : struct
53
    {
54
 0
      ValidationUtils.ArgumentTypeIsEnum(typeof(T), "T");
55

  
56
 0
      return (T)Enum.Parse(typeof(T), enumMemberName, ignoreCase);
57
 0
    }
58

  
59
    public static bool TryParse<T>(string enumMemberName, bool ignoreCase, out T value) where T : struct
60
    {
61
 0
      ValidationUtils.ArgumentTypeIsEnum(typeof(T), "T");
62

  
63
 0
      return MiscellaneousUtils.TryAction(() => Parse<T>(enumMemberName, ignoreCase), out value);
64
 0
    }
65

  
66
    public static IList<T> GetFlagsValues<T>(T value) where T : struct
67
    {
68
 72
      Type enumType = typeof(T);
69

  
70
 72
      if (!enumType.IsDefined(typeof(FlagsAttribute), false))
71
 0
        throw new Exception("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, enumType));
72

  
73
 72
      Type underlyingType = Enum.GetUnderlyingType(value.GetType());
74

  
75
 72
      ulong num = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
76
 72
      EnumValues<ulong> enumNameValues = GetNamesAndValues<T>();
77
 72
      IList<T> selectedFlagsValues = new List<T>();
78

  
79
 72
      foreach (EnumValue<ulong> enumNameValue in enumNameValues)
80
      {
81
 648
        if ((num & enumNameValue.Value) == enumNameValue.Value && enumNameValue.Value != 0)
82
 145
          selectedFlagsValues.Add((T)Convert.ChangeType(enumNameValue.Value, underlyingType, CultureInfo.CurrentCulture));
83
      }
84

  
85
 0
      if (selectedFlagsValues.Count == 0 && enumNameValues.SingleOrDefault(v => v.Value == 0) != null)
86
 0
        selectedFlagsValues.Add(default(T));
87

  
88
 72
      return selectedFlagsValues;
89
 72
    }
90

  
91
    /// <summary>
92
    /// Gets a dictionary of the names and values of an Enum type.
93
    /// </summary>
94
    /// <returns></returns>
95
    public static EnumValues<ulong> GetNamesAndValues<T>() where T : struct
96
    {
97
 72
      return GetNamesAndValues<ulong>(typeof(T));
98
 72
    }
99

  
100
    /// <summary>
101
    /// Gets a dictionary of the names and values of an Enum type.
102
    /// </summary>
103
    /// <returns></returns>
104
    public static EnumValues<TUnderlyingType> GetNamesAndValues<TEnum, TUnderlyingType>()
105
      where TEnum : struct
106
      where TUnderlyingType : struct
107
    {
108
 0
      return GetNamesAndValues<TUnderlyingType>(typeof(TEnum));
109
 0
    }
110

  
111
    /// <summary>
112
    /// Gets a dictionary of the names and values of an Enum type.
113
    /// </summary>
114
    /// <param name="enumType">The enum type to get names and values for.</param>
115
    /// <returns></returns>
116
    public static EnumValues<TUnderlyingType> GetNamesAndValues<TUnderlyingType>(Type enumType) where TUnderlyingType : struct
117
    {
118
 74
      if (enumType == null)
119
 0
        throw new ArgumentNullException("enumType");
120

  
121
 74
      ValidationUtils.ArgumentTypeIsEnum(enumType, "enumType");
122

  
123
 74
      IList<object> enumValues = GetValues(enumType);
124
 74
      IList<string> enumNames = GetNames(enumType);
125

  
126
 74
      EnumValues<TUnderlyingType> nameValues = new EnumValues<TUnderlyingType>();
127

  
128
 74
      for (int i = 0; i < enumValues.Count; i++)
129
      {
130
        try
131
        {
132
 654
          nameValues.Add(new EnumValue<TUnderlyingType>(enumNames[i], (TUnderlyingType)Convert.ChangeType(enumValues[i], typeof(TUnderlyingType), CultureInfo.CurrentCulture)));
133
        }
134
 0
        catch (OverflowException e)
135
        {
136
 0
          throw new Exception(
137
 0
            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}",
138
 0
              Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i], CultureInfo.InvariantCulture)), e);
139
        }
140
      }
141

  
142
 74
      return nameValues;
143
 74
    }
144

  
145
    public static IList<T> GetValues<T>()
146
    {
147
 0
      return GetValues(typeof(T)).Cast<T>().ToList();
148
 0
    }
149

  
150
    public static IList<object> GetValues(Type enumType)
151
    {
152
 74
      if (!enumType.IsEnum)
153
 0
        throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
154

  
155
 74
      List<object> values = new List<object>();
156

  
157
 74
      var fields = from field in enumType.GetFields()
158
 74
                   where field.IsLiteral
159
 74
                   select field;
160

  
161
 74
      foreach (FieldInfo field in fields)
162
      {
163
 654
        object value = field.GetValue(enumType);
164
 654
        values.Add(value);
165
      }
166

  
167
 74
      return values;
168
 74
    }
169

  
170
    public static IList<string> GetNames<T>()
171
    {
172
 0
      return GetNames(typeof(T));
173
 0
    }
174

  
175
    public static IList<string> GetNames(Type enumType)
176
    {
177
 74
      if (!enumType.IsEnum)
178
 0
        throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
179

  
180
 74
      List<string> values = new List<string>();
181

  
182
 74
      var fields = from field in enumType.GetFields()
183
 74
                   where field.IsLiteral
184
 74
                   select field;
185

  
186
 74
      foreach (FieldInfo field in fields)
187
      {
188
 654
        values.Add(field.Name);
189
      }
190

  
191
 74
      return values;
192
 74
    }
193

  
194

  
195
    /// <summary>
196
    /// Gets the maximum valid value of an Enum type. Flags enums are ORed.
197
    /// </summary>
198
    /// <typeparam name="TEnumType">The type of the returned value. Must be assignable from the enum's underlying value type.</typeparam>
199
    /// <param name="enumType">The enum type to get the maximum value for.</param>
200
    /// <returns></returns>
201
    public static TEnumType GetMaximumValue<TEnumType>(Type enumType) where TEnumType : IConvertible, IComparable<TEnumType>
202
    {
203
 0
      if (enumType == null)
204
 0
        throw new ArgumentNullException("enumType");
205

  
206
 0
      Type enumUnderlyingType = Enum.GetUnderlyingType(enumType);
207

  
208
 0
      if (!typeof(TEnumType).IsAssignableFrom(enumUnderlyingType))
209
 0
        throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "TEnumType is not assignable from the enum's underlying type of {0}.", enumUnderlyingType.Name));
210

  
211
 0
      ulong maximumValue = 0;
212
 0
      IList<object> enumValues = GetValues(enumType);
213

  
214
 0
      if (enumType.IsDefined(typeof(FlagsAttribute), false))
215
      {
216
 0
        foreach (TEnumType value in enumValues)
217
        {
218
 0
          maximumValue = maximumValue | value.ToUInt64(CultureInfo.InvariantCulture);
219
        }
220
      }
221
      else
222
      {
223
 0
        foreach (TEnumType value in enumValues)
224
        {
225
 0
          ulong tempValue = value.ToUInt64(CultureInfo.InvariantCulture);
226

  
227
          // maximumValue is smaller than the enum value
228
 0
          if (maximumValue.CompareTo(tempValue) == -1)
229
 0
            maximumValue = tempValue;
230
        }
231
      }
232

  
233
 0
      return (TEnumType)Convert.ChangeType(maximumValue, typeof(TEnumType), CultureInfo.InvariantCulture);
234
 0
    }
235
  }
236
}