コード例 #1
0
ファイル: AllocationTable.cs プロジェクト: gabest11/nsZip
        public int GetFreeListEntryIndex()
        {
            AllocationTableEntry freeList = ReadEntry(FreeListEntryIndex);

            return(freeList.GetNext());
        }
コード例 #2
0
ファイル: AllocationTable.cs プロジェクト: gabest11/nsZip
        /// <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);
        }