Skip to content

Commit

Permalink
Use getters in Node16
Browse files Browse the repository at this point in the history
  • Loading branch information
vishesh committed Aug 25, 2023
1 parent 976f6f3 commit 58b664a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 125 deletions.
19 changes: 9 additions & 10 deletions Sources/ARTreeModule/Node+StringConverter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,15 @@ extension Node16: NodePrettyPrinter {
func prettyPrint(depth: Int) -> String {
let addr = Const.testPrintAddr ? " \(_addressString(for: self.rawNode.buf))" : " "
var output = "Node16\(addr){childs=\(count), partial=\(partial)}\n"
withBody { keys, childs in
for idx in 0..<count {
let key = keys[idx]
let last = idx == count - 1
output += indent(depth, last: last)
output += String(key) + ": "
output += child(at: idx)!.prettyPrint(depth: depth + 1, with: Spec.self)
if !last {
output += "\n"
}

for idx in 0..<count {
let key = keys[idx]
let last = idx == count - 1
output += indent(depth, last: last)
output += String(key) + ": "
output += child(at: idx)!.prettyPrint(depth: depth + 1, with: Spec.self)
if !last {
output += "\n"
}
}

Expand Down
167 changes: 61 additions & 106 deletions Sources/ARTreeModule/Node16.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ extension Node16 {
let storage = NodeStorage<Self>.allocate()

storage.update { node in
node.withBody { keys, childs in
UnsafeMutableRawPointer(keys.baseAddress!)
.bindMemory(to: UInt8.self, capacity: Self.numKeys)
UnsafeMutableRawPointer(childs.baseAddress!)
.bindMemory(to: RawNode?.self, capacity: Self.numKeys)
}
UnsafeMutableRawPointer(node.keys.baseAddress!)
.bindMemory(to: UInt8.self, capacity: Self.numKeys)
UnsafeMutableRawPointer(node.childs.baseAddress!)
.bindMemory(to: RawNode?.self, capacity: Self.numKeys)
}

return storage
Expand All @@ -56,14 +54,12 @@ extension Node16 {
static func allocate(copyFrom: Node4<Spec>) -> NodeStorage<Self> {
let storage = Self.allocate()

storage.update { node in
node.copyHeader(from: copyFrom)
node.withBody { newKeys, newChilds in
UnsafeMutableRawBufferPointer(newKeys).copyBytes(from: copyFrom.keys)
UnsafeMutableRawBufferPointer(newChilds).copyBytes(
from: UnsafeMutableRawBufferPointer(copyFrom.childs))
Self.retainChildren(newChilds, count: node.count)
}
storage.update { newNode in
newNode.copyHeader(from: copyFrom)
UnsafeMutableRawBufferPointer(newNode.keys).copyBytes(from: copyFrom.keys)
UnsafeMutableRawBufferPointer(newNode.childs).copyBytes(
from: UnsafeMutableRawBufferPointer(copyFrom.childs))
Self.retainChildren(newNode.childs, count: newNode.count)
}

return storage
Expand All @@ -72,69 +68,44 @@ extension Node16 {
static func allocate(copyFrom: Node48<Spec>) -> NodeStorage<Self> {
let storage = NodeStorage<Self>.allocate()

storage.update { node in
node.copyHeader(from: copyFrom)
storage.update { newNode in
newNode.copyHeader(from: copyFrom)
copyFrom.withBody { fromKeys, fromChilds in
node.withBody { newKeys, newChilds in
var slot = 0
for key: UInt8 in 0...255 {
let childPosition = Int(fromKeys[Int(key)])
if childPosition == 0xFF {
continue
}

newKeys[slot] = key
newChilds[slot] = fromChilds[childPosition]
slot += 1
var slot = 0
for key: UInt8 in 0...255 {
let childPosition = Int(fromKeys[Int(key)])
if childPosition == 0xFF {
continue
}

assert(slot == node.count)
Self.retainChildren(newChilds, count: node.count)
newNode.keys[slot] = key
newNode.childs[slot] = fromChilds[childPosition]
slot += 1
}

assert(slot == newNode.count)
Self.retainChildren(newNode.childs, count: newNode.count)
}
}

return storage
}
}

extension Node16 {
typealias Keys = UnsafeMutableBufferPointer<KeyPart>
typealias Children = UnsafeMutableBufferPointer<RawNode?>

func withBody<R>(body: (Keys, Children) throws -> R) rethrows -> R {
return try storage.withBodyPointer { bodyPtr in
let keys = UnsafeMutableBufferPointer(
start: bodyPtr.assumingMemoryBound(to: KeyPart.self),
count: Self.numKeys
)
let childPtr =
bodyPtr
.advanced(by: Self.numKeys * MemoryLayout<KeyPart>.stride)
.assumingMemoryBound(to: RawNode?.self)
let childs = UnsafeMutableBufferPointer(start: childPtr, count: Self.numKeys)

return try body(keys, childs)
}
}
}

extension Node16: InternalNode {
static var size: Int {
MemoryLayout<InternalNodeHeader>.stride + Self.numKeys
* (MemoryLayout<KeyPart>.stride + MemoryLayout<RawNode?>.stride)
}

func index(forKey k: KeyPart) -> Index? {
return withBody { keys, _ in
for (index, key) in keys.enumerated() {
if key == k {
return index
}
for (index, key) in keys.enumerated() {
if key == k {
return index
}

return nil
}

return nil
}

func index() -> Index? {
Expand All @@ -152,34 +123,28 @@ extension Node16: InternalNode {
return nil
}

return withBody { keys, _ in
for idx in 0..<count {
if keys[idx] >= Int(k) {
return idx
}
for idx in 0..<count {
if keys[idx] >= Int(k) {
return idx
}

return count
}

return count
}

func child(at: Index) -> RawNode? {
assert(at < Self.numKeys, "maximum \(Self.numKeys) childs allowed")
return withBody { _, childs in
return childs[at]
}
return childs[at]
}

mutating func addChild(forKey k: KeyPart, node: RawNode) -> UpdateResult<RawNode?> {
if let slot = _insertSlot(forKey: k) {
withBody { keys, childs in
assert(count == 0 || keys[slot] != k, "node for key \(k) already exists")
keys.shiftRight(startIndex: slot, endIndex: count - 1, by: 1)
childs.shiftRight(startIndex: slot, endIndex: count - 1, by: 1)
keys[slot] = k
childs[slot] = node
count += 1
}
assert(count == 0 || keys[slot] != k, "node for key \(k) already exists")
keys.shiftRight(startIndex: slot, endIndex: count - 1, by: 1)
childs.shiftRight(startIndex: slot, endIndex: count - 1, by: 1)
keys[slot] = k
childs[slot] = node
count += 1
return .noop
} else {
return Node48.allocate(copyFrom: self).update { newNode in
Expand All @@ -193,42 +158,36 @@ extension Node16: InternalNode {
assert(index < Self.numKeys, "index can't >= 16 in Node16")
assert(index < count, "not enough childs in node")

return withBody { keys, childs in
keys[index] = 0
childs[index] = nil

count -= 1
keys.shiftLeft(startIndex: index + 1, endIndex: count, by: 1)
childs.shiftLeft(startIndex: index + 1, endIndex: count, by: 1)
childs[count] = nil // Clear the last item.
keys[index] = 0
childs[index] = nil

if count == 3 {
// Shrink to Node4.
let newNode = Node4.allocate(copyFrom: self)
return .replaceWith(newNode.node.rawNode)
}
count -= 1
keys.shiftLeft(startIndex: index + 1, endIndex: count, by: 1)
childs.shiftLeft(startIndex: index + 1, endIndex: count, by: 1)
childs[count] = nil // Clear the last item.

return .noop
if count == 3 {
// Shrink to Node4.
let newNode = Node4.allocate(copyFrom: self)
return .replaceWith(newNode.node.rawNode)
}

return .noop
}

mutating func withChildRef<R>(at index: Index, _ body: (RawNode.SlotRef) -> R) -> R {
assert(index < count, "not enough childs in node")
return withBody { _, childs in
let ref = childs.baseAddress! + index
return body(ref)
}
let ref = childs.baseAddress! + index
return body(ref)
}
}

extension Node16: ArtNode {
final class Buffer: RawNodeBuffer {
deinit {
var node = Node16(buffer: self)
node.withBody { _, childs in
for idx in 0..<16 {
childs[idx] = nil
}
for idx in 0..<16 {
node.childs[idx] = nil
}
node.count = 0
}
Expand All @@ -237,15 +196,11 @@ extension Node16: ArtNode {
func clone() -> NodeStorage<Self> {
let storage = Self.allocate()

storage.update { node in
node.copyHeader(from: self)
self.withBody { fromKeys, fromChildren in
node.withBody { newKeys, newChildren in
for idx in 0..<Self.numKeys {
newKeys[idx] = fromKeys[idx]
newChildren[idx] = fromChildren[idx]
}
}
storage.update { newNode in
newNode.copyHeader(from: self)
for idx in 0..<Self.numKeys {
newNode.keys[idx] = self.keys[idx]
newNode.childs[idx] = self.childs[idx]
}
}

Expand Down
16 changes: 7 additions & 9 deletions Sources/ARTreeModule/Node48.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,14 @@ extension Node48 {

storage.update { node in
node.copyHeader(from: copyFrom)
copyFrom.withBody { fromKeys, fromChilds in
node.withBody { newKeys, newChilds in
UnsafeMutableRawBufferPointer(newChilds).copyBytes(
from: UnsafeMutableRawBufferPointer(fromChilds))
for (idx, key) in fromKeys.enumerated() {
newKeys[Int(key)] = UInt8(idx)
}

Self.retainChildren(newChilds, count: node.count)
node.withBody { newKeys, newChilds in
UnsafeMutableRawBufferPointer(newChilds).copyBytes(
from: UnsafeMutableRawBufferPointer(copyFrom.childs))
for (idx, key) in copyFrom.keys.enumerated() {
newKeys[Int(key)] = UInt8(idx)
}

Self.retainChildren(newChilds, count: node.count)
}
}

Expand Down

0 comments on commit 58b664a

Please sign in to comment.