diff options
Diffstat (limited to 'src/libs/WixToolset.Versioning/WixVersionComparer.cs')
-rw-r--r-- | src/libs/WixToolset.Versioning/WixVersionComparer.cs | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/libs/WixToolset.Versioning/WixVersionComparer.cs b/src/libs/WixToolset.Versioning/WixVersionComparer.cs new file mode 100644 index 00000000..be203634 --- /dev/null +++ b/src/libs/WixToolset.Versioning/WixVersionComparer.cs | |||
@@ -0,0 +1,253 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Versioning | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | |||
8 | /// <summary> | ||
9 | /// WixVersion comparer. | ||
10 | /// </summary> | ||
11 | public class WixVersionComparer : IEqualityComparer<WixVersion>, IComparer<WixVersion> | ||
12 | { | ||
13 | /// <summary> | ||
14 | /// Default WixVersion comparer. | ||
15 | /// </summary> | ||
16 | public static readonly WixVersionComparer Default = new WixVersionComparer(); | ||
17 | |||
18 | /// <inheritdoc /> | ||
19 | public int Compare(WixVersion x, WixVersion y) | ||
20 | { | ||
21 | if ((object)x == y) | ||
22 | { | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | if (x is null) | ||
27 | { | ||
28 | return -1; | ||
29 | } | ||
30 | |||
31 | if (y is null) | ||
32 | { | ||
33 | return 1; | ||
34 | } | ||
35 | |||
36 | var result = x.Major.CompareTo(y.Major); | ||
37 | if (result != 0) | ||
38 | { | ||
39 | return result; | ||
40 | } | ||
41 | |||
42 | result = x.Minor.CompareTo(y.Minor); | ||
43 | if (result != 0) | ||
44 | { | ||
45 | return result; | ||
46 | } | ||
47 | |||
48 | result = x.Patch.CompareTo(y.Patch); | ||
49 | if (result != 0) | ||
50 | { | ||
51 | return result; | ||
52 | } | ||
53 | |||
54 | result = x.Revision.CompareTo(y.Revision); | ||
55 | if (result != 0) | ||
56 | { | ||
57 | return result; | ||
58 | } | ||
59 | |||
60 | var xLabelCount = x.Labels?.Length ?? 0; | ||
61 | var yLabelCount = y.Labels?.Length ?? 0; | ||
62 | var maxLabelCount = Math.Max(xLabelCount, yLabelCount); | ||
63 | |||
64 | if (xLabelCount > 0) | ||
65 | { | ||
66 | if (yLabelCount == 0) | ||
67 | { | ||
68 | return -1; | ||
69 | } | ||
70 | } | ||
71 | else if (yLabelCount > 0) | ||
72 | { | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | for (var i = 0; i < maxLabelCount; ++i) | ||
77 | { | ||
78 | var xLabel = i < xLabelCount ? x.Labels[i] : null; | ||
79 | var yLabel = i < yLabelCount ? y.Labels[i] : null; | ||
80 | |||
81 | result = CompareReleaseLabel(xLabel, yLabel); | ||
82 | if (result != 0) | ||
83 | { | ||
84 | return result; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | var compareMetadata = false; | ||
89 | |||
90 | if (x.Invalid) | ||
91 | { | ||
92 | if (!y.Invalid) | ||
93 | { | ||
94 | return -1; | ||
95 | } | ||
96 | else | ||
97 | { | ||
98 | compareMetadata = true; | ||
99 | } | ||
100 | } | ||
101 | else if (y.Invalid) | ||
102 | { | ||
103 | return 1; | ||
104 | } | ||
105 | |||
106 | if (compareMetadata) | ||
107 | { | ||
108 | result = String.Compare(x.Metadata, y.Metadata, StringComparison.OrdinalIgnoreCase); | ||
109 | } | ||
110 | |||
111 | return (result == 0) ? 0 : (result < 0) ? -1 : 1; | ||
112 | } | ||
113 | |||
114 | /// <inheritdoc /> | ||
115 | public bool Equals(WixVersion x, WixVersion y) | ||
116 | { | ||
117 | if ((object)x == y) | ||
118 | { | ||
119 | return true; | ||
120 | } | ||
121 | |||
122 | if (x is null) | ||
123 | { | ||
124 | return false; | ||
125 | } | ||
126 | |||
127 | if (y is null) | ||
128 | { | ||
129 | return false; | ||
130 | } | ||
131 | |||
132 | if (x.Major != y.Major) | ||
133 | { | ||
134 | return false; | ||
135 | } | ||
136 | |||
137 | if (x.Minor != y.Minor) | ||
138 | { | ||
139 | return false; | ||
140 | } | ||
141 | |||
142 | if (x.Patch != y.Patch) | ||
143 | { | ||
144 | return false; | ||
145 | } | ||
146 | |||
147 | if (x.Revision != y.Revision) | ||
148 | { | ||
149 | return false; | ||
150 | } | ||
151 | |||
152 | var labelCount = x.Labels?.Length ?? 0; | ||
153 | if (labelCount != (y.Labels?.Length ?? 0)) | ||
154 | { | ||
155 | return false; | ||
156 | } | ||
157 | |||
158 | for (var i = 0; i < labelCount; ++i) | ||
159 | { | ||
160 | var result = CompareReleaseLabel(x.Labels[i], y.Labels[i]); | ||
161 | if (result != 0) | ||
162 | { | ||
163 | return false; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | if (x.Invalid) | ||
168 | { | ||
169 | if (y.Invalid) | ||
170 | { | ||
171 | return String.Equals(x.Metadata, y.Metadata, StringComparison.OrdinalIgnoreCase); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | return false; | ||
176 | } | ||
177 | } | ||
178 | else if (y.Invalid) | ||
179 | { | ||
180 | return false; | ||
181 | } | ||
182 | |||
183 | return true; | ||
184 | } | ||
185 | |||
186 | /// <inheritdoc /> | ||
187 | public int GetHashCode(WixVersion version) | ||
188 | { | ||
189 | var hash = 23L; | ||
190 | hash = hash * 37 + (version.Prefix ?? '\0'); | ||
191 | hash = hash * 37 + version.Major; | ||
192 | hash = hash * 37 + version.Minor; | ||
193 | hash = hash * 37 + version.Patch; | ||
194 | hash = hash * 37 + version.Revision; | ||
195 | hash = hash * 37 + (version.Invalid ? 1 : 0); | ||
196 | hash = hash * 37 + (version.HasMajor ? 1 : 0); | ||
197 | hash = hash * 37 + (version.HasMinor ? 1 : 0); | ||
198 | hash = hash * 37 + (version.HasPatch ? 1 : 0); | ||
199 | hash = hash * 37 + (version.HasRevision ? 1 : 0); | ||
200 | |||
201 | if (version.Labels != null) | ||
202 | { | ||
203 | foreach (var label in version.Labels) | ||
204 | { | ||
205 | hash = hash * 37 + label.Label.GetHashCode(); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | hash = hash * 37 + version.Metadata?.GetHashCode() ?? 0; | ||
210 | |||
211 | return unchecked((int)hash); | ||
212 | } | ||
213 | |||
214 | private static int CompareReleaseLabel(WixVersionLabel l1, WixVersionLabel l2) | ||
215 | { | ||
216 | if (l1 == l2) | ||
217 | { | ||
218 | return 0; | ||
219 | } | ||
220 | else if (l2 == null) | ||
221 | { | ||
222 | return 1; | ||
223 | } | ||
224 | else if (l1 == null) | ||
225 | { | ||
226 | return -1; | ||
227 | } | ||
228 | |||
229 | if (l1.Numeric.HasValue) | ||
230 | { | ||
231 | if (l2.Numeric.HasValue) | ||
232 | { | ||
233 | return l1.Numeric.Value.CompareTo(l2.Numeric.Value); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | return -1; | ||
238 | } | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | if (l2.Numeric.HasValue) | ||
243 | { | ||
244 | return 1; | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | return String.Compare(l1.Label, l2.Label, StringComparison.OrdinalIgnoreCase); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | } | ||