Bool trie_retrieve (Trie *trie, const TrieChar *key, TrieData *o_data) { TrieIndex s; short suffix_idx; const TrieChar *p; size_t len; /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { if (!da_walk (trie->da, &s, *p)) return FALSE; if ('\0' == *p) break; } /* walk through tail */ s = trie_da_get_tail_index (trie->da, s); if ('\0' != *p) { suffix_idx = 0; len = strlen ((const char *) p) + 1; /* including null-terminator */ if (tail_walk_str (trie->tail, s, &suffix_idx, p, len) != len) return FALSE; } /* found, set the val and return */ if (o_data) *o_data = tail_get_data (trie->tail, s); return TRUE; }
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_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); }
Bool trie_store (Trie *trie, const TrieChar *key, TrieData data) { TrieIndex s, t; short suffix_idx; const TrieChar *p; size_t len; /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { if (!da_walk (trie->da, &s, *p)) return trie_branch_in_branch (trie, s, p, data); if ('\0' == *p) break; } /* walk through tail */ t = trie_da_get_tail_index (trie->da, s); if ('\0' != *p) { suffix_idx = 0; len = strlen ((const char *) p) + 1; /* including null-terminator */ if (tail_walk_str (trie->tail, t, &suffix_idx, p, len) != len) return trie_branch_in_tail (trie, s, p, data); } /* duplicated key, overwrite val */ tail_set_data (trie->tail, t, data); return TRUE; }
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 data from terminal state * * @param s : a terminal state * * @return the data associated with the terminal state @a s, * or TRIE_DATA_ERROR if @a s is not a terminal state * */ TrieData trie_state_get_terminal_data (const TrieState *s) { TrieIndex tail_index; TrieIndex index = s->index; if (!s) return TRIE_DATA_ERROR; if (!s->is_suffix){ if (!trie_da_is_separate(s->trie->da, index)) { /* walk to a terminal char to get the data */ Bool ret = da_walk (s->trie->da, &index, TRIE_CHAR_TERM); if (!ret) { return TRIE_DATA_ERROR; } } tail_index = trie_da_get_tail_index (s->trie->da, index); } else { tail_index = s->index; } return tail_get_data (s->trie->tail, tail_index); }
static Bool trie_store_conditionally (Trie *trie, const AlphaChar *key, TrieData data, Bool is_overwrite) { TrieIndex s, t; short suffix_idx; const AlphaChar *p, *sep; /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { if (!da_walk (trie->da, &s, alpha_map_char_to_trie (trie->alpha_map, *p))) { TrieChar *key_str; Bool res; key_str = alpha_map_char_to_trie_str (trie->alpha_map, p); res = trie_branch_in_branch (trie, s, key_str, data); free (key_str); return res; } if (0 == *p) break; } /* walk through tail */ sep = p; t = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (!tail_walk_char (trie->tail, t, &suffix_idx, alpha_map_char_to_trie (trie->alpha_map, *p))) { TrieChar *tail_str; Bool res; tail_str = alpha_map_char_to_trie_str (trie->alpha_map, sep); res = trie_branch_in_tail (trie, s, tail_str, data); free (tail_str); return res; } if (0 == *p) break; } /* duplicated key, overwrite val if flagged */ if (!is_overwrite) { return FALSE; } tail_set_data (trie->tail, t, data); trie->is_dirty = TRUE; return TRUE; }
static int trie_store_maybe(trie_t trie, const char *key, trie_data_t d, int overwritep) { trie_idx_t s, t; short int suffix_idx; const char *p, *sep; /* walk through branches */ s = da_get_root(trie->da); for (p = key; !trie_da_separate_p(trie->da, s); p++) { if (da_walk(trie->da, &s, alpha_map_char_to_trie(*p)) < 0) { char *key_str; int res; key_str = alpha_map_char_to_trie_str(p); res = trie_branch_in_branch(trie, s, key_str, d); free(key_str); return res; } if (*p == '\0') { break; } } /* walk through tail */ sep = p; t = trie_da_get_tail_index(trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (tail_walk_char( trie->tail, t, &suffix_idx, alpha_map_char_to_trie(*p)) < 0) { char *tail_str; int res; tail_str = alpha_map_char_to_trie_str(sep); res = trie_branch_in_tail(trie, s, tail_str, d); free(tail_str); return res; } if (*p == '\0') { break; } } /* duplicated key, overwrite val if flagged */ if (!overwritep) { return -1; } tail_set_data(trie->tail, t, d); trie->dirtyp = 1; return 0; }
/** * @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; }
Bool trie_state_walk (TrieState *s, const TrieChar c) { if (!s->is_suffix) { Bool ret; ret = da_walk (s->trie->da, &s->index, c); if (ret && trie_da_is_separate (s->trie->da, s->index)) { s->index = trie_da_get_tail_index (s->trie->da, s->index); s->suffix_idx = 0; s->is_suffix = TRUE; } return ret; } else { return tail_walk_char (s->trie->tail, s->index, &s->suffix_idx, c); } }
/** * @brief Walk the trie from the state * * @param s : current state * @param c : key character for walking * * @return boolean value indicating the success of the walk * * Walk the trie stepwise, using a given character @a c. * On return, the state @a s is updated to the new state if successfully walked. */ int trie_state_walk(trie_state_t s, char c) { char tc = alpha_map_char_to_trie(c); if (!s->suffixp) { int ret = da_walk(s->trie->da, &s->index, tc); if (ret == 0 && trie_da_separate_p(s->trie->da, s->index)) { s->index = trie_da_get_tail_index(s->trie->da, s->index); s->suffix_idx = 0; s->suffixp = true; } return ret; } /* otherwise */ return tail_walk_char(s->trie->tail, s->index, &s->suffix_idx, tc); }
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 Get data for the entry referenced by an iterator * * @param iter : an iterator * * @return the data associated with the entry referenced by iterator @a iter, * or TRIE_DATA_ERROR if @a iter does not reference to a unique entry * * Get value for the entry referenced by an iterator. Getting value from an * un-iterated (or broken for any reason) iterator will result in * TRIE_DATA_ERROR. * * Available since: 0.2.6 */ TrieData trie_iterator_get_data (const TrieIterator *iter) { const TrieState *s = iter->state; TrieIndex tail_index; if (!s) return TRIE_DATA_ERROR; if (!s->is_suffix) { if (!trie_da_is_separate (s->trie->da, s->index)) return TRIE_DATA_ERROR; tail_index = trie_da_get_tail_index (s->trie->da, s->index); } else { tail_index = s->index; } return tail_get_data (s->trie->tail, tail_index); }
/** * @brief Walk the trie from the state * * @param s : current state * @param c : key character for walking * * @return boolean value indicating the success of the walk * * Walk the trie stepwise, using a given character @a c. * On return, the state @a s is updated to the new state if successfully walked. */ Bool trie_state_walk (TrieState *s, AlphaChar c) { TrieChar tc = alpha_map_char_to_trie (s->trie->alpha_map, c); if (!s->is_suffix) { Bool ret; ret = da_walk (s->trie->da, &s->index, tc); if (ret && trie_da_is_separate (s->trie->da, s->index)) { s->index = trie_da_get_tail_index (s->trie->da, s->index); s->suffix_idx = 0; s->is_suffix = TRUE; } return ret; } else { return tail_walk_char (s->trie->tail, s->index, &s->suffix_idx, tc); } }
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; }
/** * @brief Delete an entry from trie * * @param trie : the trie * @param key : the key for the entry to delete * * @return boolean value indicating whether the key exists and is removed * * Delete an entry for the given @a key from @a trie. */ int trie_delete(trie_t trie, const char *key) { trie_idx_t s, t; short int suffix_idx; const char *p; /* walk through branches */ s = da_get_root(trie->da); for (p = key; !trie_da_separate_p(trie->da, s); p++) { if (da_walk(trie->da, &s, alpha_map_char_to_trie(*p)) < 0) { return -1; } if (*p == 0) { break; } } /* walk through tail */ t = trie_da_get_tail_index(trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (tail_walk_char( trie->tail, t, &suffix_idx, alpha_map_char_to_trie(*p)) < 0) { return -1; } if (*p == 0) { break; } } tail_delete(trie->tail, t); da_set_base(trie->da, s, TRIE_INDEX_ERROR); da_prune(trie->da, s); trie->dirtyp = 1; return 0; }
/** * @brief Delete an entry from trie * * @param trie : the trie * @param key : the key for the entry to delete * * @return boolean value indicating whether the key exists and is removed * * Delete an entry for the given @a key from @a trie. */ Bool trie_delete (Trie *trie, const AlphaChar *key) { TrieIndex s, t; short suffix_idx; const AlphaChar *p; /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { if (!da_walk (trie->da, &s, alpha_map_char_to_trie (trie->alpha_map, *p))) { return FALSE; } if (0 == *p) break; } /* walk through tail */ t = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (!tail_walk_char (trie->tail, t, &suffix_idx, alpha_map_char_to_trie (trie->alpha_map, *p))) { return FALSE; } if (0 == *p) break; } tail_delete (trie->tail, t); da_set_base (trie->da, s, TRIE_INDEX_ERROR); da_prune (trie->da, s); trie->is_dirty = TRUE; return TRUE; }
/** * @brief Retrieve an entry from trie * * @param trie : the trie * @param key : the key for the entry to retrieve * @param o_data : the storage for storing the entry data on return * * @return boolean value indicating the existence of the entry. * * Retrieve an entry for the given @a key from @a trie. On return, * if @a key is found and @a o_data is not NULL, @a *o_data is set * to the data associated to @a key. */ Bool trie_retrieve (const Trie *trie, const AlphaChar *key, TrieData *o_data) { TrieIndex s; short suffix_idx; const AlphaChar *p; /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { if (!da_walk (trie->da, &s, alpha_map_char_to_trie (trie->alpha_map, *p))) { return FALSE; } if (0 == *p) break; } /* walk through tail */ s = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (!tail_walk_char (trie->tail, s, &suffix_idx, alpha_map_char_to_trie (trie->alpha_map, *p))) { return FALSE; } if (0 == *p) break; } /* found, set the val and return */ if (o_data) *o_data = tail_get_data (trie->tail, s); return TRUE; }
/** * @brief Retrieve an entry from trie * * @param trie : the trie * @param key : the key for the entry to retrieve * @param o_data : the storage for storing the entry data on return * * @return boolean value indicating the existence of the entry. * * Retrieve an entry for the given @a key from @a trie. On return, * if @a key is found and @a o_data is not NULL, @a *o_data is set * to the data associated to @a key. */ int trie_retrieve(const_trie_t trie, const char *key, trie_data_t *o_data) { trie_idx_t s; short int suffix_idx; const char *p; /* walk through branches */ s = da_get_root(trie->da); for (p = key; !trie_da_separate_p(trie->da, s); p++) { if (da_walk(trie->da, &s, alpha_map_char_to_trie(*p)) < 0) { return -1; } if (*p == 0) { break; } } /* walk through tail */ s = trie_da_get_tail_index(trie->da, s); suffix_idx = 0; for ( ; ; p++) { if (tail_walk_char( trie->tail, s, &suffix_idx, alpha_map_char_to_trie(*p)) < 0) { return -1; } if (*p == 0) { break; } } /* found, set the val and return */ if (o_data) { *o_data = tail_get_data(trie->tail, s); } return 0; }