public bool MoveNext() { AllocationTableEntry currentEntry = Fat.Entries[PhysicalBlock + 1]; if (currentEntry.IsListEnd()) { return(false); } int newBlock = currentEntry.Next & 0x7FFFFFFF; AllocationTableEntry newEntry = Fat.Entries[newBlock]; VirtualBlock += CurrentSegmentSize; if (newEntry.IsSingleBlockSegment()) { CurrentSegmentSize = 1; } else { AllocationTableEntry lengthEntry = Fat.Entries[newBlock + 1]; CurrentSegmentSize = lengthEntry.Next - (newBlock - 1); } PhysicalBlock = newBlock - 1; return(true); }
/// <summary> /// Splits a single list segment into 2 segments. The sequence of blocks in the full list will remain the same. /// </summary> /// <param name="segmentBlockIndex">The block index of the segment to split.</param> /// <param name="firstSubSegmentLength">The length of the first subsegment.</param> public void Split(int segmentBlockIndex, int firstSubSegmentLength) { Debug.Assert(firstSubSegmentLength > 0); int segAIndex = BlockToEntryIndex(segmentBlockIndex); AllocationTableEntry segA = ReadEntry(segAIndex); if (!segA.IsMultiBlockSegment()) { throw new ArgumentException("Cannot split a single-entry segment."); } AllocationTableEntry segARange = ReadEntry(segAIndex + 1); int originalLength = segARange.GetNext() - segARange.GetPrev() + 1; if (firstSubSegmentLength >= originalLength) { throw new ArgumentOutOfRangeException(nameof(firstSubSegmentLength), $"Requested sub-segment length ({firstSubSegmentLength}) must be less than the full segment length ({originalLength})"); } int segBIndex = segAIndex + firstSubSegmentLength; int segALength = firstSubSegmentLength; int segBLength = originalLength - segALength; var segB = new AllocationTableEntry(); // Insert segment B between segments A and C segB.SetPrev(segAIndex); segB.SetNext(segA.GetNext()); segA.SetNext(segBIndex); if (!segB.IsListEnd()) { AllocationTableEntry segC = ReadEntry(segB.GetNext()); segC.SetPrev(segBIndex); WriteEntry(segB.GetNext(), segC); } // Write the new range entries if needed if (segBLength > 1) { segB.MakeMultiBlockSegment(); var segBRange = new AllocationTableEntry(); segBRange.SetRange(segBIndex, segBIndex + segBLength - 1); WriteEntry(segBIndex + 1, segBRange); WriteEntry(segBIndex + segBLength - 1, segBRange); } WriteEntry(segBIndex, segB); if (segALength == 1) { segA.MakeSingleBlockSegment(); } else { segARange.SetRange(segAIndex, segAIndex + segALength - 1); WriteEntry(segAIndex + 1, segARange); WriteEntry(segAIndex + segALength - 1, segARange); } WriteEntry(segAIndex, segA); }