9d28bd0e9d
git-svn-id: svn://kolibrios.org@8383 a494cfbc-eb01-0410-851d-a64ba20cac60
206 lines
5.3 KiB
C
206 lines
5.3 KiB
C
//visual text comparer
|
||
//by den po - jdp@bk.ru
|
||
|
||
#define MEMSIZE 4096 * 60
|
||
#include "../lib/fs.h"
|
||
#include "../lib/strings.h"
|
||
#include "../lib/obj/console.h"
|
||
|
||
#define MAX_PATH 260
|
||
|
||
#include "32user32.h"
|
||
#include "objects.h"
|
||
#include "diff_gui.h"
|
||
|
||
#define mincmpstrings 2
|
||
#define maxcmpstrings 10
|
||
#define maxcmpoffset 100
|
||
|
||
char window_title[] = "Kolibri Diff tool (Visual Text Comparer)";
|
||
|
||
char* srcfilename;
|
||
char* dstfilename;
|
||
dword srcfile;
|
||
dword dstfile;
|
||
dword srcfilesize;
|
||
dword dstfilesize;
|
||
TCollection srcfilelines; //file lines
|
||
TCollection dstfilelines;
|
||
TCollection srcfilenums; //lines numbers
|
||
TCollection dstfilenums;
|
||
|
||
struct TSimpleCollection:TSortedCollection
|
||
{
|
||
TSimpleCollection();
|
||
int Compare( int Key1, Key2 );
|
||
};
|
||
int TSimpleCollection::Compare( int Key1, Key2 ){
|
||
return Key1-Key2;
|
||
}
|
||
TSimpleCollection::TSimpleCollection():TSortedCollection(1000,1000);
|
||
{
|
||
comparemethod=#Compare;
|
||
}
|
||
|
||
TSimpleCollection diffs; //list of differing strings
|
||
dword srcfilelinks; //pointer to the previos line with the same first symbol
|
||
dword dstfilelinks; //
|
||
|
||
getstrings(dword srcfile,srcfilesize,srcfilelines){
|
||
ECX=srcfilesize;
|
||
ESI=srcfile;
|
||
WHILE(ECX){
|
||
$push ECX,ESI
|
||
EAX=srcfilelines;
|
||
EAX.TCollection.Insert(ESI);
|
||
$pop ESI,ECX
|
||
WHILE(ECX){
|
||
$cld $lodsb ECX--;
|
||
if(AL==0x0D)||(AL==0x0A)DSBYTE[ESI-1]=0;
|
||
if(AL==0x0D)&&(DSBYTE[ESI]==0x0A){$lodsb;ECX--;}
|
||
if(AL==0x0D)||(AL==0x0A)BREAK;
|
||
}
|
||
}
|
||
}
|
||
|
||
#include "if.h"
|
||
|
||
bool getparam()
|
||
{
|
||
int i, param_len = strlen(#param);
|
||
if (param[0]=='"') {
|
||
for (i=1; i<param_len; i++) if (param[i]=='"') param[i]=NULL;
|
||
srcfilename = #param + 1;
|
||
dstfilename = #param + strlen(#param) + 3;
|
||
return true;
|
||
}
|
||
notify("'Wrong params! Use format:\nAPPPATH \"PARAM1\" \"PARAM2\"' -E");
|
||
return false;
|
||
}
|
||
|
||
main(){
|
||
if (param[0]) getparam();
|
||
if (!srcfilename) || (!dstfilename) gui(); else console();
|
||
}
|
||
|
||
console() {
|
||
int i;
|
||
int p;
|
||
int bs,bd,bsc,bdc,bsp,bdp;
|
||
int cache[256];
|
||
char s1;
|
||
int s2;
|
||
|
||
read_file(srcfilename, #srcfile, #srcfilesize);
|
||
read_file(dstfilename, #dstfile, #dstfilesize);
|
||
|
||
if (!srcfile) die("'First file not found' -E");
|
||
if (!dstfile) die("'Second file not found' -E");
|
||
|
||
srcfilelines.TCollection(srcfilesize/40,8192);
|
||
dstfilelines.TCollection(dstfilesize/40,8192);
|
||
//fill line pointers
|
||
getstrings(srcfile,srcfilesize,#srcfilelines);
|
||
getstrings(dstfile,dstfilesize,#dstfilelines);
|
||
srcfilenums.TCollection(srcfilelines.Count,1000);
|
||
dstfilenums.TCollection(dstfilelines.Count,1000);
|
||
|
||
srcfilelinks=malloc(srcfilelines.Count*4);
|
||
dstfilelinks=malloc(dstfilelines.Count*4);
|
||
|
||
//fill links on the next strings with the same first symbols
|
||
FillMemory(#cache,sizeof(cache),-1); i=srcfilelines.Count;
|
||
WHILE(i){
|
||
i--;
|
||
EBX=srcfilelines.At(i); EBX=DSBYTE[EBX];
|
||
DSDWORD[i<<2+srcfilelinks]=cache[EBX*4];
|
||
cache[EBX*4]=i;
|
||
}
|
||
FillMemory(#cache,sizeof(cache),-1); i=dstfilelines.Count;
|
||
WHILE(i){
|
||
i--;
|
||
EBX=dstfilelines.At(i); EBX=DSBYTE[EBX];
|
||
DSDWORD[i<<2+dstfilelinks]=cache[EBX*4];
|
||
cache[EBX*4]=i;
|
||
}
|
||
|
||
diffs.TSimpleCollection();
|
||
|
||
while( bsp < srcfilelines.Count ) || ( bdp < dstfilelines.Count )
|
||
{
|
||
////////////////////////////////////////////////////////
|
||
bsc=0;
|
||
p=dstfilelines.At(bdp);//current dst position
|
||
s1=DSBYTE[p];
|
||
bs=bsp+1;//found src line, bsc - number of matched
|
||
while( bs != -1 )//no next line starting with the same symbols
|
||
&&(bs-bsp<=maxcmpoffset)//check for 100 lines depth
|
||
&&(bs<srcfilelines.Count)
|
||
{
|
||
s2=srcfilelines.At(bs);
|
||
if(!strcmp(p,s2))
|
||
{//line found
|
||
bsc=1;
|
||
WHILE(bsc<maxcmpstrings)//counting number of matching lines
|
||
&&(bdp+bsc<dstfilelines.Count)
|
||
&&(bs+bsc<srcfilelines.Count)
|
||
&&(!strcmp(dstfilelines.At(bdp+bsc),srcfilelines.At(bs+bsc)))bsc++;
|
||
BREAK;
|
||
}
|
||
if(DSBYTE[s2]==s1)bs=DSDWORD[bs<<2+srcfilelinks];else bs++;
|
||
}
|
||
bdc=0;
|
||
p=srcfilelines.At(bsp);//current src position
|
||
s1=DSBYTE[p];
|
||
bd=bdp+1;//found dst line, bsc - number of matched
|
||
while( bd != -1 )//no next line starting with the same symbols
|
||
&&(bd-bdp<=maxcmpoffset)//check for 100 lines depth
|
||
&&(bd<dstfilelines.Count)
|
||
{
|
||
s2=dstfilelines.At(bd);
|
||
if(!strcmp(p,s2))
|
||
{
|
||
bdc=1;
|
||
WHILE(bdc<maxcmpstrings)//counting number of matching lines
|
||
&&(bsp+bdc<srcfilelines.Count)
|
||
&&(bd+bdc<dstfilelines.Count)
|
||
&&(!strcmp(srcfilelines.At(bsp+bdc),dstfilelines.At(bd+bdc)))bdc++;
|
||
BREAK;
|
||
}
|
||
if(DSBYTE[s2]==s1)bd=DSDWORD[bd<<2+dstfilelinks];else bd++;
|
||
}
|
||
|
||
if(bsc<bdc)
|
||
if(bd-bdp<bdc)
|
||
||(bdc>=mincmpstrings)
|
||
{
|
||
WHILE(bdp<bd){
|
||
diffs.Insert(srcfilenums.Count);
|
||
srcfilenums.Insert(-1); dstfilenums.Insert(bdp); bdp++;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if(strcmp(srcfilelines.At(bsp),dstfilelines.At(bdp)))diffs.Insert(srcfilenums.Count);
|
||
//lines are equal
|
||
srcfilenums.Insert(bsp); bsp++;
|
||
dstfilenums.Insert(bdp); bdp++;
|
||
CONTINUE;
|
||
}
|
||
|
||
free(srcfilelinks);
|
||
free(dstfilelinks);
|
||
|
||
if(!diffs.Count)
|
||
notify("'Nothing to compare' -E");
|
||
else ifinit();
|
||
|
||
diffs.DeleteAll(); delete diffs;
|
||
dstfilenums.DeleteAll(); delete dstfilenums;
|
||
srcfilenums.DeleteAll(); delete srcfilenums;
|
||
dstfilelines.DeleteAll(); delete dstfilelines;
|
||
srcfilelines.DeleteAll(); delete srcfilelines;
|
||
free(dstfile);
|
||
free(srcfile);
|
||
}
|