/** * Caches the given token sequence in the given cache. Note that * match is supposed to contain a single match, not a match list. */ static void cache_match_internal(struct match_list* match,const int* tab,int start,int end,LocateCache *c,Abstract_allocator prv_alloc) { int token=-1; struct match_list* m=match; if (start<=end) { token=tab[start]; m=NULL; } /* No node */ if (*c==NULL) { *c=new_LocateCache(token,m,prv_alloc); if (token!=-1) { cache_match_internal(match,tab,start+1,end,&((*c)->middle),prv_alloc); } return; } /* There is a node */ if (token<(*c)->token) { /* If we have to move on the left */ return cache_match_internal(match,tab,start,end,&((*c)->left),prv_alloc); } if (token>(*c)->token) { /* If we have to move on the right */ return cache_match_internal(match,tab,start,end,&((*c)->right),prv_alloc); } /* We have the correct token */ if (token==-1) { /* If we are in a final node that already existed, we just add * the new match at the end of the match list to get the same match order as * if the cache system had not been used, but only if the match is not already present */ struct match_list* *ptr=&((*c)->matches); struct match_list* z; match->next=NULL; while ((*ptr)!=NULL) { z=*ptr; if (compare_matches(&(z->m),&(match->m))==A_EQUALS_B && !u_strcmp(z->output,match->output)) { /* We discard a match that was already in cache */ free_match_list_element(match,prv_alloc); return; } ptr=&((*ptr)->next); } (*ptr)=match; return; } cache_match_internal(match,tab,start+1,end,&((*c)->middle),prv_alloc); }
/** * This function removes all non ambiguous outputs from the given match list. * If renumber is non NULL, we have renumber[x]=y, where x is the position * of a match in the filtered list, and y its corresponding number in the * unfiltered original one. */ void filter_unambiguous_outputs(struct match_list* *list,vector_int* renumber) { struct match_list* tmp; if (*list==NULL) return; struct match_list* previous=NULL; struct match_list* l=*list; int previous_was_identical=0; int original_match_number=-1; while (l!=NULL) { original_match_number++; if (previous==NULL) { /* Case 1: we are at the beginning of the list */ /* Case 1a: there is only one cell */ if (l->next==NULL) { free_match_list(l); *list=NULL; return; } /* Case 1b: there is a next cell, but it's not ambiguous with the current one */ if (!are_ambiguous(l,l->next)) { /* We have to delete the current cell */ tmp=l->next; free_match_list_element(l); l=tmp; continue; } /* Case 1c: the next cell is an ambiguous one, we can move on */ /* Now we know the list head element */ *list=l; previous=l; previous_was_identical=1; l=l->next; vector_int_add(renumber,original_match_number); continue; } else { /* Case 2: there is a previous cell */ if (previous_was_identical) { vector_int_add(renumber,original_match_number); /* Case 2a: we know that we have to keep this current cell, but * we must check if the next is also an ambiguous one */ if (l->next==NULL) { /* No next cell ? We're done then */ return; } previous_was_identical=are_ambiguous(l,l->next); previous=l; l=l->next; continue; } /* Case 2b: previous cell is different, so we have to test the next one * to know whether we must keep the current one or not */ if (l->next==NULL) { /* No next cell ? We have to delete the current one and then * we are done */ free_match_list_element(l); previous->next=NULL; return; } previous_was_identical=are_ambiguous(l,l->next); if (previous_was_identical) { /* We have to keep the current cell */ previous=l; l=l->next; vector_int_add(renumber,original_match_number); continue; } /* Final case, the next cell is not ambiguous, so we have to delete * the current one */ tmp=l; l=l->next; free_match_list_element(tmp); previous->next=l; continue; } } }