// File: sisong[P]ApkDiffPatch/HDiffPatch/libHDiffPatch/HPatch/patch.c
// Function: patch_cache
static hpatch_BOOL _patch_cache(hpatch_TCovers** out_covers,
                                const hpatch_TStreamInput** poldData,hpatch_StreamPos_t newDataSize,
                                const hpatch_TStreamInput*  diffData,hpatch_BOOL isCompressedDiff,
                                hpatch_TDecompress* decompressPlugin,size_t kCacheCount,
                                TByte** ptemp_cache,TByte** ptemp_cache_end,hpatch_BOOL* out_isReadError){
    const hpatch_TStreamInput* oldData=*poldData;
    const hpatch_size_t kMinCacheSize=hpatch_kStreamCacheSize*kCacheCount;
#if (_IS_NEED_CACHE_OLD_BY_COVERS)
    const hpatch_size_t kBestACacheSize=hpatch_kFileIOBufBetterSize;   //内存足够时比较好的hpatch_kStreamCacheSize值;
    const hpatch_size_t _minActiveSize=(1<<20)*8;
    const hpatch_StreamPos_t _betterActiveSize=kBestACacheSize*kCacheCount*2+oldData->streamSize/8;
    const hpatch_size_t kActiveCacheOldMemorySize = //尝试激活CacheOld功能的内存下限;
                (_betterActiveSize>_minActiveSize)?_minActiveSize:(hpatch_size_t)_betterActiveSize;
#endif //_IS_NEED_CACHE_OLD_BY_COVERS
    TByte* temp_cache=*ptemp_cache;
    TByte* temp_cache_end=*ptemp_cache_end;
    *out_isReadError=hpatch_FALSE;
    if ((hpatch_size_t)(temp_cache_end-temp_cache)>=oldData->streamSize+kMinCacheSize
        +sizeof(hpatch_TStreamInput)+sizeof(hpatch_StreamPos_t)){//load all oldData
        hpatch_TStreamInput* replace_oldData=0;
        _cache_alloc(replace_oldData,hpatch_TStreamInput,sizeof(hpatch_TStreamInput),
                     temp_cache,temp_cache_end);
        if (!_cache_load_all(oldData,temp_cache_end-oldData->streamSize,
                             temp_cache_end)){ *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
        
        mem_as_hStreamInput(replace_oldData,temp_cache_end-oldData->streamSize,temp_cache_end);
        temp_cache_end-=oldData->streamSize;
        // [          patch cache            |       oldData cache     ]
        // [ (cacheSize-oldData->streamSize) |  (oldData->streamSize)  ]
        *out_covers=0;
        *poldData=replace_oldData;
        *ptemp_cache=temp_cache;
        *ptemp_cache_end=temp_cache_end;
        return hpatch_TRUE;
    }
#if (_IS_NEED_CACHE_OLD_BY_COVERS)
    else if ((hpatch_size_t)(temp_cache_end-temp_cache)>=kActiveCacheOldMemorySize) {
        hpatch_BOOL         isUsedCover32;
        TByte*              temp_cache_end_back=temp_cache_end;
        _TArrayCovers*      arrayCovers=0;
        assert((hpatch_size_t)(temp_cache_end-temp_cache)>kBestACacheSize*kCacheCount);
        assert(kBestACacheSize>sizeof(_TCompressedCovers)+sizeof(_TPackedCovers));
        if (isCompressedDiff){
            hpatch_compressedDiffInfo diffInfo;
            _TCompressedCovers* compressedCovers=0;
            if (!_compressedCovers_open(&compressedCovers,&diffInfo,diffData,decompressPlugin,
                                        temp_cache_end-kBestACacheSize-sizeof(_TCompressedCovers),temp_cache_end))
                { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
            if ((oldData->streamSize!=diffInfo.oldDataSize)||(newDataSize!=diffInfo.newDataSize))
                { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
            temp_cache_end-=kBestACacheSize+sizeof(_TCompressedCovers);
            // [                       ...                                 |   compressedCovers cache   ]
            // [           (cacheSize-kBestACacheSize)                     |      (kBestACacheSize)     ]
            *out_covers=&compressedCovers->base.ICovers;
            isUsedCover32=(diffInfo.oldDataSize|diffInfo.newDataSize)<((hpatch_StreamPos_t)1<<32);
        }else{
            _TPackedCovers* packedCovers=0;
            _THDiffHead     diffHead;
            hpatch_StreamPos_t oldDataSize=oldData->streamSize;
            if (!_packedCovers_open(&packedCovers,&diffHead,diffData,
                                    temp_cache_end-kBestACacheSize*3-sizeof(_TPackedCovers),temp_cache_end))
                { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
            temp_cache_end-=kBestACacheSize*3+sizeof(_TPackedCovers);
            // [                       ...                                 |     packedCovers cache     ]
            // [          (cacheSize-kBestACacheSize*3)                    |    (kBestACacheSize*3)     ]
            *out_covers=&packedCovers->base.ICovers;
            isUsedCover32=(oldDataSize|newDataSize)<((hpatch_StreamPos_t)1<<32);
        }
        
        if (!_arrayCovers_load(&arrayCovers,*out_covers,isUsedCover32,
                               out_isReadError,&temp_cache,temp_cache_end-kBestACacheSize)){
            if (*out_isReadError) return _hpatch_FALSE;
            // [                    patch cache                            |       *edCovers cache      ]
            // [           (cacheSize-kBestACacheSize*?)                   |     (kBestACacheSize*?)    ]
            *ptemp_cache=temp_cache;
            *ptemp_cache_end=temp_cache_end;
            return hpatch_FALSE;
        }else{
            // [         arrayCovers cache         |                         ...                        ]
            // [((new temp_cache)-(old temp_cache))|          (cacheSize-(arrayCovers cache size))      ]
            TByte* old_cache_end;
            hpatch_TStreamInput* replace_oldData=0;
            assert(!(*out_isReadError));
            if (!((*out_covers)->close(*out_covers))) return _hpatch_FALSE;
            *out_covers=&arrayCovers->ICovers;
            temp_cache_end=temp_cache_end_back; //free compressedCovers or packedCovers memory
            old_cache_end=temp_cache_end-kBestACacheSize*kCacheCount;
            // [       arrayCovers cache           |        ...        |      patch reserve cache       ]
            // [                                   |        ...        | (kBestACacheSize*kCacheCount) ]
            if (((hpatch_size_t)(temp_cache_end-temp_cache)<=kBestACacheSize*kCacheCount)
                ||(!_cache_old(&replace_oldData,oldData,arrayCovers,out_isReadError,
                               temp_cache,&old_cache_end,temp_cache_end))){
                if (*out_isReadError) return _hpatch_FALSE;
            // [         arrayCovers cache         |                   patch cache                      ]
                *ptemp_cache=temp_cache;
                *ptemp_cache_end=temp_cache_end;
                return hpatch_FALSE;
            }else{
            // [         arrayCovers cache         | oldData cache |             patch cache            ]
            // [                                   |               |(temp_cache_end-(new old_cache_end))]
                assert(!(*out_isReadError));
                assert((hpatch_size_t)(temp_cache_end-old_cache_end)>=kBestACacheSize*kCacheCount);
                temp_cache=old_cache_end;
                
                *poldData=replace_oldData;
                *ptemp_cache=temp_cache;
                *ptemp_cache_end=temp_cache_end;
                return hpatch_TRUE;
            }
        }
    }
#endif//_IS_NEED_CACHE_OLD_BY_COVERS
    return hpatch_FALSE;//not cache oldData
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movq 0x28(%rbp), %rax
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movl %r8d, -0x2c(%rbp)
movq %r9, -0x38(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
movq 0x10(%rbp), %rax
shlq $0xc, %rax
movq %rax, -0x48(%rbp)
movq $0x10000, -0x50(%rbp)   # imm = 0x10000
movq $0x800000, -0x58(%rbp)  # imm = 0x800000
movq 0x10(%rbp), %rax
shlq $0x10, %rax
shlq %rax
movq -0x40(%rbp), %rcx
movq 0x8(%rcx), %rcx
shrq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
cmpq $0x800000, -0x60(%rbp)  # imm = 0x800000
jbe 0x880c0
movl $0x800000, %eax         # imm = 0x800000
movq %rax, -0x218(%rbp)
jmp 0x880cb
movq -0x60(%rbp), %rax
movq %rax, -0x218(%rbp)
movq -0x218(%rbp), %rax
movq %rax, -0x68(%rbp)
movq 0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x70(%rbp)
movq 0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
movq 0x28(%rbp), %rax
movl $0x0, (%rax)
movq -0x78(%rbp), %rax
movq -0x70(%rbp), %rcx
subq %rcx, %rax
movq -0x40(%rbp), %rcx
movq 0x8(%rcx), %rcx
addq -0x48(%rbp), %rcx
addq $0x20, %rcx
addq $0x8, %rcx
cmpq %rcx, %rax
jb 0x88206
movq $0x0, -0x80(%rbp)
movq -0x78(%rbp), %rax
movq -0x70(%rbp), %rcx
subq %rcx, %rax
cmpq $0x28, %rax
jae 0x88143
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x70(%rbp), %rax
addq $0x7, %rax
andq $-0x8, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x70(%rbp)
movq -0x40(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq -0x40(%rbp), %rcx
xorl %eax, %eax
subq 0x8(%rcx), %rax
addq %rax, %rsi
movq -0x78(%rbp), %rdx
callq 0x8a960
cmpl $0x0, %eax
jne 0x88198
movq 0x28(%rbp), %rax
movl $0x1, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x80(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq -0x40(%rbp), %rcx
xorl %eax, %eax
subq 0x8(%rcx), %rax
addq %rax, %rsi
movq -0x78(%rbp), %rdx
callq 0x85b30
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rdx
movq -0x78(%rbp), %rax
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rax
movq $0x0, (%rax)
movq -0x80(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x70(%rbp), %rcx
movq 0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x78(%rbp), %rcx
movq 0x20(%rbp), %rax
movq %rcx, (%rax)
movl $0x1, -0x4(%rbp)
jmp 0x8860c
movq -0x78(%rbp), %rax
movq -0x70(%rbp), %rcx
subq %rcx, %rax
cmpq -0x68(%rbp), %rax
jb 0x88603
movq -0x78(%rbp), %rax
movq %rax, -0x90(%rbp)
movq $0x0, -0x98(%rbp)
movq -0x78(%rbp), %rax
movq -0x70(%rbp), %rcx
subq %rcx, %rax
movq 0x10(%rbp), %rcx
shlq $0x10, %rcx
cmpq %rcx, %rax
jbe 0x8824b
jmp 0x8826a
leaq 0x2d02f(%rip), %rdi     # 0xb5281
leaq 0x2c781(%rip), %rsi     # 0xb49da
movl $0x72b, %edx            # imm = 0x72B
leaq 0x2d063(%rip), %rcx     # 0xb52c8
callq 0x4270
cmpl $0x0, -0x2c(%rbp)
je 0x88349
movq $0x0, -0x1b8(%rbp)
movq -0x28(%rbp), %rdx
movq -0x38(%rbp), %rcx
movq -0x78(%rbp), %r8
addq $-0x10000, %r8          # imm = 0xFFFF0000
addq $-0xb8, %r8
movq -0x78(%rbp), %r9
leaq -0x1b8(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x894e0
cmpl $0x0, %eax
jne 0x882cb
movq 0x28(%rbp), %rax
movl $0x1, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
cmpq -0x1a8(%rbp), %rax
jne 0x882e9
movq -0x20(%rbp), %rax
cmpq -0x1b0(%rbp), %rax
je 0x882ff
movq 0x28(%rbp), %rax
movl $0x1, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x78(%rbp), %rax
addq $-0x100b8, %rax         # imm = 0xFFFEFF48
movq %rax, -0x78(%rbp)
movq -0x1b8(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x1a8(%rbp), %rax
orq -0x1b0(%rbp), %rax
movabsq $0x100000000, %rcx      # imm = 0x100000000
cmpq %rcx, %rax
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x84(%rbp)
jmp 0x883ed
movq $0x0, -0x1c0(%rbp)
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x200(%rbp)
movq -0x28(%rbp), %rdx
movq -0x78(%rbp), %rcx
addq $-0x30000, %rcx         # imm = 0xFFFD0000
addq $-0xe8, %rcx
movq -0x78(%rbp), %r8
leaq -0x1c0(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x89270
cmpl $0x0, %eax
jne 0x883ab
movq 0x28(%rbp), %rax
movl $0x1, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x78(%rbp), %rax
addq $-0x300e8, %rax         # imm = 0xFFFCFF18
movq %rax, -0x78(%rbp)
movq -0x1c0(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x200(%rbp), %rax
orq -0x20(%rbp), %rax
movabsq $0x100000000, %rcx      # imm = 0x100000000
cmpq %rcx, %rax
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x84(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rsi
movl -0x84(%rbp), %edx
movq 0x28(%rbp), %rcx
movq -0x78(%rbp), %r9
addq $-0x10000, %r9          # imm = 0xFFFF0000
leaq -0x98(%rbp), %rdi
leaq -0x70(%rbp), %r8
callq 0x8a9d0
cmpl $0x0, %eax
jne 0x88455
movq 0x28(%rbp), %rax
cmpl $0x0, (%rax)
je 0x88433
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x70(%rbp), %rcx
movq 0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x78(%rbp), %rcx
movq 0x20(%rbp), %rax
movq %rcx, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq $0x0, -0x210(%rbp)
movq 0x28(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x8846b
jmp 0x8848a
leaq 0x2cf1f(%rip), %rdi     # 0xb5391
leaq 0x2c561(%rip), %rsi     # 0xb49da
movl $0x755, %edx            # imm = 0x755
leaq 0x2ce43(%rip), %rcx     # 0xb52c8
callq 0x4270
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq 0x18(%rax), %rax
movq -0x10(%rbp), %rcx
movq (%rcx), %rdi
callq *%rax
cmpl $0x0, %eax
jne 0x884af
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x98(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x90(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq 0x10(%rbp), %rdx
shlq $0x10, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x208(%rbp)
movq -0x78(%rbp), %rax
movq -0x70(%rbp), %rcx
subq %rcx, %rax
movq 0x10(%rbp), %rcx
shlq $0x10, %rcx
cmpq %rcx, %rax
jbe 0x8852e
movq -0x40(%rbp), %rsi
movq -0x98(%rbp), %rdx
movq 0x28(%rbp), %rcx
movq -0x70(%rbp), %r8
movq -0x78(%rbp), %rax
leaq -0x210(%rbp), %rdi
leaq -0x208(%rbp), %r9
movq %rax, (%rsp)
callq 0x8ac90
cmpl $0x0, %eax
jne 0x88565
movq 0x28(%rbp), %rax
cmpl $0x0, (%rax)
je 0x88543
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq -0x70(%rbp), %rcx
movq 0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x78(%rbp), %rcx
movq 0x20(%rbp), %rax
movq %rcx, (%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8860c
movq 0x28(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x88570
jmp 0x8858f
leaq 0x2ce1a(%rip), %rdi     # 0xb5391
leaq 0x2c45c(%rip), %rsi     # 0xb49da
movl $0x767, %edx            # imm = 0x767
leaq 0x2cd3e(%rip), %rcx     # 0xb52c8
callq 0x4270
movq -0x78(%rbp), %rax
movq -0x208(%rbp), %rcx
subq %rcx, %rax
movq 0x10(%rbp), %rcx
shlq $0x10, %rcx
cmpq %rcx, %rax
jb 0x885ac
jmp 0x885cb
leaq 0x2cdf2(%rip), %rdi     # 0xb53a5
leaq 0x2c420(%rip), %rsi     # 0xb49da
movl $0x768, %edx            # imm = 0x768
leaq 0x2cd02(%rip), %rcx     # 0xb52c8
callq 0x4270
movq -0x208(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x210(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x70(%rbp), %rcx
movq 0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x78(%rbp), %rcx
movq 0x20(%rbp), %rax
movq %rcx, (%rax)
movl $0x1, -0x4(%rbp)
jmp 0x8860c
jmp 0x88605
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
nopl (%rax,%rax)