| 148 | } |
| 149 | |
| 150 | Status TrieBuilder::Append(std::string_view s, bool allow_duplicate) { |
| 151 | // Find or create node for string |
| 152 | fast_index_type node_index = 0; |
| 153 | fast_index_type pos = 0; |
| 154 | fast_index_type remaining = static_cast<fast_index_type>(s.length()); |
| 155 | |
| 156 | while (true) { |
| 157 | Trie::Node* node = &trie_.nodes_[node_index]; |
| 158 | const auto substring_length = node->substring_length(); |
| 159 | const auto substring_data = node->substring_data(); |
| 160 | |
| 161 | for (fast_index_type i = 0; i < substring_length; ++i) { |
| 162 | if (remaining == 0) { |
| 163 | // New string too short => need to split node |
| 164 | RETURN_NOT_OK(SplitNode(node_index, i)); |
| 165 | // Current node matches exactly |
| 166 | node = &trie_.nodes_[node_index]; |
| 167 | node->found_index_ = trie_.size_++; |
| 168 | return Status::OK(); |
| 169 | } |
| 170 | if (s[pos] != substring_data[i]) { |
| 171 | // Mismatching substring => need to split node |
| 172 | RETURN_NOT_OK(SplitNode(node_index, i)); |
| 173 | // Create new node for mismatching char |
| 174 | node = &trie_.nodes_[node_index]; |
| 175 | return CreateChildNode(node, s[pos], s.substr(pos + 1)); |
| 176 | } |
| 177 | ++pos; |
| 178 | --remaining; |
| 179 | } |
| 180 | if (remaining == 0) { |
| 181 | // Node matches exactly |
| 182 | if (node->found_index_ >= 0) { |
| 183 | if (allow_duplicate) { |
| 184 | return Status::OK(); |
| 185 | } else { |
| 186 | return Status::Invalid("Duplicate entry in trie"); |
| 187 | } |
| 188 | } |
| 189 | node->found_index_ = trie_.size_++; |
| 190 | return Status::OK(); |
| 191 | } |
| 192 | // Lookup child using next input character |
| 193 | if (node->child_lookup_ == -1) { |
| 194 | // Need to extend lookup table for this node |
| 195 | RETURN_NOT_OK(ExtendLookupTable(&node->child_lookup_)); |
| 196 | } |
| 197 | auto c = static_cast<uint8_t>(s[pos++]); |
| 198 | --remaining; |
| 199 | node_index = trie_.lookup_table_[node->child_lookup_ * 256 + c]; |
| 200 | if (node_index == -1) { |
| 201 | // Child not found => need to create child node |
| 202 | return CreateChildNode(node, c, s.substr(pos)); |
| 203 | } |
| 204 | node = &trie_.nodes_[node_index]; |
| 205 | } |
| 206 | } |
| 207 | |