Exemplo n.º 1
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;
}
Exemplo n.º 2
0
Arquivo: tail.c Projeto: pgoodman/XY
/**
 * @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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/**
 * @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;
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
Arquivo: tail.c Projeto: pgoodman/XY
/**
 * @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;
}
Exemplo n.º 9
0
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;
}