// File: /workspace/github_cpp_makefile_star2_O2/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, 0x8(%rsp)
movq %r8, 0x18(%rsp)
movq %rcx, %r14
movq %rdx, %rbp
movq %rsi, %rbx
movq %rdi, %r12
leaq 0x1a8(%rsp), %rdi
callq 0x37105
leaq 0x6b8(%rsp), %rdi
callq 0x38012
leaq 0x20(%rsp), %rdi
callq 0x358c0
leaq 0x258(%rsp), %rdi
callq 0x353b7
leaq 0x538(%rsp), %rdi
callq 0x48cec
xorps %xmm0, %xmm0
movaps %xmm0, 0x190(%rsp)
movaps %xmm0, 0x180(%rsp)
movaps %xmm0, 0x170(%rsp)
movaps %xmm0, 0x160(%rsp)
movaps %xmm0, 0x150(%rsp)
leaq 0x2bc9b(%rip), %r15     # 0x75558
movq %rbx, %rdi
movq %r15, %rsi
callq 0x358eb
pushq $0x7
popq %r13
testb %al, %al
jne 0x49900
leaq 0x2bcb1(%rip), %r15     # 0x75588
movq %rbx, %rdi
movq %r15, %rsi
callq 0x358eb
testb %al, %al
jne 0x49900
leaq 0x2bccb(%rip), %r15     # 0x755b8
movq %rbx, %rdi
movq %r15, %rsi
callq 0x358eb
testb %al, %al
je 0x49a2c
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x35a62
testb %al, %al
je 0x49a12
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 0x3719a
testb %al, %al
je 0x49a1f
movl 0x250(%rsp), %eax
addq 0x248(%rsp), %rax
subq 0x1f8(%rsp), %rax
pushq $0xa
popq %r12
cmpq %rax, 0xa8(%rsp)
jne 0x49a37
movl 0xc0(%rsp), %ebx
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x35343
cmpl %eax, %ebx
jne 0x49a40
movq 0xd8(%rsp), %rsi
cmpq $0x1, 0x10(%rsp)
jne 0x49b1a
xorl %r12d, %r12d
leaq 0x2e0(%rsp), %rdi
xorl %edx, %edx
callq 0x3d4d6
testl %eax, %eax
je 0x49df3
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 0x42c0
jmp 0x49b2f
pushq $0x9
popq %r13
leaq 0x12ca0(%rip), %rdi     # 0x5c6bd
jmp 0x49a33
pushq $0x1
popq %r13
leaq 0x12cee(%rip), %rdi     # 0x5c718
jmp 0x49a4c
leaq 0x12c34(%rip), %rdi     # 0x5c667
xorl %ebx, %ebx
jmp 0x49a4c
leaq 0x12d69(%rip), %rdi     # 0x5c7a7
jmp 0x49a47
leaq 0x12da8(%rip), %rdi     # 0x5c7ef
xorl %ebx, %ebx
movl %r12d, %r13d
xorl %r12d, %r12d
xorl %r14d, %r14d
callq 0x4510
movl %r13d, %ebp
leaq 0x6b8(%rsp), %rdi
callq 0x3801e
testb %al, %al
jne 0x49a7a
leaq 0x1363b(%rip), %rdi     # 0x5d0ad
callq 0x4510
movl %r13d, %ebp
leaq 0x538(%rsp), %rdi
callq 0x48cf8
leaq 0x258(%rsp), %rdi
callq 0x353d7
leaq 0x1a8(%rsp), %rdi
callq 0x37111
testb %al, %al
jne 0x49ab9
leaq 0x13632(%rip), %rdi     # 0x5d0de
callq 0x4510
testl %ebp, %ebp
pushq $0x3
popq %rax
cmovel %eax, %ebp
leaq 0x20(%rsp), %rdi
callq 0x358cc
leaq 0x150(%rsp), %rdi
callq 0x3f27c
testl %eax, %eax
jne 0x49ae8
leaq 0x13632(%rip), %rdi     # 0x5d10d
callq 0x4510
testl %ebp, %ebp
pushq $0x3
popq %rax
cmovel %eax, %ebp
testb %bl, %bl
je 0x49af6
movq 0x18(%rsp), %rdi
callq 0x3e699
movq %r12, %rdi
callq 0x43d0
movq %r14, %rdi
callq 0x43d0
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 0x3b886
testl %eax, %eax
je 0x49e05
cmpb $0x0, 0x434(%rsp)
je 0x49b4c
leaq 0x434(%rsp), %rdi
callq *(%r15)
testl %eax, %eax
je 0x49e28
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
callq 0x3527c
movl %eax, %r12d
cmpq %r14, %r12
seta %al
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
setne %bl
andb %al, %bl
pushq $0x2
popq %r13
cmpb $0x1, %bl
jne 0x49bb0
leaq 0x150(%rsp), %rdi
movq %r12, %rdx
callq 0x3ecc5
xorl %r12d, %r12d
testl %eax, %eax
je 0x49e34
xorl %r14d, %r14d
leaq 0x150(%rsp), %r12
jmp 0x49bdf
leal 0x1(%r12), %edi
callq 0x4430
testq %rax, %rax
je 0x49e42
movq %rax, %r14
addq %rax, %r12
leaq 0x2c0(%rsp), %rdi
movq %rax, %rsi
movq %r12, %rdx
movq %rdi, %r12
callq 0x3a656
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %rdx
leaq 0x1a8(%rsp), %rdi
movq %r12, %rcx
callq 0x352d0
testb %al, %al
je 0x49e15
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 0x35676
popq %rcx
popq %rdx
testb %al, %al
je 0x49e54
movq 0x258(%rsp), %rax
movq 0x8(%rax), %rax
cmpq 0x428(%rsp), %rax
jne 0x49e64
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 0x38181
addq $0x20, %rsp
testb %al, %al
je 0x49e77
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 0x48d28
addq $0x50, %rsp
testb %al, %al
je 0x49e80
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 0x4430
testq %rax, %rax
je 0x49e8d
movq %rax, %r12
movq 0x538(%rsp), %rdi
movq 0x258(%rsp), %rsi
movq 0xd8(%rsp), %rdx
cmpq $0x1, %r13
jne 0x49e9b
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 0x3ce56
addq $0x30, %rsp
testl %eax, %eax
jne 0x49eb4
pushq $0x15
popq %r13
leaq 0x13178(%rip), %rdi     # 0x5cf66
jmp 0x49a52
pushq $0x14
popq %r13
leaq 0x12acd(%rip), %rdi     # 0x5c8cb
xorl %ebx, %ebx
jmp 0x49a4f
pushq $0x6
popq %r13
leaq 0x12a6c(%rip), %rdi     # 0x5c87c
jmp 0x49a33
pushq $0xb
popq %r13
leaq 0x12bde(%rip), %rdi     # 0x5c9fe
xorl %r12d, %r12d
jmp 0x49a52
leaq 0x12af7(%rip), %rdi     # 0x5c926
jmp 0x49a33
movb $0x1, %bl
leaq 0x12b56(%rip), %rdi     # 0x5c993
jmp 0x49a4f
leaq 0x12b2c(%rip), %rdi     # 0x5c975
xorl %ebx, %ebx
pushq $0x4
popq %r13
jmp 0x49a4c
pushq $0xc
popq %r13
leaq 0x12c32(%rip), %rdi     # 0x5ca91
jmp 0x49a52
leaq 0x12cb6(%rip), %rdi     # 0x5cb21
xorl %r12d, %r12d
pushq $0xa
popq %r13
jmp 0x49a52
leaq 0x12ceb(%rip), %rdi     # 0x5cb69
jmp 0x49e20
pushq $0xd
popq %r13
leaq 0x12e03(%rip), %rdi     # 0x5cc8e
jmp 0x49e20
leaq 0x13012(%rip), %rdi     # 0x5cea6
xorl %r12d, %r12d
pushq $0x4
jmp 0x49e70
movq %r12, %r9
addq $0x20000, %r9           # imm = 0x20000
movq %r15, %rcx
movq %r12, %r8
callq 0x3c5aa
testl %eax, %eax
je 0x49ed9
xorl %ebp, %ebp
cmpb $0x0, 0x540(%rsp)
je 0x49ec9
pushq $0x3
popq %r13
jmp 0x49a5a
pushq $0x8
popq %r13
leaq 0x131b0(%rip), %rdi     # 0x5d084
jmp 0x49a52
pushq $0x5
popq %r13
leaq 0x12fe1(%rip), %rdi     # 0x5cec5
jmp 0x49a52