1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2023 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
extension Rope {
@inlinable
public mutating func prepend(_ item: __owned Element) {
_invalidateIndices()
insert(item, at: startIndex)
}
@inlinable
public mutating func insert(
_ item: __owned Element,
at index: Index
) {
validate(index)
insert(item, at: index._path)
}
@inlinable
mutating func insert(
_ item: __owned Element,
at path: _Path
) {
if path == _endPath {
append(item)
return
}
if let spawn = root.insert(_Item(item), at: path) {
_root = .createInner(children: root, spawn)
}
_invalidateIndices()
}
@inlinable
public mutating func insert(
_ item: __owned Element,
at position: Int,
in metric: some RopeMetric<Element>
) {
if position == metric.size(of: summary) {
append(item)
return
}
if let spawn = root.insert(_Item(item), at: position, in: metric) {
_root = .createInner(children: root, spawn)
}
_invalidateIndices()
}
}
extension Rope._Node {
@inlinable
internal mutating func prepend(_ item: __owned _Item) -> Self? {
insert(item, at: _startPath)
}
@inlinable
internal mutating func insert(
_ item: __owned _Item,
at path: _Path
) -> Self? {
ensureUnique()
let h = height
let slot = path[h]
if h > 0 {
precondition(slot < childCount, "Index out of bounds")
return _innerInsert(at: slot) { $0.insert(item, at: path) }
}
precondition(slot <= childCount, "Index out of bounds")
return _leafInsert(item, at: slot)
}
@inlinable
internal mutating func insert(
_ item: __owned _Item,
at position: Int,
in metric: some RopeMetric<Element>
) -> Self? {
ensureUnique()
if height > 0 {
let (slot, remaining) = readInner {
$0.findSlot(at: position, in: metric, preferEnd: false)
}
return _innerInsert(at: slot) { $0.insert(item, at: remaining, in: metric) }
}
let (slot, remaining) = readLeaf {
$0.findSlot(at: position, in: metric, preferEnd: false)
}
precondition(remaining == 0, "Inserted element doesn't fall on an element boundary")
return _leafInsert(item, at: slot)
}
}
extension Rope._Node {
@inlinable
internal mutating func _innerInsert(
at slot: Int,
with body: (inout Self) -> Self?
) -> Self? {
assert(slot < childCount)
var summary = self.summary
let spawn = updateInner {
let p = $0.mutableChildPtr(at: slot)
summary.subtract(p.pointee.summary)
let spawn = body(&p.pointee)
summary.add(p.pointee.summary)
return spawn
}
self.summary = summary
guard let spawn = spawn else { return nil }
return _applySpawn(spawn, of: slot)
}
@inlinable
internal mutating func _applySpawn(
_ spawn: __owned Self, of slot: Int
) -> Self? {
var spawn = spawn
var nextSlot = slot + 1
#if true // Compress existing nodes if possible.
if slot > 0 {
// Try merging remainder into previous child.
updateInner {
let c = $0.mutableChildren
let s = c[slot - 1].childCount + c[slot].childCount
guard s <= Summary.maxNodeSize else { return }
Self.redistributeChildren(&c[slot - 1], &c[slot], to: s)
let removed = $0._removeChild(at: slot)
assert(removed.childCount == 0)
nextSlot -= 1
}
}
if nextSlot < childCount {
// Try merging new spawn into subsequent child.
let merged: Summary? = updateInner {
let c = $0.mutableChildren
let s = spawn.childCount + c[nextSlot].childCount
guard s <= Summary.maxNodeSize else { return nil }
let summary = spawn.summary
Self.redistributeChildren(&spawn, &c[nextSlot], to: 0)
assert(spawn.childCount == 0)
return summary
}
if let merged = merged {
self.summary.add(merged)
return nil
}
}
#endif
guard isFull else {
_insertNode(spawn, at: nextSlot)
return nil
}
if nextSlot < Summary.minNodeSize {
let spawn2 = split(keeping: childCount / 2)
_insertNode(spawn, at: nextSlot)
return spawn2
}
var spawn2 = split(keeping: childCount / 2)
spawn2._insertNode(spawn, at: nextSlot - childCount)
return spawn2
}
}
extension Rope._Node {
@inlinable
internal mutating func _leafInsert(
_ item: __owned _Item, at slot: Int
) -> Self? {
assert(slot <= childCount)
var item = item
if item.isUndersized, childCount > 0, _rebalanceBeforeInsert(&item, at: slot) {
return nil
}
guard isFull else {
_insertItem(item, at: slot)
return nil
}
if slot < Summary.minNodeSize {
let spawn = split(keeping: childCount - Summary.minNodeSize)
_insertItem(item, at: slot)
return spawn
}
var spawn = split(keeping: Summary.minNodeSize)
spawn._insertItem(item, at: slot - childCount)
return spawn
}
@inlinable
internal mutating func _rebalanceBeforeInsert(
_ item: inout _Item, at slot: Int
) -> Bool {
assert(item.isUndersized)
let r = updateLeaf { (h) -> (merged: Bool, delta: Summary) in
if slot > 0 {
let p = h.mutableChildPtr(at: slot - 1)
let sum = p.pointee.summary
let merged = p.pointee.rebalance(nextNeighbor: &item)
let delta = p.pointee.summary.subtracting(sum)
return (merged, delta)
}
let p = h.mutableChildPtr(at: slot)
let sum = p.pointee.summary
let merged = p.pointee.rebalance(prevNeighbor: &item)
let delta = p.pointee.summary.subtracting(sum)
return (merged, delta)
}
self.summary.add(r.delta)
return r.merged
}
}
|