1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
2 
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Text;
7 
8 namespace System.Json
9 {
10     internal static class Util
11     {
12         public static bool CompareObjects<T>(T o1, T o2) where T : class
13         {
14             if ((o1 == null) != (o2 == null))
15             {
16                 return false;
17             }
18 
19             return (o1 == null) || o1.Equals(o2);
20         }
21 
22         public static bool CompareNullable<T>(Nullable<T> n1, Nullable<T> n2) where T : struct
23         {
24             if (n1.HasValue != n2.HasValue)
25             {
26                 return false;
27             }
28 
29             return (!n1.HasValue) || n1.Value.Equals(n2.Value);
30         }
31 
CompareLists(List<T> list1, List<T> list2)32         public static bool CompareLists<T>(List<T> list1, List<T> list2)
33         {
34             if (list1 == null)
35             {
36                 return list2 == null;
37             }
38 
39             if (list2 == null)
40             {
41                 return false;
42             }
43 
44             return CompareArrays(list1.ToArray(), list2.ToArray());
45         }
46 
47         public static bool CompareDictionaries<K, V>(Dictionary<K, V> dict1, Dictionary<K, V> dict2)
48             where K : IComparable
49             where V : class
50         {
51             if (dict1 == null)
52             {
53                 return dict2 == null;
54             }
55 
56             if (dict2 == null)
57             {
58                 return false;
59             }
60 
61             List<K> keys1 = new List<K>(dict1.Keys);
62             List<K> keys2 = new List<K>(dict2.Keys);
keys1.Sort()63             keys1.Sort();
keys2.Sort()64             keys2.Sort();
65             if (!CompareLists<K>(keys1, keys2))
66             {
67                 return false;
68             }
69 
70             foreach (K key in keys1)
71             {
72                 V value1 = dict1[key];
73                 V value2 = dict2[key];
74                 if (!CompareObjects<V>(value1, value2))
75                 {
76                     return false;
77                 }
78             }
79 
80             return true;
81         }
82 
CompareArrays(Array array1, Array array2)83         public static bool CompareArrays(Array array1, Array array2)
84         {
85             if (array1 == null)
86             {
87                 return array2 == null;
88             }
89 
90             if (array2 == null || array1.Length != array2.Length)
91             {
92                 return false;
93             }
94 
95             for (int i = 0; i < array1.Length; i++)
96             {
97                 object o1 = array1.GetValue(i);
98                 object o2 = array2.GetValue(i);
99                 if ((o1 == null) != (o2 == null))
100                 {
101                     return false;
102                 }
103 
104                 if (o1 != null)
105                 {
106                     if ((o1 is Array) && (o2 is Array))
107                     {
108                         if (!CompareArrays((Array)o1, (Array)o2))
109                         {
110                             return false;
111                         }
112                     }
113                     else if (o1 is IEnumerable && o2 is IEnumerable)
114                     {
115                         if (!CompareArrays(ToObjectArray((IEnumerable)o1), ToObjectArray((IEnumerable)o2)))
116                         {
117                             return false;
118                         }
119                     }
120                     else
121                     {
122                         if (!o1.Equals(o2))
123                         {
124                             return false;
125                         }
126                     }
127                 }
128             }
129 
130             return true;
131         }
132 
ComputeArrayHashCode(Array array)133         public static int ComputeArrayHashCode(Array array)
134         {
135             if (array == null)
136             {
137                 return 0;
138             }
139 
140             int result = 0;
141             result += array.Length;
142             for (int i = 0; i < array.Length; i++)
143             {
144                 object o = array.GetValue(i);
145                 if (o != null)
146                 {
147                     if (o is Array)
148                     {
149                         result ^= ComputeArrayHashCode((Array)o);
150                     }
151                     else if (o is Enumerable)
152                     {
153                         result ^= ComputeArrayHashCode(ToObjectArray((IEnumerable)o));
154                     }
155                     else
156                     {
157                         result ^= o.GetHashCode();
158                     }
159                 }
160             }
161 
162             return result;
163         }
164 
EscapeString(object obj)165         public static string EscapeString(object obj)
166         {
167             StringBuilder sb = new StringBuilder();
168             if (obj == null)
169             {
170                 return "<<null>>";
171             }
172             else
173             {
174                 string str = obj.ToString();
175                 for (int i = 0; i < str.Length; i++)
176                 {
177                     char c = str[i];
178                     if (c < ' ' || c > '~')
179                     {
180                         sb.AppendFormat("\\u{0:X4}", (int)c);
181                     }
182                     else
183                     {
184                         sb.Append(c);
185                     }
186                 }
187             }
188 
189             return sb.ToString();
190         }
191 
ToObjectArray(IEnumerable enumerable)192         static object[] ToObjectArray(IEnumerable enumerable)
193         {
194             List<object> result = new List<object>();
195             foreach (var item in enumerable)
196             {
197                 result.Add(item);
198             }
199 
200             return result.ToArray();
201         }
202     }
203 }