Beispiel #1
0
ac_error_code
ac_index_free(ac_index* self, ac_free_function object_free) {

    ac_list* queue        = NULL;
    ac_state* state       = NULL;
    ac_error_code result  = AC_SUCCESS;
    
    if ( ! self) {
        return AC_FAILURE;
    }
    
    if ( ! (queue = ac_list_new())) {
        return AC_FAILURE;
    }
    
    // Free all the state nodes by following the goto function tree breadth
    // first, starting with state_0.
    state = self->state_0;
    
    while (state) {
        // Free the state and enqueue the states from the goto list.
        if (ac_state_free(state, queue, object_free) != AC_SUCCESS) {
            result = AC_FAILURE;
        }
        
        state = ac_state_queue_get(queue);
    }
    
    ac_state_queue_free(queue);     // The queue should be empty.
    
    self->state_0 = NULL;
    FREE(self);
    
    return result;
}
Beispiel #2
0
/**
 * Construct a new state object. The goto list and the both output lists are
 * initially empty, and the failure state is initially NULL. Returns a pointer
 * to the new state object if successful or NULL if an error was encountered
 * while trying to allocate heap space for the object or while constructing
 * one of its lists.
 */
ac_state*
ac_state_new(void) {
    ac_state* self;
    
    if ( ! (self = MALLOC(sizeof(ac_state))) ) {
        return NULL;
    }

    if ( ! (self->gotos = ac_list_new())) {
        return NULL;
    }
    
    if ( ! (self->outputs = ac_list_new())) {
        return NULL;
    }
    
    if ( ! (self->extra_outputs = ac_list_new())) {
        return NULL;
    }
    
    self->failure = NULL;
    return self;
}
Beispiel #3
0
Datei: user.c Projekt: fbbs/fbbs
static ac_list *user_build_ac_list(void)
{
	if (!uidshm)
		return NULL;

	ac_list *acl = ac_list_new();
	if (!acl)
		return NULL;

	int size = uidshm->number;
	for (int i = 0; i < size; ++i) {
		const char *user_name = uidshm->userid[i];
		if (*user_name)
			ac_list_add(acl, user_name);
	}
	return acl;
}
Beispiel #4
0
/**
 * Fix the index, making it ready to be queried. This is an implementation of
 * the last part of Algorithm 2 from the paper combined with an implementation
 * of 'Algorithm 3. Construction of the failure function.' from the paper.
 * Returns AC_SUCCESS if the index was successfully fixed or AC_FAILURE if an
 * error was encountered or if the index was not 'unfixed'.
 */
ac_error_code
ac_index_fix(ac_index* self) {
    // This is an implementation of the last part of Algorithm 2 from the paper
    // combined with an implementation of 'Algorithm 3. Construction of the
    // failure function.' from the paper.

    int             symbol;
    ac_state*       state = NULL;
    ac_state*       r = NULL;
    ac_list*        queue = NULL;
    ac_list_item*   list_item = NULL;
    ac_goto*        item = NULL;
    
    // You can't fix an index that is already fixed.
    if (self->index_state != AC_INDEX_UNFIXED) {
        return AC_FAILURE;
    }
    
    // Mark the index as being fixed.
    self->index_state = AC_INDEX_FIXED;
    
    // Make a temporary queue of states.
    if ( ! (queue = ac_list_new())) {
        return AC_FAILURE;
    }
    
    // Look at all the symbols. If state_0 has a goto for a symbol, add the
    // state to the queue and point the failure state back to state_0 - the
    // first part of Algorithm 3. Otherwise make state_0 goto itself for that
    // symbol - the last part of Algorithm 2.
    // TODO: Improve efficiency of state_0 to state_0 gotos.
    for (symbol = AC_MIN_SYMBOL; symbol <= AC_MAX_SYMBOL; symbol++) {
        if ((state = ac_goto_list_get(self->state_0->gotos, symbol))) {
            if (ac_list_add(queue, state) != AC_SUCCESS) {
                return AC_FAILURE;
            }
            state->failure = self->state_0;
        }
        else {
            if (ac_goto_list_add(self->state_0->gotos,
                                 symbol,
                                 self->state_0) != AC_SUCCESS) {
                return AC_FAILURE;
            }
        }
    }
    
    // Do the second part of Algorithm 3. Burn through the queue, enqueing
    // states from goto list in order to traverse the goto tree breadth-first.
    // ...
    while ((r = ac_state_queue_get(queue))) {
        list_item = r->gotos->first;
        
        while (list_item) {
            item = (ac_goto*) list_item->item;
            symbol = item->symbol;
            
            if (ac_list_add(queue, item->state) != AC_SUCCESS) {
                return AC_FAILURE;
            }
            
            // ... For each goto state, find the failure function by following
            // the failure function back until there is a goto defined. We
            // will always find a defined goto because state_0 has a goto
            // defined for every symbol (by now). ...
            state = r->failure;
            
            while ( ! ac_goto_list_has(state->gotos, symbol)) {
                state = state->failure;
            }
            
            item->state->failure = ac_goto_list_get(state->gotos,
                                                         symbol);
            
            // ... Add the outputs for the failure state to the outputs. We
            // use the extra_outputs list because the outputs are already
            // referenced.
            if (ac_output_list_add_list(item->state->extra_outputs,
                                        item->state->failure->outputs)) {
                return AC_FAILURE;
            };

            if (ac_output_list_add_list(item->state->extra_outputs,
                                    item->state->failure->extra_outputs)) {
                return AC_FAILURE;
            };

            list_item = list_item->next;
        }
        
    }
    
    // Free the temporary queue.
    ac_state_queue_free(queue);
    
    return AC_SUCCESS;
}