Skip to content

Commit 779da80

Browse files
authored
Rewrote Guid.CompareTo (#271)
***NO_CI***
1 parent 1d0f540 commit 779da80

3 files changed

Lines changed: 110 additions & 38 deletions

File tree

Tests/NFUnitTestTypes/UnitTestGuid.cs

Lines changed: 66 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ class UnitTestGuid
1212
[TestMethod]
1313
public void Guid_Compare_To_Empty()
1414
{
15-
var empty = Guid.Empty;
16-
var notEmpty = Guid.NewGuid();
15+
Guid empty = Guid.Empty;
16+
Guid notEmpty = Guid.NewGuid();
1717
Assert.IsFalse(empty == notEmpty);
1818
}
1919

2020
[TestMethod]
2121
public void Guid_Empty_IsAllZeros()
2222
{
23-
var empty = Guid.Empty;
24-
var bytes = empty.ToByteArray();
25-
foreach (var b in bytes)
23+
Guid empty = Guid.Empty;
24+
byte[] bytes = empty.ToByteArray();
25+
foreach (byte b in bytes)
2626
{
2727
Assert.AreEqual((byte)0, b);
2828
}
@@ -31,17 +31,17 @@ public void Guid_Empty_IsAllZeros()
3131
[TestMethod]
3232
public void Guid_Constructor_ByteArray_RoundTrip()
3333
{
34-
var original = Guid.NewGuid();
35-
var bytes = original.ToByteArray();
36-
var roundTrip = new Guid(bytes);
34+
Guid original = Guid.NewGuid();
35+
byte[] bytes = original.ToByteArray();
36+
Guid roundTrip = new Guid(bytes);
3737
Assert.AreEqual(original, roundTrip);
3838
}
3939

4040
[TestMethod]
4141
public void Guid_Equals_And_Operator()
4242
{
43-
var g1 = Guid.NewGuid();
44-
var g2 = new Guid(g1.ToByteArray());
43+
Guid g1 = Guid.NewGuid();
44+
Guid g2 = new Guid(g1.ToByteArray());
4545
Assert.IsTrue(g1.Equals(g2));
4646
Assert.IsTrue(g1 == g2);
4747
Assert.IsFalse(g1 != g2);
@@ -50,8 +50,8 @@ public void Guid_Equals_And_Operator()
5050
[TestMethod]
5151
public void Guid_NotEquals_And_Operator()
5252
{
53-
var g1 = Guid.NewGuid();
54-
var g2 = Guid.NewGuid();
53+
Guid g1 = Guid.NewGuid();
54+
Guid g2 = Guid.NewGuid();
5555
Assert.IsFalse(g1.Equals(g2));
5656
Assert.IsFalse(g1 == g2);
5757
Assert.IsTrue(g1 != g2);
@@ -60,25 +60,25 @@ public void Guid_NotEquals_And_Operator()
6060
[TestMethod]
6161
public void Guid_ToString_And_Parse()
6262
{
63-
var g1 = Guid.NewGuid();
64-
var str = g1.ToString();
65-
var g2 = new Guid(str);
63+
Guid g1 = Guid.NewGuid();
64+
string str = g1.ToString();
65+
Guid g2 = new Guid(str);
6666
Assert.AreEqual(g1, g2);
6767
}
6868

6969
[TestMethod]
7070
public void Guid_GetHashCode_Consistent()
7171
{
72-
var g1 = Guid.NewGuid();
73-
var g2 = new Guid(g1.ToByteArray());
72+
Guid g1 = Guid.NewGuid();
73+
Guid g2 = new Guid(g1.ToByteArray());
7474
Assert.AreEqual(g1.GetHashCode(), g2.GetHashCode());
7575
}
7676

7777
[TestMethod]
7878
public void Guid_CompareTo_Object_And_Self()
7979
{
80-
var g1 = Guid.NewGuid();
81-
var g2 = new Guid(g1.ToByteArray());
80+
Guid g1 = Guid.NewGuid();
81+
Guid g2 = new Guid(g1.ToByteArray());
8282
Assert.AreEqual(0, g1.CompareTo(g2));
8383
Assert.AreEqual(0, g1.CompareTo((object)g2));
8484
Assert.AreEqual(1, g1.CompareTo(null));
@@ -87,7 +87,7 @@ public void Guid_CompareTo_Object_And_Self()
8787
[TestMethod]
8888
public void Guid_CompareTo_InvalidType_Throws()
8989
{
90-
var g1 = Guid.NewGuid();
90+
Guid g1 = Guid.NewGuid();
9191
Assert.ThrowsException(typeof(ArgumentException), () =>
9292
{
9393
g1.CompareTo("not a guid");
@@ -97,27 +97,29 @@ public void Guid_CompareTo_InvalidType_Throws()
9797
[TestMethod]
9898
public void Guid_TryParseGuidWithDashes_Valid()
9999
{
100-
var g1 = Guid.NewGuid();
101-
var str = g1.ToString();
102-
bool parsed = Guid.TryParse(str, out var g2);
100+
Guid g1 = Guid.NewGuid();
101+
string str = g1.ToString();
102+
Guid g2;
103+
bool parsed = Guid.TryParse(str, out g2);
103104
Assert.IsTrue(parsed);
104105
Assert.AreEqual(g1, g2);
105106
}
106107

107108
[TestMethod]
108109
public void Guid_TryParseGuidWithDashes_Invalid()
109110
{
110-
bool parsed = Guid.TryParse("invalid-guid", out var g2);
111+
Guid g2;
112+
bool parsed = Guid.TryParse("invalid-guid", out g2);
111113
Assert.IsFalse(parsed);
112114
Assert.AreEqual(Guid.Empty, g2);
113115
}
114116

115117
[TestMethod]
116118
public void Guid_Constructor_String_WithBraces()
117119
{
118-
var g1 = Guid.NewGuid();
119-
var str = "{" + g1.ToString() + "}";
120-
var g2 = new Guid(str);
120+
Guid g1 = Guid.NewGuid();
121+
string str = "{" + g1.ToString() + "}";
122+
Guid g2 = new Guid(str);
121123
Assert.AreEqual(g1, g2);
122124
}
123125

@@ -126,15 +128,50 @@ public void Guid_Constructor_String_Invalid_Throws()
126128
{
127129
Assert.ThrowsException(typeof(ArgumentException), () =>
128130
{
129-
var g = new Guid("invalid-guid");
131+
Guid g = new Guid("invalid-guid");
130132
});
131133
}
132134

133135
[TestMethod]
134136
public void Guid_GetHashCode_Empty()
135137
{
136-
var empty = Guid.Empty;
138+
Guid empty = Guid.Empty;
137139
Assert.AreEqual(0, empty.GetHashCode());
138140
}
141+
142+
[TestMethod]
143+
public void Guid_CompareTo_LessThan()
144+
{
145+
Guid g1 = new Guid(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
146+
Guid g2 = new Guid(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
147+
Assert.IsTrue(g1.CompareTo(g2) < 0, "g1 should be less than g2");
148+
}
149+
150+
[TestMethod]
151+
public void Guid_CompareTo_GreaterThan()
152+
{
153+
Guid g1 = new Guid(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
154+
Guid g2 = new Guid(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
155+
Assert.IsTrue(g1.CompareTo(g2) > 0, "g1 should be greater than g2");
156+
}
157+
158+
[TestMethod]
159+
public void Guid_CompareTo_OrdersByComponents()
160+
{
161+
// b component
162+
Guid lo = new Guid(0, (short)1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
163+
Guid hi = new Guid(0, (short)2, 0, 0, 0, 0, 0, 0, 0, 0, 0);
164+
Assert.IsTrue(lo.CompareTo(hi) < 0);
165+
166+
// 'a' high-bit: 0x80000001 as uint > 0x00000001; signed subtraction would overflow and give wrong sign
167+
Guid bigA = new Guid(unchecked((int)0x80000001), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
168+
Guid smallA = new Guid(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
169+
Assert.IsTrue(bigA.CompareTo(smallA) > 0);
170+
171+
// last byte (k)
172+
Guid loK = new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
173+
Guid hiK = new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2);
174+
Assert.IsTrue(loK.CompareTo(hiK) < 0);
175+
}
139176
}
140177
}

nanoFramework.CoreLibrary/System/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
[assembly: AssemblyProduct(".NET nanoFramework mscorlib")]
1111
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
1212

13-
[assembly: AssemblyNativeVersion("100.22.0.3")]
13+
[assembly: AssemblyNativeVersion("100.22.0.4")]

nanoFramework.CoreLibrary/System/Guid.cs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,22 +176,57 @@ public int CompareTo(object value)
176176
/// <summary>
177177
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
178178
/// </summary>
179-
/// <param name="other">An object to compare with this instance.</param>
179+
/// <param name="value">An object to compare with this instance.</param>
180180
/// <returns>A value that indicates the relative order of the objects being compared.</returns>
181-
public int CompareTo(Guid other)
181+
public int CompareTo(Guid value)
182182
{
183183
_data ??= new int[4];
184-
other._data ??= new int[4];
185-
for (int i = 0; i < 4; i++)
184+
value._data ??= new int[4];
185+
186+
uint this0 = (uint)_data[0];
187+
uint other0 = (uint)value._data[0];
188+
if (this0 != other0)
186189
{
187-
if (_data[i] != other._data[i])
188-
{
189-
return _data[i] - other._data[i];
190-
}
190+
return this0 < other0 ? -1 : 1;
191+
}
192+
193+
uint this1 = SwapHalves((uint)_data[1]);
194+
uint other1 = SwapHalves((uint)value._data[1]);
195+
if (this1 != other1)
196+
{
197+
return this1 < other1 ? -1 : 1;
198+
}
199+
200+
uint this2 = SwapBytes((uint)_data[2]);
201+
uint other2 = SwapBytes((uint)value._data[2]);
202+
if (this2 != other2)
203+
{
204+
return this2 < other2 ? -1 : 1;
191205
}
206+
207+
uint this3 = SwapBytes((uint)_data[3]);
208+
uint other3 = SwapBytes((uint)value._data[3]);
209+
if (this3 != other3)
210+
{
211+
return this3 < other3 ? -1 : 1;
212+
}
213+
192214
return 0;
193215
}
194216

217+
private static uint SwapHalves(uint value)
218+
{
219+
return (value << 16) | (value >> 16);
220+
}
221+
222+
private static uint SwapBytes(uint value)
223+
{
224+
return ((value & 0x000000FFu) << 24) |
225+
((value & 0x0000FF00u) << 8) |
226+
((value & 0x00FF0000u) >> 8) |
227+
((value & 0xFF000000u) >> 24);
228+
}
229+
195230
/// <summary>
196231
/// Returns a 16-element byte array that contains the value of this instance.
197232
/// </summary>

0 commit comments

Comments
 (0)