def _create_branch_node(self, path_a, value_a, path_b, value_b): """ Creates a branch node with up to two leaves and maybe value. Returns a reference to created node. """ assert len(path_a) != 0 or len(path_b) != 0 branches = [b''] * 16 branch_value = b'' if len(path_a) == 0: branch_value = value_a elif len(path_b) == 0: branch_value = value_b self._create_branch_leaf(path_a, value_a, branches) self._create_branch_leaf(path_b, value_b, branches) return self._store_node(Node.Branch(branches, branch_value))
def _update(self, node_ref, path, value): """ Update support method """ if not node_ref: return self._store_node(Node.Leaf(path, value)) node = self._get_node(node_ref) if type(node) == Node.Leaf: # If we're updating the leaf there are 2 possible ways: # 1. Path is equals to the rest of the key. Then we should just update value of this leaf. # 2. Path differs. Then we should split this node into several nodes. if node.path == path: # Path is the same. Just change the value. node.data = value return self._store_node(node) # If we are here, we have to split the node. # Find the common part of the key and leaf's path. common_prefix = path.common_prefix(node.path) # Cut off the common part. path.consume(len(common_prefix)) node.path.consume(len(common_prefix)) # Create branch node to split paths. branch_reference = self._create_branch_node( path, value, node.path, node.data) # If common part isn't empty, we have to create an extension node before branch node. # Otherwise, we need just branch node. if len(common_prefix) != 0: return self._store_node( Node.Extension(common_prefix, branch_reference)) else: return branch_reference elif type(node) == Node.Extension: # If we're updating an extenstion there are 2 possible ways: # 1. Key starts with the extension node's path. Then we just go ahead and all the work will be done there. # 2. Key doesn't start with extension node's path. Then we have to split extension node. if path.starts_with(node.path): # Just go ahead. new_reference = self._update(node.next_ref, path.consume(len(node.path)), value) return self._store_node( Node.Extension(node.path, new_reference)) # Split extension node. # Find the common part of the key and extension's path. common_prefix = path.common_prefix(node.path) # Cut off the common part. path.consume(len(common_prefix)) node.path.consume(len(common_prefix)) # Create an empty branch node. It may have or have not the value depending on the length # of the rest of the key. branches = [b''] * 16 branch_value = value if len(path) == 0 else b'' # If needed, create leaf branch for the value we're inserting. self._create_branch_leaf(path, value, branches) # If needed, create an extension node for the rest of the extension's path. self._create_branch_extension(node.path, node.next_ref, branches) branch_reference = self._store_node( Node.Branch(branches, branch_value)) # If common part isn't empty, we have to create an extension node before branch node. # Otherwise, we need just branch node. if len(common_prefix) != 0: return self._store_node( Node.Extension(common_prefix, branch_reference)) else: return branch_reference elif type(node) == Node.Branch: # For branch node things are easy. # 1. If key is empty, just store value in this node. # 2. If key isn't empty, just call `_update` with appropiate branch reference. if len(path) == 0: return self._store_node(Node.Branch(node.branches, value)) idx = path.at(0) new_reference = self._update(node.branches[idx], path.consume(1), value) node.branches[idx] = new_reference return self._store_node(node)