Implement MachineKey.Protect and MachineKey.Unprotect
[mono.git] / mcs / class / System.ComponentModel.Composition / src / ComponentModel / Microsoft / Internal / Collections / CollectionServices.cs
1 // -----------------------------------------------------------------------\r
2 // Copyright (c) Microsoft Corporation.  All rights reserved.\r
3 // -----------------------------------------------------------------------\r
4 using System;\r
5 using System.Collections;\r
6 using System.Collections.Generic;\r
7 using System.Collections.ObjectModel;\r
8 using System.Diagnostics.CodeAnalysis;\r
9 using System.Globalization;\r
10 using System.Linq;\r
11 \r
12 namespace Microsoft.Internal.Collections\r
13 {\r
14     internal static partial class CollectionServices\r
15     {\r
16         private static readonly Type StringType = typeof(string);\r
17         private static readonly Type IEnumerableType = typeof(IEnumerable);\r
18         private static readonly Type IEnumerableOfTType = typeof(IEnumerable<>);\r
19         private static readonly Type ICollectionOfTType = typeof(ICollection<>);\r
20 \r
21         public static bool IsEnumerableOfT(Type type)\r
22         {\r
23             if (type.IsGenericType)\r
24             {\r
25                 Type genericType = type.GetGenericTypeDefinition();\r
26 \r
27                 if (genericType == IEnumerableOfTType)\r
28                 {\r
29                     return true;\r
30                 }\r
31             }\r
32             return false;\r
33         }\r
34 \r
35         public static Type GetEnumerableElementType(Type type)\r
36         {\r
37             if (type == StringType || !IEnumerableType.IsAssignableFrom(type))\r
38             {\r
39                 return null;\r
40             }\r
41 \r
42             Type closedType;\r
43             if (ReflectionServices.TryGetGenericInterfaceType(type, IEnumerableOfTType, out closedType))\r
44             {\r
45                 return closedType.GetGenericArguments()[0];\r
46             }\r
47 \r
48             return null;\r
49         }\r
50 \r
51         public static Type GetCollectionElementType(Type type)\r
52         {\r
53             Type closedType;\r
54             if (ReflectionServices.TryGetGenericInterfaceType(type, ICollectionOfTType, out closedType))\r
55             {\r
56                 return closedType.GetGenericArguments()[0];\r
57             }\r
58 \r
59             return null;\r
60         }\r
61 \r
62         public static ReadOnlyCollection<T> ToReadOnlyCollection<T>(this IEnumerable<T> source)\r
63         {\r
64             Assumes.NotNull(source);\r
65 \r
66             return new ReadOnlyCollection<T>(source.AsArray());\r
67         }\r
68 \r
69         public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> source) where T : class\r
70         {\r
71             Assumes.NotNull(source);\r
72             return source.Where(NotNull); // Use non-generic NotNull for performance reasons\r
73         }\r
74         \r
75         private static bool NotNull(object element)\r
76         {\r
77           return element != null;\r
78         }\r
79 \r
80         public static IEnumerable<T> ConcatAllowingNull<T>(this IEnumerable<T> source, IEnumerable<T> second)\r
81         {\r
82             if (second == null || !second.FastAny())\r
83             {\r
84                 return source;\r
85             }\r
86 \r
87             if (source == null || !source.FastAny())\r
88             {\r
89                 return second;\r
90             }\r
91 \r
92             return source.Concat(second);\r
93         }\r
94  \r
95         public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)\r
96         {\r
97             foreach(T t in source)\r
98             {\r
99                 action.Invoke(t);\r
100             }\r
101         }\r
102 \r
103         public static EnumerableCardinality GetCardinality<T>(this IEnumerable<T> source)\r
104         {\r
105             Assumes.NotNull(source);\r
106 \r
107             // Cast to ICollection instead of ICollection<T> for performance reasons.\r
108             ICollection collection = source as ICollection;\r
109             if (collection != null)\r
110             {\r
111                 switch (collection.Count)\r
112                 {\r
113                     case 0:\r
114                         return EnumerableCardinality.Zero;\r
115 \r
116                     case 1:\r
117                         return EnumerableCardinality.One;\r
118 \r
119                     default:\r
120                         return EnumerableCardinality.TwoOrMore;\r
121                 }\r
122             }\r
123 \r
124             using (var enumerator = source.GetEnumerator())\r
125             {\r
126                 if (!enumerator.MoveNext())\r
127                 {\r
128                     return EnumerableCardinality.Zero;\r
129                 }\r
130 \r
131                 if (!enumerator.MoveNext())\r
132                 {\r
133                     return EnumerableCardinality.One;\r
134                 }\r
135 \r
136                 return EnumerableCardinality.TwoOrMore;\r
137             }\r
138         }\r
139 \r
140         public static bool FastAny<T>(this IEnumerable<T> source)\r
141         {\r
142             // Enumerable.Any<T> underneath doesn't cast to ICollection, \r
143             // like it does with many of the other LINQ methods.\r
144             // Below is significantly (4x) when mainly working with ICollection\r
145             // sources and a little slower if working with mainly IEnumerable<T> \r
146             // sources.\r
147 \r
148             // Cast to ICollection instead of ICollection<T> for performance reasons.\r
149             ICollection collection = source as ICollection;\r
150             if (collection != null)\r
151             {\r
152                 return collection.Count > 0;\r
153             }\r
154 \r
155             return source.Any();\r
156         }\r
157 \r
158         public static Stack<T> Copy<T>(this Stack<T> stack)\r
159         {\r
160             Assumes.NotNull(stack);\r
161 \r
162             // Stack<T>.GetEnumerator walks from top to bottom \r
163             // of the stack, whereas Stack<T>(IEnumerable<T>) \r
164             // pushes to bottom from top, so we need to reverse \r
165             // the stack to get them in the right order.\r
166             return new Stack<T>(stack.Reverse());\r
167         }\r
168 \r
169         public static T[] AsArray<T>(this IEnumerable<T> enumerable)\r
170         {\r
171             T[] array = enumerable as T[];\r
172 \r
173             if (array != null)\r
174             {\r
175                 return array;\r
176             }\r
177 \r
178             return enumerable.ToArray();\r
179         }\r
180     }\r
181 }\r