/** * Add new child node after given node */ static Node *_build_node(Node *node, unsigned char *string, unsigned short length) { Node *next_node; if (length >= 1) { Node new_node; _node_init(&new_node, (BMapNode){(BMap){NULL, 0}}, NULL); _node_array_init(&new_node); //TODO: If key length <= sizeof(ptr) don't malloc, // Just turn pointer into a union and store the array inline. if(length > 1) { _node_set_array(&new_node, length-1); memcpy(new_node.array, string+1, length-1); } Result(BMapEntryNodePtr) result = bmap_node_insert(&node->children, string[0], new_node); if(TypeOf(result) == Type(Result, Ok)) { next_node = &result.data->node; } trace_node("BUILD-NODE", next_node); } else { next_node = node; trace_node("REUSE-NODE", next_node); } return next_node; }
void rtree_remove(RTree *tree, unsigned char *string, unsigned short length) { trace("RTREE-REMOVE(%p)", &tree->root); Scan scan; _scan_init(&scan, string, length, &tree->root, S_DEFAULT); Node * node = _tree_seek(&tree->root, &scan); trace_node("ROOT", &tree->root); trace_node("NODE", node); trace("STATUS %i, %i, %p", scan.index, length, node->data); if(scan.found == 1 && node->data) { node->data = NULL; _pluck_node(node, &scan); } }
PB_DS_CLASS_T_DEC void PB_DS_CLASS_C_DEC:: trace() const { std::cerr << std::endl; trace_node(m_p_root, 0); std::cerr << std::endl; }
PB_DS_CLASS_T_DEC void PB_DS_CLASS_C_DEC:: trace() const { std::cerr << std::endl; if (m_p_head->m_p_parent == NULL) return; trace_node(m_p_head->m_p_parent, 0); std::cerr << std::endl; }
/** * create split array node in two using a tree node * TODO: Verify tests manage all cases. */ static Node * _split_node_array(Node *node, Scan *scan) { unsigned subindex = scan->subindex; Node *data_node; Node old = *node; unsigned char *old_suffix = old.array+subindex; unsigned char *new_suffix = scan->key + scan->index; unsigned int old_suffix_size = old.size - subindex; unsigned int new_suffix_size = scan->size - scan->index; if (new_suffix_size == 0) { //No new suffix, we add data to current node _node_init(node, (BMapNode){(BMap){NULL, 0}}, NULL); data_node = node; //After the data node we append the old suffix Node *branch = _build_node(node, old_suffix, old_suffix_size); _node_init(branch, old.children, old.data); } else { //make node point to new tree node _node_init(node, (BMapNode){(BMap){NULL, 0}}, NULL); //add branch to hold old suffix and delete old data Node *branch1 = _build_node(node, old_suffix, old_suffix_size); _node_init(branch1, old.children, old.data); trace_node("OLD-BRANCH", branch1); //add branch to hold new suffix and return new node Node *branch2 = _build_node(node, new_suffix, new_suffix_size); data_node = branch2; } _node_set_array(node, subindex); trace_node("PREFIX", node); return data_node; }
/** * Remove dangling node and compact tree */ static void _pluck_node(Node *node, Scan *scan) { Node *previous = scan->previous; trace_node("CLEAN", node); if(bmap_node_count(&node->children) == 0 && previous) { trace_node("PREVIOUS", previous); if(node->array) { free(node->array); set_null(node->array); } char bkey = scan->key[scan->index - scan->subindex - 1]; bmap_node_delete(&previous->children, bkey); if(previous != scan->root) { _compact_nodes(previous); } } else { _compact_nodes(node); } }
static void _node_dispose(Node *node) { trace_node("DISPOSE", node); if(node->array) { free(node->array); set_null(node->array); } BMapCursorNode cur; bmap_cursor_node_init(&cur, &node->children); while(bmap_cursor_node_next(&cur)) { BMapEntryNode *entry = bmap_cursor_node_current(&cur); _node_dispose(&entry->node); } bmap_cursor_node_dispose(&cur); bmap_node_dispose(&node->children); }
/** * Seek the node for the given key either for setting or getting a value * If the key is not found it returns the closest matching node. */ static Node *_tree_seek(Node *tree, Scan *scan) { Node *current = tree; //Move to the next node within the tree BMapEntryNode *entry = bmap_node_get(¤t->children, scan->key[scan->index]); //Break if there is no node to move to if(entry == NULL) { scan->found = -1; return current; } current = &entry->node; scan->index++; trace_node("SEEK-ARRAY", current); int j = 0; unsigned int i = scan->index; for (; j < current->size && i < scan->size; j++, i++) { //Break if a character does not match trace("[%c-%c]", current->array[j], scan->key[i]); if(current->array[j] != scan->key[i]) { scan->subindex = j; scan->index = i; scan->found = -1; return current; } } scan->subindex = j; scan->index = i; //Break if it didn't match the whole array if(j < current->size) { scan->found = -1; return current; } scan->previous = tree; if(scan->index == scan->size) { scan->found = 1; return current; } return _tree_seek(current, scan); }
PB_DS_CLASS_T_DEC void PB_DS_CLASS_C_DEC:: trace_node(const_node_pointer p_nd, size_type level) { for (size_type i = 0; i < level; ++i) std::cerr << ' '; std::cerr << p_nd << " "; std::cerr << ((p_nd->m_type == pat_trie_leaf_node_type) ? "l " : "i "); trace_node_metadata(p_nd, type_to_type<typename node::metadata_type>()); typename e_access_traits::const_iterator el_it = pref_begin(p_nd); while (el_it != pref_end(p_nd)) { std::cerr <<* el_it; ++el_it; } if (p_nd->m_type == pat_trie_leaf_node_type) { std::cerr << std::endl; return; } const_internal_node_pointer p_internal = static_cast<const_internal_node_pointer>(p_nd); std::cerr << " " << static_cast<unsigned long>(p_internal->get_e_ind()) << std::endl; const size_type num_children = std::distance(p_internal->begin(), p_internal->end()); for (size_type child_i = 0; child_i < num_children; ++child_i) { typename internal_node::const_iterator child_it = p_internal->begin(); std::advance(child_it, num_children - child_i - 1); trace_node(*child_it, level + 1); } }
PB_DS_CLASS_T_DEC void PB_DS_CLASS_C_DEC:: trace_node(node_const_pointer p_nd, size_type level) { while (p_nd != 0) { for (size_type i = 0; i < level; ++i) std::cerr << ' '; std::cerr << p_nd << " prev = " << p_nd->m_p_prev_or_parent << " next " << p_nd->m_p_next_sibling << " left = " << p_nd->m_p_l_child << " "; trace_node_metadata(p_nd, type_to_type<node_metadata>()); std::cerr << p_nd->m_value << std::endl; trace_node(p_nd->m_p_l_child, level + 1); p_nd = p_nd->m_p_next_sibling; } }