/** * @brief Get key for a trie iterator * * @param iter : an iterator * * @return the allocated key string; NULL on failure * * Get key for the current entry referenced by the trie iterator @a iter. * * The return string must be freed with free(). * * Available since: 0.2.6 */ AlphaChar * trie_iterator_get_key (const TrieIterator *iter) { const TrieState *s; const TrieChar *tail_str; AlphaChar *alpha_key, *alpha_p; s = iter->state; if (!s) return NULL; /* if s is in tail, root == s */ if (s->is_suffix) { tail_str = tail_get_suffix (s->trie->tail, s->index); if (!tail_str) return NULL; tail_str += s->suffix_idx; alpha_key = (AlphaChar *) malloc (sizeof (AlphaChar) * (strlen (tail_str) + 1)); alpha_p = alpha_key; } else { TrieIndex tail_idx; int i, key_len; const TrieChar *key_p; tail_idx = trie_da_get_tail_index (s->trie->da, s->index); tail_str = tail_get_suffix (s->trie->tail, tail_idx); if (!tail_str) return NULL; key_len = trie_string_length (iter->key); key_p = trie_string_get_val (iter->key); alpha_key = (AlphaChar *) malloc ( sizeof (AlphaChar) * (key_len + strlen (tail_str) + 1) ); alpha_p = alpha_key; for (i = key_len; i > 0; i--) { *alpha_p++ = alpha_map_trie_to_char (s->trie->alpha_map, *key_p++); } } while (*tail_str) { *alpha_p++ = alpha_map_trie_to_char (s->trie->alpha_map, *tail_str++); } *alpha_p = 0; return alpha_key; }
/** * @brief Walk in tail with a string * * @param t : the tail data * @param s : the tail data index * @param suffix_idx : pointer to current character index in suffix * @param str : the string to use in walking * @param len : total characters in @a str to walk * * @return total number of characters successfully walked * * Walk in the tail data @a t at entry @a s, from given character position * @a *suffix_idx, using @a len characters of given string @a str. On return, * @a *suffix_idx is updated to the position after the last successful walk, * and the function returns the total number of character succesfully walked. */ int tail_walk_str (const Tail *t, TrieIndex s, short *suffix_idx, const TrieChar *str, int len) { const TrieChar *suffix; int i; short j; suffix = tail_get_suffix (t, s); if (!suffix) return FALSE; i = 0; j = *suffix_idx; while (i < len) { if (str[i] != suffix[j]) break; ++i; /* stop and stay at null-terminator */ if (0 == suffix[j]) break; ++j; } *suffix_idx = j; return i; }
static int trie_da_enum_func(const char *key, trie_idx_t sep_node, void *user_data) { __walk_data_t walk_data; trie_idx_t t; const char *suffix; char *full_key, *p; int ret; trie_data_t data; size_t keyl, suffixl; walk_data = user_data; t = trie_da_get_tail_index(walk_data->trie->da, sep_node); suffix = tail_get_suffix(walk_data->trie->tail, t); keyl = strlen(key); suffixl = strlen(suffix); full_key = malloc(keyl + suffixl + 1); for (p = full_key; *key; p++, key++) { *p = alpha_map_trie_to_char(*key); } for ( ; *suffix; p++, suffix++) { *p = alpha_map_trie_to_char(*suffix); } *p = 0; data = tail_get_data(walk_data->trie->tail, t); ret = walk_data->walkf(full_key, data, walk_data->user_data); free(full_key); return ret; }
static Bool trie_da_enum_func (const TrieChar *key, TrieIndex sep_node, void *user_data) { _TrieEnumData *enum_data; TrieIndex t; const TrieChar *suffix; AlphaChar *full_key, *p; Bool ret; enum_data = (_TrieEnumData *) user_data; t = trie_da_get_tail_index (enum_data->trie->da, sep_node); suffix = tail_get_suffix (enum_data->trie->tail, t); full_key = (AlphaChar *) malloc ((strlen ((const char *)key) + strlen ((const char *)suffix) + 1) * sizeof (AlphaChar)); for (p = full_key; *key; p++, key++) { *p = alpha_map_trie_to_char (enum_data->trie->alpha_map, *key); } for ( ; *suffix; p++, suffix++) { *p = alpha_map_trie_to_char (enum_data->trie->alpha_map, *suffix); } *p = 0; ret = (*enum_data->enum_func) (full_key, tail_get_data (enum_data->trie->tail, t), enum_data->user_data); free (full_key); return ret; }
/** * @brief Get all walkable characters from state * * @param s : the state to get * @param chars : the storage for the result * @param chars_nelm : the size of @a chars[] in number of elements * * @return total walkable characters * * Get the list of all walkable characters from state @a s. At most * @a chars_nelm walkable characters are stored in @a chars[] on return. * * The function returns the actual number of walkable characters from @a s. * Note that this may not equal the number of characters stored in @a chars[] * if @a chars_nelm is less than the actual number. * * Available since: 0.2.6 */ int trie_state_walkable_chars (const TrieState *s, AlphaChar chars[], int chars_nelm) { int syms_num = 0; if (!s->is_suffix) { Symbols *syms = da_output_symbols (s->trie->da, s->index); int i; syms_num = symbols_num (syms); for (i = 0; i < syms_num && i < chars_nelm; i++) { TrieChar tc = symbols_get (syms, i); chars[i] = alpha_map_trie_to_char (s->trie->alpha_map, tc); } symbols_free (syms); } else { const TrieChar *suffix = tail_get_suffix (s->trie->tail, s->index); chars[0] = alpha_map_trie_to_char (s->trie->alpha_map, suffix[s->suffix_idx]); syms_num = 1; } return syms_num; }
static Bool trie_branch_in_tail (Trie *trie, TrieIndex sep_node, const TrieChar *suffix, TrieData data) { TrieIndex old_tail, old_da; TrieChar *old_suffix, *p; /* adjust separate point in old path */ old_tail = trie_da_get_tail_index (trie->da, sep_node); old_suffix = tail_get_suffix (trie->tail, old_tail); for (p = old_suffix; *p == *suffix; p++, suffix++) sep_node = da_insert_branch (trie->da, sep_node, *p); old_da = da_insert_branch (trie->da, sep_node, *p); if ('\0' != *p) ++p; tail_set_suffix (trie->tail, old_tail, p); trie_da_set_tail_index (trie->da, old_da, old_tail); free (old_suffix); /* insert the new branch at the new separate point */ return trie_branch_in_branch (trie, sep_node, suffix, data); }
static int trie_branch_in_tail( trie_t trie, trie_idx_t sep_node, const char *suffix, trie_data_t data) { trie_idx_t old_tail, old_da, s; const char *old_suffix, *p; /* adjust separate point in old path */ old_tail = trie_da_get_tail_index(trie->da, sep_node); if ((old_suffix = tail_get_suffix(trie->tail, old_tail)) == NULL) { return -1; } for (p = old_suffix, s = sep_node; *p == *suffix; p++, suffix++) { trie_idx_t t = da_insert_branch(trie->da, s, *p); if (t == TRIE_INDEX_ERROR) { goto fail; } s = t; } old_da = da_insert_branch(trie->da, s, *p); if (old_da == TRIE_INDEX_ERROR) { goto fail; } if (*p != '\0') { p++; } tail_set_suffix(trie->tail, old_tail, p); trie_da_set_tail_index(trie->da, old_da, old_tail); /* insert the new branch at the new separate point */ return trie_branch_in_branch(trie, s, suffix, data); fail: /* failed, undo previous insertions and return error */ da_prune_upto(trie->da, sep_node, s); trie_da_set_tail_index(trie->da, sep_node, old_tail); return -1; }
/** * @brief Walk in tail with a character * * @param t : the tail data * @param s : the tail data index * @param suffix_idx : pointer to current character index in suffix * @param c : the character to use in walking * * @return boolean indicating success * * Walk in the tail data @a t at entry @a s, from given character position * @a *suffix_idx, using given character @a c. If the walk is successful, * it returns TRUE, and @a *suffix_idx is updated to the next character. * Otherwise, it returns FALSE, and @a *suffix_idx is left unchanged. */ Bool tail_walk_char (const Tail *t, TrieIndex s, short *suffix_idx, TrieChar c) { const TrieChar *suffix; TrieChar suffix_char; suffix = tail_get_suffix (t, s); if (!suffix) return FALSE; suffix_char = suffix[*suffix_idx]; if (suffix_char == c) { if (0 != suffix_char) ++*suffix_idx; return TRUE; } return FALSE; }
static Bool trie_branch_in_tail (Trie *trie, TrieIndex sep_node, const TrieChar *suffix, TrieData data) { TrieIndex old_tail, old_da, s; const TrieChar *old_suffix, *p; /* adjust separate point in old path */ old_tail = trie_da_get_tail_index (trie->da, sep_node); old_suffix = tail_get_suffix (trie->tail, old_tail); if (!old_suffix) return FALSE; for (p = old_suffix, s = sep_node; *p == *suffix; p++, suffix++) { TrieIndex t = da_insert_branch (trie->da, s, *p); if (TRIE_INDEX_ERROR == t) goto fail; s = t; } old_da = da_insert_branch (trie->da, s, *p); if (TRIE_INDEX_ERROR == old_da) goto fail; if ('\0' != *p) ++p; tail_set_suffix (trie->tail, old_tail, p); trie_da_set_tail_index (trie->da, old_da, old_tail); /* insert the new branch at the new separate point */ return trie_branch_in_branch (trie, s, suffix, data); fail: /* failed, undo previous insertions and return error */ da_prune_upto (trie->da, sep_node, s); trie_da_set_tail_index (trie->da, sep_node, old_tail); return FALSE; }