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; }
/** * @brief Rewind a trie state * * @param s : the state to rewind * * Put the state at root. */ void trie_state_rewind(trie_state_t s) { s->index = da_get_root(s->trie->da); s->suffixp = false; return; }
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 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 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. */ 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; }
static TrieChar * da_get_state_key (const DArray *d, TrieIndex state) { TrieChar *key; int key_size, key_length; int i; key_size = 20; key_length = 0; key = (TrieChar *) malloc (key_size); /* trace back to root */ while (da_get_root (d) != state) { TrieIndex parent; if (key_length + 1 >= key_size) { key_size += 20; key = (TrieChar *) realloc (key, key_size); } parent = da_get_check (d, state); key[key_length++] = (TrieChar) (state - da_get_base (d, parent)); state = parent; } key[key_length] = '\0'; /* reverse the string */ for (i = 0; i < --key_length; i++) { TrieChar temp; temp = key[i]; key[i] = key[key_length]; key[key_length] = temp; } return key; }
/** * @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 Get root state of a trie * * @param trie : the trie * * @return the root state of the trie * * Get root state of @a trie, for stepwise walking. * * The returned state is allocated and must be freed with trie_state_free() */ trie_state_t trie_root(const_trie_t trie) { return make_trie_state(trie, da_get_root(trie->da), 0, false); }
/** * @brief Enumerate entries stored in double-array structure * * @param d : the double-array structure * @param enum_func : the callback function to be called on each separate node * @param user_data : user-supplied data to send as an argument to @a enum_func * * @return boolean value indicating whether all the keys are visited * * Enumerate all keys stored in double-array structure. For each entry, the * user-supplied @a enum_func callback function is called, with the entry key, * the separate node, and user-supplied data. Returning FALSE from such * callback will stop enumeration and return FALSE. */ Bool da_enumerate (const DArray *d, DAEnumFunc enum_func, void *user_data) { return da_enumerate_recursive (d, da_get_root (d), enum_func, user_data); }
/** * @brief Prune the single branch * * @param d : the double-array structure * @param s : the dangling state to prune off * * Prune off a non-separate path up from the final state @a s. * If @a s still has some children states, it does nothing. Otherwise, * it deletes the node and all its parents which become non-separate. */ void da_prune (DArray *d, TrieIndex s) { da_prune_upto (d, da_get_root (d), s); }
/** * @brief Rewind a trie state * * @param s : the state to rewind * * Put the state at root. */ void trie_state_rewind (TrieState *s) { s->index = da_get_root (s->trie->da); s->is_suffix = FALSE; }
/** * @brief Get root state of a trie * * @param trie : the trie * * @return the root state of the trie * * Get root state of @a trie, for stepwise walking. * * The returned state is allocated and must be freed with trie_state_free() */ TrieState * trie_root (const Trie *trie) { return trie_state_new (trie, da_get_root (trie->da), 0, FALSE); }