blob: 21ee3bba7af1fb8efd7cde77a36e4dfc554e7f2c [file] [log] [blame]
Jens Geyeraa0c8b32019-01-28 23:27:45 +01001// Licensed to the Apache Software Foundation(ASF) under one
2// or more contributor license agreements.See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18using System.Collections;
Jens Geyeraffea7b2020-05-22 17:28:30 +020019using System.Collections.Generic;
Jens Geyeraa0c8b32019-01-28 23:27:45 +010020
21namespace Thrift.Collections
22{
23 // ReSharper disable once InconsistentNaming
Jens Geyeraffea7b2020-05-22 17:28:30 +020024 public static class TCollections
Jens Geyeraa0c8b32019-01-28 23:27:45 +010025 {
26 /// <summary>
27 /// This will return true if the two collections are value-wise the same.
28 /// If the collection contains a collection, the collections will be compared using this method.
29 /// </summary>
30 public static bool Equals(IEnumerable first, IEnumerable second)
31 {
32 if (first == null && second == null)
33 {
34 return true;
35 }
36
37 if (first == null || second == null)
38 {
39 return false;
40 }
41
Jens Geyeraffea7b2020-05-22 17:28:30 +020042 // for dictionaries, we need to compare keys and values separately
43 // because KeyValuePair<K,V>.Equals() will not do what we want
44 var fdict = first as IDictionary;
45 var sdict = second as IDictionary;
46 if ((fdict != null) || (sdict != null))
47 {
48 if ((fdict == null) || (sdict == null))
49 return false;
50 return TCollections.Equals(fdict.Keys, sdict.Keys)
51 && TCollections.Equals(fdict.Values, sdict.Values);
52 }
53
Jens Geyeraa0c8b32019-01-28 23:27:45 +010054 var fiter = first.GetEnumerator();
55 var siter = second.GetEnumerator();
56
57 var fnext = fiter.MoveNext();
58 var snext = siter.MoveNext();
59
60 while (fnext && snext)
61 {
62 var fenum = fiter.Current as IEnumerable;
63 var senum = siter.Current as IEnumerable;
64
65 if (fenum != null && senum != null)
66 {
67 if (!Equals(fenum, senum))
68 {
69 return false;
70 }
71 }
72 else if (fenum == null ^ senum == null)
73 {
74 return false;
75 }
76 else if (!Equals(fiter.Current, siter.Current))
77 {
78 return false;
79 }
80
81 fnext = fiter.MoveNext();
82 snext = siter.MoveNext();
83 }
84
85 return fnext == snext;
86 }
87
88 /// <summary>
89 /// This returns a hashcode based on the value of the enumerable.
90 /// </summary>
91 public static int GetHashCode(IEnumerable enumerable)
92 {
93 if (enumerable == null)
94 {
95 return 0;
96 }
97
98 var hashcode = 0;
99
100 foreach (var obj in enumerable)
101 {
Jens Geyer526a1ac2021-02-13 13:58:09 +0100102 var objHash = (obj is IEnumerable enum2) ? GetHashCode(enum2) : obj.GetHashCode();
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100103
104 unchecked
105 {
Jens Geyeraffea7b2020-05-22 17:28:30 +0200106 hashcode = (hashcode * 397) ^ (objHash);
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100107 }
108 }
109
110 return hashcode;
111 }
Jens Geyeraffea7b2020-05-22 17:28:30 +0200112
113
Jens Geyeraa0c8b32019-01-28 23:27:45 +0100114 }
Jens Geyeraffea7b2020-05-22 17:28:30 +0200115}