1334 lines
62 KiB
C
1334 lines
62 KiB
C
//decompress_plugin_demo.h
|
|
// decompress plugin demo for HDiffz\HPatchz
|
|
/*
|
|
The MIT License (MIT)
|
|
Copyright (c) 2012-2017 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.
|
|
*/
|
|
#ifndef HPatch_decompress_plugin_demo_h
|
|
#define HPatch_decompress_plugin_demo_h
|
|
//decompress plugin demo:
|
|
// zlibDecompressPlugin;
|
|
// bz2DecompressPlugin;
|
|
// lzmaDecompressPlugin;
|
|
// lzma2DecompressPlugin;
|
|
// lz4DecompressPlugin;
|
|
// zstdDecompressPlugin;
|
|
// brotliDecompressPlugin;
|
|
// lzhamDecompressPlugin;
|
|
// tuzDecompressPlugin;
|
|
|
|
// _bz2DecompressPlugin_unsz : support for bspatch_with_cache()
|
|
// _7zXZDecompressPlugin : support for vcpatch_with_cache(), diffData created by "xdelta3 -S lzma ..."
|
|
// _7zXZDecompressPlugin_a : support for vcpatch_with_cache(), diffData created by "hdiffz -VCD-compressLevel ..."
|
|
#include <stdlib.h> //malloc free
|
|
#include <stdio.h> //fprintf
|
|
#include "libHDiffPatch/HPatch/patch_types.h"
|
|
|
|
#ifndef kDecompressBufSize
|
|
# define kDecompressBufSize (1024*32)
|
|
#endif
|
|
#ifndef _IsNeedIncludeDefaultCompressHead
|
|
# define _IsNeedIncludeDefaultCompressHead 1
|
|
#endif
|
|
|
|
#define _dec_memErr() _hpatch_update_decError(decompressPlugin,hpatch_dec_mem_error)
|
|
#define _dec_memErr_rt() do { _dec_memErr(); return 0; } while(0)
|
|
#define _dec_openErr_rt() do { _hpatch_update_decError(decompressPlugin,hpatch_dec_open_error); return 0; } while(0)
|
|
#define _dec_close_check(value) { if (!(value)) { LOG_ERR("check "#value " ERROR!\n"); \
|
|
result=hpatch_FALSE; _hpatch_update_decError(decompressPlugin,hpatch_dec_close_error); } }
|
|
|
|
#define _dec_onDecErr_rt() do { if (!(self)->decError) (self)->decError=hpatch_dec_error; return 0; } while(0)
|
|
#define _dec_onDecErr_up() do { if ((self)->decError) _hpatch_update_decError(decompressPlugin,(self)->decError); } while(0)
|
|
|
|
static void* _dec_malloc(hpatch_size_t size) {
|
|
void* result=malloc(size);
|
|
if (!result) LOG_ERRNO(errno);
|
|
return result;
|
|
}
|
|
#define __dec_Alloc_fun(_type_TDecompress,p,size) { \
|
|
void* result=_dec_malloc(size); \
|
|
if (!result) \
|
|
((_type_TDecompress*)p)->decError=hpatch_dec_mem_error; \
|
|
return result; }
|
|
|
|
static void __dec_free(void* _, void* address){
|
|
if (address) free(address); }
|
|
|
|
#ifdef _CompressPlugin_zlib
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "zlib.h" // http://zlib.net/ https://github.com/madler/zlib
|
|
#endif
|
|
typedef struct _zlib_TDecompress{
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
|
|
unsigned char* dec_buf;
|
|
size_t dec_buf_size;
|
|
z_stream d_stream;
|
|
signed char windowBits;
|
|
hpatch_dec_error_t decError;
|
|
} _zlib_TDecompress;
|
|
static void * __zlib_dec_Alloc(void* p,uInt items,uInt size)
|
|
__dec_Alloc_fun(_zlib_TDecompress,p,((items)*(size_t)(size)))
|
|
static hpatch_BOOL _zlib_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"zlib"))||(0==strcmp(compressType,"pzlib"));
|
|
}
|
|
|
|
static _zlib_TDecompress* _zlib_decompress_open_at(hpatch_TDecompress* decompressPlugin,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end,
|
|
int isSavedWindowBits,
|
|
_zlib_TDecompress* self,size_t _self_and_buf_size){
|
|
int ret;
|
|
signed char kWindowBits=-MAX_WBITS;
|
|
assert(_self_and_buf_size>sizeof(_zlib_TDecompress));
|
|
if (isSavedWindowBits){//load kWindowBits
|
|
if (code_end-code_begin<1) _dec_openErr_rt();
|
|
if (!codeStream->read(codeStream,code_begin,(unsigned char*)&kWindowBits,
|
|
(unsigned char*)&kWindowBits+1)) return 0;
|
|
++code_begin;
|
|
}
|
|
|
|
memset(self,0,sizeof(_zlib_TDecompress));
|
|
self->dec_buf=((unsigned char*)self)+sizeof(_zlib_TDecompress);
|
|
self->dec_buf_size=_self_and_buf_size-sizeof(_zlib_TDecompress);
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->windowBits=kWindowBits;
|
|
self->d_stream.zalloc=__zlib_dec_Alloc;
|
|
self->d_stream.zfree=__dec_free;
|
|
self->d_stream.opaque=self;
|
|
ret = inflateInit2(&self->d_stream,self->windowBits);
|
|
if (ret!=Z_OK) { _dec_onDecErr_up(); _dec_openErr_rt(); }
|
|
return self;
|
|
}
|
|
static hpatch_decompressHandle _zlib_decompress_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_zlib_TDecompress* self=0;
|
|
unsigned char* _mem_buf=(unsigned char*)_dec_malloc(sizeof(_zlib_TDecompress)+kDecompressBufSize);
|
|
if (!_mem_buf) _dec_memErr_rt();
|
|
self=_zlib_decompress_open_at(decompressPlugin,codeStream,code_begin,code_end,1,
|
|
(_zlib_TDecompress*)_mem_buf,sizeof(_zlib_TDecompress)+kDecompressBufSize);
|
|
if (!self)
|
|
free(_mem_buf);
|
|
return self;
|
|
}
|
|
static hpatch_decompressHandle _zlib_decompress_open_deflate(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_zlib_TDecompress* self=0;
|
|
unsigned char* _mem_buf=(unsigned char*)_dec_malloc(sizeof(_zlib_TDecompress)+kDecompressBufSize);
|
|
if (!_mem_buf) _dec_memErr_rt();
|
|
self=_zlib_decompress_open_at(decompressPlugin,codeStream,code_begin,code_end,0,
|
|
(_zlib_TDecompress*)_mem_buf,sizeof(_zlib_TDecompress)+kDecompressBufSize);
|
|
if (!self)
|
|
free(_mem_buf);
|
|
return self;
|
|
}
|
|
|
|
static _zlib_TDecompress* _zlib_decompress_open_by(hpatch_TDecompress* decompressPlugin,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end,
|
|
int isSavedWindowBits,
|
|
unsigned char* _mem_buf,size_t _mem_buf_size){
|
|
#define __MAX_TS(a,b) ((a)>=(b)?(a):(b))
|
|
const hpatch_size_t kZlibAlign=__MAX_TS(__MAX_TS(sizeof(hpatch_StreamPos_t),sizeof(void*)),sizeof(uLongf));
|
|
#undef __MAX_TS
|
|
unsigned char* _mem_buf_end=_mem_buf+_mem_buf_size;
|
|
unsigned char* self_at=(unsigned char*)_hpatch_align_upper(_mem_buf,kZlibAlign);
|
|
if (self_at>=_mem_buf_end) return 0;
|
|
return _zlib_decompress_open_at(decompressPlugin,codeStream,code_begin,code_end,isSavedWindowBits,
|
|
(_zlib_TDecompress*)self_at,_mem_buf_end-self_at);
|
|
}
|
|
static hpatch_BOOL _zlib_decompress_close_by(struct hpatch_TDecompress* decompressPlugin,
|
|
_zlib_TDecompress* self){
|
|
hpatch_BOOL result=hpatch_TRUE;
|
|
if (!self) return result;
|
|
_dec_onDecErr_up();
|
|
if (self->d_stream.state!=0){
|
|
_dec_close_check(Z_OK==inflateEnd(&self->d_stream));
|
|
}
|
|
memset(self,0,sizeof(_zlib_TDecompress));
|
|
return result;
|
|
}
|
|
|
|
static hpatch_BOOL _zlib_decompress_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_zlib_TDecompress* self=(_zlib_TDecompress*)decompressHandle;
|
|
hpatch_BOOL result=_zlib_decompress_close_by(decompressPlugin,self);
|
|
if (self) free(self);
|
|
return result;
|
|
}
|
|
|
|
static hpatch_BOOL _zlib_reset_for_next_node(_zlib_TDecompress* self){
|
|
//backup
|
|
Bytef* next_out_back=self->d_stream.next_out;
|
|
Bytef* next_in_back=self->d_stream.next_in;
|
|
unsigned int avail_out_back=self->d_stream.avail_out;
|
|
unsigned int avail_in_back=self->d_stream.avail_in;
|
|
//reset
|
|
if (Z_OK!=inflateReset(&self->d_stream)) _dec_onDecErr_rt();
|
|
//restore
|
|
self->d_stream.next_out=next_out_back;
|
|
self->d_stream.next_in=next_in_back;
|
|
self->d_stream.avail_out=avail_out_back;
|
|
self->d_stream.avail_in=avail_in_back;
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL __zlib_do_inflate(hpatch_decompressHandle decompressHandle){
|
|
_zlib_TDecompress* self=(_zlib_TDecompress*)decompressHandle;
|
|
uInt avail_out_back,avail_in_back;
|
|
int ret;
|
|
hpatch_StreamPos_t codeLen=(self->code_end - self->code_begin);
|
|
if ((self->d_stream.avail_in==0)&&(codeLen>0)) {
|
|
size_t readLen=self->dec_buf_size;
|
|
if (readLen>codeLen) readLen=(size_t)codeLen;
|
|
self->d_stream.next_in=self->dec_buf;
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,self->dec_buf,
|
|
self->dec_buf+readLen)) return hpatch_FALSE;//error;
|
|
self->d_stream.avail_in=(uInt)readLen;
|
|
self->code_begin+=readLen;
|
|
codeLen-=readLen;
|
|
}
|
|
|
|
avail_out_back=self->d_stream.avail_out;
|
|
avail_in_back=self->d_stream.avail_in;
|
|
ret=inflate(&self->d_stream,Z_NO_FLUSH);
|
|
if (ret==Z_OK){
|
|
if ((self->d_stream.avail_in==avail_in_back)&&(self->d_stream.avail_out==avail_out_back))
|
|
_dec_onDecErr_rt();//error;
|
|
}else if (ret==Z_STREAM_END){
|
|
if (self->d_stream.avail_in+codeLen>0){ //next compress node!
|
|
if (!_zlib_reset_for_next_node(self))
|
|
return hpatch_FALSE;//error;
|
|
}else{//all end
|
|
if (self->d_stream.avail_out!=0)
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _zlib_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_zlib_TDecompress* self=(_zlib_TDecompress*)decompressHandle;
|
|
assert(out_part_data<=out_part_data_end);
|
|
|
|
self->d_stream.next_out = out_part_data;
|
|
self->d_stream.avail_out =(uInt)(out_part_data_end-out_part_data);
|
|
while (self->d_stream.avail_out>0) {
|
|
if (!__zlib_do_inflate(self))
|
|
return hpatch_FALSE;//error;
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_inline int _zlib_is_decompress_finish(const hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_zlib_TDecompress* self=(_zlib_TDecompress*)decompressHandle;
|
|
while (self->code_begin!=self->code_end){ //for end tag code
|
|
unsigned char _empty;
|
|
self->d_stream.next_out = &_empty;
|
|
self->d_stream.avail_out=0;
|
|
if (!__zlib_do_inflate(self))
|
|
return hpatch_FALSE;//error;
|
|
}
|
|
return (self->code_begin==self->code_end)
|
|
&(self->d_stream.avail_in==0)
|
|
&(self->d_stream.avail_out==0);
|
|
}
|
|
static hpatch_TDecompress zlibDecompressPlugin={_zlib_is_can_open,_zlib_decompress_open,
|
|
_zlib_decompress_close,_zlib_decompress_part};
|
|
static hpatch_TDecompress zlibDecompressPlugin_deflate={_zlib_is_can_open,_zlib_decompress_open_deflate,
|
|
_zlib_decompress_close,_zlib_decompress_part};
|
|
#endif//_CompressPlugin_zlib
|
|
|
|
#ifdef _CompressPlugin_bz2
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "bzlib.h" // http://www.bzip.org/ https://github.com/sisong/bzip2
|
|
#endif
|
|
typedef struct _bz2_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
bz_stream d_stream;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char dec_buf[kDecompressBufSize];
|
|
} _bz2_TDecompress;
|
|
static hpatch_BOOL _bz2_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"bz2"))||(0==strcmp(compressType,"bzip2"))
|
|
||(0==strcmp(compressType,"pbz2"))||(0==strcmp(compressType,"pbzip2"));
|
|
}
|
|
static hpatch_decompressHandle _bz2_open(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
int ret;
|
|
_bz2_TDecompress* self=(_bz2_TDecompress*)_dec_malloc(sizeof(_bz2_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_bz2_TDecompress)-kDecompressBufSize);
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
|
|
ret=BZ2_bzDecompressInit(&self->d_stream,0,0);
|
|
if (ret!=BZ_OK){ free(self); _dec_openErr_rt(); }
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _bz2_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
hpatch_BOOL result=hpatch_TRUE;
|
|
_bz2_TDecompress* self=(_bz2_TDecompress*)decompressHandle;
|
|
if (!self) return result;
|
|
_dec_onDecErr_up();
|
|
_dec_close_check(BZ_OK==BZ2_bzDecompressEnd(&self->d_stream));
|
|
free(self);
|
|
return result;
|
|
}
|
|
static hpatch_BOOL _bz2_reset_for_next_node(_bz2_TDecompress* self){
|
|
//backup
|
|
char* next_out_back=self->d_stream.next_out;
|
|
char* next_in_back=self->d_stream.next_in;
|
|
unsigned int avail_out_back=self->d_stream.avail_out;
|
|
unsigned int avail_in_back=self->d_stream.avail_in;
|
|
//reset
|
|
if (BZ_OK!=BZ2_bzDecompressEnd(&self->d_stream)) _dec_onDecErr_rt();
|
|
if (BZ_OK!=BZ2_bzDecompressInit(&self->d_stream,0,0)) _dec_onDecErr_rt();
|
|
//restore
|
|
self->d_stream.next_out=next_out_back;
|
|
self->d_stream.next_in=next_in_back;
|
|
self->d_stream.avail_out=avail_out_back;
|
|
self->d_stream.avail_in=avail_in_back;
|
|
return hpatch_TRUE;
|
|
}
|
|
|
|
static hpatch_BOOL _bz2_decompress_part_(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end,
|
|
hpatch_BOOL isMustOutData){
|
|
_bz2_TDecompress* self=(_bz2_TDecompress*)decompressHandle;
|
|
assert(out_part_data<=out_part_data_end);
|
|
|
|
self->d_stream.next_out =(char*)out_part_data;
|
|
self->d_stream.avail_out =(unsigned int)(out_part_data_end-out_part_data);
|
|
while (self->d_stream.avail_out>0) {
|
|
unsigned int avail_out_back,avail_in_back;
|
|
int ret;
|
|
hpatch_StreamPos_t codeLen=(self->code_end - self->code_begin);
|
|
if ((self->d_stream.avail_in==0)&&(codeLen>0)) {
|
|
size_t readLen=kDecompressBufSize;
|
|
self->d_stream.next_in=(char*)self->dec_buf;
|
|
if (readLen>codeLen) readLen=(size_t)codeLen;
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,self->dec_buf,
|
|
self->dec_buf+readLen)) return hpatch_FALSE;//error;
|
|
self->d_stream.avail_in=(unsigned int)readLen;
|
|
self->code_begin+=readLen;
|
|
codeLen-=readLen;
|
|
}
|
|
|
|
avail_out_back=self->d_stream.avail_out;
|
|
avail_in_back=self->d_stream.avail_in;
|
|
ret=BZ2_bzDecompress(&self->d_stream);
|
|
if (ret==BZ_OK){
|
|
if ((self->d_stream.avail_in==avail_in_back)&&(self->d_stream.avail_out==avail_out_back))
|
|
_dec_onDecErr_rt();//error;
|
|
}else if (ret==BZ_STREAM_END){
|
|
if (self->d_stream.avail_in+codeLen>0){ //next compress node!
|
|
if (!_bz2_reset_for_next_node(self))
|
|
return hpatch_FALSE;//error;
|
|
}else{//all end
|
|
if (self->d_stream.avail_out!=0){
|
|
if (isMustOutData){ //fill out 0
|
|
memset(self->d_stream.next_out,0,self->d_stream.avail_out);
|
|
self->d_stream.next_out+=self->d_stream.avail_out;
|
|
self->d_stream.avail_out=0;
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _bz2_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
return _bz2_decompress_part_(decompressHandle,out_part_data,out_part_data_end,hpatch_FALSE);
|
|
}
|
|
static hpatch_BOOL _bz2_decompress_part_unsz(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
return _bz2_decompress_part_(decompressHandle,out_part_data,out_part_data_end,hpatch_TRUE);
|
|
}
|
|
|
|
static hpatch_TDecompress bz2DecompressPlugin={_bz2_is_can_open,_bz2_open,
|
|
_bz2_close,_bz2_decompress_part};
|
|
|
|
//unkown uncompress data size
|
|
static hpatch_TDecompress _bz2DecompressPlugin_unsz={_bz2_is_can_open,_bz2_open,
|
|
_bz2_close,_bz2_decompress_part_unsz};
|
|
#endif//_CompressPlugin_bz2
|
|
|
|
|
|
#if (defined _CompressPlugin_lzma) || (defined _CompressPlugin_lzma2)
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "LzmaDec.h" // "lzma/C/LzmaDec.h" https://github.com/sisong/lzma
|
|
# ifdef _CompressPlugin_lzma2
|
|
# include "Lzma2Dec.h"
|
|
# endif
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef _CompressPlugin_lzma
|
|
typedef struct _lzma_TDecompress{
|
|
ISzAlloc memAllocBase;
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
CLzmaDec decEnv;
|
|
SizeT decCopyPos;
|
|
SizeT decReadPos;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char dec_buf[kDecompressBufSize];
|
|
} _lzma_TDecompress;
|
|
static void * __lzma1_dec_Alloc(ISzAllocPtr p, size_t size)
|
|
__dec_Alloc_fun(_lzma_TDecompress,p,size)
|
|
|
|
static hpatch_BOOL _lzma_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"lzma"));
|
|
}
|
|
static hpatch_decompressHandle _lzma_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_lzma_TDecompress* self=0;
|
|
SRes ret;
|
|
unsigned char propsSize=0;
|
|
unsigned char props[256];
|
|
//load propsSize
|
|
if (code_end-code_begin<1) _dec_openErr_rt();
|
|
if (!codeStream->read(codeStream,code_begin,&propsSize,&propsSize+1)) return 0;
|
|
++code_begin;
|
|
if (propsSize>(code_end-code_begin)) _dec_openErr_rt();
|
|
//load props
|
|
if (!codeStream->read(codeStream,code_begin,props,props+propsSize)) return 0;
|
|
code_begin+=propsSize;
|
|
|
|
self=(_lzma_TDecompress*)_dec_malloc(sizeof(_lzma_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_lzma_TDecompress)-kDecompressBufSize);
|
|
self->memAllocBase.Alloc=__lzma1_dec_Alloc;
|
|
*((void**)&self->memAllocBase.Free)=(void*)__dec_free;
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
|
|
self->decCopyPos=0;
|
|
self->decReadPos=kDecompressBufSize;
|
|
|
|
LzmaDec_Construct(&self->decEnv);
|
|
ret=LzmaDec_Allocate(&self->decEnv,props,propsSize,&self->memAllocBase);
|
|
if (ret!=SZ_OK){ _dec_onDecErr_up(); free(self); _dec_openErr_rt(); }
|
|
LzmaDec_Init(&self->decEnv);
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _lzma_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_lzma_TDecompress* self=(_lzma_TDecompress*)decompressHandle;
|
|
if (!self) return hpatch_TRUE;
|
|
LzmaDec_Free(&self->decEnv,&self->memAllocBase);
|
|
_dec_onDecErr_up();
|
|
free(self);
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _lzma_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_lzma_TDecompress* self=(_lzma_TDecompress*)decompressHandle;
|
|
unsigned char* out_cur=out_part_data;
|
|
assert(out_part_data<=out_part_data_end);
|
|
while (out_cur<out_part_data_end){
|
|
size_t copyLen=(self->decEnv.dicPos-self->decCopyPos);
|
|
if (copyLen>0){
|
|
if (copyLen>(size_t)(out_part_data_end-out_cur))
|
|
copyLen=(out_part_data_end-out_cur);
|
|
memcpy(out_cur,self->decEnv.dic+self->decCopyPos,copyLen);
|
|
out_cur+=copyLen;
|
|
self->decCopyPos+=copyLen;
|
|
if ((self->decEnv.dicPos==self->decEnv.dicBufSize)
|
|
&&(self->decEnv.dicPos==self->decCopyPos)){
|
|
self->decEnv.dicPos=0;
|
|
self->decCopyPos=0;
|
|
}
|
|
}else{
|
|
ELzmaStatus status;
|
|
SizeT inSize,dicPos_back;
|
|
SRes res;
|
|
hpatch_StreamPos_t codeLen=(self->code_end - self->code_begin);
|
|
if ((self->decReadPos==kDecompressBufSize)&&(codeLen>0)) {
|
|
size_t readLen=kDecompressBufSize;
|
|
if (readLen>codeLen) readLen=(size_t)codeLen;
|
|
self->decReadPos=kDecompressBufSize-readLen;
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,self->dec_buf+self->decReadPos,
|
|
self->dec_buf+self->decReadPos+readLen)) return hpatch_FALSE;//error;
|
|
self->code_begin+=readLen;
|
|
}
|
|
|
|
inSize=kDecompressBufSize-self->decReadPos;
|
|
dicPos_back=self->decEnv.dicPos;
|
|
res=LzmaDec_DecodeToDic(&self->decEnv,self->decEnv.dicBufSize,
|
|
self->dec_buf+self->decReadPos,&inSize,LZMA_FINISH_ANY,&status);
|
|
if(res==SZ_OK){
|
|
if ((inSize==0)&&(self->decEnv.dicPos==dicPos_back))
|
|
_dec_onDecErr_rt();//error;
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
self->decReadPos+=inSize;
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress lzmaDecompressPlugin={_lzma_is_can_open,_lzma_open,
|
|
_lzma_close,_lzma_decompress_part};
|
|
#endif//_CompressPlugin_lzma
|
|
|
|
#ifdef _CompressPlugin_lzma2
|
|
typedef struct _lzma2_TDecompress{
|
|
ISzAlloc memAllocBase;
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
CLzma2Dec decEnv;
|
|
SizeT decCopyPos;
|
|
SizeT decReadPos;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char dec_buf[kDecompressBufSize];
|
|
} _lzma2_TDecompress;
|
|
static void * __lzma2_dec_Alloc(ISzAllocPtr p, size_t size)
|
|
__dec_Alloc_fun(_lzma2_TDecompress,p,size)
|
|
|
|
static hpatch_BOOL _lzma2_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"lzma2"));
|
|
}
|
|
static hpatch_decompressHandle _lzma2_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_lzma2_TDecompress* self=0;
|
|
SRes ret;
|
|
unsigned char propsSize=0;
|
|
//load propsSize
|
|
if (code_end-code_begin<1) _dec_openErr_rt();
|
|
if (!codeStream->read(codeStream,code_begin,&propsSize,&propsSize+1)) return 0;
|
|
++code_begin;
|
|
|
|
self=(_lzma2_TDecompress*)_dec_malloc(sizeof(_lzma2_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_lzma2_TDecompress)-kDecompressBufSize);
|
|
self->memAllocBase.Alloc=__lzma2_dec_Alloc;
|
|
*((void**)&self->memAllocBase.Free)=(void*)__dec_free;
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
|
|
self->decCopyPos=0;
|
|
self->decReadPos=kDecompressBufSize;
|
|
|
|
Lzma2Dec_Construct(&self->decEnv);
|
|
ret=Lzma2Dec_Allocate(&self->decEnv,propsSize,&self->memAllocBase);
|
|
if (ret!=SZ_OK){ _dec_onDecErr_up(); free(self); _dec_openErr_rt(); }
|
|
Lzma2Dec_Init(&self->decEnv);
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _lzma2_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_lzma2_TDecompress* self=(_lzma2_TDecompress*)decompressHandle;
|
|
if (!self) return hpatch_TRUE;
|
|
Lzma2Dec_Free(&self->decEnv,&self->memAllocBase);
|
|
_dec_onDecErr_up();
|
|
free(self);
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _lzma2_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_lzma2_TDecompress* self=(_lzma2_TDecompress*)decompressHandle;
|
|
unsigned char* out_cur=out_part_data;
|
|
assert(out_part_data<=out_part_data_end);
|
|
while (out_cur<out_part_data_end){
|
|
size_t copyLen=(self->decEnv.decoder.dicPos-self->decCopyPos);
|
|
if (copyLen>0){
|
|
if (copyLen>(size_t)(out_part_data_end-out_cur))
|
|
copyLen=(out_part_data_end-out_cur);
|
|
memcpy(out_cur,self->decEnv.decoder.dic+self->decCopyPos,copyLen);
|
|
out_cur+=copyLen;
|
|
self->decCopyPos+=copyLen;
|
|
if ((self->decEnv.decoder.dicPos==self->decEnv.decoder.dicBufSize)
|
|
&&(self->decEnv.decoder.dicPos==self->decCopyPos)){
|
|
self->decEnv.decoder.dicPos=0;
|
|
self->decCopyPos=0;
|
|
}
|
|
}else{
|
|
ELzmaStatus status;
|
|
SizeT inSize,dicPos_back;
|
|
SRes res;
|
|
hpatch_StreamPos_t codeLen=(self->code_end - self->code_begin);
|
|
if ((self->decReadPos==kDecompressBufSize)&&(codeLen>0)) {
|
|
size_t readLen=kDecompressBufSize;
|
|
if (readLen>codeLen) readLen=(size_t)codeLen;
|
|
self->decReadPos=kDecompressBufSize-readLen;
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,self->dec_buf+self->decReadPos,
|
|
self->dec_buf+self->decReadPos+readLen)) return hpatch_FALSE;//error;
|
|
self->code_begin+=readLen;
|
|
}
|
|
|
|
inSize=kDecompressBufSize-self->decReadPos;
|
|
dicPos_back=self->decEnv.decoder.dicPos;
|
|
res=Lzma2Dec_DecodeToDic(&self->decEnv,self->decEnv.decoder.dicBufSize,
|
|
self->dec_buf+self->decReadPos,&inSize,LZMA_FINISH_ANY,&status);
|
|
if(res==SZ_OK){
|
|
if ((inSize==0)&&(self->decEnv.decoder.dicPos==dicPos_back))
|
|
_dec_onDecErr_rt();//error;
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
self->decReadPos+=inSize;
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress lzma2DecompressPlugin={_lzma2_is_can_open,_lzma2_open,
|
|
_lzma2_close,_lzma2_decompress_part};
|
|
#endif//_CompressPlugin_lzma2
|
|
|
|
#ifdef _CompressPlugin_7zXZ
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "Xz.h" // "lzma/C/Xz.h" https://github.com/sisong/lzma
|
|
# include "7zCrc.h" // CrcGenerateTable()
|
|
#endif
|
|
|
|
#ifndef _init_CompressPlugin_7zXZ_DEF
|
|
# define _init_CompressPlugin_7zXZ_DEF
|
|
static int _init_CompressPlugin_7zXZ(){
|
|
static hpatch_BOOL _isInit=hpatch_FALSE;
|
|
if (!_isInit){
|
|
CrcGenerateTable();
|
|
_isInit=hpatch_TRUE;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
typedef struct _7zXZ_TDecompress{
|
|
ISzAlloc memAllocBase;
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
hpatch_TDecompress* decompressPlugin;
|
|
hpatch_BOOL isResetState;
|
|
|
|
CXzUnpacker decEnv;
|
|
SizeT decCopyPos;
|
|
SizeT decReadPos;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char dec_buf[kDecompressBufSize];
|
|
} _7zXZ_TDecompress;
|
|
static void * __7zXZ_dec_Alloc(ISzAllocPtr p, size_t size)
|
|
__dec_Alloc_fun(_7zXZ_TDecompress,p,size)
|
|
|
|
static hpatch_BOOL _7zXZ_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"7zXZ"));
|
|
}
|
|
static void _7zXZ_open_at(_7zXZ_TDecompress* self, hpatch_TDecompress* decompressPlugin,hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end,hpatch_BOOL isResetState,hpatch_BOOL isParseHead){
|
|
memset(self,0,sizeof(_7zXZ_TDecompress)-kDecompressBufSize);
|
|
self->memAllocBase.Alloc=__7zXZ_dec_Alloc;
|
|
*((void**)&self->memAllocBase.Free)=(void*)__dec_free;
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->decompressPlugin=decompressPlugin;
|
|
self->isResetState=isResetState;
|
|
|
|
self->decCopyPos=0;
|
|
self->decReadPos=kDecompressBufSize;
|
|
|
|
XzUnpacker_Construct(&self->decEnv,&self->memAllocBase);
|
|
XzUnpacker_Init(&self->decEnv);
|
|
if (!isParseHead)
|
|
self->decEnv.state=XZ_STATE_BLOCK_HEADER;
|
|
}
|
|
static void _7zXZ_close_at(hpatch_decompressHandle decompressHandle){
|
|
_7zXZ_TDecompress* self=(_7zXZ_TDecompress*)decompressHandle;
|
|
if (self){
|
|
hpatch_TDecompress* decompressPlugin=self->decompressPlugin;
|
|
XzUnpacker_Free(&self->decEnv);
|
|
_dec_onDecErr_up();
|
|
}
|
|
}
|
|
static hpatch_decompressHandle _7zXZ_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_7zXZ_TDecompress* self=0;
|
|
|
|
self=(_7zXZ_TDecompress*)_dec_malloc(sizeof(_7zXZ_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
_7zXZ_open_at(self,decompressPlugin,dataSize,codeStream,
|
|
code_begin,code_end,hpatch_FALSE,hpatch_TRUE);
|
|
return self;
|
|
}
|
|
static hpatch_decompressHandle _7zXZ_a_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_7zXZ_TDecompress* self=0;
|
|
|
|
self=(_7zXZ_TDecompress*)_dec_malloc(sizeof(_7zXZ_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
_7zXZ_open_at(self,decompressPlugin,dataSize,codeStream,
|
|
code_begin,code_end,hpatch_TRUE,hpatch_TRUE);
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _7zXZ_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
if (decompressHandle){
|
|
_7zXZ_close_at(decompressHandle);
|
|
free(decompressHandle);
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _7zXZ_reset_code(hpatch_decompressHandle decompressHandle,
|
|
hpatch_StreamPos_t dataSize,
|
|
const struct hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_7zXZ_TDecompress* self=(_7zXZ_TDecompress*)decompressHandle;
|
|
hpatch_BOOL isResetState=self->isResetState;
|
|
if (isResetState){
|
|
hpatch_TDecompress* decompressPlugin=self->decompressPlugin;
|
|
_7zXZ_close_at(self);
|
|
_7zXZ_open_at(self,decompressPlugin,dataSize,codeStream,
|
|
code_begin,code_end,isResetState,hpatch_FALSE);
|
|
}else{
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->decCopyPos=0;
|
|
self->decReadPos=kDecompressBufSize;
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _7zXZ_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_7zXZ_TDecompress* self=(_7zXZ_TDecompress*)decompressHandle;
|
|
unsigned char* out_cur=out_part_data;
|
|
assert(out_part_data<=out_part_data_end);
|
|
while (out_cur<out_part_data_end){
|
|
ECoderStatus status;
|
|
SizeT inSize;
|
|
SizeT outSize=out_part_data_end-out_cur;
|
|
SRes res;
|
|
hpatch_StreamPos_t codeLen=(self->code_end-self->code_begin);
|
|
if ((self->decReadPos==kDecompressBufSize)&&(codeLen>0)) {
|
|
size_t readLen=kDecompressBufSize;
|
|
if (readLen>codeLen) readLen=(size_t)codeLen;
|
|
self->decReadPos=kDecompressBufSize-readLen;
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,self->dec_buf+self->decReadPos,
|
|
self->dec_buf+self->decReadPos+readLen)) return hpatch_FALSE;//error;
|
|
self->code_begin+=readLen;
|
|
codeLen-=readLen;
|
|
}
|
|
|
|
inSize=kDecompressBufSize-self->decReadPos;
|
|
res=XzUnpacker_Code(&self->decEnv,out_cur,&outSize,self->dec_buf+self->decReadPos,&inSize,
|
|
codeLen==0,CODER_FINISH_ANY,&status);
|
|
if(res==SZ_OK){
|
|
if ((inSize==0)&&(outSize==0))
|
|
_dec_onDecErr_rt();//error;
|
|
}else{
|
|
_dec_onDecErr_rt();//error;
|
|
}
|
|
self->decReadPos+=inSize;
|
|
out_cur+=outSize;
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress _7zXZDecompressPlugin={_7zXZ_is_can_open,_7zXZ_open,
|
|
_7zXZ_close,_7zXZ_decompress_part,_7zXZ_reset_code};
|
|
static hpatch_TDecompress _7zXZDecompressPlugin_a={_7zXZ_is_can_open,_7zXZ_a_open,
|
|
_7zXZ_close,_7zXZ_decompress_part,_7zXZ_reset_code};
|
|
#endif//_CompressPlugin_7zXZ
|
|
|
|
|
|
#if (defined(_CompressPlugin_lz4) || defined(_CompressPlugin_lz4hc))
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "lz4.h" // "lz4/lib/lz4.h" https://github.com/lz4/lz4
|
|
#endif
|
|
typedef struct _lz4_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
LZ4_streamDecode_t *s;
|
|
int kLz4CompressBufSize;
|
|
int code_buf_size;
|
|
int data_begin;
|
|
int data_end;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char buf[1];
|
|
} _lz4_TDecompress;
|
|
static hpatch_BOOL _lz4_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"lz4"));
|
|
}
|
|
#define _lz4_read_len4(len,in_code,code_begin,code_end,__dec_err_rt) { \
|
|
unsigned char _temp_buf4[4]; \
|
|
if (4>code_end-code_begin) __dec_err_rt(); \
|
|
if (!in_code->read(in_code,code_begin,_temp_buf4,_temp_buf4+4)) \
|
|
return hpatch_FALSE; \
|
|
len=_temp_buf4[0]|(_temp_buf4[1]<<8)|(_temp_buf4[2]<<16)|(_temp_buf4[3]<<24); \
|
|
code_begin+=4; \
|
|
}
|
|
static hpatch_decompressHandle _lz4_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
const int kMaxLz4CompressBufSize=(1<<20)*64; //defence attack
|
|
_lz4_TDecompress* self=0;
|
|
int kLz4CompressBufSize=0;
|
|
int code_buf_size=0;
|
|
assert(code_begin<code_end);
|
|
{//read kLz4CompressBufSize
|
|
_lz4_read_len4(kLz4CompressBufSize,codeStream,code_begin,code_end,_dec_openErr_rt);
|
|
if ((kLz4CompressBufSize<0)||(kLz4CompressBufSize>=kMaxLz4CompressBufSize)) _dec_openErr_rt();
|
|
code_buf_size=LZ4_compressBound(kLz4CompressBufSize);
|
|
}
|
|
self=(_lz4_TDecompress*)_dec_malloc(sizeof(_lz4_TDecompress)+kLz4CompressBufSize+code_buf_size);
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_lz4_TDecompress));
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->kLz4CompressBufSize=kLz4CompressBufSize;
|
|
self->code_buf_size=code_buf_size;
|
|
self->data_begin=0;
|
|
self->data_end=0;
|
|
|
|
self->s = LZ4_createStreamDecode();
|
|
if (!self->s){ free(self); _dec_openErr_rt(); }
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _lz4_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
hpatch_BOOL result=hpatch_TRUE;
|
|
_lz4_TDecompress* self=(_lz4_TDecompress*)decompressHandle;
|
|
if (!self) return result;
|
|
_dec_onDecErr_up();
|
|
_dec_close_check(0==LZ4_freeStreamDecode(self->s));
|
|
free(self);
|
|
return result;
|
|
}
|
|
static hpatch_BOOL _lz4_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_lz4_TDecompress* self=(_lz4_TDecompress*)decompressHandle;
|
|
unsigned char* data_buf=self->buf;
|
|
unsigned char* code_buf=self->buf+self->kLz4CompressBufSize;
|
|
|
|
while (out_part_data<out_part_data_end) {
|
|
size_t dataLen=self->data_end-self->data_begin;
|
|
if (dataLen>0){
|
|
if (dataLen>(out_part_data_end-out_part_data))
|
|
dataLen=(out_part_data_end-out_part_data);
|
|
memcpy(out_part_data,data_buf+self->data_begin,dataLen);
|
|
out_part_data+=(size_t)dataLen;
|
|
self->data_begin+=dataLen;
|
|
}else{
|
|
int codeLen;
|
|
_lz4_read_len4(codeLen,self->codeStream,self->code_begin,self->code_end,_dec_onDecErr_rt);
|
|
if ((codeLen<=0)||(codeLen>self->code_buf_size)
|
|
||((size_t)codeLen>(self->code_end-self->code_begin))) _dec_onDecErr_rt();
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,
|
|
code_buf,code_buf+codeLen)) return hpatch_FALSE;
|
|
self->code_begin+=codeLen;
|
|
self->data_begin=0;
|
|
self->data_end=LZ4_decompress_safe_continue(self->s,(const char*)code_buf,(char*)data_buf,
|
|
codeLen,self->kLz4CompressBufSize);
|
|
if (self->data_end<=0) _dec_onDecErr_rt();
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress lz4DecompressPlugin={_lz4_is_can_open,_lz4_open,
|
|
_lz4_close,_lz4_decompress_part};
|
|
#endif//_CompressPlugin_lz4 or _CompressPlugin_lz4hc
|
|
|
|
#ifdef _CompressPlugin_zstd
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
//# define ZSTD_STATIC_LINKING_ONLY //for ZSTD_customMem
|
|
# include "zstd.h" // "zstd/lib/zstd.h" https://github.com/sisong/zstd
|
|
#endif
|
|
typedef struct _zstd_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
ZSTD_inBuffer s_input;
|
|
ZSTD_outBuffer s_output;
|
|
size_t data_begin;
|
|
ZSTD_DStream* s;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char buf[1];
|
|
} _zstd_TDecompress;
|
|
#ifdef ZSTD_STATIC_LINKING_ONLY
|
|
static void* __ZSTD_alloc(void* opaque, size_t size)
|
|
__dec_Alloc_fun(_zstd_TDecompress,opaque,size)
|
|
#endif
|
|
static hpatch_BOOL _zstd_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"zstd"));
|
|
}
|
|
static hpatch_decompressHandle _zstd_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
_zstd_TDecompress* self=0;
|
|
size_t ret;
|
|
size_t _input_size=ZSTD_DStreamInSize();
|
|
size_t _output_size=ZSTD_DStreamOutSize();
|
|
self=(_zstd_TDecompress*)_dec_malloc(sizeof(_zstd_TDecompress)+_input_size+_output_size);
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_zstd_TDecompress));
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->s_input.src=self->buf;
|
|
self->s_input.size=_input_size;
|
|
self->s_input.pos=_input_size;
|
|
self->s_output.dst=self->buf+_input_size;
|
|
self->s_output.size=_output_size;
|
|
self->s_output.pos=0;
|
|
self->data_begin=0;
|
|
#ifdef ZSTD_STATIC_LINKING_ONLY
|
|
{
|
|
ZSTD_customMem customMem={__ZSTD_alloc,__dec_free,self};
|
|
self->s=ZSTD_createDStream_advanced(customMem);
|
|
}
|
|
#else
|
|
self->s=ZSTD_createDStream();
|
|
#endif
|
|
if (!self->s){ _dec_onDecErr_up(); free(self); _dec_openErr_rt(); }
|
|
ret=ZSTD_initDStream(self->s);
|
|
if (ZSTD_isError(ret)) { ZSTD_freeDStream(self->s); _dec_onDecErr_up(); free(self); _dec_openErr_rt(); }
|
|
#define _ZSTD_WINDOWLOG_MAX 30
|
|
ret=ZSTD_DCtx_setParameter(self->s,ZSTD_d_windowLogMax,_ZSTD_WINDOWLOG_MAX);
|
|
//if (ZSTD_isError(ret)) { printf("WARNING: ZSTD_DCtx_setMaxWindowSize() error!"); }
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _zstd_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
hpatch_BOOL result=hpatch_TRUE;
|
|
_zstd_TDecompress* self=(_zstd_TDecompress*)decompressHandle;
|
|
if (!self) return result;
|
|
_dec_onDecErr_up();
|
|
_dec_close_check(0==ZSTD_freeDStream(self->s));
|
|
free(self);
|
|
return result;
|
|
}
|
|
static hpatch_BOOL _zstd_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_zstd_TDecompress* self=(_zstd_TDecompress*)decompressHandle;
|
|
while (out_part_data<out_part_data_end) {
|
|
size_t dataLen=(self->s_output.pos-self->data_begin);
|
|
if (dataLen>0){
|
|
if (dataLen>(size_t)(out_part_data_end-out_part_data))
|
|
dataLen=(out_part_data_end-out_part_data);
|
|
memcpy(out_part_data,(const unsigned char*)self->s_output.dst+self->data_begin,dataLen);
|
|
out_part_data+=dataLen;
|
|
self->data_begin+=dataLen;
|
|
}else{
|
|
size_t ret;
|
|
if (self->s_input.pos==self->s_input.size) {
|
|
self->s_input.pos=0;
|
|
if (self->s_input.size>self->code_end-self->code_begin)
|
|
self->s_input.size=(size_t)(self->code_end-self->code_begin);
|
|
|
|
if (self->s_input.size>0){
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,(unsigned char*)self->s_input.src,
|
|
(unsigned char*)self->s_input.src+self->s_input.size))
|
|
return hpatch_FALSE;
|
|
self->code_begin+=self->s_input.size;
|
|
}
|
|
}
|
|
self->s_output.pos=0;
|
|
self->data_begin=0;
|
|
ret=ZSTD_decompressStream(self->s,&self->s_output,&self->s_input);
|
|
if (ZSTD_isError(ret)) _dec_onDecErr_rt();
|
|
if (self->s_output.pos==self->data_begin) _dec_onDecErr_rt();
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress zstdDecompressPlugin={_zstd_is_can_open,_zstd_open,
|
|
_zstd_close,_zstd_decompress_part};
|
|
#endif//_CompressPlugin_zstd
|
|
|
|
|
|
#ifdef _CompressPlugin_brotli
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "brotli/decode.h" // "brotli/c/include/brotli/decode.h" https://github.com/google/brotli
|
|
#endif
|
|
typedef struct _brotli_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
unsigned char* input;
|
|
unsigned char* output;
|
|
size_t available_in;
|
|
size_t available_out;
|
|
const unsigned char* next_in;
|
|
unsigned char* next_out;
|
|
unsigned char* data_begin;
|
|
BrotliDecoderState* s;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char buf[1];
|
|
} _brotli_TDecompress;
|
|
static hpatch_BOOL _brotli_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"brotli"));
|
|
}
|
|
static hpatch_decompressHandle _brotli_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
const size_t kBufSize=kDecompressBufSize;
|
|
_brotli_TDecompress* self=0;
|
|
assert(code_begin<code_end);
|
|
self=(_brotli_TDecompress*)_dec_malloc(sizeof(_brotli_TDecompress)+kBufSize*2);
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_brotli_TDecompress));
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->input=self->buf;
|
|
self->output=self->buf+kBufSize;
|
|
self->code_end=code_end;
|
|
self->available_in = 0;
|
|
self->next_in = 0;
|
|
self->available_out = (self->output-self->input);
|
|
self->next_out =self->output;
|
|
self->data_begin=self->output;
|
|
|
|
self->s = BrotliDecoderCreateInstance(0,0,0);
|
|
if (!self->s){ free(self); _dec_openErr_rt(); }
|
|
if (!BrotliDecoderSetParameter(self->s, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1u))
|
|
{ BrotliDecoderDestroyInstance(self->s); free(self); _dec_openErr_rt(); }
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _brotli_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_brotli_TDecompress* self=(_brotli_TDecompress*)decompressHandle;
|
|
if (!self) return hpatch_TRUE;
|
|
_dec_onDecErr_up();
|
|
BrotliDecoderDestroyInstance(self->s);
|
|
free(self);
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _brotli_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_brotli_TDecompress* self=(_brotli_TDecompress*)decompressHandle;
|
|
while (out_part_data<out_part_data_end) {
|
|
size_t dataLen=(self->next_out-self->data_begin);
|
|
if (dataLen>0){
|
|
if (dataLen>(size_t)(out_part_data_end-out_part_data))
|
|
dataLen=(out_part_data_end-out_part_data);
|
|
memcpy(out_part_data,self->data_begin,dataLen);
|
|
out_part_data+=dataLen;
|
|
self->data_begin+=dataLen;
|
|
}else{
|
|
BrotliDecoderResult ret;
|
|
if (self->available_in==0) {
|
|
self->available_in=(self->output-self->input);
|
|
if (self->available_in>self->code_end-self->code_begin)
|
|
self->available_in=(size_t)(self->code_end-self->code_begin);
|
|
if (self->available_in>0){
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,(unsigned char*)self->input,
|
|
self->input+self->available_in))
|
|
return hpatch_FALSE;
|
|
self->code_begin+=self->available_in;
|
|
}
|
|
self->next_in=self->input;
|
|
}
|
|
self->available_out = (self->output-self->input);
|
|
self->next_out =self->output;
|
|
self->data_begin=self->output;
|
|
ret=BrotliDecoderDecompressStream(self->s,&self->available_in,&self->next_in,
|
|
&self->available_out,&self->next_out, 0);
|
|
switch (ret){
|
|
case BROTLI_DECODER_RESULT_SUCCESS:
|
|
case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: {
|
|
if (self->next_out==self->data_begin) _dec_onDecErr_rt();
|
|
} break;
|
|
case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: {
|
|
if (self->code_end==self->code_begin) _dec_onDecErr_rt();
|
|
} break;
|
|
default:
|
|
_dec_onDecErr_rt();
|
|
}
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress brotliDecompressPlugin={_brotli_is_can_open,_brotli_open,
|
|
_brotli_close,_brotli_decompress_part};
|
|
#endif//_CompressPlugin_brotli
|
|
|
|
|
|
#ifdef _CompressPlugin_lzham
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "lzham.h" // "lzham_codec/include/lzham.h" https://github.com/richgel999/lzham_codec
|
|
#endif
|
|
typedef struct _lzham_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
|
|
unsigned char* input;
|
|
unsigned char* output;
|
|
size_t available_in;
|
|
size_t available_out;
|
|
const unsigned char* next_in;
|
|
unsigned char* next_out;
|
|
unsigned char* data_begin;
|
|
lzham_decompress_state_ptr s;
|
|
hpatch_dec_error_t decError;
|
|
unsigned char buf[1];
|
|
} _lzham_TDecompress;
|
|
static hpatch_BOOL _lzham_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"lzham"));
|
|
}
|
|
static hpatch_decompressHandle _lzham_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
const size_t kBufSize=kDecompressBufSize;
|
|
lzham_decompress_params params;
|
|
unsigned char dict_bits;
|
|
_lzham_TDecompress* self=0;
|
|
assert(code_begin<code_end);
|
|
{//load head
|
|
if (code_end-code_begin<1) _dec_openErr_rt();
|
|
if (!codeStream->read(codeStream,code_begin,&dict_bits,(&dict_bits)+1))
|
|
return 0;
|
|
++code_begin;
|
|
}
|
|
|
|
self=(_lzham_TDecompress*)_dec_malloc(sizeof(_lzham_TDecompress)+kBufSize*2);
|
|
if (!self) _dec_memErr_rt();
|
|
memset(self,0,sizeof(_lzham_TDecompress));
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->input=self->buf;
|
|
self->output=self->buf+kBufSize;
|
|
self->code_end=code_end;
|
|
self->available_in = 0;
|
|
self->next_in = 0;
|
|
self->available_out = (self->output-self->input);
|
|
self->next_out =self->output;
|
|
self->data_begin=self->output;
|
|
|
|
memset(¶ms, 0, sizeof(params));
|
|
params.m_struct_size = sizeof(params);
|
|
params.m_dict_size_log2 = dict_bits;
|
|
|
|
self->s = lzham_decompress_init(¶ms);
|
|
if (!self->s){ free(self); _dec_openErr_rt(); }
|
|
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _lzham_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_lzham_TDecompress* self=(_lzham_TDecompress*)decompressHandle;
|
|
if (!self) return hpatch_TRUE;
|
|
_dec_onDecErr_up();
|
|
lzham_decompress_deinit(self->s);
|
|
free(self);
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _lzham_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
_lzham_TDecompress* self=(_lzham_TDecompress*)decompressHandle;
|
|
while (out_part_data<out_part_data_end) {
|
|
size_t dataLen=(self->next_out-self->data_begin);
|
|
if (dataLen>0){
|
|
if (dataLen>(size_t)(out_part_data_end-out_part_data))
|
|
dataLen=(out_part_data_end-out_part_data);
|
|
memcpy(out_part_data,self->data_begin,dataLen);
|
|
out_part_data+=dataLen;
|
|
self->data_begin+=dataLen;
|
|
}else{
|
|
lzham_decompress_status_t ret;
|
|
if (self->available_in==0) {
|
|
self->available_in=(self->output-self->input);
|
|
if (self->available_in>self->code_end-self->code_begin)
|
|
self->available_in=(size_t)(self->code_end-self->code_begin);
|
|
if (self->available_in>0){
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,(unsigned char*)self->input,
|
|
self->input+self->available_in))
|
|
return hpatch_FALSE;
|
|
self->code_begin+=self->available_in;
|
|
}
|
|
self->next_in=self->input;
|
|
}
|
|
{
|
|
size_t available_in_back=self->available_in;
|
|
self->available_out = (self->output-self->input);
|
|
ret=lzham_decompress(self->s,self->next_in,&self->available_in,
|
|
self->output,&self->available_out,(self->code_begin==self->code_end));
|
|
self->next_out=self->output+self->available_out;
|
|
self->next_in+=self->available_in;
|
|
self->available_in=available_in_back-self->available_in;
|
|
self->available_out=(self->output-self->input) - self->available_out;
|
|
self->data_begin=self->output;
|
|
}
|
|
switch (ret){
|
|
case LZHAM_DECOMP_STATUS_SUCCESS:
|
|
case LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT:
|
|
case LZHAM_DECOMP_STATUS_NOT_FINISHED: {
|
|
if (self->next_out==self->data_begin) _dec_onDecErr_rt();
|
|
} break;
|
|
case LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT: {
|
|
if (self->code_end==self->code_begin) _dec_onDecErr_rt();
|
|
} break;
|
|
default:
|
|
_dec_onDecErr_rt();
|
|
}
|
|
}
|
|
}
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress lzhamDecompressPlugin={_lzham_is_can_open,_lzham_open,
|
|
_lzham_close,_lzham_decompress_part};
|
|
#endif//_CompressPlugin_lzham
|
|
|
|
|
|
#ifdef _CompressPlugin_tuz
|
|
#if (_IsNeedIncludeDefaultCompressHead)
|
|
# include "tuz_dec.h" // "tinyuz/decompress/tuz_dec.h" https://github.com/sisong/tinyuz
|
|
#endif
|
|
typedef struct _tuz_TDecompress{
|
|
const struct hpatch_TStreamInput* codeStream;
|
|
hpatch_StreamPos_t code_begin;
|
|
hpatch_StreamPos_t code_end;
|
|
tuz_byte* dec_mem;
|
|
tuz_TStream s;
|
|
hpatch_dec_error_t decError;
|
|
} _tuz_TDecompress;
|
|
|
|
static tuz_BOOL _tuz_TDecompress_read_code(tuz_TInputStreamHandle listener,
|
|
tuz_byte* out_code,tuz_size_t* code_size){
|
|
_tuz_TDecompress* self=(_tuz_TDecompress*)listener;
|
|
tuz_size_t r_size=*code_size;
|
|
hpatch_StreamPos_t s_size=self->code_end-self->code_begin;
|
|
if (r_size>s_size){
|
|
r_size=(tuz_size_t)s_size;
|
|
*code_size=r_size;
|
|
}
|
|
if (!self->codeStream->read(self->codeStream,self->code_begin,
|
|
out_code,out_code+r_size)) return tuz_FALSE;
|
|
self->code_begin+=r_size;
|
|
return tuz_TRUE;
|
|
}
|
|
|
|
static hpatch_BOOL _tuz_is_can_open(const char* compressType){
|
|
return (0==strcmp(compressType,"tuz"));
|
|
}
|
|
static hpatch_decompressHandle _tuz_open(hpatch_TDecompress* decompressPlugin,
|
|
hpatch_StreamPos_t dataSize,
|
|
const hpatch_TStreamInput* codeStream,
|
|
hpatch_StreamPos_t code_begin,
|
|
hpatch_StreamPos_t code_end){
|
|
tuz_size_t dictSize;
|
|
_tuz_TDecompress* self=0;
|
|
self=(_tuz_TDecompress*)_dec_malloc(sizeof(_tuz_TDecompress));
|
|
if (!self) _dec_memErr_rt();
|
|
self->dec_mem=0;
|
|
self->codeStream=codeStream;
|
|
self->code_begin=code_begin;
|
|
self->code_end=code_end;
|
|
self->decError=hpatch_dec_ok;
|
|
dictSize=tuz_TStream_read_dict_size(self,_tuz_TDecompress_read_code);
|
|
if (((tuz_size_t)(dictSize-1))>=tuz_kMaxOfDictSize) { free(self); _dec_openErr_rt(); }
|
|
self->dec_mem=(tuz_byte*)_dec_malloc(dictSize+kDecompressBufSize);
|
|
if (self->dec_mem==0){ free(self); _dec_memErr_rt(); }
|
|
if (tuz_OK!=tuz_TStream_open(&self->s,self,_tuz_TDecompress_read_code,
|
|
self->dec_mem,dictSize,kDecompressBufSize)){
|
|
free(self->dec_mem); free(self); _dec_openErr_rt(); }
|
|
return self;
|
|
}
|
|
static hpatch_BOOL _tuz_close(struct hpatch_TDecompress* decompressPlugin,
|
|
hpatch_decompressHandle decompressHandle){
|
|
_tuz_TDecompress* self=(_tuz_TDecompress*)decompressHandle;
|
|
if (!self) return hpatch_TRUE;
|
|
_dec_onDecErr_up();
|
|
if (self->dec_mem) free(self->dec_mem);
|
|
free(self);
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_BOOL _tuz_decompress_part(hpatch_decompressHandle decompressHandle,
|
|
unsigned char* out_part_data,unsigned char* out_part_data_end){
|
|
tuz_TResult ret;
|
|
_tuz_TDecompress* self=(_tuz_TDecompress*)decompressHandle;
|
|
size_t out_size=out_part_data_end-out_part_data;
|
|
tuz_size_t data_size=(tuz_size_t)out_size;
|
|
assert(data_size==out_size);
|
|
ret=tuz_TStream_decompress_partial(&self->s,out_part_data,&data_size);
|
|
if (!((ret<=tuz_STREAM_END)&&(data_size==out_size)))
|
|
_dec_onDecErr_rt();
|
|
return hpatch_TRUE;
|
|
}
|
|
static hpatch_TDecompress tuzDecompressPlugin={_tuz_is_can_open,_tuz_open,
|
|
_tuz_close,_tuz_decompress_part};
|
|
#endif//_CompressPlugin_tuz
|
|
|
|
#endif
|