// File: /workspace/github_cpp_makefile_star2_O3/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, %rbp
movq %rsi, %rbx
movq %rdi, %r12
leaq 0x1a8(%rsp), %rdi
callq 0x3fb0c
leaq 0x6b8(%rsp), %rdi
callq 0x40a63
leaq 0x20(%rsp), %rdi
callq 0x3e174
leaq 0x258(%rsp), %rdi
callq 0x3dc43
leaq 0x538(%rsp), %rdi
callq 0x5317c
xorps %xmm0, %xmm0
movaps %xmm0, 0x190(%rsp)
movaps %xmm0, 0x180(%rsp)
movaps %xmm0, 0x170(%rsp)
movaps %xmm0, 0x160(%rsp)
movaps %xmm0, 0x150(%rsp)
leaq 0x287bd(%rip), %r15     # 0x7c548
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3e1a2
testb %al, %al
jne 0x53dca
leaq 0x287d7(%rip), %r15     # 0x7c578
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3e1a2
testb %al, %al
jne 0x53dca
leaq 0x287f1(%rip), %r15     # 0x7c5a8
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3e1a2
testb %al, %al
je 0x53f01
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x3e32c
testb %al, %al
je 0x53ee3
movq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
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 0x3fb9f
testb %al, %al
je 0x53ef2
movl %r13d, 0x8(%rsp)
movl 0x250(%rsp), %eax
addq 0x248(%rsp), %rax
subq 0x1f8(%rsp), %rax
movl $0xa, %r13d
cmpq %rax, 0xa8(%rsp)
jne 0x53f10
movl 0xc0(%rsp), %ebx
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x3dbca
cmpl %eax, %ebx
jne 0x53f19
movq 0xd8(%rsp), %rsi
cmpq $0x1, 0x10(%rsp)
jne 0x53ffe
xorl %r12d, %r12d
leaq 0x2e0(%rsp), %rdi
xorl %edx, %edx
callq 0x46721
testl %eax, %eax
je 0x542d7
leaq 0x318(%rsp), %rsi
movaps -0x38(%rsi), %xmm0
leaq 0x434(%rsp), %rdi
movaps %xmm0, -0x14(%rdi)
xorl %eax, %eax
cmpq $0x0, -0x20(%rsi)
setne %al
movl %eax, -0x4(%rdi)
movl $0x104, %edx            # imm = 0x104
callq 0x4290
jmp 0x54013
movl $0x9, %r13d
leaq 0x1376d(%rip), %rdi     # 0x6765d
jmp 0x53f20
movl $0x1, %r13d
leaq 0x137b9(%rip), %rdi     # 0x676b8
jmp 0x53f22
movl $0x7, %r13d
leaq 0x136f9(%rip), %rdi     # 0x67607
jmp 0x53f20
leaq 0x13830(%rip), %rdi     # 0x67747
jmp 0x53f20
leaq 0x1386f(%rip), %rdi     # 0x6778f
xorl %ebx, %ebx
xorl %r12d, %r12d
xorl %r14d, %r14d
callq 0x44e0
movl %r13d, %ebp
leaq 0x6b8(%rsp), %rdi
callq 0x40a6f
testb %al, %al
jne 0x53f50
leaq 0x14105(%rip), %rdi     # 0x6804d
callq 0x44e0
movl %r13d, %ebp
leaq 0x538(%rsp), %rdi
callq 0x53188
leaq 0x258(%rsp), %rdi
callq 0x3dc66
leaq 0x1a8(%rsp), %rdi
callq 0x3fb18
testb %al, %al
jne 0x53f91
leaq 0x140fc(%rip), %rdi     # 0x6807e
callq 0x44e0
testl %ebp, %ebp
movl $0x3, %eax
cmovel %eax, %ebp
leaq 0x20(%rsp), %rdi
callq 0x3e180
leaq 0x150(%rsp), %rdi
callq 0x486aa
testl %eax, %eax
jne 0x53fc2
leaq 0x140fa(%rip), %rdi     # 0x680ad
callq 0x44e0
testl %ebp, %ebp
movl $0x3, %eax
cmovel %eax, %ebp
testb %bl, %bl
je 0x53fd0
movq 0x18(%rsp), %rdi
callq 0x479da
testq %r12, %r12
je 0x53fdd
movq %r12, %rdi
callq 0x43b0
testq %r14, %r14
je 0x53fea
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 0x420(%rsp), %rdi
callq 0x4482a
testl %eax, %eax
je 0x542eb
cmpb $0x0, 0x434(%rsp)
je 0x54030
leaq 0x434(%rsp), %rdi
callq *(%r15)
testl %eax, %eax
je 0x54312
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x3dac9
movl %eax, %r12d
cmpq %r14, %r12
seta %al
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
setne %bl
andb %al, %bl
cmpb $0x1, %bl
jne 0x54090
leaq 0x150(%rsp), %rdi
movq %r12, %rdx
callq 0x48055
xorl %r12d, %r12d
testl %eax, %eax
je 0x54324
xorl %r14d, %r14d
leaq 0x150(%rsp), %r12
jmp 0x540bf
leal 0x1(%r12), %edi
callq 0x4400
testq %rax, %rax
je 0x54338
movq %rax, %r14
addq %rax, %r12
leaq 0x2c0(%rsp), %rdi
movq %rax, %rsi
movq %r12, %rdx
movq %rdi, %r12
callq 0x433f7
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
movq %r12, %rcx
callq 0x3db26
testb %al, %al
je 0x542fd
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 0x3df20
addq $0x10, %rsp
testb %al, %al
je 0x5434a
movq 0x258(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x428(%rsp), %rax
jne 0x5435c
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 %rbp, %rsi
pushq $0x0
pushq %rax
pushq 0xe0(%rsp)
callq 0x40bf5
addq $0x20, %rsp
testb %al, %al
je 0x54365
movq 0x420(%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), %ebp
movups 0x88(%rsp), %xmm0
subq $0x50, %rsp
movl 0x58(%rsp), %r12d
movl %r12d, 0x48(%rsp)
movups %xmm0, 0x38(%rsp)
movl %ebp, 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 0x531ba
addq $0x50, %rsp
testb %al, %al
je 0x54374
movq 0x310(%rsp), %rax
movl $0x20000, %edi          # imm = 0x20000
movq %rax, 0x8(%rsp)
leaq (%rax,%rdi), %rbp
movq 0x10(%rsp), %r13
cmpq $0x1, %r13
cmoveq %rbp, %rdi
callq 0x4400
testq %rax, %rax
je 0x54383
movq %rax, %r12
movq 0x538(%rsp), %rdi
movq 0x258(%rsp), %rsi
movq 0xd8(%rsp), %rdx
cmpq $0x1, %r13
jne 0x54395
movq 0x300(%rsp), %rcx
movq 0x2f0(%rsp), %r8
movq 0x2f8(%rsp), %r9
movq %r12, %rax
addq %rbp, %rax
pushq $0x0
pushq %rax
pushq %r12
pushq 0x20(%rsp)
pushq 0x328(%rsp)
pushq %r15
callq 0x45f98
addq $0x30, %rsp
testl %eax, %eax
jne 0x543ae
movl $0x15, %r13d
leaq 0x13c34(%rip), %rdi     # 0x67f06
jmp 0x53f28
movl $0x14, %r13d
leaq 0x13587(%rip), %rdi     # 0x6786b
xorl %ebx, %ebx
jmp 0x53f25
movl $0x6, %r13d
leaq 0x13524(%rip), %rdi     # 0x6781c
jmp 0x53f20
movl $0xb, %r13d
leaq 0x13694(%rip), %rdi     # 0x6799e
xorl %r12d, %r12d
jmp 0x53f28
movl $0x7, %r13d
leaq 0x135a7(%rip), %rdi     # 0x678c6
jmp 0x53f20
movb $0x1, %bl
movl $0x2, %r13d
leaq 0x13600(%rip), %rdi     # 0x67933
jmp 0x53f25
movl $0x4, %r13d
leaq 0x135d0(%rip), %rdi     # 0x67915
jmp 0x53f20
movl $0xc, %r13d
leaq 0x136da(%rip), %rdi     # 0x67a31
jmp 0x53f28
leaq 0x1375e(%rip), %rdi     # 0x67ac1
jmp 0x5430a
movl $0x2, %r13d
leaq 0x13797(%rip), %rdi     # 0x67b09
jmp 0x5430a
movl $0xd, %r13d
leaq 0x138ad(%rip), %rdi     # 0x67c2e
jmp 0x5430a
movl $0x4, %r13d
leaq 0x13ab6(%rip), %rdi     # 0x67e46
jmp 0x5430a
movq %r12, %r9
addq $0x20000, %r9           # imm = 0x20000
movq %r15, %rcx
movq %r12, %r8
callq 0x45626
testl %eax, %eax
je 0x543d7
cmpb $0x0, 0x540(%rsp)
je 0x543c5
xorl %ebp, %ebp
movl $0x3, %r13d
jmp 0x53f30
movl $0x8, %r13d
leaq 0x13c52(%rip), %rdi     # 0x68024
jmp 0x53f28
movl $0x5, %r13d
leaq 0x13a81(%rip), %rdi     # 0x67e65
jmp 0x53f28