加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
lzzip.cpp 13.97 KB
一键复制 编辑 原始数据 按行查看 历史
yuchendoudou 提交于 2020-07-26 15:07 . bsdiff也打印进度条
/*-
* Copyright 2020 chenkang
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lzzip.h"
#include "bsdiff.h"
#include <string.h>
#include <masterthread.h>
#include <QObject>
#include <QDebug>
#define H(key) (((((*key) << 8) | *(key + 1))) & (HASH_SIZE - 1))
#define HASH_SIZE (1 << 16)
int LZzip(MasterThread *func_owner, uint8_t *in_data, off_t indata_len, off_t newfile_len, uint8_t *out_data, off_t *outdata_len, int zip_flag)
{
uint8_t waitzip_buf[255];
off_t waitzipbuf_len;
off_t indata_pos;
off_t last_indata_pos;
off_t outdata_pos;
off_t IndexData_Len;
off_t INDEXPOS_DIVISION1, INDEXPOS_DIVISION2, INDEXPOS_DIVISION3, INDEXPOS_DIVISION4;
off_t MATCH_DIVISION1, MATCH_DIVISION2, MATCH_DIVISION3, MATCH_DIVISION4;
hash_list *htab;
hash_list *hsearch, *htemp;
INDEXPOS_DIVISION1 = 64;
MATCH_DIVISION1 = 3;
INDEXPOS_DIVISION2 = 1 << (zip_flag / 2 + 10);
MATCH_DIVISION2 = (1 << (4 - zip_flag / 2)) + 2;
INDEXPOS_DIVISION3 = 1 << (10 + zip_flag);
MATCH_DIVISION3 = (1 << (10 - zip_flag)) + 3;
INDEXPOS_DIVISION4 = 1 << (10 + zip_flag);
MATCH_DIVISION4 = (1 << (18 - zip_flag)) + 4;
const off_t IndexMax_Len = 1<< (10 + zip_flag);
/*初始化哈希表*/
htab = new hash_list [HASH_SIZE];
memset(htab, 0, HASH_SIZE * sizeof(hash_list));
indata_pos = 0;
last_indata_pos = 0;
IndexData_Len = 0;
waitzipbuf_len = 0;
outdata_pos = 0;
outdata_pos += 8;
out_data[outdata_pos++] = zip_flag;
out_data[outdata_pos++] = in_data[indata_pos++];
if((++IndexData_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
while(indata_pos < indata_len - 1){
off_t MaxIndex_Pos = 0;
off_t MaxMatch_Len = 0;
if((last_indata_pos / (indata_len / 50)) != (indata_pos / (indata_len / 50))){
emit func_owner->Complete_Rate(50 + indata_pos / (indata_len / 50));
}
last_indata_pos = indata_pos;
/*更新哈希表*/
// if(addmatch_len > IndexMax_Len){
// ip = &in_data[indata_pos] - IndexMax_Len;
// addmatch_len = IndexMax_Len;
// }
// while(addmatch_len--){
// hash_index = H(ip);
// hsearch = &htab[hash_index];
// if(hsearch->next){
// if(&in_data[indata_pos] - hsearch->next->anchor > IndexMax_Len){
// hsearch->next->anchor = ip;
// }
// else{
// htemp = new hash_list;
// htemp->anchor = ip;
// htemp->next = hsearch->next;
// htemp->prev = hsearch;
// htemp->next->prev = htemp;
// hsearch->next = htemp;
// }
// }
// else{
// htemp = new hash_list;
// htemp->anchor = ip;
// htemp->next = NULL;
// htemp->prev = hsearch;
// hsearch->next = htemp;
// }
// ip++;
// }
/*寻找匹配*/
hsearch = htab[H(&in_data[indata_pos])].next;
while(hsearch){
uint8_t *match_ip, *in_dataip;
off_t Match_Len = 2;
if(&in_data[indata_pos] - hsearch->anchor > IndexMax_Len){
hsearch->prev->next = NULL;
do{
htab[H(&in_data[indata_pos])].len--;
htemp = hsearch;
hsearch= hsearch->next;
delete htemp;
}while(hsearch);
continue;
}
match_ip = hsearch->anchor + 2;
in_dataip = &in_data[indata_pos] + 2;
while(in_dataip < (in_data + indata_len) && (*match_ip) == (*in_dataip)){
Match_Len++;
if(Match_Len >= MATCH_DIVISION4)
break;
match_ip++;
in_dataip++;
}
if((Match_Len > MaxMatch_Len)){
MaxMatch_Len = Match_Len;
MaxIndex_Pos = in_dataip - match_ip - 1;
}
hsearch = hsearch->next;
}
if(1){
htemp = new hash_list;
htemp->anchor = &in_data[indata_pos];
htemp->next = htab[H(&in_data[indata_pos])].next;
htab[H(&in_data[indata_pos])].next = htemp;
htemp->prev = &htab[H(&in_data[indata_pos])];
if(htemp->next)
htemp->next->prev = htemp;
htab[H(&in_data[indata_pos])].len++;
}
if(MaxMatch_Len <= 1){
waitzip_buf[waitzipbuf_len++] = in_data[indata_pos++];
if((++IndexData_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
if(waitzipbuf_len >= 16){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
}
else if((MaxMatch_Len <= MATCH_DIVISION1) && (MaxIndex_Pos < INDEXPOS_DIVISION1)){
if(waitzipbuf_len > 0){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
indata_pos += MaxMatch_Len;
if((IndexData_Len + MaxMatch_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
else{
IndexData_Len += MaxMatch_Len;
}
MaxMatch_Len = (MaxIndex_Pos << 1) | (MaxMatch_Len - 2);
out_data[outdata_pos++] = MaxMatch_Len;
}
else if((MaxMatch_Len <= 2) && (MaxIndex_Pos >= INDEXPOS_DIVISION1)){
waitzip_buf[waitzipbuf_len++] = in_data[indata_pos++];
if((++IndexData_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
if(waitzipbuf_len >= 16){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
}
else if((MaxMatch_Len <= MATCH_DIVISION2) && (MaxIndex_Pos < INDEXPOS_DIVISION2)){
if(waitzipbuf_len > 0){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
indata_pos += MaxMatch_Len;
if((IndexData_Len + MaxMatch_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
else{
IndexData_Len += MaxMatch_Len;
}
switch(INDEXPOS_DIVISION2){
case 1 << 10:
MaxMatch_Len = (MaxIndex_Pos << 4) | (MaxMatch_Len - 3) | (1 << 15);
break;
case 1 << 11:
MaxMatch_Len = (MaxIndex_Pos << 3) | (MaxMatch_Len - 3) | (1 << 15);
break;
case 1 << 12:
MaxMatch_Len = (MaxIndex_Pos << 2) | (MaxMatch_Len - 3) | (1 << 15);
break;
default:
break;
}
out_data[outdata_pos++] = (MaxMatch_Len >> 8) & 0xff; //控制数据中高位位于低地址,低位位于高地址
out_data[outdata_pos++] = MaxMatch_Len & 0xff;
}
else if((MaxMatch_Len <= 3) && (MaxIndex_Pos >= INDEXPOS_DIVISION2)){
waitzip_buf[waitzipbuf_len++] = in_data[indata_pos++];
if((++IndexData_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
if(waitzipbuf_len >= 16){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
}
else if((MaxMatch_Len <= MATCH_DIVISION3) && (MaxIndex_Pos < INDEXPOS_DIVISION3)){
if(waitzipbuf_len > 0){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
indata_pos += MaxMatch_Len;
if((IndexData_Len + MaxMatch_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
else{
IndexData_Len += MaxMatch_Len;
}
switch(INDEXPOS_DIVISION3){
case 1 << 10:
MaxMatch_Len = (MaxIndex_Pos << 10) | (MaxMatch_Len - 4) | (3 << 22);
break;
case 1 << 11:
MaxMatch_Len = (MaxIndex_Pos << 9) | (MaxMatch_Len - 4) | (3 << 22);
break;
case 1 << 12:
MaxMatch_Len = (MaxIndex_Pos << 8) | (MaxMatch_Len - 4) | (3 << 22);
break;
case 1 << 13:
MaxMatch_Len = (MaxIndex_Pos << 7) | (MaxMatch_Len - 4) | (3 << 22);
break;
case 1 << 14:
MaxMatch_Len = (MaxIndex_Pos << 6) | (MaxMatch_Len - 4) | (3 << 22);
break;
case 1 << 15:
MaxMatch_Len = (MaxIndex_Pos << 5) | (MaxMatch_Len - 4) | (3 << 22);
break;
default:
break;
}
out_data[outdata_pos++] = (MaxMatch_Len >> 16) & 0xff;
out_data[outdata_pos++] = (MaxMatch_Len >> 8) & 0xff;
out_data[outdata_pos++] = MaxMatch_Len & 0xff;
}
else if((MaxMatch_Len <= 4) && (MaxIndex_Pos >= INDEXPOS_DIVISION3)){
waitzip_buf[waitzipbuf_len++] = in_data[indata_pos++];
if((++IndexData_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
if(waitzipbuf_len >= 16){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
}
else{
if(waitzipbuf_len > 0){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
indata_pos += MaxMatch_Len;
if((IndexData_Len + MaxMatch_Len) > IndexMax_Len){
IndexData_Len = IndexMax_Len;
}
else{
IndexData_Len += MaxMatch_Len;
}
switch(INDEXPOS_DIVISION4){
case 1 << 10:
MaxMatch_Len = (MaxIndex_Pos << 18) | (MaxMatch_Len - 5) | (7 << 29);
break;
case 1 << 11:
MaxMatch_Len = (MaxIndex_Pos << 17) | (MaxMatch_Len - 5) | (7 << 29);
break;
case 1 << 12:
MaxMatch_Len = (MaxIndex_Pos << 16) | (MaxMatch_Len - 5) | (7 << 29);
break;
case 1 << 13:
MaxMatch_Len = (MaxIndex_Pos << 15) | (MaxMatch_Len - 5) | (7 << 29);
break;
case 1 << 14:
MaxMatch_Len = (MaxIndex_Pos << 14) | (MaxMatch_Len - 5) | (7 << 29);
break;
case 1 << 15:
MaxMatch_Len = (MaxIndex_Pos << 13) | (MaxMatch_Len - 5) | (7 << 29);
break;
default:
break;
}
out_data[outdata_pos++] = (MaxMatch_Len >> 24) & 0xff;
out_data[outdata_pos++] = (MaxMatch_Len >> 16) & 0xff;
out_data[outdata_pos++] = (MaxMatch_Len >> 8) & 0xff;
out_data[outdata_pos++] = MaxMatch_Len & 0xff;
}
}
if(indata_pos == indata_len - 1){
waitzip_buf[waitzipbuf_len++] = in_data[indata_pos++];
}
if(waitzipbuf_len){
out_data[outdata_pos++] = (waitzipbuf_len - 1) | 0xf0;
for(off_t i = 0; i < waitzipbuf_len; i++)
out_data[outdata_pos++] = waitzip_buf[i];
waitzipbuf_len = 0;
}
*outdata_len = outdata_pos;
out_data [4] = newfile_len & 0xff;
out_data [5] = (newfile_len >> 8) & 0xff;
out_data [6] = (newfile_len >> 16) & 0xff;
out_data [7] = (newfile_len >> 24) & 0xff;
for(int i = 0; i < HASH_SIZE; i++){
hsearch = htab[i].next;
while(hsearch){
htemp = hsearch;
hsearch = hsearch->next;
delete htemp;
}
}
return outdata_pos;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化