📄 dict.cpp
字号:
#include "Dict.h"
#include "BitIo.h"
#define DISP_BITS 11
#define COUNT_BITS 3
struct tDocHeader {
char sName[32]; // 32 bytes
DWORD dwUnknown1; // 36
DWORD dwTime1; // 40
DWORD dwTime2; // 44
DWORD dwTime3; // 48
DWORD dwLastSync; // 52
DWORD ofsSort; // 56
DWORD ofsCatagories; // 60
char dwCreator[4]; // 64
char dwType[4]; // 68
DWORD dwUnknown2; // 72
DWORD dwUnknown3; // 76
WORD wNumRecs; // 78
};
#define DOCHEADSZ 78
struct tRecord0head{
WORD Unknown1; // 0
WORD wdicnum; // 2 always be 1,maybe dictionaries num...or compressed flag?
WORD wsecnum; // 4
WORD Unknown2; //6 always be 1
char Unknown3[8]; // 48
};
WORD SwapWord21(WORD r)
{
return (r>>8) + (r<<8);
};
WORD SwapWord12(WORD r)
{
return r;
};
DWORD SwapLong4321(DWORD r)
{
return ((r>>24) & 0xFF) + (r<<24) + ((r>>8) & 0xFF00) + ((r<<8) & 0xFF0000);
};
DWORD SwapLong1234(DWORD r)
{
return r;
};
// copy bytes into a word and double word and see how they fall,
// then choose the appropriate swappers to make things come out
// in the right order.
int Dict::SwapChoose()
{
union { char b[2]; WORD w; } w;
union { char b[4]; DWORD d; } d;
strncpy(w.b, "\1\2", 2);
strncpy(d.b, "\1\2\3\4", 4);
if (w.w == 0x0201)
SwapWord = SwapWord21;
else if (w.w == 0x0102)
SwapWord = SwapWord12;
else
return 0;
if (d.d == 0x04030201)
SwapLong = SwapLong4321;
else if (d.d == 0x01020304)
SwapLong = SwapLong1234;
else
return 0;
return 1;
}
char *Dict::getLine(FILE *in)
{
int i=0;
char *buf=new char[4096];
while(buf[i]=fgetc(in))
{
if(i>4096) break;
if(buf[i]==EOF) break;
i++;
}
buf=(char *)realloc(buf,i+1);
if(!buf) printf("none buffer!");
buf[i]='\0';
return buf;
}
bool Dict::OpenDict(char * fileName)
{
SwapChoose();
//delete out-of-date data
CloseDict();
tDocHeader docHeader;
tRecord0head recHead;
fin=fopen(fileName,"rb");
if(!fin)
{
open=false;
return 0;
}
//read the doc header
fread(&docHeader, 1, DOCHEADSZ, fin);
docHeader.wNumRecs=SwapWord(docHeader.wNumRecs);
//printf("dict name: %s\nCreator: %s\nType: %s\nRecord Numbers: %d\n",docHeader.sName,docHeader.dwCreator,docHeader.dwType,docHeader.wNumRecs);
strncpy(dictName,docHeader.sName,sizeof(dictName));
if(strncmp( docHeader.dwCreator,"Kdict",5) && strncmp(docHeader.dwCreator,"Zdict",5) && strncmp(docHeader.dwCreator,"Dict",4))
{
fclose(fin);
open=false;
return 0;
}
//get the record header
fseek(fin,0x4e,SEEK_SET);
DWORD dwPos;
fread(&dwPos, 4, 1, fin); //read start pos
dwPos = SwapLong(dwPos);
//printf("First record located at %u\n",dwPos);
fseek(fin,dwPos,SEEK_SET);
fread(&recHead,sizeof(recHead),1,fin); //read header
recHead.wdicnum=SwapWord(recHead.wdicnum);
secNumber=recHead.wsecnum=SwapWord(recHead.wsecnum);
//printf("dict number: %u\nsec number: %u\n",recHead.wdicnum,recHead.wsecnum);
//get the section size
WORD size;
secSize = new int[recHead.wsecnum+1];
secSize[0]=recHead.wsecnum;
for(int i=0;i<secSize[0];i++)
{
fread(&size,2,1,fin); //read the section size
secSize[i+1]=SwapWord(size);
//printf("sec%d size:%u\n",i,secSize[i+1]);
}
//get the indexs
dicIndex = new char*[2*recHead.wsecnum]; //every section two lines
for(int i=0;i<2*secSize[0];i++)
{
dicIndex[i]=getLine(fin);
//printf("%s\n",dicIndex[i]);
}
open = true;
return 1;
}
void Dict::CloseDict()
{
if(secSize)
{
for(int i=0;i<secSize[0];i++)
delete [] dicIndex[i];
delete [] dicIndex;
delete[] secSize;
open=false;
}
curSecIndex=-1;
if(fin)
fclose(fin);
}
long Dict::SearchSector(const char* queryWord)
{
if(!open)
return -1;
//printf("Searching:%s\n",queryWord);
int s,e,mid,cmp;
for(s=0,e=secSize[0]-1;s<e;)
{
mid=2*(int)((s+e)/2);//be carefull 3,4=>3
//printf("querying '%s'\n",dicIndex[mid]);
cmp=strcmp(queryWord,dicIndex[mid]);
if(cmp>0)
s=mid/2+1;
if(cmp<0)
e=mid/2;
if(cmp==0)
s=e=mid/2+1;
}
s-=1;
if(s<0)
return -1;
if(strcmp(queryWord,dicIndex[s*2+1])<=0)
return s;
else
return -1;
}
int Dict::Decompresslzss(char* enc,long len,char** dec)
{
*dec = new byte[6000]; //申请空间
tIobuf *in_buf,*output;
in_buf=new tIobuf();
output=new tIobuf();
BIT_FILE* input;
output->len=6000;
output->buf=*dec;
in_buf->buf=enc;
in_buf->len=len;
input=OpenInputBitFile(in_buf);//输入内容
//len=ExpandFile(in_file,&out_buf);
///////////////////////////just put the things in ExpandFile here!
int i;
int current_position;
int c;
int match_length;
int match_position;
int totalbytes=0;
current_position = 1;
for ( ; ; ) {
if (c=InputBit( input ) ) {
c = (int)InputBits( input, 8 );
output->putbyte(c);totalbytes++;
window[ current_position ] = (unsigned char) c;
current_position = MOD_WINDOW( current_position + 1 );
} else {
match_position = (int) InputBits( input, INDEX_BIT_COUNT );
if ( match_position == END_OF_STREAM )
break;
match_length = (int) InputBits( input, LENGTH_BIT_COUNT );
match_length += BREAK_EVEN;
for ( i = 0 ; i <= match_length ; i++ ) {
c = window[ MOD_WINDOW( match_position + i ) ];
output->putbyte(c); totalbytes++;
window[ current_position ] = (unsigned char) c;
current_position = MOD_WINDOW( current_position + 1 );
}
}
}
CloseInputBitFile(input);
*dec=(char*)realloc(*dec,totalbytes+1);
(*dec)[totalbytes]='\0';
return totalbytes;
}
long Dict::GetSector(long secIndex, char** enc)
{
if(!open)
return -1;
int sz=secSize[secIndex+1];
if(secIndex>=secSize[0])
return -1;
fseek(fin,0x56+8*secIndex,SEEK_SET);
DWORD dwPos;
fread(&dwPos,4,1,fin);
fseek(fin,SwapLong(dwPos),SEEK_SET);
if(*enc)
delete[] *enc;
*enc=new char[sz];
if(sz!=fread(*enc,1,sz,fin))
return -1;
return sz;
}
int Dict::GetWordList(const char* queryWord, char ***list)
{
if(!open)
return -1;
long secIndex=SearchSector(queryWord);
if(secIndex==-1)
return -1;
if(curSecIndex!=secIndex)
{
curSecIndex=secIndex;
char* enc_buf=NULL;
long len=GetSector(secIndex,&enc_buf);
dec_len=Decompresslzss(enc_buf,len,&dec_buf);
delete[] enc_buf;
}
char* buf=new char[255];
bool flag=0;
int listIndex=0;
(*list)=new char*[MaxList+1];
for(int i=0,j=0;i<dec_len;i++)
{
if(dec_buf[i]==0x09)
{
flag=1;
buf[j]='\0';
//printf("listing:%s\n",buf);
if(strcmp(buf,queryWord)>=0)
{
//printf("no%d:%s\n",listIndex,buf);
(*list)[listIndex]=new char[j+1];
strcpy((*list)[listIndex],buf);
//printf("no%d:%s\n",listIndex,(*list)[listIndex]);
if(listIndex++>=MaxList)
break;
}
j=0;
}
if(!flag)
buf[j++]=dec_buf[i];
if(dec_buf[i]==0x0a)
flag=0;
}
if(listIndex<=MaxList&&++secIndex<secNumber){
curSecIndex=secIndex;
char *enc_buf=NULL;
long len=GetSector(secIndex,&enc_buf);
dec_len=Decompresslzss(enc_buf,len,&dec_buf);
delete[] enc_buf;
for(int i=0,j=0;i<dec_len;i++){
if(dec_buf[i]==0x09){
flag=1;
buf[j]='\0';
//printf("listing:%s\n",buf);
if(strcmp(buf,queryWord)>=0){
//printf("no%d:%s\n",listIndex,buf);
(*list)[listIndex]=new char[j+1];
strcpy((*list)[listIndex],buf);
//printf("no%d:%s\n",listIndex,(*list)[listIndex]);
if(listIndex++>=MaxList)
break;
}
j=0;
}
if(!flag)
buf[j++]=dec_buf[i];
if(dec_buf[i]==0x0a)
flag=0;
}
}
delete[] buf;
return listIndex;
}
int Dict::GetExp(const char* queryWord, char **exp)
{
if(!open)
return -1;
long secIndex=SearchSector(queryWord);
if(secIndex==-1)
return -1;
if(curSecIndex!=secIndex)
{
curSecIndex=secIndex;
char* enc_buf=NULL;
long len=GetSector(secIndex,&enc_buf);
dec_len=Decompresslzss(enc_buf,len,&dec_buf);
}
char* buf=new char[6000];
bool flag=0,find=0;
int i,j;
for(i=0,j=0;i<dec_len;i++)
{
if(dec_buf[i]==0x09)//extra signal word
{
if(flag==0)
{
flag=1;
buf[j]='\0';
if(strcmp(buf,queryWord)==0)//compare with dest word
{
find=1;
buf[j++]='\n';
}
else
j=0;
}
}
if(!flag)
buf[j++]=dec_buf[i];
if(dec_buf[i]==0x0a)
{
flag=0;
}
if(find)//copy and dealing explain strings.
{
if(dec_buf[i]=='\t')
;//buf[j++]='\n';
else if(dec_buf[i]=='n' && buf[j-1]=='\\')
buf[j-1]='\n';
else if(dec_buf[i]==0x0a)
{
buf[j]='\0';
break;
}
else
buf[j++]=dec_buf[i];
}
}
if(find)
{
if(j>6000)
j=6000;
*exp=new char[j+1];
memcpy(*exp,buf,j+1);
}
delete[] buf;
return find?j+1:-1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -