/** * @brief Find next separate node in a sub-trie * * @param d : the double-array structure * @param root : the sub-trie root to search from * @param sep : the current separate node * @param keybuff : the TrieString buffer for incrementally calcuating key * * @return index to the next separate node; TRIE_INDEX_ERROR if no more * separate node is found * * Find the next separate node under a sub-trie rooted at @a root starting * from the current separate node @a sep. * * On return, @a keybuff is incrementally updated from the key which walks * to previous separate node to the one which walks to the new separate node. * So, it is assumed to be initialized by at least one da_first_separate() * call before. This incremental key calculation is more efficient than later * totally reconstructing key from the given separate node. * * Available since: 0.2.6 */ TrieIndex da_next_separate (DArray *d, TrieIndex root, TrieIndex sep, TrieString *keybuff) { TrieIndex parent; TrieIndex base; TrieIndex c, max_c; while (sep != root) { parent = da_get_check (d, sep); base = da_get_base (d, parent); c = sep - base; trie_string_cut_last (keybuff); /* find next sibling of sep */ max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base); while (++c <= max_c) { if (da_get_check (d, base + c) == parent) { trie_string_append_char (keybuff, c); return da_first_separate (d, base + c, keybuff); } } sep = parent; } return TRIE_INDEX_ERROR; }
/** * @brief Move trie iterator to the next entry * * @param iter : an iterator * * @return boolean value indicating the availability of the entry * * Move trie iterator to the next entry. * On return, the iterator @a iter is updated to reference to the new entry * if successfully moved. * * Available since: 0.2.6 */ Bool trie_iterator_next (TrieIterator *iter) { TrieState *s = iter->state; TrieIndex sep; /* first iteration */ if (!s) { s = iter->state = trie_state_clone (iter->root); /* for tail state, we are already at the only entry */ if (s->is_suffix) return TRUE; iter->key = trie_string_new (20); sep = da_first_separate (s->trie->da, s->index, iter->key); if (TRIE_INDEX_ERROR == sep) return FALSE; s->index = sep; return TRUE; } /* no next entry for tail state */ if (s->is_suffix) return FALSE; /* iter->state is a separate node */ sep = da_next_separate (s->trie->da, iter->root->index, s->index, iter->key); if (TRIE_INDEX_ERROR == sep) return FALSE; s->index = sep; return TRUE; }