Пример #1
0
        /// <summary>
        /// Combines 2 lists into one list. The second list will be attached to the end of the first list.
        /// </summary>
        /// <param name="frontListBlockIndex">The index of the start block of the first list.</param>
        /// <param name="backListBlockIndex">The index of the start block of the second list.</param>
        public void Join(int frontListBlockIndex, int backListBlockIndex)
        {
            int frontEntryIndex = BlockToEntryIndex(frontListBlockIndex);
            int backEntryIndex  = BlockToEntryIndex(backListBlockIndex);

            int frontTailIndex = GetListTail(frontEntryIndex);

            AllocationTableEntry frontTail = ReadEntry(frontTailIndex);
            AllocationTableEntry backHead  = ReadEntry(backEntryIndex);

            frontTail.SetNext(backEntryIndex);
            backHead.SetPrev(frontTailIndex);

            WriteEntry(frontTailIndex, frontTail);
            WriteEntry(backEntryIndex, backHead);
        }
Пример #2
0
        /// <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);
        }