in sql_utils/base/general_trie.h [619:684]
void GeneralTrieImpl<T, NullValuePolicy>::TraverseAllMatchingStrings(
absl::string_view key, Traverser* traverser, int depth,
bool preorder) const {
// first try to match the input string in its entirety
const NodeT* node = this;
int next_pos = 0; // next position in s
int brkpt = 0; // next position in "node"
// if we find a mismatch, we return emptyhanded.
// if we find a match, we break out of the loop with
// node set to the portion of the tree that has all
// the matches for 's'.
while (node) {
if (next_pos >= key.length()) {
// done with input string. Note: empty input string
// matches everything in the trie. A break here means
// brkpt == 0 which is what we want (the entire
// comppath_ at this node is a suffix).
break;
}
const int len_to_compare =
std::min(node->comppath_.size(), (key.length() - next_pos));
if (memcmp(node->comppath_.data(), key.data() + next_pos, len_to_compare) !=
0) {
// mismatch found
return;
}
if ((key.length() - next_pos) <= node->comppath_.size()) {
// found a match (prefix of comppath_)
brkpt = len_to_compare;
break;
}
// follow first char after comppath
next_pos += len_to_compare;
node = node->Next(key[next_pos]);
++next_pos;
}
// if we got here with node == nullptr, we have no matches.
if (node == nullptr) return;
// we got here => we have one or more matches
std::string buf(key); // all of the input string
if (node->data_ != null_value_instance_ && brkpt == 0 && preorder) {
// this node is a full match by itself
traverser->Process(buf, node->data_);
}
buf.append(node->comppath_.data() + brkpt, node->comppath_.size() - brkpt);
for (int i = node->min_next_; i < node->max_next_; i++) {
NodeT* child = node->Next(i);
if (child != nullptr) {
buf.append(1, static_cast<char>(i));
child->Traverse(traverser, &buf, depth, preorder);
buf.erase(buf.size() - 1);
}
}
if (node->data_ != null_value_instance_ && brkpt == 0 && !preorder) {
// this node is a full match by itself
traverser->Process(buf, node->data_);
}
}