xref: /aosp_15_r20/external/llvm-libc/src/__support/freetrie.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Implementation for freetrie ---------------------------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker 
9*71db0c75SAndroid Build Coastguard Worker #include "freetrie.h"
10*71db0c75SAndroid Build Coastguard Worker 
11*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
12*71db0c75SAndroid Build Coastguard Worker 
remove(Node * node)13*71db0c75SAndroid Build Coastguard Worker void FreeTrie::remove(Node *node) {
14*71db0c75SAndroid Build Coastguard Worker   LIBC_ASSERT(!empty() && "cannot remove from empty trie");
15*71db0c75SAndroid Build Coastguard Worker   FreeList list = node;
16*71db0c75SAndroid Build Coastguard Worker   list.pop();
17*71db0c75SAndroid Build Coastguard Worker   Node *new_node = static_cast<Node *>(list.begin());
18*71db0c75SAndroid Build Coastguard Worker   if (!new_node) {
19*71db0c75SAndroid Build Coastguard Worker     // The freelist is empty. Replace the subtrie root with an arbitrary leaf.
20*71db0c75SAndroid Build Coastguard Worker     // This is legal because there is no relationship between the size of the
21*71db0c75SAndroid Build Coastguard Worker     // root and its children.
22*71db0c75SAndroid Build Coastguard Worker     Node *leaf = node;
23*71db0c75SAndroid Build Coastguard Worker     while (leaf->lower || leaf->upper)
24*71db0c75SAndroid Build Coastguard Worker       leaf = leaf->lower ? leaf->lower : leaf->upper;
25*71db0c75SAndroid Build Coastguard Worker     if (leaf == node) {
26*71db0c75SAndroid Build Coastguard Worker       // If the root is a leaf, then removing it empties the subtrie.
27*71db0c75SAndroid Build Coastguard Worker       replace_node(node, nullptr);
28*71db0c75SAndroid Build Coastguard Worker       return;
29*71db0c75SAndroid Build Coastguard Worker     }
30*71db0c75SAndroid Build Coastguard Worker 
31*71db0c75SAndroid Build Coastguard Worker     replace_node(leaf, nullptr);
32*71db0c75SAndroid Build Coastguard Worker     new_node = leaf;
33*71db0c75SAndroid Build Coastguard Worker   }
34*71db0c75SAndroid Build Coastguard Worker 
35*71db0c75SAndroid Build Coastguard Worker   if (!is_head(node))
36*71db0c75SAndroid Build Coastguard Worker     return;
37*71db0c75SAndroid Build Coastguard Worker 
38*71db0c75SAndroid Build Coastguard Worker   // Copy the trie links to the new head.
39*71db0c75SAndroid Build Coastguard Worker   new_node->lower = node->lower;
40*71db0c75SAndroid Build Coastguard Worker   new_node->upper = node->upper;
41*71db0c75SAndroid Build Coastguard Worker   new_node->parent = node->parent;
42*71db0c75SAndroid Build Coastguard Worker   replace_node(node, new_node);
43*71db0c75SAndroid Build Coastguard Worker }
44*71db0c75SAndroid Build Coastguard Worker 
replace_node(Node * node,Node * new_node)45*71db0c75SAndroid Build Coastguard Worker void FreeTrie::replace_node(Node *node, Node *new_node) {
46*71db0c75SAndroid Build Coastguard Worker   LIBC_ASSERT(is_head(node) && "only head nodes contain trie links");
47*71db0c75SAndroid Build Coastguard Worker 
48*71db0c75SAndroid Build Coastguard Worker   if (node->parent) {
49*71db0c75SAndroid Build Coastguard Worker     Node *&parent_child =
50*71db0c75SAndroid Build Coastguard Worker         node->parent->lower == node ? node->parent->lower : node->parent->upper;
51*71db0c75SAndroid Build Coastguard Worker     LIBC_ASSERT(parent_child == node &&
52*71db0c75SAndroid Build Coastguard Worker                 "no reference to child node found in parent");
53*71db0c75SAndroid Build Coastguard Worker     parent_child = new_node;
54*71db0c75SAndroid Build Coastguard Worker   } else {
55*71db0c75SAndroid Build Coastguard Worker     LIBC_ASSERT(root == node && "non-root node had no parent");
56*71db0c75SAndroid Build Coastguard Worker     root = new_node;
57*71db0c75SAndroid Build Coastguard Worker   }
58*71db0c75SAndroid Build Coastguard Worker   if (node->lower)
59*71db0c75SAndroid Build Coastguard Worker     node->lower->parent = new_node;
60*71db0c75SAndroid Build Coastguard Worker   if (node->upper)
61*71db0c75SAndroid Build Coastguard Worker     node->upper->parent = new_node;
62*71db0c75SAndroid Build Coastguard Worker }
63*71db0c75SAndroid Build Coastguard Worker 
64*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
65