/**
 * Frees all the memory associated to the given meta list.
 */
static void free_opt_meta(struct opt_meta* list,Abstract_allocator prv_alloc) {
struct opt_meta* tmp;
while (list!=NULL) {
   free_Transition_list(list->transition,prv_alloc);
   free_Transition_list(list->morphological_mode_ends,prv_alloc);
   tmp=list;
   list=list->next;
   free_cb(tmp,prv_alloc);
}
}
Exemple #2
0
/**
 * Removes all transitions whose destination state is n.
 */
Transition* clean_transitions(Transition* trans, int n) {
while (trans!=NULL && trans->state_number==n) {
   Transition* next=trans->next;
   free_Transition_list(trans,free_symbol);
   trans=next;
}
for (Transition* t=trans;t!=NULL;t=t->next) {
   while (t->next!=NULL && t->next->state_number==n) {
      Transition* next=t->next->next;
      free_Transition_list(t->next,free_symbol);
      t->next=next;
   }
}
return trans;
}
/**
 * Frees the whole memory associated to the given optimized state.
 */
static void free_optimized_state(OptimizedFst2State state,Abstract_allocator prv_alloc) {
if (state==NULL) return;
free_opt_graph_call(state->graph_calls,prv_alloc);
free_opt_meta(state->metas,prv_alloc);
free_opt_pattern(state->patterns,prv_alloc);
free_opt_pattern(state->compound_patterns,prv_alloc);
free_opt_token(state->token_list,prv_alloc);
free_opt_variable(state->input_variable_starts,prv_alloc);
free_opt_variable(state->input_variable_ends,prv_alloc);
free_opt_variable(state->output_variable_starts,prv_alloc);
free_opt_variable(state->output_variable_ends,prv_alloc);
free_opt_contexts(state->contexts,prv_alloc);
if (state->tokens!=NULL) free_cb(state->tokens,prv_alloc);
if (state->token_transitions!=NULL) {
   for (int i=0;i<state->number_of_tokens;i++) {
      free_Transition_list(state->token_transitions[i],prv_alloc);
   }
   free_cb(state->token_transitions,prv_alloc);
}
free_opt_graph_call(state->unoptimized_graph_calls,prv_alloc);
free_opt_meta(state->unoptimized_metas,prv_alloc);
free_opt_variable(state->unoptimized_input_variable_starts,prv_alloc);
free_opt_variable(state->unoptimized_input_variable_ends,prv_alloc);
free_opt_variable(state->unoptimized_output_variable_starts,prv_alloc);
free_opt_variable(state->unoptimized_output_variable_ends,prv_alloc);
free_cb(state,prv_alloc);
}
/**
 * Frees all the memory associated to the given variable list.
 */
static void free_opt_variable(struct opt_variable* list,Abstract_allocator prv_alloc) {
struct opt_variable* tmp;
while (list!=NULL) {
   free_Transition_list(list->transition,prv_alloc);
   tmp=list;
   list=list->next;
   free_cb(tmp,prv_alloc);
}
}
/**
 * Frees all the memory asociated to the given token tree structure.
 */
void free_fst2txt_token_tree(struct fst2txt_token_tree* t, Abstract_allocator prv_alloc) {
if (t==NULL) return;
free_string_hash(t->hash);
for (int i=0;i<t->size;i++) {
   free_Transition_list(t->transition_array[i], prv_alloc);
}
free_cb(t->transition_array,prv_alloc);
free_cb(t,prv_alloc);
}
/**
 * Removes the useless contexts, i.e. contexts to a state that has no outgoing transitions.
 */
static int remove_useless_contexts(struct opt_contexts* c,OptimizedFst2State* optimized_states,
		Abstract_allocator prv_alloc) {
if (c==NULL) return 0;
int removed=0;
/* We filter the positive contexts */
for (int i=0;i<c->size_positive;i+=2) {
	/* We have two transitions to consider: the one outgoing from the context mark, and
	 * the one pointing to the state after the end context mark. If either of those transitions
	 * points to a useless states, we can remove both.
	 */
	if (c->positive_mark[i]==NULL || c->positive_mark[i+1]==NULL) {
		continue;
	}
	int dest1=c->positive_mark[i]->state_number;
	int dest2=c->positive_mark[i+1]->state_number;
	if (is_useless_state(optimized_states[dest1]) || is_useless_state(optimized_states[dest2])) {
		free_Transition_list(c->positive_mark[i],prv_alloc);
		free_Transition_list(c->positive_mark[i+1],prv_alloc);
		c->positive_mark[i]=NULL;
		c->positive_mark[i+1]=NULL;
		c->non_NULL_positive_transitions-=2;
		removed=1;
	}
}
/* We don't filter the negative contexts, because inside a negative context,
 * a failure to match is significant. So, if we have a token 'foo' that cannot
 * match, we must not try to trim the graph too much by removing the
 * negative context mark or even modify its outgoing transitions.
 */

/* Finally, we filter the end context mark, if any */
if (c->end_mark!=NULL) {
	int dest=c->end_mark->state_number;
	if (is_useless_state(optimized_states[dest])) {
		free_Transition_list(c->end_mark,prv_alloc);
		c->end_mark=NULL;
		removed=1;
	}
}
return removed;
}
static Transition* filter_transitions(Transition* l,OptimizedFst2State* optimized_states,Abstract_allocator prv_alloc) {
Transition** ptrToCurrent = &l;
while ((*ptrToCurrent)!=NULL)
{
  if (is_useless_state(optimized_states[(*ptrToCurrent)->state_number])) {
    Transition* transition_to_free = *ptrToCurrent;
    *ptrToCurrent=transition_to_free->next;
    transition_to_free->next=NULL;
    free_Transition_list(transition_to_free,prv_alloc);
  }
  else {
    ptrToCurrent = &((*ptrToCurrent)->next);
  }
}
return l;
}
/**
 * Frees a transition list.
 */
void free_Transition_list(Transition* t,Abstract_allocator prv_alloc) {
free_Transition_list(t,NULL,prv_alloc);
}