// Span.cpp: implementation of the Span class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "PatchIT.h" #include "Span.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// void Span::DeleteChildren() { if(Next) Next->DeleteChildren(); delete Next; Next=NULL; } void Span::InsertNodeAfter(Span *span) { if(Next) { Next->Prev=span; } span->Next=Next; span->Prev=this; Next=span; } int Span::FindLargestSpan(Span *comspan,DWORD *pos1,DWORD *pos2,DWORD minsize) { DWORD maxspan=minsize; BYTE *comsbuf=comspan->Buffer; DWORD pos,cspos,dpos; for(pos=0;posSize && (cspos+maxspan)<=comspan->Size;cspos++) { if(Buffer[pos]==comsbuf[cspos] && Buffer[pos+(maxspan-1)]==comsbuf[cspos+(maxspan-1)] ) { //Check First and Last for Early out for(dpos=1;(cspos+dpos)Size && (pos+dpos)maxspan) { maxspan=dpos; *pos1=pos; *pos2=cspos; } } } } return maxspan; } //End of Find Span int Span::MapLargestSpan(Span *comspan,DWORD minsize) { DWORD spansize; DWORD pos,cspos; spansize=FindLargestSpan(comspan,&pos,&cspos,minsize); if(spansize>minsize) { // Missed creeping up Take Last One Span *new_span1,*new_span2; new_span1=AddSpanAt(Buffer+pos,spansize); new_span2=comspan->AddSpanAt(comspan->Buffer+cspos,spansize); new_span1->MappedTo=new_span2; new_span2->MappedTo=new_span1; if(new_span1->Prev!=NULL && new_span1->Prev->MappedTo==NULL && new_span2->Prev!=NULL && new_span2->Prev->MappedTo==NULL) //Map the left new_span1->Prev->MapLargestSpan(new_span2->Prev,minsize); if(new_span1->Next!=NULL && new_span1->Next->MappedTo==NULL && new_span2->Next!=NULL && new_span2->Next->MappedTo==NULL) //Map the right new_span1->Next->MapLargestSpan(new_span2->Next,minsize); return spansize; } return spansize; } //End of Find Span Span *Span::AddSpanAt(BYTE * loc,DWORD size) { /* // This will put it in the right place if(locAddSpanAt(loc,size,map); return; } */ ASSERT(loc>=Buffer && (loc+size)<=(Buffer+Size)); //Must Be a Sub Span ASSERT(MappedTo==NULL); //Cannot Split a Mapped Span DWORD endsize; Span *new_span; if((loc-Buffer)==0) //Don't Need a new one Adjust them { endsize=Size-size; Size=size; new_span=this; } else { new_span= new Span(loc,size); // Make our Span InsertNodeAfter(new_span); endsize=Size-((loc-Buffer)+size); Size=(loc-Buffer); } ASSERT(endsize>=0); if(endsize>0) { new_span->InsertNodeAfter(new Span(loc+size,endsize)); // At end span if needed; } return new_span; } void Span::SpanInfo(CString &fstr,BYTE *base1,BYTE *base2) { CString str; str.Format("Location = %i Size = %i ",Buffer-base1,Size); if(MappedTo) { CString str2; str2.Format(" -> Location = %i",MappedTo->Buffer-base2); str+=str2; } str+="\n"; fstr+=str; if(Next) Next->SpanInfo(fstr,base1,base2); } void Span::BuildOps(Span *sspan,CPatchOperation *OpList,const BYTE *base1,const BYTE *base2) { Span *cur_node1,*cur_node2; DWORD lastloc=0; cur_node1=this; cur_node2=sspan; while(cur_node1 && cur_node2) { if(cur_node2->MappedTo==NULL) { OpList->Next=new CInsert(cur_node1->Buffer-base1,cur_node2->Size,cur_node2->Buffer-base2); OpList=OpList->Next; cur_node2=cur_node2->Next; } if(cur_node1->MappedTo==NULL) { OpList->Next=new CDelete(cur_node1->Buffer-base1,cur_node1->Size); OpList=OpList->Next; lastloc=cur_node1->Buffer-base1+cur_node1->Size; cur_node1=cur_node1->Next; } ASSERT((!cur_node1 || cur_node1->MappedTo!=NULL)); ASSERT((!cur_node2 || cur_node2->MappedTo!=NULL)); if(cur_node1 || cur_node2) { ASSERT(cur_node2 && cur_node1); lastloc=cur_node1->Buffer-base1+cur_node1->Size; cur_node1=cur_node1->Next; cur_node2=cur_node2->Next; } } if(cur_node1) { ASSERT(cur_node1->MappedTo==NULL); OpList->Next=new CDelete(cur_node1->Buffer-base1,cur_node1->Size); OpList=OpList->Next; lastloc=cur_node1->Buffer-base1+cur_node1->Size; cur_node1=cur_node1->Next; } if(cur_node2) { ASSERT(cur_node2->MappedTo==NULL); OpList->Next=new CInsert(lastloc,cur_node2->Size,cur_node2->Buffer-base2); OpList=OpList->Next; cur_node2=cur_node2->Next; } ASSERT(!cur_node1 && !cur_node2); } Span::~Span() { DeleteChildren(); }