diff --git a/OpenMcdf/FatChainEnumerator.cs b/OpenMcdf/FatChainEnumerator.cs index 32b2ea3a..e950155b 100644 --- a/OpenMcdf/FatChainEnumerator.cs +++ b/OpenMcdf/FatChainEnumerator.cs @@ -1,7 +1,6 @@ using System.Collections; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Numerics; namespace OpenMcdf; @@ -12,12 +11,12 @@ internal sealed class FatChainEnumerator : IEnumerator { private readonly Fat fat; private readonly FatEnumerator fatEnumerator; - readonly HashSet visited = new(); private uint startId; private bool start = true; private uint index = uint.MaxValue; private uint current = uint.MaxValue; private long length = -1; + private uint slow = uint.MaxValue; // Floyd's cycle-finding algorithm public FatChainEnumerator(Fat fat, uint startSectorId) { @@ -65,7 +64,7 @@ public bool MoveNext() index = 0; current = startId; start = false; - visited.Add(current); + slow = startId; return true; } @@ -83,23 +82,19 @@ public bool MoveNext() index++; if (index >= fat.Context.SectorCount) { - // If the index is greater than the maximum, then the chain must contain a loop index = uint.MaxValue; current = uint.MaxValue; throw new FileFormatException("FAT chain index is greater than the sector count."); } - if (visited.Contains(value)) + if (index % 2 == 0 && !SectorType.IsFreeOrEndOfChain(slow)) { - // If the sector has already been visited, then the chain must contain a loop - index = uint.MaxValue; - current = uint.MaxValue; - throw new FileFormatException("FAT chain contains a loop."); + // Slow might become free or end of chain while shrinking + slow = fat[slow]; + if (slow == value) + throw new FileFormatException("FAT chain contains a loop."); } - if (BitOperations.IsPow2(index)) - visited.Add(value); - current = value; return true; } @@ -246,7 +241,7 @@ public void Reset(uint startSectorId) start = true; index = uint.MaxValue; current = uint.MaxValue; - visited.Clear(); + slow = uint.MaxValue; } [ExcludeFromCodeCoverage] diff --git a/OpenMcdf/System/BitOperations.cs b/OpenMcdf/System/BitOperations.cs deleted file mode 100644 index fc20bb41..00000000 --- a/OpenMcdf/System/BitOperations.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace System.Numerics; - -internal static class BitOperations -{ - public static bool IsPow2(uint value) => (value & (value - 1)) == 0 && value != 0; -}