/** * 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); } }
/** * 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); }