示例#1
0
static Bool
da_enumerate_recursive (const DArray   *d,
                        TrieIndex       state,
                        DAEnumFunc      enum_func,
                        void           *user_data)
{
    Bool        ret;
    TrieIndex   base;

    base = da_get_base (d, state);

    if (base < 0) {
        TrieChar   *key;

        key = da_get_state_key (d, state);
        ret = (*enum_func) (key, state, user_data);
        free (key);
    } else {
        Symbols *symbols;
        int      i;

        ret = TRUE;
        symbols = da_output_symbols (d, state);
        for (i = 0; ret && i < symbols_num (symbols); i++) {
            ret = da_enumerate_recursive (d, base + symbols_get (symbols, i),
                                          enum_func, user_data);
        }

        symbols_free (symbols);
    }

    return ret;
}
示例#2
0
文件: trie.c 项目: svn2github/datrie
/**
 * @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;
}
示例#3
0
/**
 * @brief Insert a branch from trie node
 *
 * @param d : the double-array structure
 * @param s : the state to add branch to
 * @param c : the character for the branch label
 *
 * @return the index of the new node
 *
 * Insert a new arc labelled with character @a c from the trie node 
 * represented by index @a s in double-array structure @a d.
 * Note that it assumes that no such arc exists before inserting.
 */
TrieIndex
da_insert_branch (DArray *d, TrieIndex s, TrieChar c)
{
    TrieIndex   base, next;

    base = da_get_base (d, s);

    if (base > 0) {
        next = base + c;

        /* if already there, do not actually insert */
        if (da_get_check (d, next) == s)
            return next;

        /* if (base + c) > TRIE_INDEX_MAX which means 'next' is overflow,
         * or cell [next] is not free, relocate to a free slot
         */
        if (base > TRIE_INDEX_MAX - c || !da_check_free_cell (d, next)) {
            Symbols    *symbols;
            TrieIndex   new_base;

            /* relocate BASE[s] */
            symbols = da_output_symbols (d, s);
            symbols_add (symbols, c);
            new_base = da_find_free_base (d, symbols);
            symbols_free (symbols);

            if (TRIE_INDEX_ERROR == new_base)
                return TRIE_INDEX_ERROR;

            da_relocate_base (d, s, new_base);
            next = new_base + c;
        }
    } else {
        Symbols    *symbols;
        TrieIndex   new_base;

        symbols = symbols_new ();
        symbols_add (symbols, c);
        new_base = da_find_free_base (d, symbols);
        symbols_free (symbols);

        if (TRIE_INDEX_ERROR == new_base)
            return TRIE_INDEX_ERROR;

        da_set_base (d, s, new_base);
        next = new_base + c;
    }
    da_alloc_cell (d, next);
    da_set_check (d, next, s);

    return next;
}
示例#4
0
static void
da_relocate_base   (DArray         *d,
                    TrieIndex       s,
                    TrieIndex       new_base)
{
    TrieIndex   old_base;
    Symbols    *symbols;
    int         i;

    old_base = da_get_base (d, s);
    symbols = da_output_symbols (d, s);

    for (i = 0; i < symbols_num (symbols); i++) {
        TrieIndex   old_next, new_next, old_next_base;

        old_next = old_base + symbols_get (symbols, i);
        new_next = new_base + symbols_get (symbols, i);
        old_next_base = da_get_base (d, old_next);

        /* allocate new next node and copy BASE value */
        da_alloc_cell (d, new_next);
        da_set_check (d, new_next, s);
        da_set_base (d, new_next, old_next_base);

        /* old_next node is now moved to new_next
         * so, all cells belonging to old_next
         * must be given to new_next
         */
        /* preventing the case of TAIL pointer */
        if (old_next_base > 0) {
            TrieIndex   c, max_c;

            max_c = MIN_VAL (TRIE_CHAR_MAX, TRIE_INDEX_MAX - old_next_base);
            for  (c = 0; c < max_c; c++) {
                if (da_get_check (d, old_next_base + c) == old_next)
                    da_set_check (d, old_next_base + c, new_next);
            }
        }

        /* free old_next node */
        da_free_cell (d, old_next);
    }

    symbols_free (symbols);

    /* finally, make BASE[s] point to new_base */
    da_set_base (d, s, new_base);
}