// File: sisong[P]ApkDiffPatch/src/diff/DiffData.cpp
// Function: serializeZipDiffData(std::vector<unsigned char, std::allocator<unsigned char>>&, ZipDiffData const*, std::vector<unsigned char, std::allocator<unsigned char>> const&, hdiff_TCompress const*, UnZipper const*)
static bool _serializeZipDiffData(std::vector<TByte>& out_data,const ZipDiffData*  data,
                                  const std::vector<TByte>& hdiffzData,
                                  const hdiff_TCompress* compressPlugin,const UnZipper* newZip){
    std::vector<TByte> headData;
    {//head data
        uint32_t backPairNew=~(uint32_t)0;
        uint32_t backPairOld=~(uint32_t)0;
        for (size_t i=0;i<data->samePairCount;++i){
            uint32_t curNewValue=data->samePairList[i*2+0];
            packUInt(headData,(uint32_t)(curNewValue-(uint32_t)(backPairNew+1)));
            backPairNew=curNewValue;
            
            uint32_t curOldValue=data->samePairList[i*2+1];
            if (curOldValue>=(uint32_t)(backPairOld+1))
                packUIntWithTag(headData,(uint32_t)(curOldValue-(uint32_t)(backPairOld+1)),0,1);
            else
                packUIntWithTag(headData,(uint32_t)((uint32_t)(backPairOld+1)-curOldValue),1,1);
            backPairOld=curOldValue;
        }
        pushIncList(headData,data->newRefOtherCompressedList,data->newRefOtherCompressedCount);
        for (size_t i=0;i<data->newRefCompressedSizeCount;++i){
            packUInt(headData,(uint32_t)data->newRefCompressedSizeList[i]);
        }
        pushIncList(headData,data->oldRefList,data->oldRefCount);
    }
    std::vector<TByte> headCode;
    {
        if (headData.empty()){
            headCode.clear();
        }else{
            headCode.resize((size_t)compressPlugin->maxCompressedSize(headData.size()));
            size_t codeSize=hdiff_compress_mem(compressPlugin,headCode.data(),headCode.data()+headCode.size(),
                                               headData.data(),headData.data()+headData.size());
            if ((0<codeSize)&(codeSize<=headCode.size()))
                headCode.resize(codeSize);
            else
                return false;//error
        }
    }
    
    {//type version
        static const char* kVersionType="ZiPat1&";
        pushBack(out_data,(const TByte*)kVersionType,(const TByte*)kVersionType+strlen(kVersionType));
    }
    {//compressType
        const char* compressType=compressPlugin->compressType();
        size_t compressTypeLen=strlen(compressType);
        if (compressTypeLen>hpatch_kMaxPluginTypeLength) return false;
        pushBack(out_data,(const TByte*)compressType,(const TByte*)compressType+compressTypeLen+1); //'\0'
    }
    //head info
    //add an empty normalizeSoPageAlign tag prefix into packed PatchModel, starting with v1.8.0
    #define kSoSmallPageAlignSize (1024*4)
    size_t tagPageAlign=data->normalizeSoPageAlign;
    tagPageAlign=(tagPageAlign==0)?kSoSmallPageAlignSize:((tagPageAlign==kSoSmallPageAlignSize)?0:tagPageAlign);
    while (tagPageAlign>=kSoSmallPageAlignSize){
        pushBack(out_data,&kPackedEmptyPrefix,1);
        tagPageAlign/=4;
    }
    packUInt(out_data,data->PatchModel);

    packUInt(out_data,data->newZipFileCount);
    packUInt(out_data,data->newZipIsDataNormalized);
    packUInt(out_data,data->newZipAlignSize);
    packUInt(out_data,data->newCompressLevel);
    packUInt(out_data,data->newCompressMemLevel);
    packUInt(out_data,data->newOtherCompressLevel);
    packUInt(out_data,data->newOtherCompressMemLevel);
    packUInt(out_data,data->newZipCESize);
    packUInt(out_data,data->samePairCount);
    packUInt(out_data,data->newRefOtherCompressedCount);
    packUInt(out_data,data->newRefCompressedSizeCount);
    packUInt(out_data,data->oldZipIsDataNormalized);
    packUInt(out_data,data->oldIsFileDataOffsetMatch);
    packUInt(out_data,data->oldZipCESize);
    packUInt(out_data,data->oldRefCount);
    packUInt(out_data,data->oldCrc);
    packUInt(out_data,headData.size());
    packUInt(out_data,headCode.size());
    packUInt(out_data,hdiffzData.size());
    
    //code data
    headData.clear();
    pushBack(out_data,headCode);
    headCode.clear();
    pushBack(out_data,hdiffzData);
    
    {//ExtraEdit
        pushBack(out_data,newZip->_cache_fvce,newZip->_centralDirectory);
        uint32_t extraSize=(uint32_t)(newZip->_centralDirectory-newZip->_cache_fvce);
        TByte buf4[4];
        writeUInt32_to(buf4,extraSize);
        pushBack(out_data,buf4,buf4+4);
        pushBack(out_data,(const TByte*)kExtraEdit,(const TByte*)kExtraEdit+kExtraEditLen);
    }
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
leaq -0x48(%rbp), %rdi
callq 0xbe70
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
movq $0x0, -0x58(%rbp)
movq -0x58(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x50(%rcx), %rax
jae 0xaff4
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x58(%rbp), %rcx
movl (%rax,%rcx,8), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movl -0x4c(%rbp), %esi
notl %esi
addl %eax, %esi
leaq -0x48(%rbp), %rdi
callq 0xb640
jmp 0xaf67
movl -0x5c(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x58(%rbp), %rcx
shlq %rcx
movl 0x4(%rax,%rcx,4), %eax
movl %eax, -0x70(%rbp)
movl -0x70(%rbp), %eax
movl -0x50(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jb 0xafbf
movl -0x70(%rbp), %eax
movl -0x50(%rbp), %esi
notl %esi
addl %eax, %esi
leaq -0x48(%rbp), %rdi
xorl %edx, %edx
movl $0x1, %ecx
callq 0xb670
jmp 0xafac
jmp 0xafdd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0xb62c
movl -0x50(%rbp), %esi
movl -0x70(%rbp), %eax
subl %eax, %esi
incl %esi
leaq -0x48(%rbp), %rdi
movl $0x1, %ecx
movl %ecx, %edx
callq 0xb670
jmp 0xafdb
jmp 0xafdd
movl -0x70(%rbp), %eax
movl %eax, -0x50(%rbp)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0xaf2e
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rsi
movq 0x60(%rax), %rdx
leaq -0x48(%rbp), %rdi
callq 0xb750
jmp 0xb00b
movq $0x0, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x70(%rcx), %rax
jae 0xb04b
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rax
movq -0x78(%rbp), %rcx
movl (%rax,%rcx,4), %esi
leaq -0x48(%rbp), %rdi
callq 0xb640
jmp 0xb03b
jmp 0xb03d
movq -0x78(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
jmp 0xb013
movq -0x18(%rbp), %rax
movq 0x90(%rax), %rsi
movq 0x98(%rax), %rdx
leaq -0x48(%rbp), %rdi
callq 0xb750
jmp 0xb068
leaq -0x90(%rbp), %rdi
callq 0xbe70
leaq -0x48(%rbp), %rdi
callq 0xce50
testb $0x1, %al
jne 0xb083
jmp 0xb094
leaq -0x90(%rbp), %rdi
callq 0xce90
jmp 0xb243
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xd0(%rbp)
leaq -0x48(%rbp), %rdi
callq 0xbe90
movq %rax, %rdi
movq -0xd0(%rbp), %rax
callq *%rax
movq %rax, -0xc8(%rbp)
jmp 0xb0c1
movq -0xc8(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0xbeb0
jmp 0xb0d6
movq -0x28(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0x90(%rbp), %rdi
movq %rdi, -0x118(%rbp)
callq 0xbb60
movq -0x118(%rbp), %rdi
movq %rax, -0xf0(%rbp)
callq 0xbb60
movq -0x118(%rbp), %rdi
movq %rax, -0x110(%rbp)
callq 0xbe90
movq %rax, %rcx
movq -0x110(%rbp), %rax
addq %rcx, %rax
movq %rax, -0xe8(%rbp)
leaq -0x48(%rbp), %rdi
movq %rdi, -0x108(%rbp)
callq 0xbb60
movq -0x108(%rbp), %rdi
movq %rax, -0xe0(%rbp)
callq 0xbb60
movq -0x108(%rbp), %rdi
movq %rax, -0x100(%rbp)
callq 0xbe90
movq -0x100(%rbp), %r8
movq -0xf8(%rbp), %rdi
movq -0xf0(%rbp), %rsi
movq -0xe8(%rbp), %rdx
movq -0xe0(%rbp), %rcx
addq %rax, %r8
callq 0xb7c0
movq %rax, -0xd8(%rbp)
jmp 0xb198
movq -0xd8(%rbp), %rax
movq %rax, -0x98(%rbp)
xorl %eax, %eax
cmpq -0x98(%rbp), %rax
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x11c(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x128(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xbe90
movq -0x128(%rbp), %rcx
movq %rax, %rdx
movl -0x11c(%rbp), %eax
cmpq %rdx, %rcx
setbe %cl
andb $0x1, %cl
movzbl %cl, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0xb22e
movq -0x98(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0xbeb0
jmp 0xb20f
jmp 0xb241
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xbb80
jmp 0xb62c
movb $0x0, -0x1(%rbp)
movl $0x1, -0x9c(%rbp)
jmp 0xb609
jmp 0xb243
movq -0x10(%rbp), %rax
movq %rax, -0x138(%rbp)
movq 0xdb313(%rip), %rdi     # 0xe6568
movq %rdi, -0x130(%rbp)
callq 0x4180
movq -0x138(%rbp), %rdi
movq -0x130(%rbp), %rsi
movq %rsi, %rdx
addq %rax, %rdx
callq 0xb850
jmp 0xb27c
movq -0x28(%rbp), %rax
movq (%rax), %rax
callq *%rax
movq %rax, -0x140(%rbp)
jmp 0xb28e
movq -0x140(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rdi
callq 0x4180
movq %rax, -0xb0(%rbp)
cmpq $0x103, -0xb0(%rbp) # imm = 0x103
jbe 0xb2cf
movb $0x0, -0x1(%rbp)
movl $0x1, -0x9c(%rbp)
jmp 0xb609
movq -0x10(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movq -0xb0(%rbp), %rax
leaq 0x1(%rsi,%rax), %rdx
callq 0xb850
jmp 0xb2ed
movq -0x18(%rbp), %rax
movq 0xa8(%rax), %rax
movq %rax, -0xb8(%rbp)
cmpq $0x0, -0xb8(%rbp)
jne 0xb317
movl $0x1000, %eax           # imm = 0x1000
movq %rax, -0x148(%rbp)
jmp 0xb34b
cmpq $0x1000, -0xb8(%rbp) # imm = 0x1000
jne 0xb32f
xorl %eax, %eax
movq %rax, -0x150(%rbp)
jmp 0xb33d
movq -0xb8(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rax
movq %rax, -0xb8(%rbp)
cmpq $0x1000, -0xb8(%rbp) # imm = 0x1000
jb 0xb391
movq -0x10(%rbp), %rdi
leaq 0xa2957(%rip), %rsi     # 0xadcc8
movl $0x1, %edx
callq 0xb8b0
jmp 0xb37d
movq -0xb8(%rbp), %rax
shrq $0x2, %rax
movq %rax, -0xb8(%rbp)
jmp 0xb359
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq (%rax), %rsi
callq 0xb8e0
jmp 0xb3a3
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0xb8e0
jmp 0xb3b6
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0xb8e0
jmp 0xb3c9
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0xb8e0
jmp 0xb3dc
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0xb8e0
jmp 0xb3ef
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rsi
callq 0xb8e0
jmp 0xb402
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0xb8e0
jmp 0xb415
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0xb8e0
jmp 0xb428
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x40(%rax), %rsi
callq 0xb8e0
jmp 0xb43b
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rsi
callq 0xb8e0
jmp 0xb44e
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x60(%rax), %rsi
callq 0xb8e0
jmp 0xb461
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rsi
callq 0xb8e0
jmp 0xb474
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x78(%rax), %rsi
callq 0xb8e0
jmp 0xb487
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x80(%rax), %rsi
callq 0xb8e0
jmp 0xb49d
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x88(%rax), %rsi
callq 0xb8e0
jmp 0xb4b3
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x98(%rax), %rsi
callq 0xb8e0
jmp 0xb4c9
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0xa0(%rax), %esi
callq 0xb640
jmp 0xb4de
movq -0x10(%rbp), %rax
movq %rax, -0x158(%rbp)
leaq -0x48(%rbp), %rdi
callq 0xbe90
movq -0x158(%rbp), %rdi
movq %rax, %rsi
callq 0xb8e0
jmp 0xb503
movq -0x10(%rbp), %rax
movq %rax, -0x160(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xbe90
movq -0x160(%rbp), %rdi
movq %rax, %rsi
callq 0xb8e0
jmp 0xb52b
movq -0x10(%rbp), %rax
movq %rax, -0x168(%rbp)
movq -0x20(%rbp), %rdi
callq 0xbe90
movq -0x168(%rbp), %rdi
movq %rax, %rsi
callq 0xb8e0
jmp 0xb550
leaq -0x48(%rbp), %rdi
callq 0xce90
movq -0x10(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0xb910
jmp 0xb56b
leaq -0x90(%rbp), %rdi
callq 0xce90
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xb910
jmp 0xb586
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x50(%rax), %rdx
movq 0xa0(%rax), %rsi
callq 0xb850
jmp 0xb5a0
movq -0x30(%rbp), %rcx
movl 0x50(%rcx), %eax
movl 0xa0(%rcx), %ecx
subl %ecx, %eax
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %esi
leaq -0xc0(%rbp), %rdi
callq 0xb980
jmp 0xb5c9
movq -0x10(%rbp), %rdi
leaq -0xbc(%rbp), %rdx
leaq -0xc0(%rbp), %rsi
callq 0xb850
jmp 0xb5e2
movq -0x10(%rbp), %rdi
movq 0xdaf83(%rip), %rsi     # 0xe6570
movq %rsi, %rdx
addq $0xc, %rdx
callq 0xb850
jmp 0xb5fb
movb $0x1, -0x1(%rbp)
movl $0x1, -0x9c(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xbb80
leaq -0x48(%rbp), %rdi
callq 0xbb80
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
leaq -0x48(%rbp), %rdi
callq 0xbb80
movq -0x68(%rbp), %rdi
callq 0x4680
nop