// File: /workspace/github_cpp_makefile_star2_O1/sisong[P]ApkDiffPatch/src/patch/Patcher.cpp
// Function: VirtualZipPatchWithStream(hpatch_TStreamInput const*, hpatch_TStreamInput const*, hpatch_TStreamOutput const*, unsigned long, char const*, int, void*, void*)
TPatchResult VirtualZipPatchWithStream(const hpatch_TStreamInput* oldZipStream,const hpatch_TStreamInput* zipDiffStream,
                                       const hpatch_TStreamOutput* outNewZipStream,size_t maxUncompressMemory,
                                       const char* tempUncompressFileName,int threadNum,
                                       IVirtualZip_in* _virtual_in,IVirtualZip_out* virtual_out){
#define HPATCH_CACHE_SIZE  (128*1024)
    UnZipper            oldZip;
    Zipper              out_newZip;
    ZipDiffData         zipDiffData;
    OldStream           oldStream;
    NewStream           newStream;
    hpatch_compressedDiffInfo   diffInfo;
    TByte*                      ref_cache=0;
    hpatch_TFileStreamOutput    io_refFile;
    hpatch_TStreamOutput        io_ref_cache;
    hpatch_TStreamInput*        input_ref=0;
    hpatch_TStreamOutput*       output_ref=0;
    TPatchResult    result=PATCH_SUCCESS;
    bool            _isInClear=false;
    bool            isUsedTempFile=false;
    TByte*          temp_cache =0;
    size_t          temp_cahe_size;
    ZipFilePos_t    decompressSumSize=0;
    hpatch_TDecompress* decompressPlugin=0;
    bool isSD=false;
    hpatch_singleCompressedDiffInfo sdiffInfo;

    UnZipper_init(&oldZip);
    Zipper_init(&out_newZip);
    ZipDiffData_init(&zipDiffData);
    OldStream_init(&oldStream);
    NewStream_init(&newStream);
    hpatch_TFileStreamOutput_init(&io_refFile);
    
#if (_IS_NEED_VIRTUAL_ZIP)
    VirtualZip_in*  virtual_in=0;
    VirtualZip_in   _virtual_in_;
    if (_virtual_in) { VirtualZip_in_init(&_virtual_in_); virtual_in=&_virtual_in_; }
#else
    assert(_virtual_in==0);
    assert(virtual_out==0);
#endif

#ifdef _CompressPlugin_lzma2
    if (decompressPlugin==0){
        if (ZipDiffData_isCanDecompress(zipDiffStream,&lzma2DecompressPlugin))
            decompressPlugin=&lzma2DecompressPlugin;
    }
#endif
#ifdef _CompressPlugin_lzma
    if (decompressPlugin==0){
        if (ZipDiffData_isCanDecompress(zipDiffStream,&lzmaDecompressPlugin))
            decompressPlugin=&lzmaDecompressPlugin;
    }
#endif
    if (decompressPlugin==0){
        decompressPlugin=&zlibDecompressPlugin;
        check(ZipDiffData_isCanDecompress(zipDiffStream,decompressPlugin),PATCH_COMPRESSTYPE_ERROR);
    }
    
    check(ZipDiffData_openRead(&zipDiffData,zipDiffStream,decompressPlugin),PATCH_ZIPDIFFINFO_ERROR);
    isSD=(zipDiffData.PatchModel==1);
    check(UnZipper_openStream(&oldZip,oldZipStream,zipDiffData.oldZipIsDataNormalized!=0,
                              zipDiffData.oldIsFileDataOffsetMatch!=0),PATCH_OPENREAD_ERROR);
    check(zipDiffData.oldZipCESize==UnZipper_CESize(&oldZip),PATCH_OLDDATA_ERROR);
#if (_IS_NEED_VIRTUAL_ZIP)
    if (virtual_in)
        check(VirtualZip_in_open(virtual_in,_virtual_in,&oldZip),PATCH_VIRTUAL_IN_BEGIN_ERROR);
#endif
    check(zipDiffData.oldCrc==OldStream_getOldCrc(&oldZip,zipDiffData.oldRefList,zipDiffData.oldRefCount
                                                  _VIRTUAL_IN(virtual_in)), PATCH_OLDDATA_ERROR);
    if (!isSD){
        check(getCompressedDiffInfo(&diffInfo,zipDiffData.hdiffzData),PATCH_HDIFFINFO_ERROR);
    }else{
        check(getSingleCompressedDiffInfo(&sdiffInfo,zipDiffData.hdiffzData,0),PATCH_SD_HDIFFINFO_ERROR);
        memset(&diffInfo,0,sizeof(diffInfo));
        diffInfo.newDataSize=sdiffInfo.newDataSize;
        diffInfo.oldDataSize=sdiffInfo.oldDataSize;
        diffInfo.compressedCount=(sdiffInfo.compressedSize>0)?1:0;
        memcpy(diffInfo.compressType,sdiffInfo.compressType,sizeof(diffInfo.compressType));
    }
    if (strlen(diffInfo.compressType) > 0)
        check(decompressPlugin->is_can_open(diffInfo.compressType),PATCH_COMPRESSTYPE_ERROR);
    
    decompressSumSize=OldStream_getDecompressSumSize(&oldZip,zipDiffData.oldRefList,zipDiffData.oldRefCount
                                                     _VIRTUAL_IN(virtual_in));
    
    isUsedTempFile=(decompressSumSize > maxUncompressMemory)&&(tempUncompressFileName!=0);
    if (isUsedTempFile){
        check(hpatch_TFileStreamOutput_open(&io_refFile,tempUncompressFileName,decompressSumSize),
              PATCH_OPENWRITE_ERROR);
        output_ref=&io_refFile.base;
        input_ref=(hpatch_TStreamInput*)&io_refFile.base;
    }else{
        ref_cache=(TByte*)malloc(decompressSumSize+1);//+1 not null
        check(ref_cache!=0, PATCH_MEM_ERROR);
        mem_as_hStreamOutput(&io_ref_cache,ref_cache,ref_cache+decompressSumSize);
        output_ref=&io_ref_cache;
        input_ref=(hpatch_TStreamInput*)&io_ref_cache;
    }
    
    check(OldStream_getDecompressData(&oldZip,zipDiffData.oldRefList,zipDiffData.oldRefCount,
                                      output_ref _VIRTUAL_IN(virtual_in)),PATCH_OLDDECOMPRESS_ERROR);
    check(OldStream_open(&oldStream,&oldZip,zipDiffData.oldRefList,zipDiffData.oldRefCount,
                         0,0,input_ref _VIRTUAL_IN(virtual_in)), PATCH_OLDSTREAM_ERROR);
    check(oldStream.stream->streamSize==diffInfo.oldDataSize,PATCH_OLDDATA_ERROR);
    
    check(Zipper_openStream(&out_newZip,outNewZipStream,(int)zipDiffData.newZipFileCount,(int)zipDiffData.newZipAlignSize,
                            (int)zipDiffData.newCompressLevel,(int)zipDiffData.newCompressMemLevel,
                            zipDiffData.normalizeSoPageAlign,zipDiffData.pageAlignCompatible,kPageAlign_inPatch),PATCH_OPENWRITE_ERROR);
    check(NewStream_open(&newStream,&out_newZip,&oldZip,  (size_t)diffInfo.newDataSize,
                         zipDiffData.newZipIsDataNormalized!=0,
                         zipDiffData.newZipCESize,zipDiffData.extraEdit,
                         zipDiffData.samePairList,zipDiffData.samePairCount,
                         zipDiffData.newRefOtherCompressedList,zipDiffData.newRefOtherCompressedCount,
                         (int)zipDiffData.newOtherCompressLevel,(int)zipDiffData.newOtherCompressMemLevel,
                         zipDiffData.newRefCompressedSizeList,zipDiffData.newRefCompressedSizeCount,
                         threadNum _VIRTUAL_IN(virtual_in) _VIRTUAL_OUT(virtual_out)),PATCH_NEWSTREAM_ERROR);
    
    temp_cahe_size=HPATCH_CACHE_SIZE+(isSD?sdiffInfo.stepMemSize:0);
    temp_cache =(TByte*)malloc(temp_cahe_size);
    check(temp_cache!=0,PATCH_MEM_ERROR);
    if (!isSD){
        check(patch_decompress_with_cache(newStream.stream,oldStream.stream,zipDiffData.hdiffzData,
                                          decompressPlugin,temp_cache,temp_cache+temp_cahe_size),PATCH_HPATCH_ERROR);
    }else{
        check(patch_single_compressed_diff(newStream.stream,oldStream.stream,zipDiffData.hdiffzData,
                                           sdiffInfo.diffDataPos,sdiffInfo.uncompressedSize,sdiffInfo.compressedSize,
                                           decompressPlugin,sdiffInfo.coverCount,sdiffInfo.stepMemSize,
                                           temp_cache,temp_cache+temp_cahe_size,0),PATCH_SD_HPATCH_ERROR);
    }
    check(newStream.isFinish,PATCH_ZIPPATCH_ERROR);
    
clear:
    _isInClear=true;
    check(Zipper_close(&out_newZip),PATCH_CLOSEFILE_ERROR);
    NewStream_close(&newStream);
    OldStream_close(&oldStream);
#if (_IS_NEED_VIRTUAL_ZIP)
    if (virtual_in) check(VirtualZip_in_close(virtual_in),PATCH_VIRTUAL_IN_END_ERROR);
#endif
    check(UnZipper_close(&oldZip),PATCH_CLOSEFILE_ERROR);
    ZipDiffData_close(&zipDiffData);
    check(hpatch_TFileStreamOutput_close(&io_refFile),PATCH_CLOSEFILE_ERROR);
    if (isUsedTempFile) hpatch_removeFile(tempUncompressFileName);
    if (temp_cache) free(temp_cache);
    if (ref_cache) free(ref_cache);
    return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x818, %rsp            # imm = 0x818
movl %r9d, %r13d
movq %r8, 0x18(%rsp)
movq %rcx, %r14
movq %rdx, 0x8(%rsp)
movq %rsi, %rbx
movq %rdi, %r12
leaq 0x1a8(%rsp), %rdi
callq 0x3ff18
leaq 0x6b8(%rsp), %rdi
callq 0x40e6a
leaq 0x20(%rsp), %rdi
callq 0x3e5fc
leaq 0x258(%rsp), %rdi
callq 0x3e0a0
leaq 0x538(%rsp), %rdi
callq 0x5334c
xorps %xmm0, %xmm0
movaps %xmm0, 0x190(%rsp)
movaps %xmm0, 0x180(%rsp)
movaps %xmm0, 0x170(%rsp)
movaps %xmm0, 0x160(%rsp)
movaps %xmm0, 0x150(%rsp)
leaq 0x285af(%rip), %rbp     # 0x7c548
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x3e62a
xorl %r15d, %r15d
testb %al, %al
cmovneq %rbp, %r15
jne 0x53fca
leaq 0x285c2(%rip), %rbp     # 0x7c578
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x3e62a
xorl %r15d, %r15d
testb %al, %al
cmovneq %rbp, %r15
testq %r15, %r15
jne 0x53fe9
leaq 0x285d2(%rip), %r15     # 0x7c5a8
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3e62a
testb %al, %al
je 0x5412f
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x3e7b4
testb %al, %al
je 0x54111
movq 0x20(%rsp), %rbp
xorl %edx, %edx
cmpq $0x0, 0x98(%rsp)
setne %dl
xorl %ecx, %ecx
cmpq $0x0, 0xa0(%rsp)
setne %cl
leaq 0x1a8(%rsp), %rdi
xorl %ebx, %ebx
movq %r12, %rsi
xorl %r8d, %r8d
callq 0x3ffab
testb %al, %al
je 0x54120
movl %r13d, 0x14(%rsp)
movl 0x250(%rsp), %eax
addq 0x248(%rsp), %rax
subq 0x1f8(%rsp), %rax
movl $0xa, %r13d
cmpq %rax, 0xa8(%rsp)
jne 0x5413e
movl 0xc0(%rsp), %ebx
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x3e027
cmpl %eax, %ebx
jne 0x54147
movq 0xd8(%rsp), %rsi
cmpq $0x1, %rbp
jne 0x5422c
xorl %r12d, %r12d
leaq 0x3f8(%rsp), %rdi
xorl %edx, %edx
callq 0x472a1
testl %eax, %eax
je 0x54507
leaq 0x2e0(%rsp), %rbx
movl $0x118, %edx            # imm = 0x118
movq %rbx, %rdi
xorl %esi, %esi
callq 0x41c0
leaq 0x430(%rsp), %rsi
movups -0x38(%rsi), %xmm0
xorl %eax, %eax
cmpq $0x0, -0x20(%rsi)
movups %xmm0, (%rbx)
setne %al
movl %eax, 0x10(%rbx)
leaq 0x2f4(%rsp), %rdi
movl $0x104, %edx            # imm = 0x104
callq 0x4290
jmp 0x54241
movl $0x9, %r13d
leaq 0x1348f(%rip), %rdi     # 0x675ad
jmp 0x5414e
movl $0x1, %r13d
leaq 0x134db(%rip), %rdi     # 0x67608
jmp 0x54150
movl $0x7, %r13d
leaq 0x1341b(%rip), %rdi     # 0x67557
jmp 0x5414e
leaq 0x13552(%rip), %rdi     # 0x67697
jmp 0x5414e
leaq 0x13591(%rip), %rdi     # 0x676df
xorl %ebx, %ebx
xorl %r12d, %r12d
xorl %r14d, %r14d
callq 0x44e0
movl %r13d, %ebp
leaq 0x6b8(%rsp), %rdi
callq 0x40e76
testb %al, %al
jne 0x5417e
leaq 0x13e27(%rip), %rdi     # 0x67f9d
callq 0x44e0
movl %r13d, %ebp
leaq 0x538(%rsp), %rdi
callq 0x53358
leaq 0x258(%rsp), %rdi
callq 0x3e0c3
leaq 0x1a8(%rsp), %rdi
callq 0x3ff24
testb %al, %al
jne 0x541bf
leaq 0x13e1e(%rip), %rdi     # 0x67fce
callq 0x44e0
testl %ebp, %ebp
movl $0x3, %eax
cmovel %eax, %ebp
leaq 0x20(%rsp), %rdi
callq 0x3e608
leaq 0x150(%rsp), %rdi
callq 0x49335
testl %eax, %eax
jne 0x541f0
leaq 0x13e1c(%rip), %rdi     # 0x67ffd
callq 0x44e0
testl %ebp, %ebp
movl $0x3, %eax
cmovel %eax, %ebp
testb %bl, %bl
je 0x541fe
movq 0x18(%rsp), %rdi
callq 0x486d9
testq %r12, %r12
je 0x5420b
movq %r12, %rdi
callq 0x43b0
testq %r14, %r14
je 0x54218
movq %r14, %rdi
callq 0x43b0
movl %ebp, %eax
addq $0x818, %rsp            # imm = 0x818
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2e0(%rsp), %rdi
callq 0x45035
testl %eax, %eax
je 0x5451b
cmpb $0x0, 0x2f4(%rsp)
je 0x5425e
leaq 0x2f4(%rsp), %rdi
callq *(%r15)
testl %eax, %eax
je 0x54542
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x3df0d
movl %eax, %r12d
cmpq %r14, %r12
seta %al
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
setne %bl
andb %al, %bl
cmpb $0x1, %bl
jne 0x542be
leaq 0x150(%rsp), %rdi
movq %r12, %rdx
callq 0x48d2e
xorl %r12d, %r12d
testl %eax, %eax
je 0x54554
xorl %r14d, %r14d
leaq 0x150(%rsp), %r12
jmp 0x542ed
leal 0x1(%r12), %edi
callq 0x4400
testq %rax, %rax
je 0x54568
movq %rax, %r14
addq %rax, %r12
leaq 0x2c0(%rsp), %rdi
movq %rax, %rsi
movq %r12, %rdx
movq %rdi, %r12
callq 0x4397b
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
movq %r12, %rcx
callq 0x3df6a
testb %al, %al
je 0x5452d
movq 0xb0(%rsp), %rdx
movq 0xb8(%rsp), %rcx
subq $0x8, %rsp
movq %r12, %rax
xorl %r12d, %r12d
leaq 0x260(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
xorl %r8d, %r8d
xorl %r9d, %r9d
pushq %rax
callq 0x3e379
addq $0x10, %rsp
testb %al, %al
je 0x5457a
movq 0x258(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x2e8(%rsp), %rax
jne 0x5458c
movl 0x28(%rsp), %edx
movl 0x38(%rsp), %ecx
movl 0x40(%rsp), %r8d
movl 0x48(%rsp), %r9d
movzbl 0xd0(%rsp), %eax
subq $0x8, %rsp
leaq 0x6c0(%rsp), %rdi
movq 0x10(%rsp), %rsi
pushq $0x0
pushq %rax
pushq 0xe0(%rsp)
callq 0x40ffb
addq $0x20, %rsp
testb %al, %al
je 0x54595
movq 0x2e0(%rsp), %rcx
xorl %r8d, %r8d
cmpq $0x0, 0x30(%rsp)
setne %r8b
movq 0x60(%rsp), %r9
movq 0xe0(%rsp), %rax
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rsi
movq 0x78(%rsp), %rdi
movq 0x80(%rsp), %r10
movl 0x50(%rsp), %r11d
movl 0x58(%rsp), %r12d
movups 0x88(%rsp), %xmm0
subq $0x50, %rsp
movl 0x64(%rsp), %r13d
movl %r13d, 0x48(%rsp)
movups %xmm0, 0x38(%rsp)
movl %r12d, 0x30(%rsp)
movl %r11d, 0x28(%rsp)
movq %r10, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
movq %rsi, 0x10(%rsp)
movq %rdx, 0x8(%rsp)
movq %rax, (%rsp)
leaq 0x588(%rsp), %rdi
leaq 0x708(%rsp), %rsi
leaq 0x1f8(%rsp), %rdx
callq 0x5338a
addq $0x50, %rsp
testb %al, %al
je 0x545a4
movq 0x428(%rsp), %rcx
movl $0x20000, %eax          # imm = 0x20000
movq %rcx, 0x8(%rsp)
leaq (%rcx,%rax), %r13
cmpq $0x1, %rbp
cmovneq %rax, %r13
movq %r13, %rdi
callq 0x4400
testq %rax, %rax
je 0x545b3
movq %rax, %r12
movq 0x538(%rsp), %rdi
movq 0x258(%rsp), %rsi
movq 0xd8(%rsp), %rdx
cmpq $0x1, %rbp
jne 0x545c5
movq 0x418(%rsp), %rcx
movq 0x408(%rsp), %r8
movq 0x410(%rsp), %r9
movq %r12, %rax
addq %r13, %rax
pushq $0x0
pushq %rax
pushq %r12
pushq 0x20(%rsp)
pushq 0x440(%rsp)
pushq %r15
callq 0x46a18
addq $0x30, %rsp
testl %eax, %eax
jne 0x545da
movl $0x15, %r13d
leaq 0x13954(%rip), %rdi     # 0x67e56
jmp 0x54156
movl $0x14, %r13d
leaq 0x132a7(%rip), %rdi     # 0x677bb
xorl %ebx, %ebx
jmp 0x54153
movl $0x6, %r13d
leaq 0x13244(%rip), %rdi     # 0x6776c
jmp 0x5414e
movl $0xb, %r13d
leaq 0x133b4(%rip), %rdi     # 0x678ee
xorl %r12d, %r12d
jmp 0x54156
movl $0x7, %r13d
leaq 0x132c7(%rip), %rdi     # 0x67816
jmp 0x5414e
movb $0x1, %bl
movl $0x2, %r13d
leaq 0x13320(%rip), %rdi     # 0x67883
jmp 0x54153
movl $0x4, %r13d
leaq 0x132f0(%rip), %rdi     # 0x67865
jmp 0x5414e
movl $0xc, %r13d
leaq 0x133fa(%rip), %rdi     # 0x67981
jmp 0x54156
leaq 0x1347e(%rip), %rdi     # 0x67a11
jmp 0x5453a
movl $0x2, %r13d
leaq 0x134b7(%rip), %rdi     # 0x67a59
jmp 0x5453a
movl $0xd, %r13d
leaq 0x135cd(%rip), %rdi     # 0x67b7e
jmp 0x5453a
movl $0x4, %r13d
leaq 0x137d6(%rip), %rdi     # 0x67d96
jmp 0x5453a
movq %r12, %r9
addq %r13, %r9
movq %r15, %rcx
movq %r12, %r8
callq 0x4606c
testl %eax, %eax
je 0x54603
cmpb $0x0, 0x540(%rsp)
je 0x545f1
xorl %ebp, %ebp
movl $0x3, %r13d
jmp 0x5415e
movl $0x8, %r13d
leaq 0x13976(%rip), %rdi     # 0x67f74
jmp 0x54156
movl $0x5, %r13d
leaq 0x137a5(%rip), %rdi     # 0x67db5
jmp 0x54156