Skip to content

Commit

Permalink
Use Floyd's algorithm for FAT cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-visionaid committed Nov 20, 2024
1 parent aa1c1ea commit 3eb5d2d
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 22 deletions.
26 changes: 10 additions & 16 deletions OpenMcdf/FatChainEnumerator.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;

namespace OpenMcdf;

Expand All @@ -12,12 +11,12 @@ internal sealed class FatChainEnumerator : IEnumerator<uint>
{
private readonly Fat fat;
private readonly FatEnumerator fatEnumerator;
readonly HashSet<uint> 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)
{
Expand Down Expand Up @@ -65,7 +64,7 @@ public bool MoveNext()
index = 0;
current = startId;
start = false;
visited.Add(current);
slow = startId;
return true;
}

Expand All @@ -80,26 +79,22 @@ public bool MoveNext()
return false;
}

index++;
if (index >= fat.Context.SectorCount)
uint nextSlow = fat[slow];
if (slow != startId)
{
// 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 (slow == value)
throw new FileFormatException("FAT chain contains a loop.");
}
slow = nextSlow;

if (visited.Contains(value))
index++;
if (index >= fat.Context.SectorCount)
{
// 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.");
throw new FileFormatException("FAT chain index is greater than the sector count.");
}

if (BitOperations.IsPow2(index))
visited.Add(value);

current = value;
return true;
}
Expand Down Expand Up @@ -246,7 +241,6 @@ public void Reset(uint startSectorId)
start = true;
index = uint.MaxValue;
current = uint.MaxValue;
visited.Clear();
}

[ExcludeFromCodeCoverage]
Expand Down
6 changes: 0 additions & 6 deletions OpenMcdf/System/BitOperations.cs

This file was deleted.

0 comments on commit 3eb5d2d

Please sign in to comment.