in packages/core/micro/src/adjust-tree/delete.ts [97:206]
function partitionNode<T>(ctx: TreeContext<T>, node: InteriorNode<T>, startOffset: number, startIndex: number, endOffset: number, endIndex: number): Deletion<T> {
assert("startIndex < endIndex", startIndex < endIndex);
const { lengths, segments, size } = node;
let leftSplitState = startOffset === 0 ? undefined : startIndex;
let rightSplitState = endOffset === 0 ? undefined : endIndex;
const firstSplit: Deletion<T> = startOffset === 0 ?
{ orphan: undefined, deleted: leftmostLeaf(segments[startIndex]) }
: splitChildL(ctx, node, startIndex, startOffset);
if (startOffset !== 0) {
lengths[startIndex] = startOffset;
}
const secondSplit: Deletion<T> | undefined = endOffset === 0 ?
endIndex === size
? undefined
: { orphan: undefined, deleted: leftmostLeaf(segments[endIndex]).prev! }
: splitChildR(ctx, node, endIndex, endOffset);
if (endOffset !== 0) {
lengths[endIndex] -= endOffset;
}
const firstDeletedLeaf = firstSplit.deleted;
const firstRetainedLeaf = firstDeletedLeaf.prev;
const lastDeletedLeaf = secondSplit ? secondSplit.deleted : undefined;
const lastRetainedLeaf = lastDeletedLeaf ? lastDeletedLeaf.next : undefined;
if (firstRetainedLeaf) {
firstRetainedLeaf.next = lastRetainedLeaf;
}
if (lastRetainedLeaf) {
lastRetainedLeaf.prev = firstRetainedLeaf;
}
if (lastDeletedLeaf) {
lastDeletedLeaf.next = undefined;
}
firstDeletedLeaf.prev = undefined;
const wholeStartIndex = startOffset === 0 ? startIndex : startIndex + 1;
const toRemove = endIndex - wholeStartIndex;
if (toRemove > 0) {
deleteNodeRange(node, wholeStartIndex, toRemove, undefined!)
rightSplitState = rightSplitState === undefined ? undefined : rightSplitState - toRemove;
endIndex -= toRemove;
}
let remainingOrphan: Orphan<T> | undefined;
let remainingOrphanIndex: number | undefined;
if (firstSplit.orphan && secondSplit && secondSplit.orphan) {
leftSplitState = undefined;
rightSplitState = undefined;
[remainingOrphanIndex, remainingOrphan] =
mergeOrphans(ctx, node, startIndex, firstSplit.orphan, endIndex, secondSplit.orphan);
}
else if (firstSplit.orphan) {
remainingOrphan = firstSplit.orphan;
remainingOrphanIndex = startIndex;
leftSplitState = undefined;
}
else if (secondSplit && secondSplit.orphan) {
remainingOrphan = secondSplit.orphan;
remainingOrphanIndex = endIndex;
rightSplitState = undefined;
}
if (remainingOrphan) {
assert("remainingOrphanIndex is defined when orphan is", remainingOrphanIndex !== undefined);
if (node.size === 1) {
return remainingOrphan.heightDelta++, { orphan: remainingOrphan, deleted: firstDeletedLeaf };
}
deleteNodeRange(node, remainingOrphanIndex, 1, undefined!);
if (leftSplitState !== undefined && leftSplitState > remainingOrphanIndex) { leftSplitState--; }
if (rightSplitState !== undefined && rightSplitState > remainingOrphanIndex) { rightSplitState--; }
const size = node.size;
if (remainingOrphanIndex === 0) {
applyInsertion(ctx, node, 0, remainingOrphan.length, reparent(ctx, node.segments[0], remainingOrphan, /* before */ true));
const adjustment = node.size - size;
if (leftSplitState !== undefined) { leftSplitState + adjustment; }
if (rightSplitState !== undefined) { rightSplitState + adjustment; }
}
else {
const idx = remainingOrphanIndex - 1;
applyInsertion(ctx, node, idx, remainingOrphan.length, reparent(ctx, node.segments[idx], remainingOrphan, /* before */ false));
const adjustment = node.size - size;
if (leftSplitState !== undefined && leftSplitState > idx) { leftSplitState + adjustment; }
if (rightSplitState !== undefined && rightSplitState > idx) { rightSplitState + adjustment; }
}
}
let o1: Orphan<T> | undefined;
let o2: Orphan<T> | undefined;
if (leftSplitState !== undefined) {
const size = node.size;
o1 = ensureBalancedChildInNode(ctx, node, leftSplitState);
if (size !== node.size) {
rightSplitState = rightSplitState === undefined ? undefined : rightSplitState - 1;
}
}
if (rightSplitState !== undefined) {
o2 = ensureBalancedChildInNode(ctx, node, rightSplitState);
}
return { orphan: o1 || o2, deleted: firstDeletedLeaf };
}