946 lines
42 KiB
C
Raw Normal View History

// vcpatch_wrapper.c
// HDiffPatch
/*
The MIT License (MIT)
Copyright (c) 2022 HouSisong
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "vcpatch_wrapper.h"
#include "../libHDiffPatch/HPatch/patch_types.h"
#include "../libHDiffPatch/HPatch/patch_private.h"
#include "../libHDiffPatch/HDiff/private_diff/limit_mem_diff/adler_roll.h"
#include "vcpatch_code_table.h"
#include <string.h>
#define _hpatch_FALSE hpatch_FALSE
//hpatch_uint __vcpatch_debug_check_false_x=0; //for debug
//#define _hpatch_FALSE (1/__vcpatch_debug_check_false_x)
#ifndef _IS_RUN_MEM_SAFE_CHECK
# define _IS_RUN_MEM_SAFE_CHECK 1
#endif
#if (_IS_RUN_MEM_SAFE_CHECK)
//__RUN_MEM_SAFE_CHECK用来启动内存访问越界检查,用以防御可能被意外或故意损坏的数据.
# define __RUN_MEM_SAFE_CHECK
#endif
static const hpatch_byte kVcDiffType[3]={('V'|(1<<7)),('C'|(1<<7)),('D'|(1<<7))};
#define kVcDiffDefaultVersion 0
#define kVcDiffGoogleVersion 'S'
#define kVcDiffMinHeadLen (sizeof(kVcDiffType)+1+1)
static const char* kHDiffzAppHead_a="$hdiffz-VCDIFF&7zXZ#a";
#define kHDiffzAppHeadLen 21 // = strlen(kHDiffzAppHead_a);
#define _clip_unpackUInt64(_clip,_result) { \
if (!_TStreamCacheClip_unpackUIntWithTag(_clip,_result,0)) \
return _hpatch_FALSE; \
}
#define _clip_readUInt8(_clip,_result) { \
const hpatch_byte* buf=_TStreamCacheClip_readData(_clip,1); \
if (buf!=0) *(_result)=*buf; \
else return _hpatch_FALSE; \
}
#define _clip_readUInt32_BigEndian(_clip,_result) { \
const hpatch_byte* buf=_TStreamCacheClip_readData(_clip,4); \
if (buf!=0) *(_result)=(((hpatch_uint32_t)buf[0])<<24)|(((hpatch_uint32_t)buf[1])<<16) \
|(((hpatch_uint32_t)buf[2])<<8)|((hpatch_uint32_t)buf[3]); \
else return _hpatch_FALSE; \
}
#define N vcdiff_code_NOOP
#define A vcdiff_code_ADD
#define R vcdiff_code_RUN
#define C vcdiff_code_COPY
#define C0 (C+0)
#define C1 (C+1)
#define C2 (C+2)
#define C3 (C+3)
#define C4 (C+4)
#define C5 (C+5)
#define C6 (C+6)
#define C7 (C+7)
#define C8 (C+8)
/*
TYPE SIZE MODE TYPE SIZE MODE INDEX
---------------------------------------------------------------
1. RUN 0 0 NOOP 0 0 0
2. ADD 0, [1,17] 0 NOOP 0 0 [1,18]
3. COPY 0, [4,18] 0 NOOP 0 0 [19,34]
4. COPY 0, [4,18] 1 NOOP 0 0 [35,50]
5. COPY 0, [4,18] 2 NOOP 0 0 [51,66]
6. COPY 0, [4,18] 3 NOOP 0 0 [67,82]
7. COPY 0, [4,18] 4 NOOP 0 0 [83,98]
8. COPY 0, [4,18] 5 NOOP 0 0 [99,114]
9. COPY 0, [4,18] 6 NOOP 0 0 [115,130]
10. COPY 0, [4,18] 7 NOOP 0 0 [131,146]
11. COPY 0, [4,18] 8 NOOP 0 0 [147,162]
12. ADD [1,4] 0 COPY [4,6] 0 [163,174]
13. ADD [1,4] 0 COPY [4,6] 1 [175,186]
14. ADD [1,4] 0 COPY [4,6] 2 [187,198]
15. ADD [1,4] 0 COPY [4,6] 3 [199,210]
16. ADD [1,4] 0 COPY [4,6] 4 [211,222]
17. ADD [1,4] 0 COPY [4,6] 5 [223,234]
18. ADD [1,4] 0 COPY 4 6 [235,238]
19. ADD [1,4] 0 COPY 4 7 [239,242]
20. ADD [1,4] 0 COPY 4 8 [243,246]
21. COPY 4 [0,8] ADD 1 0 [247,255]
---------------------------------------------------------------
*/
/* //gen _vcdiff_code_table_default
static hpatch_byte* __incset(hpatch_byte* cur,hpatch_byte blockLen,hpatch_byte v,hpatch_byte runCount){
while (runCount--){
hpatch_byte runLen=blockLen;
while (runLen--){
*cur=v;
cur+=sizeof(vcdiff_code_pair_t);
}
v++;
}
return cur;
}
static hpatch_inline hpatch_byte* _inc(hpatch_byte* cur,hpatch_byte blockLen,hpatch_byte v,hpatch_byte indexs){
hpatch_byte runCount=(indexs+1)/blockLen;
assert(blockLen*runCount==(indexs+1));
return __incset(cur,blockLen,v,runCount);
}
static hpatch_inline hpatch_byte* _set(hpatch_byte* cur,hpatch_byte v,hpatch_byte indexs){
return __incset(cur,(indexs+1),v,1); }
static hpatch_byte* _cpy(hpatch_byte* cur, hpatch_byte blockLen, hpatch_byte indexs) {
hpatch_byte runCount=(indexs+1)/blockLen;
assert(blockLen*runCount==(indexs+1));
const hpatch_size_t offset=(hpatch_size_t)blockLen*sizeof(vcdiff_code_pair_t);
while (runCount--){
hpatch_byte runLen=blockLen;
while (runLen--){
*cur=cur[-offset];
cur+=sizeof(vcdiff_code_pair_t);
}
}
return cur;
}
static int _set_vcdiff_code_table_default(vcdiff_code_table_t code_table){
hpatch_byte* cur0,* cur;
cur0=&code_table[0].code1.inst;
cur=cur0;
cur=_set(cur,R,0);
cur=_set(cur,A,18-1);
cur=_inc(cur,16,C,162-19);
cur=_set(cur,A,246-163);
cur=_inc(cur,1,C,255-247);
assert((cur-cur0)==256*sizeof(vcdiff_code_pair_t));
cur0=&code_table[0].code2.inst;
cur=cur0;
cur=_set(cur,N,162-0);
cur=_inc(cur,12,C,234-163);
cur=_inc(cur,4,C+6,246-235);
cur=_set(cur,A,255-247);
assert((cur-cur0)==256*sizeof(vcdiff_code_pair_t));
cur0=&code_table[0].code1.size;
cur=cur0;
cur=_inc(cur,1,0,0);
cur=_inc(cur,1,0,18-1);
cur=_inc(cur,1,0,19-19);
cur=_inc(cur,1,4,34-20);
cur=_cpy(cur,16,162-35);
cur=_inc(cur,3,1,174-163);
cur=_cpy(cur,12,234-175);
cur=_inc(cur,1,1,238-235);
cur=_cpy(cur,4,246-239);
cur=_set(cur,4,255-247);
assert((cur-cur0)==256*sizeof(vcdiff_code_pair_t));
cur0=&code_table[0].code2.size;
cur=cur0;
cur=_set(cur,0,162-0);
cur=_inc(cur,1,4,165-163);
cur=_cpy(cur,3,234-166);
cur=_set(cur,4,246-235);
cur=_set(cur,1,255-247);
assert((cur-cur0)==256*sizeof(vcdiff_code_pair_t));
return 0;
}
vcdiff_code_pair_t g_code_table[256];
int _print_vcdiff_code_table_default(){
_set_vcdiff_code_table_default(g_code_table);
const char* inst2s[4+8]={" N"," A"," R","C0","C1","C2","C3","C4","C5","C6","C7","C8"};
for (int i=0;i<256;++i){
vcdiff_code_pair_t c=g_code_table[i];
printf("{{%s,%2d},{%s,%2d}},",inst2s[c.code1.inst],c.code1.size,inst2s[c.code2.inst],c.code2.size);
if (((i+1)&7)==0) printf("\n");
}
return 0;
}
*/
//_vcdiff_code_table_default gen by _print_vcdiff_code_table_default()
static const vcdiff_code_pair_t _vcdiff_code_table_default[256]={
{{ R, 0},{ N, 0}},{{ A, 0},{ N, 0}},{{ A, 1},{ N, 0}},{{ A, 2},{ N, 0}},{{ A, 3},{ N, 0}},{{ A, 4},{ N, 0}},{{ A, 5},{ N, 0}},{{ A, 6},{ N, 0}},
{{ A, 7},{ N, 0}},{{ A, 8},{ N, 0}},{{ A, 9},{ N, 0}},{{ A,10},{ N, 0}},{{ A,11},{ N, 0}},{{ A,12},{ N, 0}},{{ A,13},{ N, 0}},{{ A,14},{ N, 0}},
{{ A,15},{ N, 0}},{{ A,16},{ N, 0}},{{ A,17},{ N, 0}},{{C0, 0},{ N, 0}},{{C0, 4},{ N, 0}},{{C0, 5},{ N, 0}},{{C0, 6},{ N, 0}},{{C0, 7},{ N, 0}},
{{C0, 8},{ N, 0}},{{C0, 9},{ N, 0}},{{C0,10},{ N, 0}},{{C0,11},{ N, 0}},{{C0,12},{ N, 0}},{{C0,13},{ N, 0}},{{C0,14},{ N, 0}},{{C0,15},{ N, 0}},
{{C0,16},{ N, 0}},{{C0,17},{ N, 0}},{{C0,18},{ N, 0}},{{C1, 0},{ N, 0}},{{C1, 4},{ N, 0}},{{C1, 5},{ N, 0}},{{C1, 6},{ N, 0}},{{C1, 7},{ N, 0}},
{{C1, 8},{ N, 0}},{{C1, 9},{ N, 0}},{{C1,10},{ N, 0}},{{C1,11},{ N, 0}},{{C1,12},{ N, 0}},{{C1,13},{ N, 0}},{{C1,14},{ N, 0}},{{C1,15},{ N, 0}},
{{C1,16},{ N, 0}},{{C1,17},{ N, 0}},{{C1,18},{ N, 0}},{{C2, 0},{ N, 0}},{{C2, 4},{ N, 0}},{{C2, 5},{ N, 0}},{{C2, 6},{ N, 0}},{{C2, 7},{ N, 0}},
{{C2, 8},{ N, 0}},{{C2, 9},{ N, 0}},{{C2,10},{ N, 0}},{{C2,11},{ N, 0}},{{C2,12},{ N, 0}},{{C2,13},{ N, 0}},{{C2,14},{ N, 0}},{{C2,15},{ N, 0}},
{{C2,16},{ N, 0}},{{C2,17},{ N, 0}},{{C2,18},{ N, 0}},{{C3, 0},{ N, 0}},{{C3, 4},{ N, 0}},{{C3, 5},{ N, 0}},{{C3, 6},{ N, 0}},{{C3, 7},{ N, 0}},
{{C3, 8},{ N, 0}},{{C3, 9},{ N, 0}},{{C3,10},{ N, 0}},{{C3,11},{ N, 0}},{{C3,12},{ N, 0}},{{C3,13},{ N, 0}},{{C3,14},{ N, 0}},{{C3,15},{ N, 0}},
{{C3,16},{ N, 0}},{{C3,17},{ N, 0}},{{C3,18},{ N, 0}},{{C4, 0},{ N, 0}},{{C4, 4},{ N, 0}},{{C4, 5},{ N, 0}},{{C4, 6},{ N, 0}},{{C4, 7},{ N, 0}},
{{C4, 8},{ N, 0}},{{C4, 9},{ N, 0}},{{C4,10},{ N, 0}},{{C4,11},{ N, 0}},{{C4,12},{ N, 0}},{{C4,13},{ N, 0}},{{C4,14},{ N, 0}},{{C4,15},{ N, 0}},
{{C4,16},{ N, 0}},{{C4,17},{ N, 0}},{{C4,18},{ N, 0}},{{C5, 0},{ N, 0}},{{C5, 4},{ N, 0}},{{C5, 5},{ N, 0}},{{C5, 6},{ N, 0}},{{C5, 7},{ N, 0}},
{{C5, 8},{ N, 0}},{{C5, 9},{ N, 0}},{{C5,10},{ N, 0}},{{C5,11},{ N, 0}},{{C5,12},{ N, 0}},{{C5,13},{ N, 0}},{{C5,14},{ N, 0}},{{C5,15},{ N, 0}},
{{C5,16},{ N, 0}},{{C5,17},{ N, 0}},{{C5,18},{ N, 0}},{{C6, 0},{ N, 0}},{{C6, 4},{ N, 0}},{{C6, 5},{ N, 0}},{{C6, 6},{ N, 0}},{{C6, 7},{ N, 0}},
{{C6, 8},{ N, 0}},{{C6, 9},{ N, 0}},{{C6,10},{ N, 0}},{{C6,11},{ N, 0}},{{C6,12},{ N, 0}},{{C6,13},{ N, 0}},{{C6,14},{ N, 0}},{{C6,15},{ N, 0}},
{{C6,16},{ N, 0}},{{C6,17},{ N, 0}},{{C6,18},{ N, 0}},{{C7, 0},{ N, 0}},{{C7, 4},{ N, 0}},{{C7, 5},{ N, 0}},{{C7, 6},{ N, 0}},{{C7, 7},{ N, 0}},
{{C7, 8},{ N, 0}},{{C7, 9},{ N, 0}},{{C7,10},{ N, 0}},{{C7,11},{ N, 0}},{{C7,12},{ N, 0}},{{C7,13},{ N, 0}},{{C7,14},{ N, 0}},{{C7,15},{ N, 0}},
{{C7,16},{ N, 0}},{{C7,17},{ N, 0}},{{C7,18},{ N, 0}},{{C8, 0},{ N, 0}},{{C8, 4},{ N, 0}},{{C8, 5},{ N, 0}},{{C8, 6},{ N, 0}},{{C8, 7},{ N, 0}},
{{C8, 8},{ N, 0}},{{C8, 9},{ N, 0}},{{C8,10},{ N, 0}},{{C8,11},{ N, 0}},{{C8,12},{ N, 0}},{{C8,13},{ N, 0}},{{C8,14},{ N, 0}},{{C8,15},{ N, 0}},
{{C8,16},{ N, 0}},{{C8,17},{ N, 0}},{{C8,18},{ N, 0}},{{ A, 1},{C0, 4}},{{ A, 1},{C0, 5}},{{ A, 1},{C0, 6}},{{ A, 2},{C0, 4}},{{ A, 2},{C0, 5}},
{{ A, 2},{C0, 6}},{{ A, 3},{C0, 4}},{{ A, 3},{C0, 5}},{{ A, 3},{C0, 6}},{{ A, 4},{C0, 4}},{{ A, 4},{C0, 5}},{{ A, 4},{C0, 6}},{{ A, 1},{C1, 4}},
{{ A, 1},{C1, 5}},{{ A, 1},{C1, 6}},{{ A, 2},{C1, 4}},{{ A, 2},{C1, 5}},{{ A, 2},{C1, 6}},{{ A, 3},{C1, 4}},{{ A, 3},{C1, 5}},{{ A, 3},{C1, 6}},
{{ A, 4},{C1, 4}},{{ A, 4},{C1, 5}},{{ A, 4},{C1, 6}},{{ A, 1},{C2, 4}},{{ A, 1},{C2, 5}},{{ A, 1},{C2, 6}},{{ A, 2},{C2, 4}},{{ A, 2},{C2, 5}},
{{ A, 2},{C2, 6}},{{ A, 3},{C2, 4}},{{ A, 3},{C2, 5}},{{ A, 3},{C2, 6}},{{ A, 4},{C2, 4}},{{ A, 4},{C2, 5}},{{ A, 4},{C2, 6}},{{ A, 1},{C3, 4}},
{{ A, 1},{C3, 5}},{{ A, 1},{C3, 6}},{{ A, 2},{C3, 4}},{{ A, 2},{C3, 5}},{{ A, 2},{C3, 6}},{{ A, 3},{C3, 4}},{{ A, 3},{C3, 5}},{{ A, 3},{C3, 6}},
{{ A, 4},{C3, 4}},{{ A, 4},{C3, 5}},{{ A, 4},{C3, 6}},{{ A, 1},{C4, 4}},{{ A, 1},{C4, 5}},{{ A, 1},{C4, 6}},{{ A, 2},{C4, 4}},{{ A, 2},{C4, 5}},
{{ A, 2},{C4, 6}},{{ A, 3},{C4, 4}},{{ A, 3},{C4, 5}},{{ A, 3},{C4, 6}},{{ A, 4},{C4, 4}},{{ A, 4},{C4, 5}},{{ A, 4},{C4, 6}},{{ A, 1},{C5, 4}},
{{ A, 1},{C5, 5}},{{ A, 1},{C5, 6}},{{ A, 2},{C5, 4}},{{ A, 2},{C5, 5}},{{ A, 2},{C5, 6}},{{ A, 3},{C5, 4}},{{ A, 3},{C5, 5}},{{ A, 3},{C5, 6}},
{{ A, 4},{C5, 4}},{{ A, 4},{C5, 5}},{{ A, 4},{C5, 6}},{{ A, 1},{C6, 4}},{{ A, 2},{C6, 4}},{{ A, 3},{C6, 4}},{{ A, 4},{C6, 4}},{{ A, 1},{C7, 4}},
{{ A, 2},{C7, 4}},{{ A, 3},{C7, 4}},{{ A, 4},{C7, 4}},{{ A, 1},{C8, 4}},{{ A, 2},{C8, 4}},{{ A, 3},{C8, 4}},{{ A, 4},{C8, 4}},{{C0, 4},{ A, 1}},
{{C1, 4},{ A, 1}},{{C2, 4},{ A, 1}},{{C3, 4},{ A, 1}},{{C4, 4},{ A, 1}},{{C5, 4},{ A, 1}},{{C6, 4},{ A, 1}},{{C7, 4},{ A, 1}},{{C8, 4},{ A, 1}}
};
const vcdiff_code_table_t get_vcdiff_code_table_default(){
return &_vcdiff_code_table_default[0];
}
#undef N
#undef A
#undef R
#undef C
#undef C0
#undef C1
#undef C2
#undef C3
#undef C4
#undef C5
#undef C6
#undef C7
#undef C8
#define _kWindowCacheSize 1024
static hpatch_BOOL _getVcDiffWindowSizes(hpatch_VcDiffInfo* out_diffinfo,const hpatch_TStreamInput* diffStream);
hpatch_BOOL getVcDiffInfo(hpatch_VcDiffInfo* out_diffinfo,const hpatch_TStreamInput* diffStream,
hpatch_BOOL isNeedWindowSize){
TStreamCacheClip diffClip;
hpatch_byte _window_cache[_kWindowCacheSize];
hpatch_byte Hdr_Indicator;
memset(out_diffinfo,0,sizeof(*out_diffinfo));
if (diffStream->streamSize<kVcDiffMinHeadLen)
return _hpatch_FALSE;
assert(kVcDiffMinHeadLen<=_kWindowCacheSize);
_TStreamCacheClip_init(&diffClip,diffStream,0,diffStream->streamSize,_window_cache,sizeof(_window_cache));
{//head
const hpatch_byte* buf=_TStreamCacheClip_readData(&diffClip,kVcDiffMinHeadLen);
if (buf==0)
return _hpatch_FALSE;
if (0!=memcmp(buf,kVcDiffType,sizeof(kVcDiffType)))
return _hpatch_FALSE; //not VCDIFF
buf+=sizeof(kVcDiffType);
switch (*buf++){ // version
case kVcDiffDefaultVersion: out_diffinfo->isGoogleVersion=hpatch_FALSE; break;
case kVcDiffGoogleVersion: out_diffinfo->isGoogleVersion=hpatch_TRUE; break;
default:
return _hpatch_FALSE; //unsupport version
}
Hdr_Indicator=*buf++; // Hdr_Indicator
}
if (Hdr_Indicator&(1<<0)){ // VCD_DECOMPRESS
_clip_readUInt8(&diffClip,&out_diffinfo->compressorID);
if (out_diffinfo->compressorID!=kVcDiff_compressorID_7zXZ)
return _hpatch_FALSE; //unsupport compressor ID
}
if (Hdr_Indicator&(1<<1)) // VCD_CODETABLE
return _hpatch_FALSE; // unsupport code table
if (Hdr_Indicator&(1<<2)) // VCD_APPHEADER
_clip_unpackUInt64(&diffClip,&out_diffinfo->appHeadDataLen);
out_diffinfo->appHeadDataOffset=_TStreamCacheClip_readPosOfSrcStream(&diffClip);
out_diffinfo->windowOffset=out_diffinfo->appHeadDataOffset+out_diffinfo->appHeadDataLen;
#ifdef __RUN_MEM_SAFE_CHECK
{
const hpatch_StreamPos_t maxPos=_TStreamCacheClip_leaveSize(&diffClip);
if ( (out_diffinfo->appHeadDataLen>maxPos)|(out_diffinfo->windowOffset>maxPos) )
return _hpatch_FALSE; //data size error
}
#endif
assert(kHDiffzAppHeadLen==strlen(kHDiffzAppHead_a));
assert(kHDiffzAppHeadLen<=_kWindowCacheSize);
if (out_diffinfo->appHeadDataLen==kHDiffzAppHeadLen){
const hpatch_byte* pAppHead=_TStreamCacheClip_accessData(&diffClip,kHDiffzAppHeadLen);
if (pAppHead==0)
return _hpatch_FALSE;
if (0==memcmp(pAppHead,kHDiffzAppHead_a,kHDiffzAppHeadLen))
out_diffinfo->isHDiffzAppHead_a=hpatch_TRUE;
}
if (isNeedWindowSize){
return _getVcDiffWindowSizes(out_diffinfo,diffStream);
}else{
out_diffinfo->maxSrcWindowsSize=hpatch_kNullStreamPos;
out_diffinfo->maxTargetWindowsSize=hpatch_kNullStreamPos;
out_diffinfo->sumTargetWindowsSize=hpatch_kNullStreamPos;
return hpatch_TRUE;
}
}
hpatch_BOOL getVcDiffInfo_mem(hpatch_VcDiffInfo* out_diffinfo,const hpatch_byte* diffData,
const hpatch_byte* diffData_end,hpatch_BOOL isNeedWindowSize){
hpatch_TStreamInput diffStream;
mem_as_hStreamInput(&diffStream,diffData,diffData_end);
return getVcDiffInfo(out_diffinfo,&diffStream,isNeedWindowSize);
}
hpatch_BOOL getIsVcDiff(const hpatch_TStreamInput* diffData){
hpatch_VcDiffInfo diffinfo;
return getVcDiffInfo(&diffinfo,diffData,hpatch_FALSE);
}
hpatch_BOOL getIsVcDiff_mem(const hpatch_byte* diffData,const hpatch_byte* diffData_end){
hpatch_TStreamInput diffStream;
mem_as_hStreamInput(&diffStream,diffData,diffData_end);
return getIsVcDiff(&diffStream);
}
typedef struct{
hpatch_BOOL isGoogleVersion;
hpatch_BOOL isNeedChecksum;
hpatch_BOOL window_isHaveAdler32;
hpatch_uint32_t window_savedAdler32;
hpatch_uint32_t window_curAdler32;
const hpatch_TStreamOutput* _dstStream;
hpatch_TStreamOutput _hookStream;
} vcpatch_checksum_t;
static hpatch_inline void vcpatch_checksum_init(vcpatch_checksum_t* self,hpatch_BOOL isGoogleVersion,
hpatch_BOOL isNeedChecksum,hpatch_BOOL window_isHaveAdler32){
memset(self,0,sizeof(*self));
self->isGoogleVersion=isGoogleVersion;
self->isNeedChecksum=isNeedChecksum;
self->window_isHaveAdler32=window_isHaveAdler32;
}
#define vcpatch_checksum_readAdler32(self,diffClip){ \
if ((self)->window_isHaveAdler32){ \
if ((self)->isGoogleVersion){ \
hpatch_StreamPos_t _v; \
_clip_unpackUInt64(diffClip,&_v); \
if ((_v>>32)>0) return _hpatch_FALSE; /*error data or no data*/ \
(self)->window_savedAdler32=(hpatch_uint32_t)_v; \
}else{ \
_clip_readUInt32_BigEndian(diffClip,&(self)->window_savedAdler32); \
} \
} }
static hpatch_BOOL __vcpatch_checksum_read_writed(const struct hpatch_TStreamOutput* stream,hpatch_StreamPos_t readFromPos,
hpatch_byte* out_data,hpatch_byte* out_data_end){
vcpatch_checksum_t* self=(vcpatch_checksum_t*)stream->streamImport;
return self->_dstStream->read_writed(self->_dstStream,readFromPos,out_data,out_data_end);
}
static hpatch_BOOL __vcpatch_checksum_write(const struct hpatch_TStreamOutput* stream,hpatch_StreamPos_t writeToPos,
const hpatch_byte* data,const hpatch_byte* data_end){
vcpatch_checksum_t* self=(vcpatch_checksum_t*)stream->streamImport;
self->window_curAdler32=adler32_append(self->window_curAdler32,data,data_end-data);
return self->_dstStream->write(self->_dstStream,writeToPos,data,data_end);
}
static hpatch_BOOL __vcpatch_checksum_begin_(vcpatch_checksum_t* self,_TOutStreamCache* outCache){
assert(self->_dstStream==0);
assert(_TOutStreamCache_cachedDataSize(outCache)==0);
self->_hookStream.streamImport=self;
self->_hookStream.streamSize=outCache->dstStream->streamSize;
self->_hookStream.read_writed=(outCache->dstStream->read_writed?__vcpatch_checksum_read_writed:0);
self->_hookStream.write=__vcpatch_checksum_write;
self->_dstStream=outCache->dstStream;
outCache->dstStream=&self->_hookStream;
self->window_curAdler32=(self->isGoogleVersion?0:1);
return hpatch_TRUE;
}
static hpatch_BOOL __vcpatch_checksum_end_(vcpatch_checksum_t* self,_TOutStreamCache* outCache){
assert(self->_dstStream!=0);
assert(outCache->dstStream==&self->_hookStream);
assert(_TOutStreamCache_cachedDataSize(outCache)==0);
outCache->dstStream=self->_dstStream;
self->_dstStream=0;
return self->window_curAdler32==self->window_savedAdler32;
}
static hpatch_inline hpatch_BOOL vcpatch_checksum_begin(vcpatch_checksum_t* self,_TOutStreamCache* outCache){
if ((self)->isNeedChecksum&(self)->window_isHaveAdler32)
return __vcpatch_checksum_begin_(self,outCache);
else
return hpatch_TRUE;
}
static hpatch_inline hpatch_BOOL vcpatch_checksum_end(vcpatch_checksum_t* self,_TOutStreamCache* outCache){
if ((self)->isNeedChecksum&(self)->window_isHaveAdler32)
return __vcpatch_checksum_end_(self,outCache);
else
return hpatch_TRUE;
}
hpatch_BOOL _vcpatch_delta(_TOutStreamCache* outCache,hpatch_StreamPos_t targetLen,
const hpatch_TStreamInput* srcData,hpatch_StreamPos_t srcPos,hpatch_StreamPos_t srcLen,
TStreamCacheClip* dataClip,TStreamCacheClip* instClip,TStreamCacheClip* addrClip){
hpatch_StreamPos_t same_array[vcdiff_s_same*256]={0};
hpatch_StreamPos_t near_array[vcdiff_s_near]={0};
hpatch_StreamPos_t here=0;
hpatch_StreamPos_t near_index=0;
const vcdiff_code_table_t code_table=get_vcdiff_code_table_default();
while (here<targetLen){
const vcdiff_code_t* codes;
const vcdiff_code_t* codes_end;
{
hpatch_byte insti;
_clip_readUInt8(instClip,&insti);
codes=(const vcdiff_code_t*)&code_table[insti];
assert(codes[0].inst!=vcdiff_code_NOOP);
codes_end=codes+((codes[1].inst==vcdiff_code_NOOP)?1:2);
}
for (;codes<codes_end;++codes){
hpatch_StreamPos_t addr;
hpatch_StreamPos_t cur_here=here;
hpatch_StreamPos_t size=codes->size;
const hpatch_size_t inst=codes->inst;
assert(inst<=vcdiff_code_MAX);
if (size==0)
_clip_unpackUInt64(instClip,&size);
here+=size;
#ifdef __RUN_MEM_SAFE_CHECK
if (here>targetLen)
return _hpatch_FALSE;
#endif
switch (inst){
case vcdiff_code_ADD: {
if (!_TOutStreamCache_copyFromClip(outCache,dataClip,size))
return _hpatch_FALSE;
} continue;
case vcdiff_code_RUN: {
hpatch_byte v;
_clip_readUInt8(dataClip,&v);
if (!_TOutStreamCache_fill(outCache,v,size))
return _hpatch_FALSE;
} continue;
case vcdiff_code_COPY_SELF:
case vcdiff_code_COPY_HERE:
case vcdiff_code_COPY_NEAR0:
case vcdiff_code_COPY_NEAR1:
case vcdiff_code_COPY_NEAR2:
case vcdiff_code_COPY_NEAR3: {
_clip_unpackUInt64(addrClip,&addr);
switch (inst){
case vcdiff_code_COPY_SELF: {
} break;
case vcdiff_code_COPY_HERE: {
addr=srcLen+cur_here-addr;
} break;
default: {
addr+=near_array[inst-vcdiff_code_COPY_NEAR0];
} break;
}
} break;
default: { // vcdiff_code_COPY_SAME
hpatch_byte samei;
_clip_readUInt8(addrClip,&samei);
addr=same_array[((hpatch_size_t)(inst-vcdiff_code_COPY_SAME0))*256+samei];
} break;
}//switch inst
vcdiff_update_addr(same_array,near_array,&near_index,addr);
if (addr<srcLen){//copy from src
hpatch_StreamPos_t copyLen=(addr+size<=srcLen)?size:srcLen-addr;
if (!_TOutStreamCache_copyFromStream(outCache,srcData,srcPos+addr,copyLen))
return _hpatch_FALSE;
cur_here+=copyLen;
addr+=copyLen;
size-=copyLen;
}
if (size>0){ //copy from outCache
addr-=srcLen;
#ifdef __RUN_MEM_SAFE_CHECK
if (addr>=cur_here)
return _hpatch_FALSE;
#endif
if (!_TOutStreamCache_copyFromSelf(outCache,cur_here-addr,size))
return _hpatch_FALSE;
}
}//for codes
}//while
return hpatch_TRUE;
}
static hpatch_BOOL _getStreamClip(TStreamCacheClip* clip,hpatch_byte Delta_Indicator,hpatch_byte index,
const hpatch_TStreamInput* diffStream,hpatch_StreamPos_t* curDiffOffset,
hpatch_TDecompress* decompressPlugin,_TDecompressInputStream* decompressers,
hpatch_StreamPos_t dataLen,hpatch_byte* temp_cache,hpatch_size_t cache_size){
hpatch_StreamPos_t uncompressedLen;
hpatch_StreamPos_t compressedLen;
if ((Delta_Indicator&(1<<index))){
hpatch_StreamPos_t readedBytes;
TStreamCacheClip tempClip;
hpatch_byte _temp_cache[hpatch_kMaxPackedUIntBytes];
_TStreamCacheClip_init(&tempClip,diffStream,*curDiffOffset,
diffStream->streamSize,_temp_cache,sizeof(_temp_cache));
_clip_unpackUInt64(&tempClip,&uncompressedLen);
readedBytes=_TStreamCacheClip_readPosOfSrcStream(&tempClip)-(*curDiffOffset);
(*curDiffOffset)+=readedBytes;
compressedLen=dataLen-readedBytes;
}else{
uncompressedLen=dataLen;
compressedLen=0;
}
return getStreamClip(clip,&decompressers[index],uncompressedLen,compressedLen,diffStream,
curDiffOffset,decompressPlugin,temp_cache,cache_size);
}
static hpatch_BOOL _getVcDiffWindowSizes(hpatch_VcDiffInfo* out_diffinfo,const hpatch_TStreamInput* diffStream){
hpatch_StreamPos_t windowOffset=out_diffinfo->windowOffset;
hpatch_StreamPos_t maxSrcWindowsSize=0;
hpatch_StreamPos_t maxTargetWindowsSize=0;
hpatch_StreamPos_t sumTargetWindowsSize=0;
hpatch_byte _cacheBuf[1024];
//window loop
while (windowOffset<diffStream->streamSize){
hpatch_StreamPos_t srcPos=0;
hpatch_StreamPos_t srcLen=0;
hpatch_StreamPos_t targetLen;
hpatch_StreamPos_t deltaLen;
hpatch_StreamPos_t dataLen;
hpatch_StreamPos_t instLen;
hpatch_StreamPos_t addrLen;
hpatch_StreamPos_t curDiffOffset;
hpatch_BOOL isHave_srcData;
vcpatch_checksum_t checksumer;
hpatch_byte Delta_Indicator;
{
TStreamCacheClip diffClip;
_TStreamCacheClip_init(&diffClip,diffStream,windowOffset,diffStream->streamSize,
_cacheBuf,sizeof(_cacheBuf));
{
hpatch_BOOL window_isHaveAdler32;
hpatch_byte Win_Indicator;
_clip_readUInt8(&diffClip,&Win_Indicator);
window_isHaveAdler32=(0!=(Win_Indicator&VCD_ADLER32));
if (window_isHaveAdler32) Win_Indicator-=VCD_ADLER32;
vcpatch_checksum_init(&checksumer,out_diffinfo->isGoogleVersion,hpatch_FALSE,window_isHaveAdler32);
switch (Win_Indicator){
case 0 :{ isHave_srcData=hpatch_FALSE; } break;
case VCD_SOURCE:
case VCD_TARGET:{ isHave_srcData=hpatch_TRUE; } break;
default: return _hpatch_FALSE; //error data or unsupport
}
}
if (isHave_srcData){
_clip_unpackUInt64(&diffClip,&srcLen);
_clip_unpackUInt64(&diffClip,&srcPos);
}
_clip_unpackUInt64(&diffClip,&deltaLen);
{
#ifdef __RUN_MEM_SAFE_CHECK
hpatch_StreamPos_t deltaHeadSize=_TStreamCacheClip_readPosOfSrcStream(&diffClip);
if (deltaLen>_TStreamCacheClip_leaveSize(&diffClip))
return _hpatch_FALSE; //error data
#endif
_clip_unpackUInt64(&diffClip,&targetLen);
_clip_readUInt8(&diffClip,&Delta_Indicator);
_clip_unpackUInt64(&diffClip,&dataLen);
_clip_unpackUInt64(&diffClip,&instLen);
_clip_unpackUInt64(&diffClip,&addrLen);
vcpatch_checksum_readAdler32(&checksumer,&diffClip);
curDiffOffset=_TStreamCacheClip_readPosOfSrcStream(&diffClip);
#ifdef __RUN_MEM_SAFE_CHECK
deltaHeadSize=curDiffOffset-deltaHeadSize;
if (deltaLen!=deltaHeadSize+dataLen+instLen+addrLen)
return _hpatch_FALSE; //error data
#endif
}
windowOffset=curDiffOffset+dataLen+instLen+addrLen;
{
hpatch_StreamPos_t sumSize=sumTargetWindowsSize+targetLen;
#ifdef __RUN_MEM_SAFE_CHECK
if (sumSize<sumTargetWindowsSize)
return _hpatch_FALSE; //error data
#endif
sumTargetWindowsSize=sumSize;
maxSrcWindowsSize=(maxSrcWindowsSize>=srcLen)?maxSrcWindowsSize:srcLen;
maxTargetWindowsSize=(maxTargetWindowsSize>=targetLen)?maxTargetWindowsSize:targetLen;
}
}
}
out_diffinfo->maxSrcWindowsSize=maxSrcWindowsSize;
out_diffinfo->maxTargetWindowsSize=maxTargetWindowsSize;
out_diffinfo->sumTargetWindowsSize=sumTargetWindowsSize;
return hpatch_TRUE;
}
#define _kCacheVcDecCount (1+3)
typedef struct{
hpatch_TStreamInput srcStream;
hpatch_StreamPos_t srcPos_bck;
hpatch_size_t srcLen_bck;
hpatch_size_t mem_offset;
hpatch_size_t mem_size;
hpatch_byte* mem_cache;
const hpatch_TStreamInput* srcData_bck;
}src_cache_t;
static hpatch_inline void _src_cache_move_by_offset(src_cache_t* self,hpatch_size_t dstPos,hpatch_size_t movePos){
hpatch_size_t mem_size=self->mem_size;
hpatch_StreamPos_t noff=(hpatch_StreamPos_t)self->mem_offset+mem_size+movePos-dstPos;
if (noff>mem_size){
noff-=mem_size;
if (noff>mem_size)
noff-=mem_size;
}
self->mem_offset=(hpatch_size_t)noff;
}
static hpatch_BOOL _src_cache_update_by_offset(src_cache_t* self,const hpatch_TStreamInput* srcData,
hpatch_StreamPos_t srcPos,hpatch_StreamPos_t dstPos,hpatch_size_t updateLen){
const hpatch_size_t mem_size=self->mem_size;
hpatch_byte* temp_cache=self->mem_cache;
srcPos+=dstPos;
dstPos+=self->mem_offset;
if (dstPos<mem_size){
hpatch_size_t readLen=updateLen;
if (dstPos+readLen>mem_size) readLen=mem_size-(hpatch_size_t)dstPos;
if (!srcData->read(srcData,srcPos,temp_cache+(hpatch_size_t)dstPos,temp_cache+(hpatch_size_t)dstPos+readLen))
return _hpatch_FALSE;
srcPos+=readLen;
dstPos+=readLen;
updateLen-=readLen;
if (updateLen==0) return hpatch_TRUE;
}
dstPos-=mem_size;
if (!srcData->read(srcData,srcPos,temp_cache+(hpatch_size_t)dstPos,temp_cache+(hpatch_size_t)dstPos+updateLen))
return _hpatch_FALSE;
return hpatch_TRUE;
}
static hpatch_BOOL _src_cache_read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
unsigned char* out_data,unsigned char* out_data_end){
src_cache_t* self=(src_cache_t*)stream->streamImport;
hpatch_size_t readLen;
const hpatch_size_t mem_size=self->mem_size;
assert(mem_size>=readFromPos+(hpatch_size_t)(out_data_end-out_data));
readFromPos+=self->mem_offset;
if (readFromPos<mem_size){
readLen=out_data_end-out_data;
if (readFromPos+readLen>mem_size)
readLen=mem_size-(hpatch_size_t)readFromPos;
memcpy(out_data,self->mem_cache+(hpatch_size_t)readFromPos,readLen);
readFromPos+=readLen;
out_data+=readLen;
if (out_data==out_data_end) return hpatch_TRUE;
}
readFromPos-=mem_size;
readLen=out_data_end-out_data;
assert(mem_size>=readFromPos+readLen);
memcpy(out_data,self->mem_cache+(hpatch_size_t)readFromPos,readLen);
return hpatch_TRUE;
}
static hpatch_inline void src_cache_init(src_cache_t* self,hpatch_StreamPos_t srcLenMax,hpatch_byte** mem_cache,hpatch_size_t* allCacheSize){
hpatch_size_t mem_size=0;
if ((srcLenMax>0)&&(srcLenMax+_kCacheVcDecCount*hpatch_kStreamCacheSize<=(*allCacheSize))){
mem_size=(hpatch_size_t)srcLenMax;
}
self->srcPos_bck=0;
self->srcData_bck=0;
self->mem_cache=*mem_cache;
self->mem_offset=0;
self->mem_size=mem_size;
(*allCacheSize)-=mem_size;
(*mem_cache)+=mem_size;
}
static hpatch_inline hpatch_BOOL src_cache_isCanCache(src_cache_t* self,hpatch_StreamPos_t srcLen){
return (srcLen>0)&&(srcLen<=self->mem_size);
}
static hpatch_TStreamInput* src_cache_update(src_cache_t* self,const hpatch_TStreamInput* srcData,
hpatch_size_t srcLen,hpatch_StreamPos_t srcPos){
if ((self->srcData_bck!=srcData)||(self->srcPos_bck+self->srcLen_bck<=srcPos)||(self->srcPos_bck>=srcPos+srcLen)){
self->mem_offset=0;
if (!srcData->read(srcData,srcPos,self->mem_cache,self->mem_cache+srcLen))
return _hpatch_FALSE;
}else{//hit cache
hpatch_size_t dstPos;
hpatch_size_t movePos;
hpatch_size_t moveLen;
if (self->srcPos_bck<=srcPos){
dstPos=0;
movePos=(hpatch_size_t)(srcPos-self->srcPos_bck);
moveLen=self->srcLen_bck-movePos;
}else{
dstPos=(hpatch_size_t)(self->srcPos_bck-srcPos);
movePos=0;
moveLen=self->srcLen_bck;
}
if (dstPos+moveLen>=srcLen)
moveLen=srcLen-dstPos;
_src_cache_move_by_offset(self,dstPos,movePos);
if (dstPos>0){
if (!_src_cache_update_by_offset(self,srcData,srcPos,0,dstPos))
return _hpatch_FALSE;
}
dstPos+=moveLen;
if (dstPos<srcLen){
if (!_src_cache_update_by_offset(self,srcData,srcPos,dstPos,srcLen-dstPos))
return _hpatch_FALSE;
}
}
self->srcStream.streamImport=self;
self->srcStream.streamSize=srcLen;
self->srcStream.read=_src_cache_read;
self->srcStream.streamImport=self;
self->srcStream.streamImport=self;
self->srcPos_bck=srcPos;
self->srcLen_bck=srcLen;
self->srcData_bck=srcData;
return &self->srcStream;
}
hpatch_BOOL _vcpatch_window(const hpatch_TStreamOutput* out_newData,const hpatch_TStreamInput* oldData,
const hpatch_TStreamInput* diffStream,hpatch_TDecompress* decompressPlugin,
_TDecompressInputStream* decompressers,hpatch_StreamPos_t windowOffset,
hpatch_StreamPos_t srcLenMax,hpatch_BOOL isGoogleVersion,
hpatch_BOOL isNeedChecksum,hpatch_byte* tempCaches,hpatch_size_t allCacheSize){
src_cache_t src_cache;
_TOutStreamCache outCache;
if (allCacheSize<hpatch_kMaxPackedUIntBytes*_kCacheVcDecCount) return _hpatch_FALSE;
_TOutStreamCache_init(&outCache,out_newData,0,0); //need reset cache
src_cache_init(&src_cache,srcLenMax,&tempCaches,&allCacheSize);
//window loop
while (windowOffset<diffStream->streamSize){
hpatch_StreamPos_t srcPos=0;
hpatch_StreamPos_t srcLen=0;
hpatch_StreamPos_t targetLen;
hpatch_StreamPos_t deltaLen;
hpatch_StreamPos_t dataLen;
hpatch_StreamPos_t instLen;
hpatch_StreamPos_t addrLen;
hpatch_StreamPos_t curDiffOffset;
const hpatch_TStreamInput* srcData;
vcpatch_checksum_t checksumer;
hpatch_byte Delta_Indicator;
{
TStreamCacheClip diffClip;
hpatch_byte _window_cache[_kWindowCacheSize];
_TStreamCacheClip_init(&diffClip,diffStream,windowOffset,diffStream->streamSize,
_window_cache,sizeof(_window_cache));
{
hpatch_BOOL window_isHaveAdler32;
hpatch_byte Win_Indicator;
_clip_readUInt8(&diffClip,&Win_Indicator);
window_isHaveAdler32=(0!=(Win_Indicator&VCD_ADLER32));
if (window_isHaveAdler32) Win_Indicator-=VCD_ADLER32;
vcpatch_checksum_init(&checksumer,isGoogleVersion,isNeedChecksum,window_isHaveAdler32);
switch (Win_Indicator){
case 0 :{ srcData=0; } break;
case VCD_SOURCE:{ srcData=oldData; } break;
case VCD_TARGET:{
srcData=(const hpatch_TStreamInput*)outCache.dstStream;
if (srcData->read==0)
return _hpatch_FALSE; //unsupport, target can't read
} break;
default:
return _hpatch_FALSE; //error data or unsupport
}
}
if (srcData){
_clip_unpackUInt64(&diffClip,&srcLen);
_clip_unpackUInt64(&diffClip,&srcPos);
#ifdef __RUN_MEM_SAFE_CHECK
{
hpatch_StreamPos_t streamSafeEnd=(srcData==oldData)?srcData->streamSize:outCache.writeToPos;
hpatch_StreamPos_t srcPosEnd=srcPos+srcLen;
if ((srcPosEnd<srcPos)|(srcPosEnd<srcLen)|(srcPosEnd>streamSafeEnd))
return _hpatch_FALSE; //error data
}
#endif
}
_clip_unpackUInt64(&diffClip,&deltaLen);
{
#ifdef __RUN_MEM_SAFE_CHECK
hpatch_StreamPos_t deltaHeadSize=_TStreamCacheClip_readPosOfSrcStream(&diffClip);
if (deltaLen>_TStreamCacheClip_leaveSize(&diffClip))
return _hpatch_FALSE; //error data
#endif
_clip_unpackUInt64(&diffClip,&targetLen);
_clip_readUInt8(&diffClip,&Delta_Indicator);
if (decompressPlugin==0) Delta_Indicator=0;
_clip_unpackUInt64(&diffClip,&dataLen);
_clip_unpackUInt64(&diffClip,&instLen);
_clip_unpackUInt64(&diffClip,&addrLen);
vcpatch_checksum_readAdler32(&checksumer,&diffClip);
curDiffOffset=_TStreamCacheClip_readPosOfSrcStream(&diffClip);
#ifdef __RUN_MEM_SAFE_CHECK
deltaHeadSize=curDiffOffset-deltaHeadSize;
if (deltaLen!=deltaHeadSize+dataLen+instLen+addrLen)
return _hpatch_FALSE; //error data
#endif
}
windowOffset=curDiffOffset+dataLen+instLen+addrLen;
}
if (src_cache_isCanCache(&src_cache,srcLen)){//old all in cache?
assert(srcData!=0);
srcData=src_cache_update(&src_cache,srcData,(hpatch_size_t)srcLen,srcPos);
if (srcData==0) return _hpatch_FALSE;
srcPos=0;
}
{
hpatch_BOOL ret;
const hpatch_BOOL isInterleaved=((dataLen==0)&(addrLen==0));
TStreamCacheClip dataClip;
TStreamCacheClip instClip;
TStreamCacheClip addrClip;
hpatch_byte* temp_cache=tempCaches;
hpatch_size_t cache_size=allCacheSize;
{
hpatch_size_t out_cache_size;
if ((targetLen>0)&&(targetLen+3*hpatch_kStreamCacheSize<=cache_size)){//target all in cache?
out_cache_size=(hpatch_size_t)targetLen;
cache_size=(cache_size-out_cache_size)/(isInterleaved?1:3);
}else{
#define kBetterDecompressBufSize (1024*32)
hpatch_size_t dec_size=cache_size/_kCacheVcDecCount;
dec_size=(dec_size<=kBetterDecompressBufSize)?dec_size:kBetterDecompressBufSize;
out_cache_size=cache_size-dec_size*(isInterleaved?1:3);
cache_size=dec_size;
}
_TOutStreamCache_resetCache(&outCache,temp_cache,out_cache_size);
temp_cache+=out_cache_size;
}
#define __getStreamClip(clip,index,len) { \
if (!(_getStreamClip(clip,Delta_Indicator,index,diffStream,&curDiffOffset, \
decompressPlugin,decompressers,len,temp_cache,cache_size))) \
return _hpatch_FALSE; \
temp_cache+=cache_size; }
if (!isInterleaved){
__getStreamClip(&dataClip,0,dataLen);
__getStreamClip(&instClip,1,instLen);
__getStreamClip(&addrClip,2,addrLen);
}else{
__getStreamClip(&instClip,0,instLen);
}
assert(curDiffOffset==windowOffset);
if (!vcpatch_checksum_begin(&checksumer,&outCache))
return _hpatch_FALSE;
ret=_vcpatch_delta(&outCache,targetLen,srcData,srcPos,srcLen,
isInterleaved?&instClip:&dataClip,&instClip,
isInterleaved?&instClip:&addrClip);
if (!_TOutStreamCache_flush(&outCache))
ret=_hpatch_FALSE;
if ((!vcpatch_checksum_end(&checksumer,&outCache))||(!ret))
return _hpatch_FALSE;
}
}
if (_TOutStreamCache_isFinish(&outCache)||(outCache.dstStream->streamSize==hpatch_kNullStreamPos))
return hpatch_TRUE;
else
return _hpatch_FALSE;
}
hpatch_BOOL vcpatch_with_cache(const hpatch_TStreamOutput* out_newData,
const hpatch_TStreamInput* oldData,
const hpatch_TStreamInput* diffStream,
hpatch_TDecompress* decompressPlugin,hpatch_BOOL isNeedChecksum,
hpatch_byte* temp_cache,hpatch_byte* temp_cache_end){
hpatch_VcDiffInfo diffInfo;
hpatch_size_t i;
hpatch_BOOL result=hpatch_TRUE;
_TDecompressInputStream decompressers[3];
for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i)
decompressers[i].decompressHandle=0;
assert(out_newData!=0);
assert(out_newData->write!=0);
assert(oldData!=0);
assert(oldData->read!=0);
assert(diffStream!=0);
assert(diffStream->read!=0);
if (!getVcDiffInfo(&diffInfo,diffStream,hpatch_TRUE))
return _hpatch_FALSE;
if (diffInfo.compressorID){
if (decompressPlugin==0)
return _hpatch_FALSE;
}else{
decompressPlugin=0;
}
result=_vcpatch_window(out_newData,oldData,diffStream,decompressPlugin,decompressers,
diffInfo.windowOffset,diffInfo.maxSrcWindowsSize,diffInfo.isGoogleVersion,
isNeedChecksum,temp_cache,temp_cache_end-temp_cache);
for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i) {
if (decompressers[i].decompressHandle){
if (!decompressPlugin->close(decompressPlugin,decompressers[i].decompressHandle))
result=_hpatch_FALSE;
decompressers[i].decompressHandle=0;
}
}
return result;
}