@@ -16,7 +16,11 @@ internal sealed class FatChainEnumerator : IEnumerator<uint>
16
16
private uint index = uint . MaxValue ;
17
17
private uint current = uint . MaxValue ;
18
18
private long length = - 1 ;
19
- private uint slow = uint . MaxValue ; // Floyd's cycle-finding algorithm
19
+
20
+ // Brent's cycle detection algorithm
21
+ private uint cycleLength = 1 ;
22
+ private uint power = 1 ;
23
+ private uint slow = uint . MaxValue ;
20
24
21
25
public FatChainEnumerator ( Fat fat , uint startSectorId )
22
26
{
@@ -64,7 +68,7 @@ public bool MoveNext()
64
68
index = 0 ;
65
69
current = startId ;
66
70
start = false ;
67
- slow = startId ;
71
+ slow = uint . MaxValue ;
68
72
return true ;
69
73
}
70
74
@@ -87,15 +91,18 @@ public bool MoveNext()
87
91
throw new FileFormatException ( "FAT chain index is greater than the sector count." ) ;
88
92
}
89
93
90
- if ( index % 2 == 0 && ! SectorType . IsFreeOrEndOfChain ( slow ) )
94
+ if ( value == slow )
95
+ throw new FileFormatException ( "FAT chain contains a loop." ) ;
96
+
97
+ if ( cycleLength == power )
91
98
{
92
- // Slow might become free or end of chain while shrinking
93
- slow = fat [ slow ] ;
94
- if ( slow == value )
95
- throw new FileFormatException ( "FAT chain contains a loop." ) ;
99
+ cycleLength = 0 ;
100
+ power *= 2 ;
101
+ slow = value ;
96
102
}
97
103
98
104
current = value ;
105
+ cycleLength ++ ;
99
106
return true ;
100
107
}
101
108
@@ -242,6 +249,8 @@ public void Reset(uint startSectorId)
242
249
index = uint . MaxValue ;
243
250
current = uint . MaxValue ;
244
251
slow = uint . MaxValue ;
252
+ cycleLength = 1 ;
253
+ power = 1 ;
245
254
}
246
255
247
256
[ ExcludeFromCodeCoverage ]