@@ -15,7 +15,11 @@ internal sealed class MiniFatChainEnumerator : ContextBase, IEnumerator<uint>
15
15
uint index = uint . MaxValue ;
16
16
private uint current = uint . MaxValue ;
17
17
private long length = - 1 ;
18
- private uint slow = uint . MaxValue ; // Floyd's cycle-finding algorithm
18
+
19
+ // Brent's cycle-finding algorithm
20
+ private uint cycleLength = 1 ;
21
+ private uint power = 1 ;
22
+ private uint slow = uint . MaxValue ;
19
23
20
24
public MiniFatChainEnumerator ( RootContextSite rootContextSite , uint startSectorId )
21
25
: base ( rootContextSite )
@@ -66,23 +70,27 @@ public bool MoveNext()
66
70
{
67
71
index = uint . MaxValue ;
68
72
current = uint . MaxValue ;
73
+ slow = uint . MaxValue ;
69
74
return false ;
70
75
}
71
76
72
77
uint nextIndex = index + 1 ;
73
78
if ( nextIndex > SectorType . Maximum )
74
79
throw new FileFormatException ( "Mini FAT chain length is greater than the maximum." ) ;
75
80
76
- if ( nextIndex % 2 == 0 && ! SectorType . IsFreeOrEndOfChain ( slow ) )
81
+ if ( value == slow )
82
+ throw new FileFormatException ( "Mini FAT chain contains a loop." ) ;
83
+
84
+ if ( cycleLength == power )
77
85
{
78
- // Slow might become free or end of chain while shrinking
79
- slow = Context . MiniFat [ slow ] ;
80
- if ( slow == value )
81
- throw new FileFormatException ( "Mini FAT chain contains a loop." ) ;
86
+ cycleLength = 0 ;
87
+ power *= 2 ;
88
+ slow = value ;
82
89
}
83
90
84
91
index = nextIndex ;
85
92
current = value ;
93
+ cycleLength ++ ;
86
94
return true ;
87
95
}
88
96
@@ -213,6 +221,8 @@ public void Reset()
213
221
index = uint . MaxValue ;
214
222
current = uint . MaxValue ;
215
223
slow = uint . MaxValue ;
224
+ cycleLength = 1 ;
225
+ power = 1 ;
216
226
}
217
227
218
228
[ ExcludeFromCodeCoverage ]