Переглянути джерело

Merge pull request #3 from wdfk-prog/Sub

使用 git submodule 导入 HPatchLite 模块
sulfurandcu 4 місяців тому
батько
коміт
70a46faa49

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "HPatchLite"]
+	path = HPatchLite
+	url = https://github.com/sisong/HPatchLite.git

+ 1 - 0
HPatchLite

@@ -0,0 +1 @@
+Subproject commit 9650af468cce97ebcecc0ee7f751afc837faee9b

+ 131 - 30
README.md

@@ -1,10 +1,29 @@
 # hpatchlite-wrapper
 
-A lightweight and user-friendly wrapper for the [HPatchLite](https://github.com/sisong/HPatchLite).
+一个为 [HPatchLite](https://github.com/sisong/HPatchLite) 设计的、轻量级且用户友好的封装层。
 
-## API
+## 项目简介
+
+本项目提供了一个简化的API,旨在帮助开发者将功能强大的 `HPatchLite` 二进制差分库快速集成到嵌入式系统中,尤其是在 RT-Thread 生态下。本封装层处理了复杂的内存管理和不同解压插件的抽象,让您能更专注于上层业务逻辑。
+
+## 使用说明
+- 本项目使用 `HPatchLite` 作为Git子模块。在克隆主仓库后,请使用以下命令来拉取子模块的完整代码:
+> git submodule update --init --recursive
+
+## API 接口
 
 ```c
+/**
+ * @brief 使用 HPatchLite 库执行差分合并操作
+ * 
+ * @param listener              指向监听器结构的指针,同时也作为用户上下文句柄。
+ * @param patch_cache_size      用于核心差分算法的内部缓存大小。
+ * @param decompress_cache_size 用于解压数据流的缓存大小。
+ * @param _do_read_diff         读取差分补丁数据流的回调函数。
+ * @param _do_read_old          读取旧版本固件数据的回调函数。
+ * @param _do_write_new         写入新合成的固件数据的回调函数。
+ * @return hpi_patch_result_t   成功时返回 HPATCHI_SUCCESS,失败时返回对应的错误码。
+ */
 hpi_patch_result_t hpi_patch(hpatchi_listener_t *listener,
                              int patch_cache_size,
                              int decompress_cache_size,
@@ -13,64 +32,146 @@ hpi_patch_result_t hpi_patch(hpatchi_listener_t *listener,
                              write_new_t _do_write_new);
 ```
 
-## Example
+## 使用示例
 
 ```c
+#include "hpatch_impl.h"
+
+// 定义一个上下文结构体,用于保存所有必要的状态和数据
 typedef struct hpatchi_instance_t
 {
-    hpatchi_listener_t parent;
+    hpatchi_listener_t parent; // 必须作为第一个成员
 
-    // define your own variable data here
-    int var1;
-    int var2;
-    int var3;
+    // 在此处定义您自己的状态变量
+    const fal_partition_t patch_part;
+    const fal_partition_t old_part;
+    int patch_read_pos;
+    // ... 等等
 
 } hpatchi_instance_t;
 
-hpi_BOOL _do_read_empty(struct hpatchi_listener_t *listener, hpi_pos_t addr, hpi_byte *data, hpi_size_t size)
-{
-    ...
-}
-
+// 实现所需的回调函数
 hpi_BOOL _do_read_old(struct hpatchi_listener_t *listener, hpi_pos_t addr, hpi_byte *data, hpi_size_t size)
 {
+    // 实现从旧固件分区读取的逻辑
     ...
 }
 
 hpi_BOOL _do_read_patch(hpi_TInputStreamHandle input_stream, hpi_byte *data, hpi_size_t *size)
 {
+    // 实现从差分补丁数据流读取的逻辑
     ...
 }
 
 hpi_BOOL _do_write_new(struct hpatchi_listener_t *listener, const hpi_byte *data, hpi_size_t size)
 {
+    // 实现原地升级的逻辑 (例如,使用交换缓冲区)
     ...
 }
 
-void demo(void)
+void demo_patch_update(void)
 {
-    hpatchi_instance_t instance = {0};
-    instance.var1 = ;
-    instance.var2 = ;
-    instance.var3 = ;
-
-    // 差分全量升级 (full update with hpatchlite)
-    {
-        hpi_patch(&instance.parent, 128, 128, _do_read_patch, _do_read_empty, _do_write_new);
-    }
-
-    // 差分增量升级 (diff update with hpatchlite)
-    {
-        hpi_patch(&instance.parent, 128, 128, _do_read_patch, _do_read_old, _do_write_new);
+    // 初始化您的实例,包含所有必要的分区信息和状态
+    hpatchi_instance_t instance = {
+        .patch_part = fal_partition_find("download"),
+        .old_part = fal_partition_find("app"),
+        .patch_read_pos = 0,
+        // ... 初始化其他成员
+    };
+
+    // 使用您的实例和回调函数来调用差分合并接口
+    hpi_patch_result_t result = hpi_patch(&instance.parent, 
+                                          4096, // patch_cache_size
+                                          4096, // decompress_cache_size
+                                          _do_read_patch, 
+                                          _do_read_old, 
+                                          _do_write_new);
+    
+    if (result == HPATCHI_SUCCESS) {
+        // 差分合并成功!
+    } else {
+        // 差分合并失败,处理错误
     }
 }
 ```
 
-## Contact
+## 补丁文件结构
+
+由 `hdiffi` 工具生成的差分补丁文件主要由两部分构成:HPatchLite 主文件头,以及紧随其后的数据流。数据流本身根据压缩类型的不同,可能还会包含自己的子文件头。
+
+### 原始十六进制数据示例
+
+```
+68 49 01 53 10 23 02 36 cd b9 69 00 00 ff 03 82 ...
+```
+
+### 逐字节分析
+
+文件被按顺序解析。
+
+#### 1. HPatchLite 主文件头 (由 `hpatch_lite_open` 解析)
+
+| 字节 | 十六进制 | 值/ASCII | 解释                                                                                                                                                             |
+|:-----|:---------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0    | `68`     | `'h'`    | **HPatchLite 魔法数 1**                                                                                                                                          |
+| 1    | `49`     | `'I'`    | **HPatchLite 魔法数 2**                                                                                                                                          |
+| 2    | `01`     | `1`      | **压缩类型 (Compress Type)**:`1` 对应 `hpi_compressType_tuz`,表示本补丁使用了 `tuz` 压缩。                                                                     |
+| 3    | `53`     | `83`     | **版本与长度编码字节**:二进制为 `01010011`。<br>- **高2位 (`01`)**: 版本号 `1`。<br>- **中3位 (`010`)**: `uncompressSize` 字段占 **2** 个字节。<br>- **低3位 (`011`)**: `newSize` 字段占 **3** 个字节。 |
+| 4-6  | `10 23 02` | -        | **newSize (3 字节)**:小端(Little-Endian)编码的值。<br>`0x022310` = **140048**。这个值是最终生成的新固件 `new.bin` 的总大小。                               |
+| 7-8  | `36 cd`  | -        | **uncompressSize (2 字节)**:小端编码。<br>`0xCD36` = **52534**。这个值是未经压缩的、原始的差分指令流的大小。                                                    |
+
+**结论**: 主文件头的长度是**可变的**。解析完这部分后,数据流指针将指向下一个部分,准备交给相应的解压器处理。
+
+#### 2. 解压器子文件头 (以 `tuz` 为例)
+
+紧跟在主文件头之后的数据属于特定的解压器。对于 `tuz` 来说,这部分以字典大小信息开头。
+
+| 字节 | 十六进制 | 值       | 解释                                                                                                                                                            |
+|:-----|:---------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 9-10 | `b9 69`  | -        | **字典大小信息**: 这是 `tuz` 专有的头部数据,由 `_tuz_TStream_getReservedMemSize` 函数读取。在此示例中,小端编码的 `0x69B9` 等于 **27065**。这个值是解压器**实际需要的总内存**,不一定等于您在打包时指定的字典大小。 |
+
+## 压缩功能
+
+为了显著减小补丁包的体积,可以使用 `-c` 参数在生成补丁时启用压缩功能。
+
+### 使用 `tuz` 压缩
+
+`tuz` 是一种轻量级压缩算法,非常适合在嵌入式系统上使用。
+
+*   **打包示例**:
+    以下命令创建了一个使用 `tuz` 压缩的补丁。由于未指定字典大小,`hdiffi` 会使用默认的 **32KB** 字典。
+
+    ```sh
+    # -c-tuz 参数启用了 tuz 压缩
+    .\hdiffi.exe -c-tuz .\old.bin .\new.bin .\patch_tuz_de.bin
+    ```
+
+*   **输出日志解读**:
+    ```sh
+    old : ".\old.bin"
+    new : ".\new.bin"
+    out : ".\patch_tuz_de.bin"
+    hdiffi run with compress plugin: "tuz"
+    oldDataSize : 140048
+    newDataSize : 140048
+      (used one tinyuz dictSize: 32768  (input data: 52534))
+    diffDataSize: 76
+    ...
+    hpatchi run with decompresser: "tuz"
+      requirements memory size: (must) 27065 + (custom cache) 32768
+    ...
+    ```
+
+*   **关键信息解读**:
+    1.  `used one tinyuz dictSize: 32768`: 这行日志确认了PC端的压缩器确实按照要求,**使用了32KB的窗口**来寻找重复数据。
+    2.  `requirements memory size: (must) 27065`: **这是对嵌入式设备至关重要的信息。** 它指明了在单片机上执行解压时,`tuz` 解压器将通过 `hpi_malloc` **强制要求分配的RAM大小**。这个大小包括了字典缓冲区和解压器自身需要的状态内存。
+    3.  **结论**: 打包时指定的字典大小 (`-dictSize=32k`) 是一个**上限和参考**。设备端实际需要的内存(`27065`)是由压缩后的数据流本身决定的。您**必须确保**您的设备有足够的堆内存来满足这个 "must" 的要求,否则升级将会因内存分配失败而终止。
+
+## 联系方式
 
 - sulfurandcu@gmail.com
 - https://github.com/sulfurandcu/hpatchlite-wrapper
 
-## Reference
+## 参考链接
 
--  https://sulfurandcu.github.io/sulfurandcu.io/cloidefbf00hzv0rqa7zg722r.html
+-  https://sulfurandcu.github.io/sulfurandcu.io/cloidefbf00hzv0rqa7zg722r.html

+ 32 - 12
SConscript

@@ -1,19 +1,39 @@
+# SConscript file for hpatchlite-wrapper package
+
 from building import *
+import os
 
+# Get the absolute path of the current SConscript file
 cwd = GetCurrentDir()
 
-inc = [
-cwd,
-cwd+'/decompresser',
-cwd+'/decompresser/tinyuz',
-cwd+'/hpatch/HPatch',
-cwd+'/hpatch/HPatchLite',
-]
+# --- Source Files ---
+# Add all necessary source files for the build.
+# We only need the core hpatch_lite implementation and the selected decompressor.
+src = []
+src += Glob('hpatch_impl.c')
+src += Glob('HPatchLite/decompresser/tinyuz/tuz_dec.c')
+src += Glob('HPatchLite/HDiffPatch/libHDiffPatch/HPatchLite/hpatch_lite.c')
+
+# --- Include Paths ---
+# Add all necessary include paths for the compiler.
+# This ensures that #include directives can find the required header files.
+inc = []
+inc.append(cwd)
+# Since HPatchLite is a submodule, all its internal paths are relative to its root.
+hpatchlite_root = os.path.join(cwd, 'HPatchLite')
+inc.append(hpatchlite_root)
+inc.append(os.path.join(hpatchlite_root, 'HDiffPatch/libHDiffPatch/HPatchLite'))
+inc.append(os.path.join(hpatchlite_root, 'HDiffPatch/libHDiffPatch/HPatch'))
 
-src  = Glob('hpatch_impl.c')
-src += Glob('decompresser/tinyuz/*.c')
-src += Glob('hpatch/HPatchLite/*.c')
+# Add decompressor source files only if they are enabled in the configuration.
+if GetDepend(['PKG_HPATCHLITE_DECOMPRESSER_TUZ']):
+    src += Glob('HPatchLite/tinyuz/decompress/tuz_dec.c')
+    inc.append(os.path.join(hpatchlite_root, 'tinyuz/decompress'))
 
-group = DefineGroup('hpatchlite', src, depend = ['PKG_USING_HPATCHLITE'], CPPPATH = inc)
+# --- Define the Component Group --- 
+# Define a group named 'hpatchlite' that will be added to the build system.
+# This group will only be compiled if the Kconfig option 'PKG_USING_HPATCHLITE' is enabled.
+group = DefineGroup('hpatchlite-wrapper', src, depend=['PKG_USING_HPATCHLITE'], CPPPATH=inc)
 
-Return('group')
+# Return the defined group to the build system
+Return('group')

+ 0 - 35
decompresser/decompresser_demo.h

@@ -1,35 +0,0 @@
-//decompresser_demo.h
-// decompresser demo for HPatchLite
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2020-2022 HouSisong All Rights Reserved.
- */
-#ifndef hpatchi_decompresser_demo_h
-#define hpatchi_decompresser_demo_h
-
-
-#define _CompressPlugin_tuz
-
-
-#ifndef _IsNeedIncludeDefaultCompressHead
-#   define _IsNeedIncludeDefaultCompressHead 1
-#endif
-
-
-#ifdef _CompressPlugin_tuz
-#if (_IsNeedIncludeDefaultCompressHead)
-#   include "tuz_dec.h"  // "tinyuz/decompress/tuz_dec.h" https://github.com/sisong/tinyuz
-#endif
-    static size_t _tuz_TStream_getReservedMemSize(hpi_TInputStreamHandle codeStream,hpi_TInputStream_read readCode){
-        const tuz_size_t dictSize=tuz_TStream_read_dict_size(codeStream,readCode);
-        if (((tuz_size_t)(dictSize-1))>=tuz_kMaxOfDictSize)
-            return 0;//error
-        return dictSize;
-    }
-    static hpi_BOOL _tuz_TStream_decompress(hpi_TInputStreamHandle diffStream,hpi_byte* out_part_data,hpi_size_t* data_size){
-        return tuz_STREAM_END>=tuz_TStream_decompress_partial((tuz_TStream*)diffStream,out_part_data,data_size);
-    }
-#endif //_CompressPlugin_tuz
-
-#endif //hpatchi_decompresser_demo_h

+ 0 - 493
decompresser/tinyuz/tuz_dec.c

@@ -1,493 +0,0 @@
-//  tuz_dec.c
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
-*/
-#include "tuz_dec.h"
-#include "tuz_types_private.h"
-#if _IS_USED_C_MEMCPY
-#   include <string.h> // memcpy
-#endif
-
-#if (_IS_RUN_MEM_SAFE_CHECK)
-#   define __RUN_MEM_SAFE_CHECK
-#endif
-
-#define  _memmove_order    memmove_order
-#if (!(_IS_USED_C_MEMCPY))
-#   define  _memcpy        memmove_order
-#else
-#   define  _memcpy        memcpy
-    tuz_force_inline
-#endif
-    static void memmove_order(tuz_byte* dst,const tuz_byte* src,tuz_size_t len){
-        while (len--) *dst++=*src++;
-    }
-
-//low to high bitmap: xx?xx?xx?xx? ...
-#define _def_unpack_len(self,readBit,_read_lowbits){ \
-    tuz_length_t v=0;   \
-    for(;;){            \
-        tuz_fast_uint8 lowbit=_read_lowbits(self,readBit);  \
-        v=(v<<(readBit-1))+(lowbit&((1<<(readBit-1))-1));   \
-        if (!(lowbit&(1<<(readBit-1)))) return v;           \
-        v+=1;           \
-    } }
-
-
-#define _TInputCache                _tuz_TInputCache
-#define _cache_read_typeBits        _cache_read_1byte
-
-#if (_IS_USED_SHARE_hpatch_lite_types)
-#   define _cache_success_finish    _hpi_cache_success_finish
-#   define _cache_update            _hpi__cache_update
-#   define _cache_read_1byte        _hpi_cache_read_1byte
-#else
-
-static tuz_force_inline 
-tuz_BOOL _cache_success_finish(const _TInputCache* self){ return (self->cache_end!=0); }
-
-static tuz_BOOL _cache_update(struct _TInputCache* self){
-    //    [                    cache  buf                        ]
-    tuz_size_t len=self->cache_end;
-    assert(len==self->cache_begin); //empty
-    if (!self->read_code(self->inputStream,self->cache_buf,&len))
-        len=0;
-    //    |                                   len|               |
-    self->cache_begin=0;
-    self->cache_end=len;
-    return len!=0;
-}
-
-static tuz_try_inline 
-tuz_fast_uint8 _cache_read_1byte(struct _TInputCache* self){
-    if (self->cache_begin!=self->cache_end){
-__cache_read_1byte:
-        return self->cache_buf[self->cache_begin++];
-    }
-    if(_cache_update(self))
-        goto __cache_read_1byte;
-    else
-        return 0;
-}
-
-#endif //_IS_USED_SHARE_hpatch_lite_types
-
-static tuz_try_inline tuz_fast_uint8 _cache_read_lowbits(tuz_TStream* self,tuz_fast_uint8 bitCount){
-    tuz_fast_uint8 count=self->_state.type_count;
-    tuz_fast_uint8 result=self->_state.types;
-    if (count>=bitCount){
-        self->_state.type_count=count-bitCount;
-        self->_state.types=(result>>bitCount);
-        return result;
-    }else{
-        tuz_fast_uint8 v=_cache_read_typeBits(&self->_code_cache);
-        bitCount-=count;
-        self->_state.type_count=tuz_kMaxTypeBitCount-bitCount;
-        self->_state.types=v>>bitCount;
-        return result|(v<<count);
-    }
-}
-
-static tuz_force_inline tuz_fast_uint8 _cache_read_1bit(tuz_TStream* self){
-    return _cache_read_lowbits(self,1)&0x1;
-}
-
-static tuz_force_inline void _cache_push_1bit(tuz_TStream* self,tuz_fast_uint8 bitv){
-    //assert(self->_state.type_count<tuz_kMaxTypeBitCount);
-    self->_state.types=(self->_state.types<<1)+bitv;
-    ++self->_state.type_count;
-}
-
-static tuz_force_inline tuz_length_t _cache_unpack_len(tuz_TStream* self){
-    _def_unpack_len(self,2,_cache_read_lowbits);
-}
-
-#if tuz_isNeedLiteralLine
-    tuz_try_inline
-#else
-    tuz_force_inline
-#endif
-static tuz_length_t _cache_unpack_pos_len(tuz_TStream* self){
-    _def_unpack_len(self,3,_cache_read_lowbits);
-}
-
-static tuz_force_inline tuz_size_t _cache_unpack_dict_pos(tuz_TStream* self){
-    tuz_size_t result=_cache_read_1byte(&self->_code_cache);
-    if (result<(1<<7))
-        return result;
-    else
-        return ((result&((1<<7)-1))|(_cache_unpack_pos_len(self)<<7))+(1<<7);
-}
-
-
-static void _update_dict(tuz_TStream *self,const tuz_byte* out_data,const tuz_byte* cur_out_data) {
-    //  [               dict buf                 ]|[          out buf        ]
-    //           |dict_cur               dict_size|out_data      cur_out_data]
-    //           [         out buf         ]
-    //           [                      out buf                ]
-    const tuz_size_t out_len=(tuz_size_t)(cur_out_data-out_data);
-    const tuz_size_t dict_size=self->_dict.dict_size;
-    tuz_byte*  dict=self->_dict.dict_buf;
-    if (self->_state.dictType_pos_inc>=out_len){
-        self->_state.dictType_pos_inc-=out_len;
-    }else{
-        self->_state.dictType_pos-=(tuz_size_t)(out_len-self->_state.dictType_pos_inc);
-        self->_state.dictType_pos_inc=0;
-    }
-    if (out_len>=dict_size){
-        _memcpy(dict,cur_out_data-dict_size,dict_size);
-        self->_dict.dict_cur=0;
-    }else{
-        tuz_size_t dict_cur=self->_dict.dict_cur;
-        const tuz_size_t sub_len=dict_size-dict_cur;
-        if (out_len<=sub_len){
-            _memcpy(dict+dict_cur,out_data,out_len);
-        }else{
-            _memcpy(dict+dict_cur,out_data,sub_len);
-            _memcpy(dict,out_data+sub_len,out_len-sub_len);
-        }
-        self->_dict.dict_cur=(out_len<=sub_len)?
-                             (out_len+dict_cur):(out_len-sub_len);
-    }
-}
-
-static tuz_size_t _copy_from_dict(tuz_TStream *self,tuz_byte* cur_out_data,tuz_size_t dsize) {
-    // [                       dict buf                      ]
-    //              dict_cur+dictType_pos|   <-- len -->  |
-    //                                     dict_cur+dictType_pos|   <-- len -->  |
-    //                       dict_cur+dictType_pos|   <-- len -->  |
-    tuz_size_t len,pos;
-    len=self->_dict.dict_size-self->_state.dictType_pos;
-    len=(len<dsize)?len:dsize;
-    len=(self->_state.dictType_len<len)?(tuz_size_t)self->_state.dictType_len:len;
-    pos=self->_dict.dict_size-self->_dict.dict_cur;
-    if (self->_state.dictType_pos<pos)
-        pos=self->_dict.dict_cur+self->_state.dictType_pos;
-    else
-        pos=self->_state.dictType_pos-pos;
-    if (len<=(self->_dict.dict_size-pos)){
-        _memcpy(cur_out_data,self->_dict.dict_buf+pos,len);
-    }else{
-        tuz_size_t part_len=self->_dict.dict_size-pos;
-        _memcpy(cur_out_data,self->_dict.dict_buf+pos,part_len);
-        _memcpy(cur_out_data+part_len,self->_dict.dict_buf,len-part_len);
-    }
-    return len;
-}
-
-
-tuz_size_t tuz_TStream_read_dict_size(tuz_TInputStreamHandle inputStream,tuz_TInputStream_read read_code){
-    tuz_size_t v=tuz_kDictSizeSavedBytes;
-    tuz_byte   saved[tuz_kDictSizeSavedBytes];
-    assert(read_code!=0);
-    if ((read_code(inputStream,saved,&v))&&(v==tuz_kDictSizeSavedBytes)){
-        #if (tuz_kDictSizeSavedBytes==1)
-            v=saved[0];
-            assert(v>0);
-        #elif (tuz_kDictSizeSavedBytes==2)
-            v=saved[0]|(((tuz_size_t)saved[1])<<8);
-            assert((v>0)&(((v>>8)&0xFF)==saved[1]));
-        #elif (tuz_kDictSizeSavedBytes==3)
-            v=saved[0]|(((tuz_size_t)saved[1])<<8)|(((tuz_size_t)saved[2])<<16);
-            assert((v>0)&(((v>>8)&0xFF)==saved[1])&((v>>16)==saved[2]));
-        #elif (tuz_kDictSizeSavedBytes==4)
-            v=saved[0]|(((tuz_size_t)saved[1])<<8)|(((tuz_size_t)saved[2])<<16)|(((tuz_size_t)saved[3])<<24);
-            assert((v>0)&(((v>>8)&0xFF)==saved[1])&(((v>>16)&0xFF)==saved[2])&((v>>24)==saved[3]));
-        #else
-        #   error unsupport tuz_kDictSizeSavedBytes
-        #endif
-        return v;
-    }else{ //error 
-        return 0;
-    }
-}
-
-tuz_TResult tuz_TStream_open(tuz_TStream* self,tuz_TInputStreamHandle inputStream,tuz_TInputStream_read read_code,
-                             tuz_byte* dict_and_cache,tuz_size_t dict_size,tuz_size_t cache_size){
-    assert((read_code!=0)&&(dict_and_cache!=0));
-    if (dict_size==0) return tuz_READ_DICT_SIZE_ERROR;
-    if (cache_size==0) return tuz_CACHE_SIZE_ERROR;
-    self->_code_cache.cache_begin=cache_size;
-    self->_code_cache.cache_end=cache_size;
-    self->_code_cache.cache_buf=dict_and_cache+dict_size;
-    self->_code_cache.inputStream=inputStream;
-    self->_code_cache.read_code=read_code;
-    self->_dict.dict_cur=0;
-    self->_dict.dict_size=dict_size;
-    self->_dict.dict_buf=dict_and_cache;
-    
-    self->_state.dictType_pos=0;
-    self->_state.dictType_pos_inc=0;
-    self->_state.dict_pos_back=1;
-    self->_state.dictType_len=0;    
-  #if tuz_isNeedLiteralLine
-    self->_state.literalType_len=0;
-  #endif
-    self->_state.types=0;
-    self->_state.type_count=0;
-    self->_state.isHaveData_back=tuz_FALSE;
-    return tuz_OK;
-}
-
-tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,tuz_size_t* data_size){
-    tuz_byte*  cur_out_data=out_data;
-    tuz_size_t dsize=*data_size;
-#ifdef __RUN_MEM_SAFE_CHECK
-    const tuz_BOOL isNeedOut=(dsize>0);
-#endif
-    for(;;){
-        copyDict_cmp_process:
-        if (self->_state.dictType_len){ //copy from dict or out_data
-        copyDict_process:
-            if (dsize){
-                //  [                 dict buf                 ]|[          out buf        |              ]
-                //             |dict_cur               dict_size|out_data      cur_out_data| <-- dsize -->|
-                //       dictType_pos| <-- dictType_len --> |
-                //                        dictType_pos|                  <--  dictType_len -->                 |
-                //                                     dictType_pos| <-  dictType_len -> |
-                tuz_size_t len;
-                if (self->_state.dictType_pos<self->_dict.dict_size){
-                    len=_copy_from_dict(self,cur_out_data,dsize);
-                    self->_state.dictType_pos+=len;
-                }else{
-                    len=(self->_state.dictType_len<dsize)?(tuz_size_t)self->_state.dictType_len:dsize;
-                    _memmove_order(cur_out_data,out_data+self->_state.dictType_pos_inc,len);
-                    self->_state.dictType_pos_inc+=len;
-                }
-                self->_state.dictType_len-=len;
-                cur_out_data+=len;
-                dsize-=len;
-                goto copyDict_cmp_process;
-            }else{
-                break;
-            }
-        }
-
-  #if tuz_isNeedLiteralLine
-    copyLiteral_cmp_process:
-        if (self->_state.literalType_len){
-        copyLiteral_process:
-            if (dsize){
-                tuz_length_t cpyLen=(self->_state.literalType_len<dsize)?self->_state.literalType_len:dsize;
-                self->_state.literalType_len-=cpyLen;
-                dsize-=cpyLen;
-                while (cpyLen--)
-                    *cur_out_data++=_cache_read_1byte(&self->_code_cache);
-                goto copyLiteral_cmp_process;
-            }else{
-                break;
-            }
-        }
-  #endif
-  
-    type_process:
-        {
-            if (_cache_read_1bit(self)==tuz_codeType_dict){
-                tuz_size_t saved_len=_cache_unpack_len(self);
-                tuz_size_t saved_dict_pos;
-                if ((self->_state.isHaveData_back)&&(_cache_read_1bit(self))){
-                    saved_dict_pos=self->_state.dict_pos_back;
-                }else{
-                    saved_dict_pos=_cache_unpack_dict_pos(self);
-                    if (saved_dict_pos>tuz_kBigPosForLen) ++saved_len;
-                }
-                self->_state.isHaveData_back=tuz_FALSE;
-
-                if (saved_dict_pos){
-                    const tuz_size_t outed_size=(tuz_size_t)(cur_out_data-out_data);
-                    self->_state.dict_pos_back=saved_dict_pos;
-                    self->_state.dictType_len=saved_len+tuz_kMinDictMatchLen;
-                    saved_dict_pos=(self->_dict.dict_size-saved_dict_pos);
-#ifdef __RUN_MEM_SAFE_CHECK
-                    if (saved_dict_pos>=self->_dict.dict_size) return tuz_DICT_POS_ERROR;
-#endif
-                    if (outed_size<self->_dict.dict_size-saved_dict_pos){
-                        self->_state.dictType_pos=outed_size+saved_dict_pos;
-                        self->_state.dictType_pos_inc=0;
-                    }else{
-                        self->_state.dictType_pos=self->_dict.dict_size;
-                        self->_state.dictType_pos_inc=outed_size+saved_dict_pos-self->_dict.dict_size;
-                    }
-                    goto copyDict_process;
-                }else{ // ctrlType
-                  #if tuz_isNeedLiteralLine
-                    if (tuz_ctrlType_literalLine==saved_len){
-                        self->_state.isHaveData_back=tuz_TRUE;
-                        self->_state.literalType_len=_cache_unpack_pos_len(self)+tuz_kMinLiteralLen;
-                        goto copyLiteral_process;
-                    }
-                  #endif
-
-                    self->_state.dict_pos_back=1;
-                    self->_state.type_count=0;
-                    if (tuz_ctrlType_clipEnd==saved_len){ //clip end
-                        goto type_process;
-                    }else if (tuz_ctrlType_streamEnd==saved_len){ //stream end
-                        *data_size=(tuz_size_t)(cur_out_data-out_data);
-                        return tuz_STREAM_END;
-                    }else{
-                        return _cache_success_finish(&self->_code_cache)?
-                                    tuz_CTRLTYPE_UNKNOW_ERROR:tuz_READ_CODE_ERROR;
-                    }
-                }
-            }else{
-                if (dsize){                
-                    self->_state.isHaveData_back=tuz_TRUE;
-                    *cur_out_data++=_cache_read_1byte(&self->_code_cache);
-                    --dsize;
-                    goto type_process;
-                }else{
-                    _cache_push_1bit(self,tuz_codeType_data);
-                    break;
-                }
-            }
-        }
-    }//end for
-
-//return_process:
-    {
-        assert(dsize==0);
-        if (out_data!=cur_out_data)
-            _update_dict(self,out_data,cur_out_data);
-        if (!_cache_success_finish(&self->_code_cache))
-            return tuz_READ_CODE_ERROR;
-
-        #ifdef __RUN_MEM_SAFE_CHECK
-            return isNeedOut?tuz_OK:tuz_OUT_SIZE_OR_CODE_ERROR;
-        #else
-            return tuz_OK;
-        #endif
-    }
-}
-
-
-//---------------------------------------------------------------------------------------------
-
-typedef struct _mem_TStream{
-    const tuz_byte* in_code;
-    const tuz_byte* in_code_end;
-    tuz_fast_uint8  types;
-    tuz_fast_uint8  type_count;
-} _mem_TStream;
-
-#ifdef __RUN_MEM_SAFE_CHECK
-#   define __SafeTest(t) t 
-#else
-#   define __SafeTest(t) tuz_TRUE 
-#endif
-
-#define _mem_read_1byte(result) {   \
-    if (__SafeTest(self.in_code<self.in_code_end)){ \
-        result=*self.in_code++;     \
-    }else{                          \
-        return tuz_READ_CODE_ERROR; \
-    } }
-
-static tuz_try_inline tuz_fast_uint8 _mem_read_lowbits(_mem_TStream* self,tuz_fast_uint8 bitCount){
-    tuz_fast_uint8 count=self->type_count;
-    tuz_fast_uint8 result=self->types;
-    if (count>=bitCount){
-        self->type_count=count-bitCount;
-        self->types=(result>>bitCount);
-        return result;
-    }else{
-        if (__SafeTest(self->in_code<self->in_code_end)){
-            tuz_fast_uint8 v=*self->in_code++;
-            bitCount-=count;
-            self->type_count=tuz_kMaxTypeBitCount-bitCount;
-            self->types=v>>bitCount;
-            return result|(v<<count);
-        }else{
-            return 0;
-        }
-    }
-}
-
-static tuz_force_inline tuz_length_t _mem_unpack_len(_mem_TStream* self){
-    _def_unpack_len(self,2,_mem_read_lowbits);
-}
-
-#if tuz_isNeedLiteralLine
-    tuz_try_inline
-#else
-    tuz_force_inline
-#endif
-static tuz_length_t _mem_unpack_pos_len(_mem_TStream* self){
-    _def_unpack_len(self,3,_mem_read_lowbits);
-}
-
-#define _mem_unpack_dict_pos(result) {  \
-    if (__SafeTest(self.in_code<self.in_code_end)){ \
-        result=(*self.in_code++);       \
-        if (result>=(1<<7))             \
-            result=((result&((1<<7)-1))|(_mem_unpack_pos_len(&self)<<7))+(1<<7); \
-    }else{ \
-        return tuz_READ_CODE_ERROR;     \
-    } }
-
-tuz_TResult tuz_decompress_mem(const tuz_byte* in_code,tuz_size_t code_size,tuz_byte* out_data,tuz_size_t* data_size){
-    _mem_TStream self={in_code+tuz_kDictSizeSavedBytes,in_code+code_size,0,0};
-    tuz_byte*  cur_out_data=out_data;
-    tuz_byte*  out_data_end=out_data+(*data_size);
-    tuz_size_t dict_pos_back=1;
-    tuz_BOOL   isHaveData_back=tuz_FALSE;
-    for(;;){
-        if ((_mem_read_lowbits(&self,1)&1)==tuz_codeType_dict){
-            tuz_size_t saved_len=_mem_unpack_len(&self);
-            tuz_size_t saved_dict_pos; 
-            if ((isHaveData_back)&&(_mem_read_lowbits(&self,1)&1)){
-                saved_dict_pos=dict_pos_back;
-            }else{
-                _mem_unpack_dict_pos(saved_dict_pos);
-                if (saved_dict_pos>tuz_kBigPosForLen) ++saved_len;
-            }
-            isHaveData_back=tuz_FALSE;
-            if (saved_dict_pos){
-                tuz_size_t dictType_len=saved_len+tuz_kMinDictMatchLen;
-                dict_pos_back=saved_dict_pos;
-#ifdef __RUN_MEM_SAFE_CHECK
-                if (saved_dict_pos>(tuz_size_t)(cur_out_data-out_data)) return tuz_DICT_POS_ERROR;
-                if (dictType_len>(tuz_size_t)(out_data_end-cur_out_data)) return tuz_OUT_SIZE_OR_CODE_ERROR;
-#endif
-                {
-                    const tuz_byte* src=cur_out_data-saved_dict_pos;
-                    while (dictType_len--)
-                        *cur_out_data++=*src++;
-                }
-            }else {// ctrlType
-            #if tuz_isNeedLiteralLine
-                if (tuz_ctrlType_literalLine==saved_len){
-                    tuz_size_t literalType_len=_mem_unpack_pos_len(&self)+tuz_kMinLiteralLen;
-                    const tuz_byte* src=self.in_code;
-#ifdef __RUN_MEM_SAFE_CHECK
-                    if (literalType_len>(tuz_size_t)(self.in_code_end-src)) return tuz_READ_CODE_ERROR;
-                    if (literalType_len>(tuz_size_t)(out_data_end-cur_out_data)) return tuz_OUT_SIZE_OR_CODE_ERROR;
-#endif
-                    while (literalType_len--)//copy literal line
-                        *cur_out_data++=*src++;
-                    self.in_code=src;
-                    isHaveData_back=tuz_TRUE;
-                    continue;
-                }
-            #endif
-                dict_pos_back=1;
-                self.type_count=0;
-                if (tuz_ctrlType_clipEnd==saved_len){ //clip end
-                }else if (tuz_ctrlType_streamEnd==saved_len){ //stream end
-                    *data_size=(tuz_size_t)(cur_out_data-out_data);
-                    return tuz_STREAM_END;
-                }else{
-                    return tuz_CTRLTYPE_UNKNOW_ERROR;
-                }
-            }
-        }else{
-            if (__SafeTest(cur_out_data<out_data_end)){
-                isHaveData_back=tuz_TRUE;
-                _mem_read_1byte(*cur_out_data++); 
-            }else{
-                return tuz_OUT_SIZE_OR_CODE_ERROR;
-            }
-        }
-    }//end for
-}

+ 0 - 70
decompresser/tinyuz/tuz_dec.h

@@ -1,70 +0,0 @@
-//  tuz_dec.h
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
-*/
-#ifndef _tuz_dec_h
-#define _tuz_dec_h
-#include "tuz_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum tuz_TResult{
-    tuz_OK=0,
-    tuz_STREAM_END,
-    
-    tuz_CTRLTYPE_UNKNOW_ERROR=10,
-    tuz_CTRLTYPE_STREAM_END_ERROR,
-    
-    tuz_READ_CODE_ERROR=20,
-    tuz_READ_DICT_SIZE_ERROR,
-    tuz_CACHE_SIZE_ERROR,
-    tuz_DICT_POS_ERROR,
-    tuz_OUT_SIZE_OR_CODE_ERROR,
-    tuz_CODE_ERROR, //unknow code, or decode len(tuz_length_t) overflow
-
-} tuz_TResult;
-
-
-//-----------------------------------------------------------------------------------------------------------------
-// decompress step by step: compiled by Mbed Studio is 856 bytes
-//   if set tuz_isNeedLiteralLine=0 & _IS_RUN_MEM_SAFE_CHECK=0, compiled by Mbed Studio is 758 bytes
-
-typedef struct tuz_TStream{
-    _tuz_TInputCache    _code_cache;
-    _tuz_TDict          _dict;
-    _tuz_TState         _state;
-} tuz_TStream;
-
-//read dict_size from inputStream
-tuz_size_t tuz_TStream_read_dict_size(tuz_TInputStreamHandle inputStream,tuz_TInputStream_read read_code);
-
-//open tuz_TStream
-//  not need clear tuz_TStream before open;
-//  dict_and_cache lifetime need holding by caller;
-//  must cache_size>0, cache_size only affect decompress speed;
-//  if success return tuz_OK
-tuz_TResult tuz_TStream_open(tuz_TStream* self,tuz_TInputStreamHandle inputStream,tuz_TInputStream_read read_code,
-                             tuz_byte* dict_and_cache,tuz_size_t dict_size,tuz_size_t cache_size);
-
-//decompress partial to out_data
-//  data_size: input out_data buf's size, output decompressed data size when return tuz_STREAM_END;
-//  if success return tuz_OK or tuz_STREAM_END, tuz_STREAM_END means decompress finish;
-tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,tuz_size_t* data_size);
-
-
-//-----------------------------------------------------------------------------------------------------------------
-
-//decompress all to out_data memory
-//  compiled by Mbed Studio is 424 bytes; faster than decompress by tuz_TStream; 
-//    if set tuz_isNeedLiteralLine=0 & _IS_RUN_MEM_SAFE_CHECK=0, compiled by Mbed Studio is 298 bytes
-//  data_size: input out_data buf's size, output decompressed data size;
-//  if success return tuz_STREAM_END;
-tuz_TResult tuz_decompress_mem(const tuz_byte* in_code,tuz_size_t code_size,tuz_byte* out_data,tuz_size_t* data_size);
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_tuz_dec_h

+ 0 - 176
decompresser/tinyuz/tuz_types.h

@@ -1,176 +0,0 @@
-//  tuz_types.h
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
-*/
-#ifndef _tuz_types_h
-#define _tuz_types_h
-#ifndef _IS_USED_SHARE_hpatch_lite_types
-//if _IS_USED_SHARE_hpatch_lite_types==1, share _hpi_TInputCache can reduce 52 bytes
-#   define  _IS_USED_SHARE_hpatch_lite_types 0
-#endif
-
-#ifndef tuz_isNeedLiteralLine  // optimize incompressible data for improve compression ratio
-//if tuz_isNeedLiteralLine==0 when decompress, must also be set to 0 when compress, can reduce 80 bytes
-#   define tuz_isNeedLiteralLine 1
-#endif
-
-#if (_IS_USED_SHARE_hpatch_lite_types)
-#   include "hpatch_lite_types.h"  //in "HDiffPatch/libHDiffPatch/HPatchLite/"
-#   include "hpatch_lite_input_cache.h"
-#   define     _tuz_TInputCache         _hpi_TInputCache
-
-#   define     tuz_byte         hpi_byte
-#   define     tuz_fast_uint8   hpi_fast_uint8
-#   define     tuz_BOOL         hpi_BOOL
-#   define     tuz_FALSE        hpi_FALSE
-#   define     tuz_TRUE         hpi_TRUE
-#   define     tuz_size_t       hpi_size_t  //memory size type
-#   define     tuz_inline               hpi_inline
-#   define     tuz_force_inline         hpi_force_inline
-#   define     tuz_try_inline           hpi_try_inline
-#   define     tuz_TInputStreamHandle   hpi_TInputStreamHandle
-#   define     tuz_TInputStream_read    hpi_TInputStream_read
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TINYUZ_VERSION_MAJOR    0
-#define TINYUZ_VERSION_MINOR    9
-#define TINYUZ_VERSION_RELEASE  2
-
-#define _TINYUZ_VERSION                 TINYUZ_VERSION_MAJOR.TINYUZ_VERSION_MINOR.TINYUZ_VERSION_RELEASE
-#define _TINYUZ_QUOTE(str)              #str
-#define _TINYUZ_EXPAND_AND_QUOTE(str)   _TINYUZ_QUOTE(str)
-#define TINYUZ_VERSION_STRING           _TINYUZ_EXPAND_AND_QUOTE(_TINYUZ_VERSION)
-
-#define NDEBUG
-#ifdef NDEBUG
-# ifndef assert
-#   define  assert(expression) ((void)0)
-# endif
-#else
-#   include <assert.h> //assert
-#endif
-
-#ifndef tuz_byte
-    typedef  unsigned char      tuz_byte;
-#endif
-#ifndef tuz_fast_uint8
-    typedef  unsigned int       tuz_fast_uint8; //>= 8bit uint
-#endif
-#ifndef tuz_BOOL
-    typedef  tuz_fast_uint8     tuz_BOOL;
-#endif
-#ifndef tuz_FALSE
-    #define  tuz_FALSE      0
-#endif
-#ifndef tuz_TRUE
-    #define  tuz_TRUE       1
-#endif
-
-#ifndef tuz_length_t
-    //tuz_length_t must can saved CompressProps.maxSaveLength & dictSize value
-    //  if tuz_length_t==uint8_t, must CompressProps.maxSaveLength & dictSize <= 255 when compress;
-    //  if tuz_length_t==int16_t, must CompressProps.maxSaveLength & dictSize <= (2<<15)-1 ; ...
-    typedef  unsigned int       tuz_length_t;
-#endif
-#ifndef tuz_size_t
-    typedef  tuz_length_t       tuz_size_t; //memory size type
-#endif
-
-#ifndef tuz_inline
-#if (defined(_MSC_VER))
-#   define tuz_inline __inline
-#else
-#   define tuz_inline inline
-#endif
-#endif
-#ifndef tuz_force_inline
-#if defined(_MSC_VER)
-#   define tuz_force_inline __forceinline
-#elif defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
-#   define tuz_force_inline __attribute__((always_inline)) inline
-#elif defined(__ICCARM__)
-#   define tuz_force_inline _Pragma("inline=forced")
-#else
-#   define tuz_force_inline tuz_inline
-#endif
-#endif
-
-#ifndef tuz_try_inline
-//#   define tuz_try_inline   tuz_inline
-#   define tuz_try_inline
-#endif
-
-#ifndef _IS_RUN_MEM_SAFE_CHECK
-#   define _IS_RUN_MEM_SAFE_CHECK  1
-#endif
-
-#ifndef _IS_USED_C_MEMCPY  // use memcpy() in <string.h>?
-#   define _IS_USED_C_MEMCPY  1
-#endif
-
-#ifndef tuz_kMaxOfDictSize
-#   define tuz_kMaxOfDictSize   __tuz_kMaxOfDictSize_MAX
-//#   define tuz_kMaxOfDictSize   ((1<<24)-1)   //3 bytes
-//#   define tuz_kMaxOfDictSize   ((1<<16)-1)   //2 bytes
-#endif
-
-//save dictSize at the beginning of the compressed code stream, little-endian order, tuz_kDictSizeSavedBytes bytes
-#define __tuz_kMaxOfDictSize_MAX  (1<<30) //now limit for uint32
-#if (tuz_kMaxOfDictSize>__tuz_kMaxOfDictSize_MAX)
-#   error tuz_kMaxOfDictSize error
-#elif ((tuz_kMaxOfDictSize>>24)>=1)
-#   define tuz_kDictSizeSavedBytes 4
-#elif ((tuz_kMaxOfDictSize>>16)>=1)
-#   define tuz_kDictSizeSavedBytes 3
-#elif ((tuz_kMaxOfDictSize>>8)>=1)
-#   define tuz_kDictSizeSavedBytes 2
-#elif (tuz_kMaxOfDictSize>=1)
-#   define tuz_kDictSizeSavedBytes 1
-#else
-#   error tuz_kMaxOfDictSize error
-#endif
-
-#ifndef tuz_TInputStreamHandle
-    typedef void*   tuz_TInputStreamHandle;
-#endif
-#ifndef tuz_TInputStream_read
-//read (*data_size) bytes data from inputStream to out_data; if input stream end,set *data_size readed size; if read error return tuz_FALSE;
-typedef tuz_BOOL (*tuz_TInputStream_read)(tuz_TInputStreamHandle inputStream,tuz_byte* out_data,tuz_size_t* data_size);
-#endif
-
-#ifndef _tuz_TInputCache
-typedef struct _tuz_TInputCache{
-    tuz_size_t      cache_begin;
-    tuz_size_t      cache_end;
-    tuz_byte*       cache_buf;
-    tuz_TInputStreamHandle  inputStream;
-    tuz_TInputStream_read   read_code;
-} _tuz_TInputCache;
-#endif
-typedef struct _tuz_TDict{
-    tuz_size_t      dict_cur;
-    tuz_size_t      dict_size;
-    tuz_byte*       dict_buf;
-} _tuz_TDict;
-typedef struct _tuz_TState{
-    tuz_size_t      dictType_pos;
-    tuz_size_t      dictType_pos_inc;
-    tuz_size_t      dict_pos_back;
-    tuz_length_t    dictType_len;
-  #if tuz_isNeedLiteralLine
-    tuz_length_t    literalType_len;
-  #endif
-    tuz_fast_uint8  types;
-    tuz_fast_uint8  type_count;
-    tuz_BOOL        isHaveData_back;
-} _tuz_TState;
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_tuz_types_h

+ 0 - 37
decompresser/tinyuz/tuz_types_private.h

@@ -1,37 +0,0 @@
-//  tuz_types_private.h
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
-*/
-#ifndef _tuz_types_private_h
-#define _tuz_types_private_h
-#include "tuz_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-    typedef enum tuz_TCodeType{
-        tuz_codeType_dict=0,
-        tuz_codeType_data=1,
-    } tuz_TCodeType;
-    
-    typedef enum tuz_TCtrlType{
-        //0 for error type
-    #if tuz_isNeedLiteralLine
-        tuz_ctrlType_literalLine=1,
-    #endif
-        tuz_ctrlType_clipEnd=2,
-        tuz_ctrlType_streamEnd=3,
-    } tuz_TCtrlType;
-
-    #if tuz_isNeedLiteralLine
-    #   define tuz_kMinLiteralLen   15
-    #endif
-    #define tuz_kMinDictMatchLen    2
-    #define tuz_kMaxTypeBitCount    8
-    #define tuz_kBigPosForLen       ((1<<11)+(1<<9)+(1<<7)-1)
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_tuz_types_private_h

+ 0 - 52
hpatch/HPatch/checksum_plugin.h

@@ -1,52 +0,0 @@
-//checksum_plugin.h
-//  checksum plugin type
-/*
- The MIT License (MIT)
- Copyright (c) 2018-2019 HouSisong
- 
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- 
- The above copyright notice and this permission notice shall be
- included in all copies of the Software.
- 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef HPatch_checksum_plugin_h
-#define HPatch_checksum_plugin_h
-#include "patch_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-    typedef void*  hpatch_checksumHandle;
-    typedef struct hpatch_TChecksum{
-        //return type tag; strlen(result)<=hpatch_kMaxPluginTypeLength; (Note:result lifetime)
-        const char*   (*checksumType)(void); //ascii cstring,cannot contain '&'
-        hpatch_size_t (*checksumByteSize)(void); //result<=hpatch_kStreamCacheSize
-        hpatch_checksumHandle (*open)(struct hpatch_TChecksum* plugin);
-        void                 (*close)(struct hpatch_TChecksum* plugin,hpatch_checksumHandle handle);
-        void                 (*begin)(hpatch_checksumHandle handle);
-        void                (*append)(hpatch_checksumHandle handle,
-                                      const unsigned char* part_data,const unsigned char* part_data_end);
-        void                   (*end)(hpatch_checksumHandle handle,
-                                      unsigned char* checksum,unsigned char* checksum_end);
-    } hpatch_TChecksum;
-    
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 2384
hpatch/HPatch/patch.c

@@ -1,2384 +0,0 @@
-//patch.c
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2018 HouSisong
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-*/
-#include "patch.h"
-#if (_IS_NEED_CACHE_OLD_BY_COVERS)
-#   include <stdlib.h> //qsort
-#endif
-#include "patch_private.h"
-
-#ifndef _IS_RUN_MEM_SAFE_CHECK
-#   define _IS_RUN_MEM_SAFE_CHECK  1
-#endif
-
-#if (_IS_RUN_MEM_SAFE_CHECK)
-//__RUN_MEM_SAFE_CHECK用来启动内存访问越界检查,用以防御可能被意外或故意损坏的数据.
-#   define __RUN_MEM_SAFE_CHECK
-#endif
-
-#ifdef __RUN_MEM_SAFE_CHECK
-#   define  _SAFE_CHECK_DO(code)    do{ if (!(code)) return _hpatch_FALSE; }while(0)
-#else
-#   define  _SAFE_CHECK_DO(code)    do{ code; }while(0)
-#endif
-
-#define _hpatch_FALSE   hpatch_FALSE
-//hpatch_uint __hpatch_debug_check_false_x=0; //for debug
-//#define _hpatch_FALSE (1/__hpatch_debug_check_false_x)
-
-typedef unsigned char TByte;
-
-
-//变长正整数编码方案(x bit额外类型标志位,x<=7),从高位开始输出1--n byte:
-// x0*  7-x bit
-// x1* 0*  7+7-x bit
-// x1* 1* 0*  7+7+7-x bit
-// x1* 1* 1* 0*  7+7+7+7-x bit
-// x1* 1* 1* 1* 0*  7+7+7+7+7-x bit
-// ......
-hpatch_BOOL hpatch_packUIntWithTag(TByte** out_code,TByte* out_code_end,
-                                   hpatch_StreamPos_t uValue,hpatch_uint highTag,
-                                   const hpatch_uint kTagBit){//写入整数并前进指针.
-    TByte*          pcode=*out_code;
-    const hpatch_StreamPos_t kMaxValueWithTag=((hpatch_StreamPos_t)1<<(7-kTagBit))-1;
-    TByte           codeBuf[hpatch_kMaxPackedUIntBytes];
-    TByte*          codeEnd=codeBuf;
-#ifdef __RUN_MEM_SAFE_CHECK
-    //static const hpatch_uint kPackMaxTagBit=7;
-    //assert((0<=kTagBit)&&(kTagBit<=kPackMaxTagBit));
-    //assert((highTag>>kTagBit)==0);
-#endif
-    while (uValue>kMaxValueWithTag) {
-        *codeEnd=uValue&((1<<7)-1); ++codeEnd;
-        uValue>>=7;
-    }
-#ifdef __RUN_MEM_SAFE_CHECK
-    if ((out_code_end-pcode)<(1+(codeEnd-codeBuf))) return _hpatch_FALSE;
-#endif
-    *pcode=(TByte)( (TByte)uValue | (highTag<<(8-kTagBit))
-                   | (((codeBuf!=codeEnd)?1:0)<<(7-kTagBit))  );
-    ++pcode;
-    while (codeBuf!=codeEnd) {
-        --codeEnd;
-        *pcode=(*codeEnd) | (((codeBuf!=codeEnd)?1:0)<<7);
-        ++pcode;
-    }
-    *out_code=pcode;
-    return hpatch_TRUE;
-}
-
-hpatch_uint hpatch_packUIntWithTag_size(hpatch_StreamPos_t uValue,const hpatch_uint kTagBit){
-    const hpatch_StreamPos_t kMaxValueWithTag=((hpatch_StreamPos_t)1<<(7-kTagBit))-1;
-    hpatch_uint size=0;
-    while (uValue>kMaxValueWithTag) {
-        ++size;
-        uValue>>=7;
-    }
-    ++size;
-    return size;
-}
-
-hpatch_BOOL hpatch_unpackUIntWithTag(const TByte** src_code,const TByte* src_code_end,
-                                     hpatch_StreamPos_t* result,const hpatch_uint kTagBit){//读出整数并前进指针.
-#ifdef __RUN_MEM_SAFE_CHECK
-    //const hpatch_uint kPackMaxTagBit=7;
-#endif
-    hpatch_StreamPos_t  value;
-    TByte               code;
-    const TByte*        pcode=*src_code;
-    
-#ifdef __RUN_MEM_SAFE_CHECK
-    //assert(kTagBit<=kPackMaxTagBit);
-    if (src_code_end<=pcode) return _hpatch_FALSE;
-#endif
-    code=*pcode; ++pcode;
-    value=code&((1<<(7-kTagBit))-1);
-    if ((code&(1<<(7-kTagBit)))!=0){
-        do {
-#ifdef __RUN_MEM_SAFE_CHECK
-            if ((value>>(sizeof(value)*8-7))!=0) return _hpatch_FALSE;//cannot save 7bit
-            if (src_code_end==pcode) return _hpatch_FALSE;
-#endif
-            code=*pcode; ++pcode;
-            value=(value<<7) | (code&((1<<7)-1));
-        } while ((code&(1<<7))!=0);
-    }
-    (*src_code)=pcode;
-    *result=value;
-    return hpatch_TRUE;
-}
-
-
-    static hpatch_BOOL _read_mem_stream(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
-                                        unsigned char* out_data,unsigned char* out_data_end){
-        const unsigned char* src=(const unsigned char*)stream->streamImport;
-        hpatch_size_t readLen=out_data_end-out_data;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (readFromPos>stream->streamSize) return _hpatch_FALSE;
-        if (readLen>(hpatch_StreamPos_t)(stream->streamSize-readFromPos)) return _hpatch_FALSE;
-#endif
-        memcpy(out_data,src+readFromPos,readLen);
-        return hpatch_TRUE;
-    }
-const hpatch_TStreamInput* mem_as_hStreamInput(hpatch_TStreamInput* out_stream,
-                                               const unsigned char* mem,const unsigned char* mem_end){
-    out_stream->streamImport=(void*)mem;
-    out_stream->streamSize=mem_end-mem;
-    out_stream->read=_read_mem_stream;
-    return out_stream;
-}
-
-    static hpatch_BOOL _write_mem_stream(const hpatch_TStreamOutput* stream,hpatch_StreamPos_t writeToPos,
-                                         const unsigned char* data,const unsigned char* data_end){
-        unsigned char* out_dst=(unsigned char*)stream->streamImport;
-        hpatch_size_t writeLen=data_end-data;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (writeToPos>stream->streamSize) return _hpatch_FALSE;
-        if (writeLen>(hpatch_StreamPos_t)(stream->streamSize-writeToPos)) return _hpatch_FALSE;
-#endif
-        memcpy(out_dst+writeToPos,data,writeLen);
-        return hpatch_TRUE;
-    }
-    typedef hpatch_BOOL (*_read_mem_stream_t)(const hpatch_TStreamOutput* stream,hpatch_StreamPos_t readFromPos,
-                                              unsigned char* out_data,unsigned char* out_data_end);
-const hpatch_TStreamOutput* mem_as_hStreamOutput(hpatch_TStreamOutput* out_stream,
-                                                 unsigned char* mem,unsigned char* mem_end){
-    out_stream->streamImport=mem;
-    out_stream->streamSize=mem_end-mem;
-    out_stream->read_writed=(_read_mem_stream_t)_read_mem_stream;
-    out_stream->write=_write_mem_stream;
-    return out_stream;
-}
-
-hpatch_BOOL hpatch_deccompress_mem(hpatch_TDecompress* decompressPlugin,
-                                   const unsigned char* code,const unsigned char* code_end,
-                                   unsigned char* out_data,unsigned char* out_data_end){
-    hpatch_decompressHandle dec=0;
-    hpatch_BOOL result,colose_rt;
-    hpatch_TStreamInput  codeStream;
-    mem_as_hStreamInput(&codeStream,code,code_end);
-    dec=decompressPlugin->open(decompressPlugin,(out_data_end-out_data),
-                               &codeStream,0,codeStream.streamSize);
-    if (dec==0) return _hpatch_FALSE;
-    result=decompressPlugin->decompress_part(dec,out_data,out_data_end);
-    colose_rt=decompressPlugin->close(decompressPlugin,dec);
-    assert(colose_rt);
-    return result;
-}
-
-
-////////
-//patch by memory
-
-static const hpatch_uint kSignTagBit=1;
-
-static hpatch_BOOL _bytesRle_load(TByte* out_data,TByte* out_dataEnd,
-                                  const TByte* rle_code,const TByte* rle_code_end);
-static void addData(TByte* dst,const TByte* src,hpatch_size_t length);
-hpatch_inline
-static hpatch_BOOL _unpackUIntWithTag(const TByte** src_code,const TByte* src_code_end,
-                                      hpatch_size_t* result,const hpatch_uint kTagBit){
-    if (sizeof(hpatch_size_t)==sizeof(hpatch_StreamPos_t)){
-        return hpatch_unpackUIntWithTag(src_code,src_code_end,(hpatch_StreamPos_t*)result,kTagBit);
-    }else{
-        hpatch_StreamPos_t u64=0;
-        hpatch_BOOL rt=hpatch_unpackUIntWithTag(src_code,src_code_end,&u64,kTagBit);
-        hpatch_size_t u=(hpatch_size_t)u64;
-        *result=u;
-#ifdef __RUN_MEM_SAFE_CHECK
-        return rt&(u==u64);
-#else
-        return rt;
-#endif
-    }
-}
-
-#define unpackUIntWithTagTo(puint,src_code,src_code_end,kTagBit) \
-        _SAFE_CHECK_DO(_unpackUIntWithTag(src_code,src_code_end,puint,kTagBit))
-#define unpackUIntTo(puint,src_code,src_code_end) \
-        unpackUIntWithTagTo(puint,src_code,src_code_end,0)
-
-hpatch_BOOL patch(TByte* out_newData,TByte* out_newData_end,
-                  const TByte* oldData,const TByte* oldData_end,
-                  const TByte* serializedDiff,const TByte* serializedDiff_end){
-    const TByte *code_lengths, *code_lengths_end,
-                *code_inc_newPos, *code_inc_newPos_end,
-                *code_inc_oldPos, *code_inc_oldPos_end,
-                *code_newDataDiff, *code_newDataDiff_end;
-    hpatch_size_t  coverCount;
-
-    assert(out_newData<=out_newData_end);
-    assert(oldData<=oldData_end);
-    assert(serializedDiff<=serializedDiff_end);
-    unpackUIntTo(&coverCount,&serializedDiff, serializedDiff_end);
-    {   //head
-        hpatch_size_t lengthSize,inc_newPosSize,inc_oldPosSize,newDataDiffSize;
-        unpackUIntTo(&lengthSize,&serializedDiff, serializedDiff_end);
-        unpackUIntTo(&inc_newPosSize,&serializedDiff, serializedDiff_end);
-        unpackUIntTo(&inc_oldPosSize,&serializedDiff, serializedDiff_end);
-        unpackUIntTo(&newDataDiffSize,&serializedDiff, serializedDiff_end);
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (lengthSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
-#endif
-        code_lengths=serializedDiff;     serializedDiff+=lengthSize;
-        code_lengths_end=serializedDiff;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (inc_newPosSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
-#endif
-        code_inc_newPos=serializedDiff; serializedDiff+=inc_newPosSize;
-        code_inc_newPos_end=serializedDiff;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (inc_oldPosSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
-#endif
-        code_inc_oldPos=serializedDiff; serializedDiff+=inc_oldPosSize;
-        code_inc_oldPos_end=serializedDiff;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (newDataDiffSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
-#endif
-        code_newDataDiff=serializedDiff; serializedDiff+=newDataDiffSize;
-        code_newDataDiff_end=serializedDiff;
-    }
-
-    //decode rle ; rle data begin==cur serializedDiff;
-    _SAFE_CHECK_DO(_bytesRle_load(out_newData, out_newData_end, serializedDiff, serializedDiff_end));
-
-    {   //patch
-        const hpatch_size_t newDataSize=(hpatch_size_t)(out_newData_end-out_newData);
-        hpatch_size_t oldPosBack=0;
-        hpatch_size_t newPosBack=0;
-        hpatch_size_t i;
-        for (i=0; i<coverCount; ++i){
-            hpatch_size_t copyLength,addLength, oldPos,inc_oldPos,inc_oldPos_sign;
-            unpackUIntTo(&copyLength,&code_inc_newPos, code_inc_newPos_end);
-            unpackUIntTo(&addLength,&code_lengths, code_lengths_end);
-#ifdef __RUN_MEM_SAFE_CHECK
-            if (code_inc_oldPos>=code_inc_oldPos_end) return _hpatch_FALSE;
-#endif
-            inc_oldPos_sign=(*code_inc_oldPos)>>(8-kSignTagBit);
-            unpackUIntWithTagTo(&inc_oldPos,&code_inc_oldPos, code_inc_oldPos_end, kSignTagBit);
-            if (inc_oldPos_sign==0)
-                oldPos=oldPosBack+inc_oldPos;
-            else
-                oldPos=oldPosBack-inc_oldPos;
-            if (copyLength>0){
-#ifdef __RUN_MEM_SAFE_CHECK
-                if (copyLength>(hpatch_size_t)(newDataSize-newPosBack)) return _hpatch_FALSE;
-                if (copyLength>(hpatch_size_t)(code_newDataDiff_end-code_newDataDiff)) return _hpatch_FALSE;
-#endif
-                memcpy(out_newData+newPosBack,code_newDataDiff,copyLength);
-                code_newDataDiff+=copyLength;
-                newPosBack+=copyLength;
-            }
-#ifdef __RUN_MEM_SAFE_CHECK
-            if ( (addLength>(hpatch_size_t)(newDataSize-newPosBack)) ) return _hpatch_FALSE;
-            if ( (oldPos>(hpatch_size_t)(oldData_end-oldData)) ||
-                 (addLength>(hpatch_size_t)(oldData_end-oldData-oldPos)) ) return _hpatch_FALSE;
-#endif
-            addData(out_newData+newPosBack,oldData+oldPos,addLength);
-            oldPosBack=oldPos;
-            newPosBack+=addLength;
-        }
-
-        if (newPosBack<newDataSize){
-            hpatch_size_t copyLength=newDataSize-newPosBack;
-#ifdef __RUN_MEM_SAFE_CHECK
-            if (copyLength>(hpatch_size_t)(code_newDataDiff_end-code_newDataDiff)) return _hpatch_FALSE;
-#endif
-            memcpy(out_newData+newPosBack,code_newDataDiff,copyLength);
-            code_newDataDiff+=copyLength;
-            //newPosBack=newDataSize;
-        }
-    }
-
-    if (  (code_lengths==code_lengths_end)
-        &&(code_inc_newPos==code_inc_newPos_end)
-        &&(code_inc_oldPos==code_inc_oldPos_end)
-        &&(code_newDataDiff==code_newDataDiff_end))
-        return hpatch_TRUE;
-    else
-        return _hpatch_FALSE;
-}
-
-hpatch_inline static void addData(TByte* dst,const TByte* src,hpatch_size_t length){
-    while (length--) { *dst++ += *src++; }
-}
-
-static hpatch_BOOL _bytesRle_load(TByte* out_data,TByte* out_dataEnd,
-                                  const TByte* rle_code,const TByte* rle_code_end){
-    const TByte*    ctrlBuf,*ctrlBuf_end;
-    hpatch_size_t ctrlSize;
-    unpackUIntTo(&ctrlSize,&rle_code,rle_code_end);
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (ctrlSize>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
-#endif
-    ctrlBuf=rle_code;
-    rle_code+=ctrlSize;
-    ctrlBuf_end=rle_code;
-    while (ctrlBuf_end-ctrlBuf>0){
-        enum TByteRleType type=(enum TByteRleType)((*ctrlBuf)>>(8-kByteRleType_bit));
-        hpatch_size_t length;
-        unpackUIntWithTagTo(&length,&ctrlBuf,ctrlBuf_end,kByteRleType_bit);
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (length>=(hpatch_size_t)(out_dataEnd-out_data)) return _hpatch_FALSE;
-#endif
-        ++length;
-        switch (type){
-            case kByteRleType_rle0:{
-                memset(out_data,0,length);
-                out_data+=length;
-            }break;
-            case kByteRleType_rle255:{
-                memset(out_data,255,length);
-                out_data+=length;
-            }break;
-            case kByteRleType_rle:{
-#ifdef __RUN_MEM_SAFE_CHECK
-                if (1>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
-#endif
-                memset(out_data,*rle_code,length);
-                ++rle_code;
-                out_data+=length;
-            }break;
-            case kByteRleType_unrle:{
-#ifdef __RUN_MEM_SAFE_CHECK
-                if (length>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
-#endif
-                memcpy(out_data,rle_code,length);
-                rle_code+=length;
-                out_data+=length;
-            }break;
-        }
-    }
-    
-    if (  (ctrlBuf==ctrlBuf_end)
-        &&(rle_code==rle_code_end)
-        &&(out_data==out_dataEnd))
-        return hpatch_TRUE;
-    else
-        return _hpatch_FALSE;
-}
-
-//----------------------
-//patch by stream
-
-    static hpatch_BOOL _TStreamInputClip_read(const hpatch_TStreamInput* stream,
-                                              hpatch_StreamPos_t readFromPos,
-                                              unsigned char* out_data,unsigned char* out_data_end){
-        TStreamInputClip* self=(TStreamInputClip*)stream->streamImport;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (readFromPos+(out_data_end-out_data)>self->base.streamSize) return _hpatch_FALSE;
-#endif
-        return self->srcStream->read(self->srcStream,readFromPos+self->clipBeginPos,out_data,out_data_end);
-    }
-void TStreamInputClip_init(TStreamInputClip* self,const hpatch_TStreamInput*  srcStream,
-                           hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos){
-    assert(self!=0);
-    assert(srcStream!=0);
-    assert(clipBeginPos<=clipEndPos);
-    assert(clipEndPos<=srcStream->streamSize);
-    self->srcStream=srcStream;
-    self->clipBeginPos=clipBeginPos;
-    self->base.streamImport=self;
-    self->base.streamSize=clipEndPos-clipBeginPos;
-    self->base.read=_TStreamInputClip_read;
-}
-
-    static hpatch_BOOL _TStreamOutputClip_write(const hpatch_TStreamOutput* stream,
-                                                hpatch_StreamPos_t writePos,
-                                                const unsigned char* data,const unsigned char* data_end){
-    TStreamOutputClip* self=(TStreamOutputClip*)stream->streamImport;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (writePos+(data_end-data)>self->base.streamSize) return _hpatch_FALSE;
-#endif
-    return self->srcStream->write(self->srcStream,writePos+self->clipBeginPos,data,data_end);
-}
-
-void TStreamOutputClip_init(TStreamOutputClip* self,const hpatch_TStreamOutput*  srcStream,
-                            hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos){
-    assert(self!=0);
-    assert(srcStream!=0);
-    assert(clipBeginPos<=clipEndPos);
-    assert(clipEndPos<=srcStream->streamSize);
-    self->srcStream=srcStream;
-    self->clipBeginPos=clipBeginPos;
-    self->base.streamImport=self;
-    self->base.streamSize=clipEndPos-clipBeginPos;
-    ((TStreamInputClip*)self)->base.read=_TStreamInputClip_read;
-    self->base.write=_TStreamOutputClip_write;
-}
-
-
-
-//assert(hpatch_kStreamCacheSize>=hpatch_kMaxPluginTypeLength+1);
-struct __private_hpatch_check_kMaxCompressTypeLength {
-    char _[(hpatch_kStreamCacheSize>=(hpatch_kMaxPluginTypeLength+1))?1:-1];};
-
-hpatch_BOOL _TStreamCacheClip_readType_end(TStreamCacheClip* sclip,TByte endTag,
-                                           char out_type[hpatch_kMaxPluginTypeLength+1]){
-    const TByte* type_begin;
-    hpatch_size_t i;
-    hpatch_size_t readLen=hpatch_kMaxPluginTypeLength+1;
-    if (readLen>_TStreamCacheClip_leaveSize(sclip))
-        readLen=(hpatch_size_t)_TStreamCacheClip_leaveSize(sclip);
-    type_begin=_TStreamCacheClip_accessData(sclip,readLen);
-    if (type_begin==0) return _hpatch_FALSE;//not found
-    for (i=0; i<readLen; ++i) {
-        if (type_begin[i]!=endTag)
-            continue;
-        else{
-            memcpy(out_type,type_begin,i);  out_type[i]='\0';
-            _TStreamCacheClip_skipData_noCheck(sclip,i+1);
-            return hpatch_TRUE;
-        }
-    }
-    return _hpatch_FALSE;//not found
-}
-
-hpatch_BOOL _TStreamCacheClip_updateCache(TStreamCacheClip* sclip){
-    TByte* buf0=&sclip->cacheBuf[0];
-    const hpatch_StreamPos_t streamSize=sclip->streamPos_end-sclip->streamPos;
-    hpatch_size_t readSize=sclip->cacheBegin;
-    if (readSize>streamSize)
-        readSize=(hpatch_size_t)streamSize;
-    if (readSize==0) return hpatch_TRUE;
-    if (!_TStreamCacheClip_isCacheEmpty(sclip)){
-        memmove(buf0+(hpatch_size_t)(sclip->cacheBegin-readSize),
-                buf0+sclip->cacheBegin,_TStreamCacheClip_cachedSize(sclip));
-    }
-    if (!sclip->srcStream->read(sclip->srcStream,sclip->streamPos,
-                                buf0+(sclip->cacheEnd-readSize),buf0+sclip->cacheEnd))
-        return _hpatch_FALSE;//read error
-    sclip->cacheBegin-=readSize;
-    sclip->streamPos+=readSize;
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TStreamCacheClip_skipData(TStreamCacheClip* sclip,hpatch_StreamPos_t skipLongSize){
-    while (skipLongSize>0) {
-        hpatch_size_t len=sclip->cacheEnd;
-        if (len>skipLongSize)
-            len=(hpatch_size_t)skipLongSize;
-        if (_TStreamCacheClip_accessData(sclip,len)){
-            _TStreamCacheClip_skipData_noCheck(sclip,len);
-            skipLongSize-=len;
-        }else{
-            return _hpatch_FALSE;
-        }
-    }
-    return hpatch_TRUE;
-}
-
-//assert(hpatch_kStreamCacheSize>=hpatch_kMaxPackedUIntBytes);
-struct __private_hpatch_check_hpatch_kMaxPackedUIntBytes {
-    char _[(hpatch_kStreamCacheSize>=hpatch_kMaxPackedUIntBytes)?1:-1]; };
-
-hpatch_BOOL _TStreamCacheClip_unpackUIntWithTag(TStreamCacheClip* sclip,hpatch_StreamPos_t* result,const hpatch_uint kTagBit){
-    TByte* curCode,*codeBegin;
-    hpatch_size_t readSize=hpatch_kMaxPackedUIntBytes;
-    const hpatch_StreamPos_t dataSize=_TStreamCacheClip_leaveSize(sclip);
-    if (readSize>dataSize)
-        readSize=(hpatch_size_t)dataSize;
-    codeBegin=_TStreamCacheClip_accessData(sclip,readSize);
-    if (codeBegin==0) return _hpatch_FALSE;
-    curCode=codeBegin;
-    _SAFE_CHECK_DO(hpatch_unpackUIntWithTag((const TByte**)&curCode,codeBegin+readSize,result,kTagBit));
-    _TStreamCacheClip_skipData_noCheck(sclip,(hpatch_size_t)(curCode-codeBegin));
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TStreamCacheClip_readDataTo(TStreamCacheClip* sclip,TByte* out_buf,TByte* bufEnd){
-    hpatch_size_t readLen=_TStreamCacheClip_cachedSize(sclip);
-    hpatch_size_t outLen=bufEnd-out_buf;
-    if (readLen>=outLen)
-        readLen=outLen;
-    memcpy(out_buf,&sclip->cacheBuf[sclip->cacheBegin],readLen);
-    sclip->cacheBegin+=readLen;
-    outLen-=readLen;
-    if (outLen){
-        out_buf += readLen;
-        if (outLen<(sclip->cacheEnd>>1)){
-            if (!_TStreamCacheClip_updateCache(sclip)) return _hpatch_FALSE;
-#ifdef __RUN_MEM_SAFE_CHECK
-            if (outLen>_TStreamCacheClip_cachedSize(sclip)) return _hpatch_FALSE;
-#endif
-            return _TStreamCacheClip_readDataTo(sclip, out_buf, bufEnd);
-        }else{
-            if (!sclip->srcStream->read(sclip->srcStream,sclip->streamPos,
-                                        out_buf,bufEnd)) return _hpatch_FALSE;
-            sclip->streamPos+=outLen;
-        }
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TStreamCacheClip_addDataTo(TStreamCacheClip* self,unsigned char* dst,hpatch_size_t addLen){
-    const unsigned char* src=_TStreamCacheClip_readData(self,addLen);
-    if (src==0) return _hpatch_FALSE;
-    addData(dst,src,addLen);
-    return hpatch_TRUE;
-}
-
-    static hpatch_BOOL _decompress_read(const hpatch_TStreamInput* stream,
-                                        const hpatch_StreamPos_t  readFromPos,
-                                        TByte* out_data,TByte* out_data_end){
-        _TDecompressInputStream* self=(_TDecompressInputStream*)stream->streamImport;
-        return self->decompressPlugin->decompress_part(self->decompressHandle,out_data,out_data_end);
-    }
-hpatch_BOOL getStreamClip(TStreamCacheClip* out_clip,_TDecompressInputStream* out_stream,
-                          hpatch_StreamPos_t dataSize,hpatch_StreamPos_t compressedSize,
-                          const hpatch_TStreamInput* stream,hpatch_StreamPos_t* pCurStreamPos,
-                          hpatch_TDecompress* decompressPlugin,TByte* aCache,hpatch_size_t cacheSize){
-    hpatch_StreamPos_t curStreamPos=*pCurStreamPos;
-    if (compressedSize==0){
-#ifdef __RUN_MEM_SAFE_CHECK
-        if ((curStreamPos+dataSize)<curStreamPos) return _hpatch_FALSE;
-        if ((curStreamPos+dataSize)>stream->streamSize) return _hpatch_FALSE;
-#endif
-        if (out_clip)
-            _TStreamCacheClip_init(out_clip,stream,curStreamPos,curStreamPos+dataSize,aCache,cacheSize);
-        curStreamPos+=dataSize;
-    }else{
-#ifdef __RUN_MEM_SAFE_CHECK
-        if ((curStreamPos+compressedSize)<curStreamPos) return _hpatch_FALSE;
-        if ((curStreamPos+compressedSize)>stream->streamSize) return _hpatch_FALSE;
-#endif
-        if (out_clip){
-            out_stream->IInputStream.streamImport=out_stream;
-            out_stream->IInputStream.streamSize=dataSize;
-            out_stream->IInputStream.read=_decompress_read;
-            out_stream->decompressPlugin=decompressPlugin;
-            if (out_stream->decompressHandle==0){
-                out_stream->decompressHandle=decompressPlugin->open(decompressPlugin,dataSize,stream,
-                                                                    curStreamPos,curStreamPos+compressedSize);
-                if (!out_stream->decompressHandle) return _hpatch_FALSE;
-            }else{
-                if (decompressPlugin->reset_code==0) return _hpatch_FALSE;
-                if (!decompressPlugin->reset_code(out_stream->decompressHandle,dataSize,stream,curStreamPos,
-                                                  curStreamPos+compressedSize)) return _hpatch_FALSE;
-            }
-            _TStreamCacheClip_init(out_clip,&out_stream->IInputStream,0,
-                                   out_stream->IInputStream.streamSize,aCache,cacheSize);
-        }
-        curStreamPos+=compressedSize;
-    }
-    *pCurStreamPos=curStreamPos;
-    return hpatch_TRUE;
-}
-
-///////
-
-static hpatch_inline hpatch_BOOL __TOutStreamCache_writeStream(_TOutStreamCache* self,const TByte* data,hpatch_size_t dataSize){
-    if (!self->dstStream->write(self->dstStream,self->writeToPos,data,data+dataSize))
-        return _hpatch_FALSE;
-    self->writeToPos+=dataSize;
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_flush(_TOutStreamCache* self){
-    hpatch_size_t curSize=self->cacheCur;
-    if (curSize>0){
-        if (!__TOutStreamCache_writeStream(self,self->cacheBuf,curSize))
-            return _hpatch_FALSE;
-        self->cacheCur=0;
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_write(_TOutStreamCache* self,const TByte* data,hpatch_size_t dataSize){
-    while (dataSize>0) {
-        hpatch_size_t copyLen;
-        hpatch_size_t curSize=self->cacheCur;
-        if ((dataSize>=self->cacheEnd)&&(curSize==0)){
-            return __TOutStreamCache_writeStream(self,data,dataSize);
-        }
-        copyLen=self->cacheEnd-curSize;
-        copyLen=(copyLen<=dataSize)?copyLen:dataSize;
-        memcpy(self->cacheBuf+curSize,data,copyLen);
-        self->cacheCur=curSize+copyLen;
-        data+=copyLen;
-        dataSize-=copyLen;
-        if (self->cacheCur==self->cacheEnd){
-            if (!_TOutStreamCache_flush(self))
-                return _hpatch_FALSE;
-        }
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_fill(_TOutStreamCache* self,hpatch_byte fillValue,hpatch_StreamPos_t fillLength){
-    while (fillLength>0){
-        hpatch_size_t curSize=self->cacheCur;
-        hpatch_size_t runStep=self->cacheEnd-curSize;
-        runStep=(runStep<=fillLength)?runStep:(hpatch_size_t)fillLength;
-        memset(self->cacheBuf+curSize,fillValue,runStep);
-        self->cacheCur=curSize+runStep;
-        fillLength-=runStep;
-        if (self->cacheCur==self->cacheEnd){
-            if (!_TOutStreamCache_flush(self))
-                return _hpatch_FALSE;
-        }
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_copyFromStream(_TOutStreamCache* self,const hpatch_TStreamInput* src,
-                                            hpatch_StreamPos_t srcPos,hpatch_StreamPos_t copyLength){
-    while (copyLength>0){
-        hpatch_size_t curSize=self->cacheCur;
-        hpatch_size_t runStep=self->cacheEnd-curSize;
-        hpatch_byte* buf=self->cacheBuf+curSize;
-        runStep=(runStep<=copyLength)?runStep:(hpatch_size_t)copyLength;
-        if (!src->read(src,srcPos,buf,buf+runStep))
-             return _hpatch_FALSE;
-        srcPos+=runStep;
-        self->cacheCur=curSize+runStep;
-        copyLength-=runStep;
-        if (self->cacheCur==self->cacheEnd){
-            if (!_TOutStreamCache_flush(self))
-                return _hpatch_FALSE;
-        }
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_copyFromClip(_TOutStreamCache* self,TStreamCacheClip* src,hpatch_StreamPos_t copyLength){
-    while (copyLength>0){
-        const TByte* data;
-        hpatch_size_t runStep=(src->cacheEnd<=copyLength)?src->cacheEnd:(hpatch_size_t)copyLength;
-        data=_TStreamCacheClip_readData(src,runStep);
-        if (data==0) return
-            _hpatch_FALSE;
-        if (!_TOutStreamCache_write(self,data,runStep))
-            return _hpatch_FALSE;
-        copyLength-=runStep;
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL _TOutStreamCache_copyFromSelf(_TOutStreamCache* self,hpatch_StreamPos_t aheadLength,hpatch_StreamPos_t copyLength){
-    //      [          writed                 ]
-    //                                        [    cached buf    |        empty buf         ]
-    const hpatch_TStreamInput* src=(const hpatch_TStreamInput*)self->dstStream;
-    hpatch_StreamPos_t srcPos=self->writeToPos+self->cacheCur-aheadLength;
-    if (src->read==0) //can't read
-        return _hpatch_FALSE;
-    if ((aheadLength<1)|(aheadLength>self->writeToPos+self->cacheCur))
-            return _hpatch_FALSE;
-    
-    if (srcPos+copyLength<=self->writeToPos){//copy from stream
-        //    [        copyLength          ]
-__copy_in_stream:
-        return _TOutStreamCache_copyFromStream(self,src,srcPos,copyLength);
-    }else if (srcPos>=self->writeToPos){ //copy in mem
-        //                                      [        copyLength        ]
-__copy_in_mem:
-        while (copyLength>0){
-            hpatch_byte* dstBuf=self->cacheBuf+self->cacheCur;
-            hpatch_byte* srcBuf=dstBuf-(hpatch_size_t)aheadLength;
-            hpatch_size_t runLen=(self->cacheCur+copyLength<=self->cacheEnd)?(hpatch_size_t)copyLength:(self->cacheEnd-self->cacheCur);
-            hpatch_size_t i;
-            for (i=0;i<runLen;i++)
-                dstBuf[i]=srcBuf[i];
-            copyLength-=runLen;
-            self->cacheCur+=runLen;
-            if (self->cacheCur==self->cacheEnd){
-                if (!_TOutStreamCache_flush(self))
-                    return _hpatch_FALSE;
-                runLen=(hpatch_size_t)((aheadLength<=copyLength)?aheadLength:copyLength);
-                memmove(self->cacheBuf,self->cacheBuf+self->cacheEnd-(hpatch_size_t)aheadLength,runLen);
-                self->cacheCur=runLen;
-                copyLength-=runLen;
-            }else{
-                assert(copyLength==0);
-            }
-        }
-        return hpatch_TRUE;
-    }else if (self->writeToPos+self->cacheCur<=srcPos+self->cacheEnd){ 
-        // small data in stream,can as copy in mem
-        hpatch_byte* dstBuf=self->cacheBuf+self->cacheCur;
-        hpatch_size_t runLen=(hpatch_size_t)(self->writeToPos-srcPos);
-        if (!src->read(src,srcPos,dstBuf,dstBuf+runLen))
-            return _hpatch_FALSE;
-        //srcPos+=runLen; //not used
-        copyLength-=runLen;
-        self->cacheCur+=runLen;
-        if (self->cacheCur==self->cacheEnd){
-            while (hpatch_TRUE){
-                if (self->cacheCur==self->cacheEnd){
-                    if (!_TOutStreamCache_flush(self))
-                        return _hpatch_FALSE;
-                }
-                if (copyLength>0){
-                    runLen=(self->cacheEnd<=copyLength)?self->cacheEnd:(hpatch_size_t)copyLength;
-                    //srcPos+=runLen; //not used
-                    copyLength-=runLen;
-                    self->cacheCur=runLen;
-                }else{
-                    return hpatch_TRUE;
-                }
-            }
-        }else{
-            goto __copy_in_mem;
-        }
-    }else{
-        goto __copy_in_stream;
-    }
-}
-
-
-typedef struct _TBytesRle_load_stream{
-    hpatch_StreamPos_t  memCopyLength;
-    hpatch_StreamPos_t  memSetLength;
-    TByte               memSetValue;
-    TStreamCacheClip    ctrlClip;
-    TStreamCacheClip    rleCodeClip;
-} _TBytesRle_load_stream;
-
-hpatch_inline
-static void _TBytesRle_load_stream_init(_TBytesRle_load_stream* loader){
-    loader->memSetLength=0;
-    loader->memSetValue=0;//nil;
-    loader->memCopyLength=0;
-    _TStreamCacheClip_init(&loader->ctrlClip,0,0,0,0,0);
-    _TStreamCacheClip_init(&loader->rleCodeClip,0,0,0,0,0);
-}
-
-hpatch_inline static void memSet_add(TByte* dst,const TByte src,hpatch_size_t length){
-    while (length--) { (*dst++) += src; }
-}
-
-static hpatch_BOOL _TBytesRle_load_stream_mem_add(_TBytesRle_load_stream* loader,
-                                                  hpatch_size_t* _decodeSize,TByte** _out_data){
-    hpatch_size_t  decodeSize=*_decodeSize;
-    TByte* out_data=*_out_data;
-    TStreamCacheClip* rleCodeClip=&loader->rleCodeClip;
-    
-    hpatch_StreamPos_t memSetLength=loader->memSetLength;
-    if (memSetLength!=0){
-        hpatch_size_t memSetStep=((memSetLength<=decodeSize)?(hpatch_size_t)memSetLength:decodeSize);
-        const TByte byteSetValue=loader->memSetValue;
-        if (out_data!=0){
-            if (byteSetValue!=0)
-                memSet_add(out_data,byteSetValue,memSetStep);
-            out_data+=memSetStep;
-        }
-        decodeSize-=memSetStep;
-        loader->memSetLength=memSetLength-memSetStep;
-    }
-    while ((loader->memCopyLength>0)&&(decodeSize>0)) {
-        TByte* rleData;
-        hpatch_size_t decodeStep=rleCodeClip->cacheEnd;
-        if (decodeStep>loader->memCopyLength)
-            decodeStep=(hpatch_size_t)loader->memCopyLength;
-        if (decodeStep>decodeSize)
-            decodeStep=decodeSize;
-        rleData=_TStreamCacheClip_readData(rleCodeClip,decodeStep);
-        if (rleData==0) return _hpatch_FALSE;
-        if (out_data){
-            addData(out_data,rleData,decodeStep);
-            out_data+=decodeStep;
-        }
-        decodeSize-=decodeStep;
-        loader->memCopyLength-=decodeStep;
-    }
-    *_decodeSize=decodeSize;
-    *_out_data=out_data;
-    return hpatch_TRUE;
-}
-
-hpatch_inline
-static hpatch_BOOL _TBytesRle_load_stream_isFinish(const _TBytesRle_load_stream* loader){
-    return(loader->memSetLength==0)
-        &&(loader->memCopyLength==0)
-        &&(_TStreamCacheClip_isFinish(&loader->rleCodeClip))
-        &&(_TStreamCacheClip_isFinish(&loader->ctrlClip));
-}
-
-
-
-#define _clip_unpackUIntWithTagTo(puint,sclip,kTagBit) \
-    { if (!_TStreamCacheClip_unpackUIntWithTag(sclip,puint,kTagBit)) return _hpatch_FALSE; }
-#define _clip_unpackUIntTo(puint,sclip) _clip_unpackUIntWithTagTo(puint,sclip,0)
-
-static hpatch_BOOL _TBytesRle_load_stream_decode_add(_TBytesRle_load_stream* loader,
-                                                     TByte* out_data,hpatch_size_t decodeSize){
-    if (!_TBytesRle_load_stream_mem_add(loader,&decodeSize,&out_data))
-        return _hpatch_FALSE;
-
-    while ((decodeSize>0)&&(!_TStreamCacheClip_isFinish(&loader->ctrlClip))){
-        enum TByteRleType type;
-        hpatch_StreamPos_t length;
-        const TByte* pType=_TStreamCacheClip_accessData(&loader->ctrlClip,1);
-        if (pType==0) return _hpatch_FALSE;
-        type=(enum TByteRleType)((*pType)>>(8-kByteRleType_bit));
-        _clip_unpackUIntWithTagTo(&length,&loader->ctrlClip,kByteRleType_bit);
-        ++length;
-        switch (type){
-            case kByteRleType_rle0:{
-                loader->memSetLength=length;
-                loader->memSetValue=0;
-            }break;
-            case kByteRleType_rle255:{
-                loader->memSetLength=length;
-                loader->memSetValue=255;
-            }break;
-            case kByteRleType_rle:{
-                const TByte* pSetValue=_TStreamCacheClip_readData(&loader->rleCodeClip,1);
-                if (pSetValue==0) return _hpatch_FALSE;
-                loader->memSetValue=*pSetValue;
-                loader->memSetLength=length;
-            }break;
-            case kByteRleType_unrle:{
-                loader->memCopyLength=length;
-            }break;
-        }
-        if (!_TBytesRle_load_stream_mem_add(loader,&decodeSize,&out_data)) return _hpatch_FALSE;
-    }
-
-    if (decodeSize==0)
-        return hpatch_TRUE;
-    else
-        return _hpatch_FALSE;
-}
-
-#define _TBytesRle_load_stream_decode_skip(loader,decodeSize) \
-        _TBytesRle_load_stream_decode_add(loader,0,decodeSize)
-
-static  hpatch_BOOL _patch_add_old_with_rle(_TOutStreamCache* outCache,_TBytesRle_load_stream* rle_loader,
-                                            const hpatch_TStreamInput* old,hpatch_StreamPos_t oldPos,
-                                            hpatch_StreamPos_t addLength,TByte* aCache,hpatch_size_t aCacheSize){
-    while (addLength>0){
-        hpatch_size_t decodeStep=aCacheSize;
-        if (decodeStep>addLength)
-            decodeStep=(hpatch_size_t)addLength;
-        if (!old->read(old,oldPos,aCache,aCache+decodeStep)) return _hpatch_FALSE;
-        if (!_TBytesRle_load_stream_decode_add(rle_loader,aCache,decodeStep)) return _hpatch_FALSE;
-        if (!_TOutStreamCache_write(outCache,aCache,decodeStep)) return _hpatch_FALSE;
-        oldPos+=decodeStep;
-        addLength-=decodeStep;
-    }
-    return hpatch_TRUE;
-}
-
-typedef struct _TCovers{
-    hpatch_TCovers      ICovers;
-    hpatch_StreamPos_t  coverCount;
-    hpatch_StreamPos_t  oldPosBack;
-    hpatch_StreamPos_t  newPosBack;
-    TStreamCacheClip*   code_inc_oldPosClip;
-    TStreamCacheClip*   code_inc_newPosClip;
-    TStreamCacheClip*   code_lengthsClip;
-    hpatch_BOOL         isOldPosBackNeedAddLength;
-} _TCovers;
-
-static hpatch_StreamPos_t _covers_leaveCoverCount(const hpatch_TCovers* covers){
-    const _TCovers* self=(const _TCovers*)covers;
-    return self->coverCount;
-}
-static hpatch_BOOL _covers_close_nil(hpatch_TCovers* covers){
-    //empty
-    return hpatch_TRUE;
-}
-
-static  hpatch_BOOL _covers_read_cover(hpatch_TCovers* covers,hpatch_TCover* out_cover){
-    _TCovers* self=(_TCovers*)covers;
-    hpatch_StreamPos_t oldPosBack=self->oldPosBack;
-    hpatch_StreamPos_t newPosBack=self->newPosBack;
-    hpatch_StreamPos_t coverCount=self->coverCount;
-    if (coverCount>0)
-        self->coverCount=coverCount-1;
-    else
-        return _hpatch_FALSE;
-    
-    {
-        hpatch_StreamPos_t copyLength,coverLength, oldPos,inc_oldPos;
-        TByte inc_oldPos_sign;
-        const TByte* pSign=_TStreamCacheClip_accessData(self->code_inc_oldPosClip,1);
-        if (pSign)
-            inc_oldPos_sign=(*pSign)>>(8-kSignTagBit);
-        else
-            return _hpatch_FALSE;
-        _clip_unpackUIntWithTagTo(&inc_oldPos,self->code_inc_oldPosClip,kSignTagBit);
-        oldPos=(inc_oldPos_sign==0)?(oldPosBack+inc_oldPos):(oldPosBack-inc_oldPos);
-        _clip_unpackUIntTo(&copyLength,self->code_inc_newPosClip);
-        _clip_unpackUIntTo(&coverLength,self->code_lengthsClip);
-        newPosBack+=copyLength;
-        oldPosBack=oldPos;
-        oldPosBack+=(self->isOldPosBackNeedAddLength)?coverLength:0;
-        
-        out_cover->oldPos=oldPos;
-        out_cover->newPos=newPosBack;
-        out_cover->length=coverLength;
-        newPosBack+=coverLength;
-    }
-    self->oldPosBack=oldPosBack;
-    self->newPosBack=newPosBack;
-    return hpatch_TRUE;
-}
-
-static  hpatch_BOOL _covers_is_finish(const struct hpatch_TCovers* covers){
-    _TCovers* self=(_TCovers*)covers;
-    return _TStreamCacheClip_isFinish(self->code_lengthsClip)
-        && _TStreamCacheClip_isFinish(self->code_inc_newPosClip)
-        && _TStreamCacheClip_isFinish(self->code_inc_oldPosClip);
-}
-
-
-static void _covers_init(_TCovers* covers,hpatch_StreamPos_t coverCount,
-                         TStreamCacheClip* code_inc_oldPosClip,
-                         TStreamCacheClip* code_inc_newPosClip,
-                         TStreamCacheClip* code_lengthsClip,
-                         hpatch_BOOL  isOldPosBackNeedAddLength){
-    covers->ICovers.leave_cover_count=_covers_leaveCoverCount;
-    covers->ICovers.read_cover=_covers_read_cover;
-    covers->ICovers.is_finish=_covers_is_finish;
-    covers->ICovers.close=_covers_close_nil;
-    covers->coverCount=coverCount;
-    covers->newPosBack=0;
-    covers->oldPosBack=0;
-    covers->code_inc_oldPosClip=code_inc_oldPosClip;
-    covers->code_inc_newPosClip=code_inc_newPosClip;
-    covers->code_lengthsClip=code_lengthsClip;
-    covers->isOldPosBackNeedAddLength=isOldPosBackNeedAddLength;
-}
-
-static hpatch_BOOL _rle_decode_skip(struct _TBytesRle_load_stream* rle_loader,hpatch_StreamPos_t copyLength){
-    while (copyLength>0) {
-        hpatch_size_t len=(~(hpatch_size_t)0);
-        if (len>copyLength)
-            len=(hpatch_size_t)copyLength;
-        if (!_TBytesRle_load_stream_decode_skip(rle_loader,len)) return _hpatch_FALSE;
-        copyLength-=len;
-    }
-    return hpatch_TRUE;
-}
-
-static hpatch_BOOL patchByClip(_TOutStreamCache* outCache,
-                               const hpatch_TStreamInput*  oldData,
-                               hpatch_TCovers* covers,
-                               TStreamCacheClip* code_newDataDiffClip,
-                               struct _TBytesRle_load_stream* rle_loader,
-                               TByte* temp_cache,hpatch_size_t cache_size){
-    const hpatch_StreamPos_t newDataSize=_TOutStreamCache_leaveSize(outCache);
-    const hpatch_StreamPos_t oldDataSize=oldData->streamSize;
-    hpatch_StreamPos_t coverCount=covers->leave_cover_count(covers);
-    hpatch_StreamPos_t newPosBack=0;
-    assert(cache_size>=hpatch_kMaxPackedUIntBytes);
-    
-    while (coverCount--){
-        hpatch_TCover cover;
-        if(!covers->read_cover(covers,&cover)) return _hpatch_FALSE;
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (cover.newPos<newPosBack) return _hpatch_FALSE;
-        if (cover.length>(hpatch_StreamPos_t)(newDataSize-cover.newPos)) return _hpatch_FALSE;
-        if (cover.oldPos>oldDataSize) return _hpatch_FALSE;
-        if (cover.length>(hpatch_StreamPos_t)(oldDataSize-cover.oldPos)) return _hpatch_FALSE;
-#endif
-        if (newPosBack<cover.newPos){
-            hpatch_StreamPos_t copyLength=cover.newPos-newPosBack;
-            if (!_TOutStreamCache_copyFromClip(outCache,code_newDataDiffClip,copyLength)) return _hpatch_FALSE;
-            if (!_rle_decode_skip(rle_loader,copyLength)) return _hpatch_FALSE;
-        }
-        if (!_patch_add_old_with_rle(outCache,rle_loader,oldData,cover.oldPos,cover.length,
-                                     temp_cache,cache_size)) return _hpatch_FALSE;
-        newPosBack=cover.newPos+cover.length;
-    }
-    
-    if (newPosBack<newDataSize){
-        hpatch_StreamPos_t copyLength=newDataSize-newPosBack;
-        if (!_TOutStreamCache_copyFromClip(outCache,code_newDataDiffClip,copyLength)) return _hpatch_FALSE;
-        if (!_rle_decode_skip(rle_loader,copyLength)) return _hpatch_FALSE;
-        newPosBack=newDataSize;
-    }
-    if (!_TOutStreamCache_flush(outCache))
-        return _hpatch_FALSE;
-    if (   _TBytesRle_load_stream_isFinish(rle_loader)
-        && covers->is_finish(covers)
-        && _TOutStreamCache_isFinish(outCache)
-        && _TStreamCacheClip_isFinish(code_newDataDiffClip)
-        && (newPosBack==newDataSize) )
-        return hpatch_TRUE;
-    else
-        return _hpatch_FALSE;
-}
-
-
-#define _kCachePatCount 8
-
-#define _cache_alloc(dst,dst_type,memSize,temp_cache,temp_cache_end){   \
-    if ((hpatch_size_t)(temp_cache_end-temp_cache) <   \
-        sizeof(hpatch_StreamPos_t)+(memSize))  return hpatch_FALSE;      \
-    (dst)=(dst_type*)_hpatch_align_upper(temp_cache,sizeof(hpatch_StreamPos_t));\
-    temp_cache=(TByte*)(dst)+(hpatch_size_t)(memSize); \
-}
-
-typedef struct _TPackedCovers{
-    _TCovers            base;
-    TStreamCacheClip    code_inc_oldPosClip;
-    TStreamCacheClip    code_inc_newPosClip;
-    TStreamCacheClip    code_lengthsClip;
-} _TPackedCovers;
-
-typedef struct _THDiffHead{
-    hpatch_StreamPos_t coverCount;
-    hpatch_StreamPos_t lengthSize;
-    hpatch_StreamPos_t inc_newPosSize;
-    hpatch_StreamPos_t inc_oldPosSize;
-    hpatch_StreamPos_t newDataDiffSize;
-    hpatch_StreamPos_t headEndPos;
-    hpatch_StreamPos_t coverEndPos;
-} _THDiffHead;
-
-static hpatch_BOOL read_diff_head(_THDiffHead* out_diffHead,
-                                  const hpatch_TStreamInput* serializedDiff){
-    hpatch_StreamPos_t       diffPos0;
-    const hpatch_StreamPos_t diffPos_end=serializedDiff->streamSize;
-    TByte       temp_cache[hpatch_kStreamCacheSize];
-    TStreamCacheClip  diffHeadClip;
-    _TStreamCacheClip_init(&diffHeadClip,serializedDiff,0,diffPos_end,temp_cache,hpatch_kStreamCacheSize);
-    _clip_unpackUIntTo(&out_diffHead->coverCount,&diffHeadClip);
-    _clip_unpackUIntTo(&out_diffHead->lengthSize,&diffHeadClip);
-    _clip_unpackUIntTo(&out_diffHead->inc_newPosSize,&diffHeadClip);
-    _clip_unpackUIntTo(&out_diffHead->inc_oldPosSize,&diffHeadClip);
-    _clip_unpackUIntTo(&out_diffHead->newDataDiffSize,&diffHeadClip);
-    diffPos0=(hpatch_StreamPos_t)(_TStreamCacheClip_readPosOfSrcStream(&diffHeadClip));
-    out_diffHead->headEndPos=diffPos0;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (out_diffHead->lengthSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
-#endif
-    diffPos0+=out_diffHead->lengthSize;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (out_diffHead->inc_newPosSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
-#endif
-    diffPos0+=out_diffHead->inc_newPosSize;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (out_diffHead->inc_oldPosSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
-#endif
-    diffPos0+=out_diffHead->inc_oldPosSize;
-    out_diffHead->coverEndPos=diffPos0;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (out_diffHead->newDataDiffSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
-#endif
-    return hpatch_TRUE;
-}
-
-static hpatch_BOOL _packedCovers_open(_TPackedCovers** out_self,
-                                      _THDiffHead* out_diffHead,
-                                      const hpatch_TStreamInput* serializedDiff,
-                                      TByte* temp_cache,TByte* temp_cache_end){
-    hpatch_size_t   cacheSize;
-    _TPackedCovers* self=0;
-    _cache_alloc(self,_TPackedCovers,sizeof(_TPackedCovers),temp_cache,temp_cache_end);
-    cacheSize=(temp_cache_end-temp_cache)/3;
-    {
-        hpatch_StreamPos_t       diffPos0;
-        if (!read_diff_head(out_diffHead,serializedDiff)) return _hpatch_FALSE;
-        diffPos0=out_diffHead->headEndPos;
-        _TStreamCacheClip_init(&self->code_lengthsClip,serializedDiff,diffPos0,
-                               diffPos0+out_diffHead->lengthSize,temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-        diffPos0+=out_diffHead->lengthSize;
-        _TStreamCacheClip_init(&self->code_inc_newPosClip,serializedDiff,diffPos0,
-                               diffPos0+out_diffHead->inc_newPosSize,temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-        diffPos0+=out_diffHead->inc_newPosSize;
-        _TStreamCacheClip_init(&self->code_inc_oldPosClip,serializedDiff,diffPos0,
-                               diffPos0+out_diffHead->inc_oldPosSize,temp_cache,cacheSize);
-    }
-    
-     _covers_init(&self->base,out_diffHead->coverCount,&self->code_inc_oldPosClip,
-                  &self->code_inc_newPosClip,&self->code_lengthsClip,hpatch_FALSE);
-    *out_self=self;
-    return hpatch_TRUE;
-}
-
-static hpatch_BOOL _patch_stream_with_cache(const hpatch_TStreamOutput* out_newData,
-                                            const hpatch_TStreamInput*  oldData,
-                                            const hpatch_TStreamInput*  serializedDiff,
-                                            hpatch_TCovers*  cached_covers,
-                                            TByte*   temp_cache,TByte* temp_cache_end){
-    struct _THDiffHead              diffHead;
-    TStreamCacheClip                code_newDataDiffClip;
-    struct _TBytesRle_load_stream   rle_loader;
-    hpatch_TCovers*                 pcovers=0;
-    hpatch_StreamPos_t       diffPos0;
-    const hpatch_StreamPos_t diffPos_end=serializedDiff->streamSize;
-    const hpatch_size_t cacheSize=(temp_cache_end-temp_cache)/(cached_covers?(_kCachePatCount-3):_kCachePatCount);
-
-    assert(out_newData!=0);
-    assert(out_newData->write!=0);
-    assert(oldData!=0);
-    assert(oldData->read!=0);
-    assert(serializedDiff!=0);
-    assert(serializedDiff->read!=0);
-    
-    //covers
-    if (cached_covers==0){
-        struct _TPackedCovers* packedCovers;
-        if (!_packedCovers_open(&packedCovers,&diffHead,serializedDiff,temp_cache+cacheSize*(_kCachePatCount-3),
-                                temp_cache_end)) return _hpatch_FALSE;
-            pcovers=&packedCovers->base.ICovers; //not need close before return
-    }else{
-        pcovers=cached_covers;
-        if (!read_diff_head(&diffHead,serializedDiff)) return _hpatch_FALSE;
-    }
-    //newDataDiff
-    diffPos0=diffHead.coverEndPos;
-    _TStreamCacheClip_init(&code_newDataDiffClip,serializedDiff,diffPos0,
-                           diffPos0+diffHead.newDataDiffSize,temp_cache,cacheSize);
-    temp_cache+=cacheSize;
-    diffPos0+=diffHead.newDataDiffSize;
-        
-    {//rle
-        hpatch_StreamPos_t rleCtrlSize;
-        hpatch_StreamPos_t rlePos0;
-        TStreamCacheClip*  rleHeadClip=&rle_loader.ctrlClip;//rename, share address
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (cacheSize<hpatch_kMaxPackedUIntBytes) return _hpatch_FALSE;
-#endif
-        _TStreamCacheClip_init(rleHeadClip,serializedDiff,diffPos0,diffPos_end,
-                               temp_cache,hpatch_kMaxPackedUIntBytes);
-        _clip_unpackUIntTo(&rleCtrlSize,rleHeadClip);
-        rlePos0=(hpatch_StreamPos_t)(_TStreamCacheClip_readPosOfSrcStream(rleHeadClip));
-#ifdef __RUN_MEM_SAFE_CHECK
-        if (rleCtrlSize>(hpatch_StreamPos_t)(diffPos_end-rlePos0)) return _hpatch_FALSE;
-#endif
-        _TBytesRle_load_stream_init(&rle_loader);
-        _TStreamCacheClip_init(&rle_loader.ctrlClip,serializedDiff,rlePos0,rlePos0+rleCtrlSize,
-                               temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-        _TStreamCacheClip_init(&rle_loader.rleCodeClip,serializedDiff,rlePos0+rleCtrlSize,diffPos_end,
-                               temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-    }
-    {
-        _TOutStreamCache outCache;
-        _TOutStreamCache_init(&outCache,out_newData,temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-        return patchByClip(&outCache,oldData,pcovers,&code_newDataDiffClip,
-                           &rle_loader,temp_cache,cacheSize);
-    }
-}
-
-
-hpatch_BOOL read_diffz_head(hpatch_compressedDiffInfo* out_diffInfo,_THDiffzHead* out_head,
-                            const hpatch_TStreamInput* compressedDiff){
-    TStreamCacheClip  _diffHeadClip;
-    TStreamCacheClip* diffHeadClip=&_diffHeadClip;
-    TByte             temp_cache[hpatch_kStreamCacheSize];
-    _TStreamCacheClip_init(&_diffHeadClip,compressedDiff,0,compressedDiff->streamSize,
-                           temp_cache,hpatch_kStreamCacheSize);
-    {//type
-        const char* kVersionType="HDIFF13";
-        char* tempType=out_diffInfo->compressType;
-        if (!_TStreamCacheClip_readType_end(diffHeadClip,'&',tempType)) return _hpatch_FALSE;
-        if (0!=strcmp(tempType,kVersionType)) return _hpatch_FALSE;
-    }
-    {//read compressType
-        if (!_TStreamCacheClip_readType_end(diffHeadClip,'\0',
-                                            out_diffInfo->compressType)) return _hpatch_FALSE;
-        out_head->typesEndPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
-    }
-    _clip_unpackUIntTo(&out_diffInfo->newDataSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->oldDataSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->coverCount,diffHeadClip);
-    out_head->compressSizeBeginPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
-    _clip_unpackUIntTo(&out_head->cover_buf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->compress_cover_buf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->rle_ctrlBuf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->compress_rle_ctrlBuf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->rle_codeBuf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->compress_rle_codeBuf_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->newDataDiff_size,diffHeadClip);
-    _clip_unpackUIntTo(&out_head->compress_newDataDiff_size,diffHeadClip);
-    out_head->headEndPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
-    
-    out_diffInfo->compressedCount=((out_head->compress_cover_buf_size)?1:0)
-                                 +((out_head->compress_rle_ctrlBuf_size)?1:0)
-                                 +((out_head->compress_rle_codeBuf_size)?1:0)
-                                 +((out_head->compress_newDataDiff_size)?1:0);
-    if (out_head->compress_cover_buf_size>0)
-        out_head->coverEndPos=out_head->headEndPos+out_head->compress_cover_buf_size;
-    else
-        out_head->coverEndPos=out_head->headEndPos+out_head->cover_buf_size;
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL getCompressedDiffInfo(hpatch_compressedDiffInfo* out_diffInfo,
-                                  const hpatch_TStreamInput* compressedDiff){
-    _THDiffzHead head;
-    assert(out_diffInfo!=0);
-    assert(compressedDiff!=0);
-    assert(compressedDiff->read!=0);
-    return read_diffz_head(out_diffInfo,&head,compressedDiff);
-}
-
-#define _clear_return(exitValue) {  result=exitValue; goto clear; }
-
-#define _kCacheDecCount 6
-
-static
-hpatch_BOOL _patch_decompress_cache(const hpatch_TStreamOutput*  out_newData,
-                                    hpatch_TStreamInput*         once_in_newData,
-                                    const hpatch_TStreamInput*   oldData,
-                                    const hpatch_TStreamInput*   compressedDiff,
-                                    hpatch_TDecompress*          decompressPlugin,
-                                    hpatch_TCovers*              cached_covers,
-                                    TByte* temp_cache, TByte* temp_cache_end){
-    TStreamCacheClip              coverClip;
-    TStreamCacheClip              code_newDataDiffClip;
-    struct _TBytesRle_load_stream   rle_loader;
-    _THDiffzHead                head;
-    hpatch_compressedDiffInfo   diffInfo;
-    _TDecompressInputStream     decompressers[4];
-    hpatch_size_t               i;
-    hpatch_StreamPos_t          coverCount;
-    hpatch_BOOL  result=hpatch_TRUE;
-    hpatch_StreamPos_t        diffPos0=0;
-    const hpatch_StreamPos_t  diffPos_end=compressedDiff->streamSize;
-    const hpatch_size_t cacheSize=(temp_cache_end-temp_cache)/(cached_covers?(_kCacheDecCount-1):_kCacheDecCount);
-    if (cacheSize<=hpatch_kMaxPluginTypeLength) return _hpatch_FALSE;
-    assert(out_newData!=0);
-    assert(out_newData->write!=0);
-    assert(oldData!=0);
-    assert(oldData->read!=0);
-    assert(compressedDiff!=0);
-    assert(compressedDiff->read!=0);
-    {//head
-        if (!read_diffz_head(&diffInfo,&head,compressedDiff)) return _hpatch_FALSE;
-        if ((diffInfo.oldDataSize!=oldData->streamSize)
-            ||(diffInfo.newDataSize!=out_newData->streamSize)) return _hpatch_FALSE;
-            
-        if ((decompressPlugin==0)&&(diffInfo.compressedCount!=0)) return _hpatch_FALSE;
-        if ((decompressPlugin)&&(diffInfo.compressedCount>0))
-            if (!decompressPlugin->is_can_open(diffInfo.compressType)) return _hpatch_FALSE;
-        diffPos0=head.headEndPos;
-    }
-    
-    for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i)
-        decompressers[i].decompressHandle=0;
-    _TBytesRle_load_stream_init(&rle_loader);
-    
-    if (cached_covers){
-        diffPos0=head.coverEndPos;
-    }else{
-        if (!getStreamClip(&coverClip,&decompressers[0],
-                           head.cover_buf_size,head.compress_cover_buf_size,compressedDiff,&diffPos0,
-                           decompressPlugin,temp_cache+cacheSize*(_kCacheDecCount-1),cacheSize)) _clear_return(_hpatch_FALSE);
-    }
-    if (!getStreamClip(&rle_loader.ctrlClip,&decompressers[1],
-                       head.rle_ctrlBuf_size,head.compress_rle_ctrlBuf_size,compressedDiff,&diffPos0,
-                       decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
-    temp_cache+=cacheSize;
-    if (!getStreamClip(&rle_loader.rleCodeClip,&decompressers[2],
-                       head.rle_codeBuf_size,head.compress_rle_codeBuf_size,compressedDiff,&diffPos0,
-                       decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
-    temp_cache+=cacheSize;
-    if (!getStreamClip(&code_newDataDiffClip,&decompressers[3],
-                       head.newDataDiff_size,head.compress_newDataDiff_size,compressedDiff,&diffPos0,
-                       decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
-    temp_cache+=cacheSize;
-#ifdef __RUN_MEM_SAFE_CHECK
-    if (diffPos0!=diffPos_end) _clear_return(_hpatch_FALSE);
-#endif
-    
-    coverCount=head.coverCount;
-    {
-        _TCovers         covers;
-        hpatch_TCovers*  pcovers=0;
-        _TOutStreamCache outCache;
-        _TOutStreamCache_init(&outCache,out_newData,temp_cache,cacheSize);
-        temp_cache+=cacheSize;
-        if (cached_covers){
-            pcovers=cached_covers;
-        }else{
-            _covers_init(&covers,coverCount,&coverClip,&coverClip,&coverClip,hpatch_TRUE);
-            pcovers=&covers.ICovers;  //not need close before return
-        }
-        result=patchByClip(&outCache,oldData,pcovers,&code_newDataDiffClip,&rle_loader,
-                           temp_cache,cacheSize);
-        //if ((pcovers!=cached_covers)&&(!pcovers->close(pcovers))) result=_hpatch_FALSE;
-    }
-clear:
-    for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i) {
-        if (decompressers[i].decompressHandle){
-            if (!decompressPlugin->close(decompressPlugin,decompressers[i].decompressHandle))
-                result=_hpatch_FALSE;
-            decompressers[i].decompressHandle=0;
-        }
-    }
-    return result;
-}
-
-
-hpatch_inline static hpatch_BOOL _cache_load_all(const hpatch_TStreamInput* data,
-                                                 TByte* cache,TByte* cache_end){
-    assert((hpatch_size_t)(cache_end-cache)==data->streamSize);
-    return data->read(data,0,cache,cache_end);
-}
-
-typedef struct _TCompressedCovers{
-    _TCovers                base;
-    TStreamCacheClip        coverClip;
-    _TDecompressInputStream decompresser;
-} _TCompressedCovers;
-
-static hpatch_BOOL _compressedCovers_close(hpatch_TCovers* covers){
-    hpatch_BOOL result=hpatch_TRUE;
-    _TCompressedCovers* self=(_TCompressedCovers*)covers;
-    if (self){
-        if (self->decompresser.decompressHandle){
-            result=self->decompresser.decompressPlugin->close(self->decompresser.decompressPlugin,
-                                                              self->decompresser.decompressHandle);
-            self->decompresser.decompressHandle=0;
-        }
-    }
-    return result;
-}
-
-static hpatch_BOOL _compressedCovers_open(_TCompressedCovers** out_self,
-                                          hpatch_compressedDiffInfo* out_diffInfo,
-                                          const hpatch_TStreamInput* compressedDiff,
-                                          hpatch_TDecompress* decompressPlugin,
-                                          TByte* temp_cache,TByte* temp_cache_end){
-    _THDiffzHead    head;
-    hpatch_StreamPos_t  diffPos0=0;
-    _TCompressedCovers* self=0;
-    _cache_alloc(self,_TCompressedCovers,sizeof(_TCompressedCovers),temp_cache,temp_cache_end);
-    if (!read_diffz_head(out_diffInfo,&head,compressedDiff)) return _hpatch_FALSE;
-    diffPos0=head.headEndPos;
-    if (head.compress_cover_buf_size>0){
-        if (decompressPlugin==0) return _hpatch_FALSE;
-        if (!decompressPlugin->is_can_open(out_diffInfo->compressType)) return _hpatch_FALSE;
-    }
-    
-    _covers_init(&self->base,head.coverCount,&self->coverClip,
-                 &self->coverClip,&self->coverClip,hpatch_TRUE);
-    self->base.ICovers.close=_compressedCovers_close;
-    memset(&self->decompresser,0, sizeof(self->decompresser));
-    if (!getStreamClip(&self->coverClip,&self->decompresser,
-                       head.cover_buf_size,head.compress_cover_buf_size,
-                       compressedDiff,&diffPos0,decompressPlugin,
-                       temp_cache,temp_cache_end-temp_cache)) {
-        return _hpatch_FALSE;
-    };
-    *out_self=self;
-    return hpatch_TRUE;
-}
-
-#if (_IS_NEED_CACHE_OLD_BY_COVERS)
-
-typedef struct _TArrayCovers{
-    hpatch_TCovers  ICovers;
-    void*           pCCovers;
-    hpatch_size_t   coverCount;
-    hpatch_size_t   cur_index;
-    hpatch_BOOL     is32;
-} _TArrayCovers;
-
-
-typedef struct hpatch_TCCover32{
-    hpatch_uint32_t oldPos;
-    hpatch_uint32_t newPos;
-    hpatch_uint32_t length;
-    hpatch_uint32_t cachePos; //todo:放到临时内存中,用完释放?逻辑会比较复杂;
-} hpatch_TCCover32;
-
-typedef struct hpatch_TCCover64{
-    hpatch_StreamPos_t oldPos;
-    hpatch_StreamPos_t newPos;
-    hpatch_StreamPos_t length;
-    hpatch_StreamPos_t cachePos;
-} hpatch_TCCover64;
-
-#define _arrayCovers_get(self,i,item) (((self)->is32)? \
-    ((const hpatch_uint32_t*)(self)->pCCovers)[(i)*4+(item)]:\
-    ((const hpatch_StreamPos_t*)(self)->pCCovers)[(i)*4+(item)])
-#define _arrayCovers_get_oldPos(self,i)   _arrayCovers_get(self,i,0)
-#define _arrayCovers_get_len(self,i)      _arrayCovers_get(self,i,2)
-#define _arrayCovers_get_cachePos(self,i) _arrayCovers_get(self,i,3)
-
-#define _arrayCovers_set(self,i,item,v) { if ((self)->is32){ \
-    ((hpatch_uint32_t*)(self)->pCCovers)[(i)*4+(item)]=(hpatch_uint32_t)(v); }else{ \
-    ((hpatch_StreamPos_t*)(self)->pCCovers)[(i)*4+(item)]=(v); } }
-#define _arrayCovers_set_cachePos(self,i,v) _arrayCovers_set(self,i,3,v)
-
-hpatch_inline static hpatch_StreamPos_t arrayCovers_memSize(hpatch_StreamPos_t coverCount,hpatch_BOOL is32){
-    return coverCount*(is32?sizeof(hpatch_TCCover32):sizeof(hpatch_TCCover64));
-}
-
-static hpatch_BOOL _arrayCovers_is_finish(const hpatch_TCovers* covers){
-    const _TArrayCovers* self=(const _TArrayCovers*)covers;
-    return (self->coverCount==self->cur_index);
-}
-static hpatch_StreamPos_t _arrayCovers_leaveCoverCount(const hpatch_TCovers* covers){
-    const _TArrayCovers* self=(const _TArrayCovers*)covers;
-    return self->coverCount-self->cur_index;
-}
-static hpatch_BOOL _arrayCovers_read_cover(struct hpatch_TCovers* covers,hpatch_TCover* out_cover){
-    _TArrayCovers* self=(_TArrayCovers*)covers;
-    hpatch_size_t i=self->cur_index;
-    if (i<self->coverCount){
-        if (self->is32){
-            const hpatch_TCCover32* pCover=((const hpatch_TCCover32*)self->pCCovers)+i;
-            out_cover->oldPos=pCover->oldPos;
-            out_cover->newPos=pCover->newPos;
-            out_cover->length=pCover->length;
-        }else{
-            const hpatch_TCCover64* pCover=((const hpatch_TCCover64*)self->pCCovers)+i;
-            out_cover->oldPos=pCover->oldPos;
-            out_cover->newPos=pCover->newPos;
-            out_cover->length=pCover->length;
-        }
-        self->cur_index=i+1;
-        return hpatch_TRUE;
-    }else{
-        return _hpatch_FALSE;
-    }
-}
-
-static hpatch_BOOL _arrayCovers_load(_TArrayCovers** out_self,hpatch_TCovers* src_covers,
-                                     hpatch_BOOL isUsedCover32,hpatch_BOOL* out_isReadError,
-                                     TByte** ptemp_cache,TByte* temp_cache_end){
-    TByte* temp_cache=*ptemp_cache;
-    hpatch_StreamPos_t _coverCount=src_covers->leave_cover_count(src_covers);
-    hpatch_StreamPos_t memSize=arrayCovers_memSize(_coverCount,isUsedCover32);
-    hpatch_size_t i;
-    void*  pCovers;
-    _TArrayCovers* self=0;
-    hpatch_size_t coverCount=(hpatch_size_t)_coverCount;
-    
-    *out_isReadError=hpatch_FALSE;
-    if (coverCount!=_coverCount) return hpatch_FALSE;
-    
-    _cache_alloc(self,_TArrayCovers,sizeof(_TArrayCovers),temp_cache,temp_cache_end);
-    _cache_alloc(pCovers,void,memSize,temp_cache,temp_cache_end);
-    if (isUsedCover32){
-        hpatch_TCCover32* pdst=(hpatch_TCCover32*)pCovers;
-        for (i=0;i<coverCount;++i,++pdst) {
-            hpatch_TCover cover;
-            if (!src_covers->read_cover(src_covers,&cover))
-                { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
-            pdst->oldPos=(hpatch_uint32_t)cover.oldPos;
-            pdst->newPos=(hpatch_uint32_t)cover.newPos;
-            pdst->length=(hpatch_uint32_t)cover.length;
-        }
-    }else{
-        hpatch_TCCover64* pdst=(hpatch_TCCover64*)pCovers;
-        for (i=0;i<coverCount;++i,++pdst) {
-            if (!src_covers->read_cover(src_covers,(hpatch_TCover*)pdst))
-                { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
-        }
-    }
-    if (!src_covers->is_finish(src_covers))
-        { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
-
-    self->pCCovers=pCovers;
-    self->is32=isUsedCover32;
-    self->coverCount=coverCount;
-    self->cur_index=0;
-    self->ICovers.close=_covers_close_nil;
-    self->ICovers.is_finish=_arrayCovers_is_finish;
-    self->ICovers.leave_cover_count=_arrayCovers_leaveCoverCount;
-    self->ICovers.read_cover=_arrayCovers_read_cover;
-    *out_self=self;
-    *ptemp_cache=temp_cache;
-    return hpatch_TRUE;
-}
-
-#define _arrayCovers_comp(_uint_t,_x,_y,item){ \
-    _uint_t x=((const _uint_t*)_x)[item]; \
-    _uint_t y=((const _uint_t*)_y)[item]; \
-    return (x<y)?(-1):((x>y)?1:0); \
-}
-#ifdef _MSC_VER
-#   define __CALL_BACK_C    __cdecl
-#else
-#   define __CALL_BACK_C
-#endif
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_old_32(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_uint32_t,_x,_y,0);
-}
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_old(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,0);
-}
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_new_32(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_uint32_t,_x,_y,1);
-}
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_new(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,1);
-}
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_len_32(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_uint32_t,_x,_y,2);
-}
-static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_len(const void* _x, const void *_y){
-    _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,2);
-}
-
-static void _arrayCovers_sort_by_old(_TArrayCovers* self){
-    if (self->is32)
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_old_32);
-    else
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_old);
-}
-static void _arrayCovers_sort_by_new(_TArrayCovers* self){
-    if (self->is32)
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_new_32);
-    else
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_new);
-}
-static void _arrayCovers_sort_by_len(_TArrayCovers* self){
-    if (self->is32)
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_len_32);
-    else
-        qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_len);
-}
-
-static hpatch_size_t _getMaxCachedLen(const _TArrayCovers* src_covers,
-                                      TByte* temp_cache,TByte* temp_cache_end,TByte* cache_buf_end){
-    const hpatch_size_t kMaxCachedLen  =~((hpatch_size_t)0);//允许缓存的最长单个数据长度;
-    hpatch_StreamPos_t mlen=0;
-    hpatch_StreamPos_t sum=0;
-    const hpatch_size_t coverCount=src_covers->coverCount;
-    hpatch_size_t i;
-    _TArrayCovers cur_covers=*src_covers;
-    hpatch_size_t cacheSize=temp_cache_end-temp_cache;
-    hpatch_StreamPos_t memSize=arrayCovers_memSize(src_covers->coverCount,src_covers->is32);
-    _cache_alloc(cur_covers.pCCovers,void,memSize,temp_cache,temp_cache_end); //fail return 0
-    memcpy(cur_covers.pCCovers,src_covers->pCCovers,(hpatch_size_t)memSize);
-    _arrayCovers_sort_by_len(&cur_covers);
-    
-    for (i=0; i<coverCount;++i) {
-        mlen=_arrayCovers_get_len(&cur_covers,i);
-        sum+=mlen;
-        if (sum<=cacheSize){
-            continue;
-        }else{
-            --mlen;
-            break;
-        }
-    }
-    if (mlen>kMaxCachedLen)
-        mlen=kMaxCachedLen;
-    return (hpatch_size_t)mlen;
-}
-
-static hpatch_size_t _set_cache_pos(_TArrayCovers* covers,hpatch_size_t maxCachedLen,
-                                    hpatch_StreamPos_t* poldPosBegin,hpatch_StreamPos_t* poldPosEnd){
-    const hpatch_size_t coverCount=covers->coverCount;
-    const hpatch_size_t kMinCacheCoverCount=coverCount/8+1; //控制最小缓存数量,否则缓存的意义太小;
-    hpatch_StreamPos_t oldPosBegin=hpatch_kNullStreamPos;
-    hpatch_StreamPos_t oldPosEnd=0;
-    hpatch_size_t cacheCoverCount=0;
-    hpatch_size_t sum=0;//result
-    hpatch_size_t i;
-    for (i=0; i<coverCount;++i) {
-        hpatch_StreamPos_t clen=_arrayCovers_get_len(covers,i);
-        if (clen<=maxCachedLen){
-            hpatch_StreamPos_t oldPos;
-            _arrayCovers_set_cachePos(covers,i,sum);
-            sum+=(hpatch_size_t)clen;
-            ++cacheCoverCount;
-            
-            oldPos=_arrayCovers_get_oldPos(covers,i);
-            if (oldPos<oldPosBegin) oldPosBegin=oldPos;
-            if (oldPos+clen>oldPosEnd) oldPosEnd=oldPos+clen;
-        }
-    }
-    if (cacheCoverCount<kMinCacheCoverCount)
-        return 0;//fail
-    *poldPosBegin=oldPosBegin;
-    *poldPosEnd=oldPosEnd;
-    return sum;
-}
-
-//一个比较简单的缓存策略:
-//  1. 根据缓冲区大小限制,选择出最短的一批覆盖线来缓存;
-//  2. 顺序访问一次oldData文件,填充这些缓存;
-//  3. 顺序访问时跳过中间过大的对缓存无用的区域;
-
-static hpatch_BOOL _cache_old_load(const hpatch_TStreamInput*oldData,
-                                   hpatch_StreamPos_t oldPos,hpatch_StreamPos_t oldPosAllEnd,
-                                   _TArrayCovers* arrayCovers,hpatch_size_t maxCachedLen,hpatch_size_t sumCacheLen,
-                                   TByte* old_cache,TByte* old_cache_end,TByte* cache_buf_end){
-    const hpatch_size_t kMinSpaceLen   =(1<<(20+2));//跳过seekTime*speed长度的空间(SSD可以更小)时间上划得来,否则就顺序访问;
-    const hpatch_size_t kAccessPageSize=(1<<(10+2));//页面对齐访问;
-    hpatch_BOOL result=hpatch_TRUE;
-    hpatch_size_t cur_i=0,i;
-    const hpatch_size_t coverCount=arrayCovers->coverCount;
-    TByte* cache_buf=old_cache_end;
-    assert((hpatch_size_t)(old_cache_end-old_cache)>=sumCacheLen);
-    
-    if ((hpatch_size_t)(cache_buf_end-cache_buf)>=kAccessPageSize*2){
-        cache_buf=(TByte*)_hpatch_align_upper(cache_buf,kAccessPageSize);
-        if ((hpatch_size_t)(cache_buf_end-cache_buf)>=(kMinSpaceLen>>1))
-            cache_buf_end=cache_buf+(kMinSpaceLen>>1);
-        else
-            cache_buf_end=(TByte*)_hpatch_align_lower(cache_buf_end,kAccessPageSize);
-    }
-    oldPos=_hpatch_align_type_lower(hpatch_StreamPos_t,oldPos,kAccessPageSize);
-    if (oldPos<kMinSpaceLen) oldPos=0;
-    
-    _arrayCovers_sort_by_old(arrayCovers);
-    while ((oldPos<oldPosAllEnd)&(cur_i<coverCount)) {
-        hpatch_StreamPos_t oldPosEnd;
-        hpatch_size_t readLen=(cache_buf_end-cache_buf);
-        if (readLen>(oldPosAllEnd-oldPos)) readLen=(hpatch_size_t)(oldPosAllEnd-oldPos);
-        if (!oldData->read(oldData,oldPos,cache_buf,
-                           cache_buf+readLen)) { result=_hpatch_FALSE; break; } //error
-        oldPosEnd=oldPos+readLen;
-        for (i=cur_i;i<coverCount;++i){
-            hpatch_StreamPos_t ioldPos,ioldPosEnd;
-            hpatch_StreamPos_t ilen=_arrayCovers_get_len(arrayCovers,i);
-            if (ilen>maxCachedLen){//覆盖线比较长不需要缓存,下一个覆盖线;
-                if (i==cur_i)
-                    ++cur_i;
-                continue;
-            }
-            ioldPos=_arrayCovers_get_oldPos(arrayCovers,i);
-            ioldPosEnd=ioldPos+ilen;
-            if (ioldPosEnd>oldPos){
-                //        [oldPos                  oldPosEnd]
-                //                           ioldPosEnd]----or----]
-                if (ioldPos<oldPosEnd){//有交集,需要cache
-                //  [----or----[ioldPos      ioldPosEnd]----or----]
-                    hpatch_StreamPos_t from;
-                    hpatch_size_t      copyLen;
-                    hpatch_StreamPos_t dstPos=_arrayCovers_get_cachePos(arrayCovers,i);
-                    //assert(dstPos<=(hpatch_size_t)(old_cache_end-old_cache));
-                    if (ioldPos>=oldPos){
-                //             [ioldPos      ioldPosEnd]----or----]
-                        from=ioldPos;
-                    }else{
-                //  [ioldPos                 ioldPosEnd]----or----]
-                        from=oldPos;
-                        dstPos+=(oldPos-ioldPos);
-                    }
-                    copyLen=(hpatch_size_t)(((ioldPosEnd<=oldPosEnd)?ioldPosEnd:oldPosEnd)-from);
-                    //assert(dstPos+copyLen<=(hpatch_size_t)(old_cache_end-old_cache));
-                    //assert(sumCacheLen>=copyLen);
-                    memcpy(old_cache+(hpatch_size_t)dstPos,cache_buf+(from-oldPos),copyLen);
-                    sumCacheLen-=copyLen;
-                    if ((i==cur_i)&(oldPosEnd>=ioldPosEnd))
-                        ++cur_i;
-                }else{//后面覆盖线暂时都不会与当前数据有交集了,下一块数据;
-                //  [oldPos     oldPosEnd]
-                //                        [ioldPos      ioldPosEnd]
-                    if ((i==cur_i)&&(ioldPos-oldPosEnd>=kMinSpaceLen))
-                        oldPosEnd=_hpatch_align_type_lower(hpatch_StreamPos_t,ioldPos,kAccessPageSize);
-                    break;
-                }
-            }else{//当前覆盖线已经落后于当前数据,下一个覆盖线;
-                //                        [oldPos     oldPosEnd]
-                // [ioldPos    ioldPosEnd]
-                if (i==cur_i)
-                    ++cur_i;
-            }
-        }
-        oldPos=oldPosEnd;
-    }
-    _arrayCovers_sort_by_new(arrayCovers);
-    assert(sumCacheLen==0);
-    return result;
-}
-
-typedef struct _cache_old_TStreamInput{
-    _TArrayCovers       arrayCovers;
-    hpatch_BOOL         isInHitCache;
-    hpatch_size_t       maxCachedLen;
-    hpatch_StreamPos_t  readFromPos;
-    hpatch_StreamPos_t  readFromPosEnd;
-    const TByte*        caches;
-    const TByte*        cachesEnd;
-    const hpatch_TStreamInput* oldData;
-} _cache_old_TStreamInput;
-
-static hpatch_BOOL _cache_old_StreamInput_read(const hpatch_TStreamInput* stream,
-                                               hpatch_StreamPos_t readFromPos,
-                                               unsigned char* out_data,unsigned char* out_data_end){
-    _cache_old_TStreamInput* self=(_cache_old_TStreamInput*)stream->streamImport;
-    hpatch_StreamPos_t dataLen=(hpatch_size_t)(self->readFromPosEnd-self->readFromPos);
-    hpatch_size_t readLen;
-    if (dataLen==0){//next cover
-        hpatch_StreamPos_t oldPos;
-        hpatch_size_t i=self->arrayCovers.cur_index++;
-        if (i>=self->arrayCovers.coverCount) return _hpatch_FALSE;//error;
-        oldPos=_arrayCovers_get_oldPos(&self->arrayCovers,i);
-        dataLen=_arrayCovers_get_len(&self->arrayCovers,i);
-        self->isInHitCache=(dataLen<=self->maxCachedLen);
-        self->readFromPos=oldPos;
-        self->readFromPosEnd=oldPos+dataLen;
-    }
-    readLen=out_data_end-out_data;
-    if ((readLen>dataLen)||(self->readFromPos!=readFromPos)) return _hpatch_FALSE; //error
-    self->readFromPos=readFromPos+readLen;
-    if (self->isInHitCache){
-        assert(readLen<=(hpatch_size_t)(self->cachesEnd-self->caches));
-        memcpy(out_data,self->caches,readLen);
-        self->caches+=readLen;
-        return hpatch_TRUE;
-    }else{
-        return self->oldData->read(self->oldData,readFromPos,out_data,out_data_end);
-    }
-}
-
-static hpatch_BOOL _cache_old(hpatch_TStreamInput** out_cachedOld,const hpatch_TStreamInput* oldData,
-                              _TArrayCovers* arrayCovers,hpatch_BOOL* out_isReadError,
-                              TByte* temp_cache,TByte** ptemp_cache_end,TByte* cache_buf_end){
-    _cache_old_TStreamInput* self;
-    TByte* temp_cache_end=*ptemp_cache_end;
-    hpatch_StreamPos_t oldPosBegin;
-    hpatch_StreamPos_t oldPosEnd;
-    hpatch_size_t      sumCacheLen;
-    hpatch_size_t      maxCachedLen;
-    *out_isReadError=hpatch_FALSE;
-    _cache_alloc(*out_cachedOld,hpatch_TStreamInput,sizeof(hpatch_TStreamInput),
-                 temp_cache,temp_cache_end);
-    _cache_alloc(self,_cache_old_TStreamInput,sizeof(_cache_old_TStreamInput),
-                 temp_cache,temp_cache_end);
-    
-    maxCachedLen=_getMaxCachedLen(arrayCovers,temp_cache,temp_cache_end,cache_buf_end);
-    if (maxCachedLen==0) return hpatch_FALSE;
-    sumCacheLen=_set_cache_pos(arrayCovers,maxCachedLen,&oldPosBegin,&oldPosEnd);
-    if (sumCacheLen==0) return hpatch_FALSE;
-    temp_cache_end=temp_cache+sumCacheLen;
-    
-    if (!_cache_old_load(oldData,oldPosBegin,oldPosEnd,arrayCovers,maxCachedLen,sumCacheLen,
-                         temp_cache,temp_cache_end,cache_buf_end))
-        { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
-    
-    {//out
-        self->arrayCovers=*arrayCovers;
-        self->arrayCovers.cur_index=0;
-        self->isInHitCache=hpatch_FALSE;
-        self->maxCachedLen=maxCachedLen;
-        self->caches=temp_cache;
-        self->cachesEnd=temp_cache_end;
-        self->readFromPos=0;
-        self->readFromPosEnd=0;
-        self->oldData=oldData;
-        (*out_cachedOld)->streamImport=self;
-        (*out_cachedOld)->streamSize=oldData->streamSize;
-        (*out_cachedOld)->read=_cache_old_StreamInput_read;
-        *ptemp_cache_end=temp_cache_end;
-    }
-    return hpatch_TRUE;
-}
-
-#endif //_IS_NEED_CACHE_OLD_BY_COVERS
-
-
-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
-}
-
-hpatch_BOOL patch_stream_with_cache(const struct hpatch_TStreamOutput* out_newData,
-                                    const struct hpatch_TStreamInput*  oldData,
-                                    const struct hpatch_TStreamInput*  serializedDiff,
-                                    TByte*   temp_cache,TByte* temp_cache_end){
-    hpatch_BOOL     result;
-    hpatch_TCovers* covers=0;//not need close before return
-    hpatch_BOOL    isReadError=hpatch_FALSE;
-    _patch_cache(&covers,&oldData,out_newData->streamSize,serializedDiff,hpatch_FALSE,0,
-                _kCachePatCount,&temp_cache,&temp_cache_end,&isReadError);
-    if (isReadError) return _hpatch_FALSE;
-    result=_patch_stream_with_cache(out_newData,oldData,serializedDiff,covers,
-                                    temp_cache,temp_cache_end);
-    //if ((covers!=0)&&(!covers->close(covers))) result=_hpatch_FALSE;
-    return result;
-}
-
-hpatch_BOOL patch_stream(const hpatch_TStreamOutput* out_newData,
-                         const hpatch_TStreamInput*  oldData,
-                         const hpatch_TStreamInput*  serializedDiff){
-    TByte temp_cache[hpatch_kStreamCacheSize*_kCachePatCount];
-    return _patch_stream_with_cache(out_newData,oldData,serializedDiff,0,
-                                    temp_cache,temp_cache+sizeof(temp_cache)/sizeof(TByte));
-}
-
-hpatch_BOOL patch_decompress_with_cache(const hpatch_TStreamOutput* out_newData,
-                                        const hpatch_TStreamInput*  oldData,
-                                        const hpatch_TStreamInput*  compressedDiff,
-                                        hpatch_TDecompress* decompressPlugin,
-                                        TByte* temp_cache,TByte* temp_cache_end){
-    hpatch_BOOL     result;
-    hpatch_TCovers* covers=0; //need close before return
-    hpatch_BOOL    isReadError=hpatch_FALSE;
-    _patch_cache(&covers,&oldData,out_newData->streamSize,compressedDiff,hpatch_TRUE,
-                 decompressPlugin,_kCacheDecCount,&temp_cache,&temp_cache_end,&isReadError);
-    if (isReadError) return _hpatch_FALSE;
-    result=_patch_decompress_cache(out_newData,0,oldData,compressedDiff,decompressPlugin,
-                                   covers,temp_cache,temp_cache_end);
-    if ((covers!=0)&&(!covers->close(covers))) result=_hpatch_FALSE;
-    return result;
-}
-
-hpatch_BOOL patch_decompress(const hpatch_TStreamOutput* out_newData,
-                             const hpatch_TStreamInput*  oldData,
-                             const hpatch_TStreamInput*  compressedDiff,
-                             hpatch_TDecompress* decompressPlugin){
-    TByte temp_cache[hpatch_kStreamCacheSize*_kCacheDecCount];
-    return _patch_decompress_cache(out_newData,0,oldData,compressedDiff,decompressPlugin,
-                                   0,temp_cache,temp_cache+sizeof(temp_cache)/sizeof(TByte));
-}
-
-hpatch_BOOL hpatch_coverList_open_serializedDiff(hpatch_TCoverList* out_coverList,
-                                                 const hpatch_TStreamInput*  serializedDiff){
-    TByte* temp_cache;
-    TByte* temp_cache_end;
-    _TPackedCovers* packedCovers=0;
-    _THDiffHead     diffHead;
-    assert((out_coverList!=0)&&(out_coverList->ICovers==0));
-    temp_cache=out_coverList->_buf;
-    temp_cache_end=temp_cache+sizeof(out_coverList->_buf);
-    if (!_packedCovers_open(&packedCovers,&diffHead,serializedDiff,
-                            temp_cache,temp_cache_end))
-        return _hpatch_FALSE;
-    out_coverList->ICovers=&packedCovers->base.ICovers;
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL hpatch_coverList_open_compressedDiff(hpatch_TCoverList* out_coverList,
-                                                 const hpatch_TStreamInput*  compressedDiff,
-                                                 hpatch_TDecompress*         decompressPlugin){
-    TByte* temp_cache;
-    TByte* temp_cache_end;
-    _TCompressedCovers* compressedCovers=0;
-    hpatch_compressedDiffInfo diffInfo;
-    assert((out_coverList!=0)&&(out_coverList->ICovers==0));
-    temp_cache=out_coverList->_buf;
-    temp_cache_end=temp_cache+sizeof(out_coverList->_buf);
-    if (!_compressedCovers_open(&compressedCovers,&diffInfo,compressedDiff,decompressPlugin,
-                                temp_cache,temp_cache_end))
-        return _hpatch_FALSE;
-    out_coverList->ICovers=&compressedCovers->base.ICovers;
-    return hpatch_TRUE;
-}
-
-//
-
-#define     _kCacheSgCount  3
-
-hpatch_BOOL patch_single_compressed_diff(const hpatch_TStreamOutput* out_newData,
-                                         const hpatch_TStreamInput*  oldData,
-                                         const hpatch_TStreamInput*  singleCompressedDiff,
-                                         hpatch_StreamPos_t          diffData_pos,
-                                         hpatch_StreamPos_t          uncompressedSize,
-                                         hpatch_StreamPos_t          compressedSize,
-                                         hpatch_TDecompress*         decompressPlugin,
-                                         hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
-                                         unsigned char* temp_cache,unsigned char* temp_cache_end,
-                                         sspatch_coversListener_t* coversListener){
-    hpatch_BOOL result;
-    hpatch_TUncompresser_t uncompressedStream;
-    hpatch_StreamPos_t diffData_posEnd;
-    memset(&uncompressedStream,0,sizeof(uncompressedStream));
-    if (compressedSize==0){
-        decompressPlugin=0;
-    }else{
-        if (decompressPlugin==0) return _hpatch_FALSE;
-    }
-    diffData_posEnd=(decompressPlugin?compressedSize:uncompressedSize)+diffData_pos;
-    if (diffData_posEnd>singleCompressedDiff->streamSize) return _hpatch_FALSE;
-    if (decompressPlugin){
-        if (!compressed_stream_as_uncompressed(&uncompressedStream,uncompressedSize,decompressPlugin,singleCompressedDiff,
-                                               diffData_pos,diffData_posEnd)) return _hpatch_FALSE;
-        singleCompressedDiff=&uncompressedStream.base;
-        diffData_pos=0;
-        diffData_posEnd=singleCompressedDiff->streamSize;
-    }
-    result=patch_single_stream_diff(out_newData,oldData,singleCompressedDiff,diffData_pos,diffData_posEnd,
-                                    coverCount,stepMemSize,temp_cache,temp_cache_end,coversListener);
-    if (decompressPlugin)
-        close_compressed_stream_as_uncompressed(&uncompressedStream);
-    return result;
-}
-
-static const size_t _kStepMemSizeSafeLimit =(1<<20)*16;
-hpatch_BOOL getSingleCompressedDiffInfo(hpatch_singleCompressedDiffInfo* out_diffInfo,
-                                        const hpatch_TStreamInput* singleCompressedDiff,
-                                        hpatch_StreamPos_t         diffInfo_pos){
-    TStreamCacheClip  _diffHeadClip;
-    TStreamCacheClip* diffHeadClip=&_diffHeadClip;
-    TByte             temp_cache[hpatch_kStreamCacheSize];
-    _TStreamCacheClip_init(&_diffHeadClip,singleCompressedDiff,diffInfo_pos,singleCompressedDiff->streamSize,
-                           temp_cache,hpatch_kStreamCacheSize);
-    {//type
-        const char* kVersionType="HDIFFSF20";
-        char* tempType=out_diffInfo->compressType;
-        if (!_TStreamCacheClip_readType_end(diffHeadClip,'&',tempType)) return _hpatch_FALSE;
-        if (0!=strcmp(tempType,kVersionType)) return _hpatch_FALSE;
-    }
-    {//read compressType
-        if (!_TStreamCacheClip_readType_end(diffHeadClip,'\0',
-                                            out_diffInfo->compressType)) return _hpatch_FALSE;
-    }
-    _clip_unpackUIntTo(&out_diffInfo->newDataSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->oldDataSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->coverCount,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->stepMemSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->uncompressedSize,diffHeadClip);
-    _clip_unpackUIntTo(&out_diffInfo->compressedSize,diffHeadClip);
-    out_diffInfo->diffDataPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip)-diffInfo_pos;
-    if (out_diffInfo->compressedSize>out_diffInfo->uncompressedSize)
-        return _hpatch_FALSE;
-    if (out_diffInfo->stepMemSize>(out_diffInfo->newDataSize>=_kStepMemSizeSafeLimit?out_diffInfo->newDataSize:_kStepMemSizeSafeLimit))
-        return _hpatch_FALSE;
-    if (out_diffInfo->stepMemSize>out_diffInfo->uncompressedSize)
-        return _hpatch_FALSE;
-    return hpatch_TRUE;
-}
-
-static hpatch_BOOL _TUncompresser_read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
-                                       unsigned char* out_data,unsigned char* out_data_end){
-    hpatch_TUncompresser_t* self=(hpatch_TUncompresser_t*)stream->streamImport;
-    return self->_decompressPlugin->decompress_part(self->_decompressHandle,out_data,out_data_end);
-}
-
-hpatch_BOOL compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream,hpatch_StreamPos_t uncompressedSize,
-                                              hpatch_TDecompress* decompressPlugin,const hpatch_TStreamInput* compressedStream,
-                                              hpatch_StreamPos_t compressed_pos,hpatch_StreamPos_t compressed_end){
-    hpatch_TUncompresser_t* self=uncompressedStream;
-    assert(decompressPlugin!=0);
-    assert(self->_decompressHandle==0);
-    self->_decompressHandle=decompressPlugin->open(decompressPlugin,uncompressedSize,compressedStream,
-                                                   compressed_pos,compressed_end);
-    if (self->_decompressHandle==0) return _hpatch_FALSE;
-    self->_decompressPlugin=decompressPlugin;
-    
-    self->base.streamImport=self;
-    self->base.streamSize=uncompressedSize;
-    self->base.read=_TUncompresser_read;
-    return hpatch_TRUE;
-}
-
-void close_compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream){
-    hpatch_TUncompresser_t* self=uncompressedStream;
-    if (self==0) return;
-    if (self->_decompressHandle==0) return;
-    self->_decompressPlugin->close(self->_decompressPlugin,self->_decompressHandle);
-    self->_decompressHandle=0;
-}
-
-typedef struct{
-    const unsigned char* code;
-    const unsigned char* code_end;
-    hpatch_size_t   len0;
-    hpatch_size_t   lenv;
-    hpatch_BOOL     isNeedDecode0;
-} rle0_decoder_t;
-
-static void _rle0_decoder_init(rle0_decoder_t* self,const unsigned char* code,const unsigned char* code_end){
-    self->code=code;
-    self->code_end=code_end;
-    self->len0=0;
-    self->lenv=0;
-    self->isNeedDecode0=hpatch_TRUE;
-}
-
-static hpatch_BOOL _rle0_decoder_add(rle0_decoder_t* self,TByte* out_data,hpatch_size_t decodeSize){
-    if (self->len0){
-    _0_process:
-        if (self->len0>=decodeSize){
-            self->len0-=decodeSize;
-            return hpatch_TRUE;
-        }else{
-            decodeSize-=self->len0;
-            out_data+=self->len0;
-            self->len0=0;
-            goto _decode_v_process;
-        }
-    }
-    
-    if (self->lenv){
-    _v_process:
-        if (self->lenv>=decodeSize){
-            addData(out_data,self->code,decodeSize);
-            self->code+=decodeSize;
-            self->lenv-=decodeSize;
-            return hpatch_TRUE;
-        }else{
-            addData(out_data,self->code,self->lenv);
-            out_data+=self->lenv;
-            decodeSize-=self->lenv;
-            self->code+=self->lenv;
-            self->lenv=0;
-            goto _decode_0_process;
-        }
-    }
-    
-    assert(decodeSize>0);
-    if (self->isNeedDecode0){
-        hpatch_StreamPos_t len0;
-    _decode_0_process:
-        self->isNeedDecode0=hpatch_FALSE;
-        if (!hpatch_unpackUInt(&self->code,self->code_end,&len0)) return _hpatch_FALSE;
-        if (len0!=(hpatch_size_t)len0) return _hpatch_FALSE;
-        self->len0=(hpatch_size_t)len0;
-        goto _0_process;
-    }else{
-        hpatch_StreamPos_t lenv;
-    _decode_v_process:
-        self->isNeedDecode0=hpatch_TRUE;
-        if (!hpatch_unpackUInt(&self->code,self->code_end,&lenv)) return _hpatch_FALSE;
-        if (lenv>(size_t)(self->code_end-self->code)) return _hpatch_FALSE;
-        self->lenv=(hpatch_size_t)lenv;
-        goto _v_process;
-    }
-}
-
-
-static  hpatch_BOOL _patch_add_old_with_rle0(_TOutStreamCache* outCache,rle0_decoder_t* rle0_decoder,
-                                             const hpatch_TStreamInput* old,hpatch_StreamPos_t oldPos,
-                                             hpatch_StreamPos_t addLength,TByte* aCache,hpatch_size_t aCacheSize){
-    while (addLength>0){
-        hpatch_size_t decodeStep=aCacheSize;
-        if (decodeStep>addLength)
-            decodeStep=(hpatch_size_t)addLength;
-        if (!old->read(old,oldPos,aCache,aCache+decodeStep)) return _hpatch_FALSE;
-        if (!_rle0_decoder_add(rle0_decoder,aCache,decodeStep)) return _hpatch_FALSE;
-        if (!_TOutStreamCache_write(outCache,aCache,decodeStep)) return _hpatch_FALSE;
-        oldPos+=decodeStep;
-        addLength-=decodeStep;
-    }
-    return hpatch_TRUE;
-}
-
-hpatch_BOOL sspatch_covers_nextCover(sspatch_covers_t* self){
-    hpatch_BOOL inc_oldPos_sign=(*(self->covers_cache))>>(8-1);
-    self->lastOldEnd=self->cover.oldPos+self->cover.length;
-    self->lastNewEnd=self->cover.newPos+self->cover.length;
-    if (!hpatch_unpackUIntWithTag(&self->covers_cache,self->covers_cacheEnd,&self->cover.oldPos,1)) return _hpatch_FALSE;
-    if (inc_oldPos_sign==0)
-        self->cover.oldPos+=self->lastOldEnd;
-    else
-        self->cover.oldPos=self->lastOldEnd-self->cover.oldPos;
-    if (!hpatch_unpackUInt(&self->covers_cache,self->covers_cacheEnd,&self->cover.newPos)) return _hpatch_FALSE;
-    self->cover.newPos+=self->lastNewEnd;
-    if (!hpatch_unpackUInt(&self->covers_cache,self->covers_cacheEnd,&self->cover.length)) return _hpatch_FALSE;
-    return hpatch_TRUE;
-}
-
-
-hpatch_BOOL patch_single_stream_diff(const hpatch_TStreamOutput*  out_newData,
-                                     const hpatch_TStreamInput*   oldData,
-                                     const hpatch_TStreamInput*   uncompressedDiffData,
-                                     hpatch_StreamPos_t           diffData_pos,
-                                     hpatch_StreamPos_t           diffData_posEnd,
-                                     hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
-                                     unsigned char* temp_cache,unsigned char* temp_cache_end,
-                                     sspatch_coversListener_t* coversListener){
-    unsigned char*      step_cache=temp_cache;
-    hpatch_size_t       cache_size;
-    TStreamCacheClip    inClip;
-    _TOutStreamCache     outCache;
-    sspatch_covers_t    covers;
-    assert(diffData_posEnd<=uncompressedDiffData->streamSize);
-    sspatch_covers_init(&covers);
-    if (coversListener) assert(coversListener->onStepCovers);
-    {//cache
-        if ((size_t)(temp_cache_end-temp_cache)<stepMemSize+hpatch_kStreamCacheSize*_kCacheSgCount) return _hpatch_FALSE;
-        temp_cache+=stepMemSize;
-        cache_size=(temp_cache_end-temp_cache)/_kCacheSgCount;
-        _TStreamCacheClip_init(&inClip,uncompressedDiffData,diffData_pos,diffData_posEnd,
-                               temp_cache,cache_size);
-        temp_cache+=cache_size;
-        _TOutStreamCache_init(&outCache,out_newData,temp_cache+cache_size,cache_size);
-    }
-    while (coverCount) {//step loop
-        rle0_decoder_t       rle0_decoder;
-        {//read step info
-            unsigned char*      covers_cacheEnd;
-            unsigned char*      bufRle_cache_end;
-            {
-                hpatch_StreamPos_t  bufCover_size;
-                hpatch_StreamPos_t  bufRle_size;
-                _clip_unpackUIntTo(&bufCover_size,&inClip);
-                _clip_unpackUIntTo(&bufRle_size,&inClip);
-                #ifdef __RUN_MEM_SAFE_CHECK
-                    if ((bufCover_size>stepMemSize)|(bufRle_size>stepMemSize)|
-                        (bufCover_size+bufRle_size>stepMemSize)) return _hpatch_FALSE;
-                #endif
-                covers_cacheEnd=step_cache+(size_t)bufCover_size;
-                bufRle_cache_end=covers_cacheEnd+(size_t)bufRle_size;
-            }
-            if (coversListener&&coversListener->onStepCoversReset)
-                coversListener->onStepCoversReset(coversListener,coverCount);
-            if (!_TStreamCacheClip_readDataTo(&inClip,step_cache,bufRle_cache_end))
-                return _hpatch_FALSE;
-            if (coversListener)
-                coversListener->onStepCovers(coversListener,step_cache,covers_cacheEnd);
-            sspatch_covers_setCoversCache(&covers,step_cache,covers_cacheEnd);
-            _rle0_decoder_init(&rle0_decoder,covers_cacheEnd,bufRle_cache_end);
-        }
-        while (sspatch_covers_isHaveNextCover(&covers)) {//cover loop
-            if (!sspatch_covers_nextCover(&covers)) 
-                return _hpatch_FALSE;
-            if (covers.cover.newPos>covers.lastNewEnd){
-                if (!_TOutStreamCache_copyFromClip(&outCache,&inClip,covers.cover.newPos-covers.lastNewEnd))
-                    return _hpatch_FALSE;
-            }
-            
-            --coverCount;
-            if (covers.cover.length){
-                #ifdef __RUN_MEM_SAFE_CHECK
-                    if ((covers.cover.oldPos>oldData->streamSize)|
-                        (covers.cover.length>(hpatch_StreamPos_t)(oldData->streamSize-covers.cover.oldPos))) return _hpatch_FALSE;
-                #endif
-                if (!_patch_add_old_with_rle0(&outCache,&rle0_decoder,oldData,covers.cover.oldPos,covers.cover.length,
-                                              temp_cache,cache_size)) return _hpatch_FALSE;
-            }else{
-                #ifdef __RUN_MEM_SAFE_CHECK
-                    if (coverCount!=0) return _hpatch_FALSE;
-                #endif
-            }
-        }
-    }
-    
-    if (!_TOutStreamCache_flush(&outCache))
-        return _hpatch_FALSE;
-    if (_TStreamCacheClip_isFinish(&inClip)&_TOutStreamCache_isFinish(&outCache)&(coverCount==0))
-        return hpatch_TRUE;
-    else
-        return _hpatch_FALSE;
-}
-
-
-static hpatch_BOOL _TDiffToSingleStream_read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
-                                           unsigned char* out_data,unsigned char* out_data_end){
-    //[                                                         |readedSize                  ]
-    //     [     |cachedBufBegin   _TDiffToSingleStream_kBufSize]
-    //                                 readFromPos[out_data       out_data_end]
-    TDiffToSingleStream* self=(TDiffToSingleStream*)stream->streamImport;
-    hpatch_StreamPos_t readedSize=self->readedSize;
-    while (1){
-        size_t rLen=out_data_end-out_data;
-        if (readFromPos==readedSize){
-            hpatch_BOOL result=self->diffStream->read(self->diffStream,readedSize,out_data,out_data_end);
-            self->readedSize=readedSize+rLen;
-            if ((self->isInSingleStream)||(rLen>_TDiffToSingleStream_kBufSize)){
-                self->cachedBufBegin=_TDiffToSingleStream_kBufSize;
-            }else{
-                //cache
-                if (rLen>=_TDiffToSingleStream_kBufSize){
-                    memcpy(self->buf,out_data_end-_TDiffToSingleStream_kBufSize,_TDiffToSingleStream_kBufSize);
-                    self->cachedBufBegin = 0;
-                }else{
-                    size_t new_cachedBufBegin;
-                    if (self->cachedBufBegin>=rLen){
-                        new_cachedBufBegin=self->cachedBufBegin-rLen;
-                        memmove(self->buf+new_cachedBufBegin,self->buf+self->cachedBufBegin,_TDiffToSingleStream_kBufSize-self->cachedBufBegin);
-                    }else{
-                        new_cachedBufBegin=0;
-                        memmove(self->buf,self->buf+rLen,_TDiffToSingleStream_kBufSize-rLen);
-                    }
-                    memcpy(self->buf+(_TDiffToSingleStream_kBufSize-rLen),out_data,rLen);
-                    self->cachedBufBegin=new_cachedBufBegin;
-                }
-            }
-            return result;
-        }else{
-            size_t cachedSize=_TDiffToSingleStream_kBufSize-self->cachedBufBegin;
-            size_t bufSize=(size_t)(readedSize-readFromPos);
-            if ((readFromPos<readedSize)&(bufSize<=cachedSize)){
-                if (rLen>bufSize)
-                    rLen=bufSize;
-                memcpy(out_data,self->buf+(_TDiffToSingleStream_kBufSize-bufSize),rLen);
-                out_data+=rLen;
-                readFromPos+=rLen;
-                if (out_data==out_data_end) 
-                    return hpatch_TRUE;
-                else
-                    continue;
-            }else{
-                return _hpatch_FALSE;
-            }
-        }
-    }
-}
-void TDiffToSingleStream_init(TDiffToSingleStream* self,const hpatch_TStreamInput* diffStream){
-    self->base.streamImport=self;
-    self->base.streamSize=diffStream->streamSize;
-    self->base.read=_TDiffToSingleStream_read;
-    self->base._private_reserved=0;
-    self->diffStream=diffStream;
-    self->readedSize=0;
-    self->cachedBufBegin=_TDiffToSingleStream_kBufSize;
-    self->isInSingleStream=hpatch_FALSE;
-}
-
-hpatch_BOOL patch_single_stream(sspatch_listener_t* listener,
-                                const hpatch_TStreamOutput* __out_newData,
-                                const hpatch_TStreamInput*  oldData,
-                                const hpatch_TStreamInput*  singleCompressedDiff, 
-                                hpatch_StreamPos_t  diffInfo_pos,
-                                sspatch_coversListener_t* coversListener){
-    hpatch_BOOL result=hpatch_TRUE;
-    hpatch_TDecompress*     decompressPlugin=0;
-    unsigned char*          temp_cache=0;
-    unsigned char*          temp_cacheEnd=0;
-    hpatch_singleCompressedDiffInfo diffInfo;
-    hpatch_TStreamOutput    _out_newData=*__out_newData;
-    hpatch_TStreamOutput*   out_newData=&_out_newData;
-    TDiffToSingleStream     _toSStream;
-    assert((listener)&&(listener->onDiffInfo));
-    TDiffToSingleStream_init(&_toSStream,singleCompressedDiff);
-    singleCompressedDiff=&_toSStream.base;
-
-    if (!getSingleCompressedDiffInfo(&diffInfo,singleCompressedDiff,diffInfo_pos))
-        return _hpatch_FALSE;
-    if (diffInfo.newDataSize>out_newData->streamSize)
-        return _hpatch_FALSE;
-    out_newData->streamSize=diffInfo.newDataSize;
-    if (diffInfo.oldDataSize!=oldData->streamSize)
-        return _hpatch_FALSE;
-    if (!listener->onDiffInfo(listener,&diffInfo,&decompressPlugin,&temp_cache,&temp_cacheEnd))
-        return _hpatch_FALSE;
-
-    if ((temp_cache==0)||(temp_cache>=temp_cacheEnd))
-        result=_hpatch_FALSE;
-    if (result){
-        result=patch_single_compressed_diff(out_newData,oldData,singleCompressedDiff,diffInfo.diffDataPos,
-                                            diffInfo.uncompressedSize,diffInfo.compressedSize,decompressPlugin,
-                                            diffInfo.coverCount,(size_t)diffInfo.stepMemSize,
-                                            temp_cache,temp_cacheEnd,coversListener);
-    }
-    if (listener->onPatchFinish)
-        listener->onPatchFinish(listener,temp_cache,temp_cacheEnd);
-    return result;
-}

+ 0 - 229
hpatch/HPatch/patch.h

@@ -1,229 +0,0 @@
-//patch.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2018 HouSisong
- 
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- 
- The above copyright notice and this permission notice shall be
- included in all copies of the Software.
- 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifndef HPatch_patch_h
-#define HPatch_patch_h
-#include "patch_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//all patch*() functions do not allocate memory
-
-//optimize speed for patch_stream_with_cache() && patch_decompress_with_cache():
-//  preload part of oldData into cache,
-//  cache memory size (temp_cache_end-temp_cache) the larger the better for large oldData file
-#ifndef _IS_NEED_CACHE_OLD_BY_COVERS
-#   define _IS_NEED_CACHE_OLD_BY_COVERS 1
-#endif
-
-
-//generate newData by patch(oldData + serializedDiff)
-//  serializedDiff create by create_diff()
-hpatch_BOOL patch(unsigned char* out_newData,unsigned char* out_newData_end,
-                  const unsigned char* oldData,const unsigned char* oldData_end,
-                  const unsigned char* serializedDiff,const unsigned char* serializedDiff_end);
-
-//patch by stream, see patch()
-//  used (hpatch_kStreamCacheSize*8 stack memory) for I/O cache
-//  if use patch_stream_with_cache(), can passing larger memory cache to optimize speed
-//  serializedDiff create by create_diff()
-hpatch_BOOL patch_stream(const hpatch_TStreamOutput* out_newData,       //sequential write
-                         const hpatch_TStreamInput*  oldData,           //random read
-                         const hpatch_TStreamInput*  serializedDiff);   //random read
-
-//see patch_stream()
-//  can passing more memory for I/O cache to optimize speed
-//  note: (temp_cache_end-temp_cache)>=2048
-hpatch_BOOL patch_stream_with_cache(const hpatch_TStreamOutput* out_newData,    //sequential write
-                                    const hpatch_TStreamInput*  oldData,        //random read
-                                    const hpatch_TStreamInput*  serializedDiff, //random read
-                                    unsigned char* temp_cache,unsigned char* temp_cache_end);
-
-
-
-
-//get compressedDiff info
-//  compressedDiff created by create_compressed_diff() or create_compressed_diff_stream()
-hpatch_BOOL getCompressedDiffInfo(hpatch_compressedDiffInfo* out_diffInfo,
-                                  const hpatch_TStreamInput* compressedDiff);
-//see getCompressedDiffInfo()
-hpatch_inline static hpatch_BOOL
-    getCompressedDiffInfo_mem(hpatch_compressedDiffInfo* out_diffInfo,
-                              const unsigned char* compressedDiff,
-                              const unsigned char* compressedDiff_end){
-        hpatch_TStreamInput  diffStream;
-        mem_as_hStreamInput(&diffStream,compressedDiff,compressedDiff_end);
-        return getCompressedDiffInfo(out_diffInfo,&diffStream);
-    }
-    
-//patch with decompress plugin
-//  used (hpatch_kStreamCacheSize*6 stack memory) + (decompress buffer*4)
-//  compressedDiff create by create_compressed_diff() or create_compressed_diff_stream()
-//  decompressPlugin can null when no compressed data in compressedDiff
-//  if use patch_decompress_with_cache(), can passing larger memory cache to optimize speed
-hpatch_BOOL patch_decompress(const hpatch_TStreamOutput* out_newData,       //sequential write
-                             const hpatch_TStreamInput*  oldData,           //random read
-                             const hpatch_TStreamInput*  compressedDiff,    //random read
-                             hpatch_TDecompress* decompressPlugin);
-
-//see patch_decompress()
-//  can passing larger memory cache to optimize speed
-//  note: (temp_cache_end-temp_cache)>=2048
-hpatch_BOOL patch_decompress_with_cache(const hpatch_TStreamOutput* out_newData,    //sequential write
-                                        const hpatch_TStreamInput*  oldData,        //random read
-                                        const hpatch_TStreamInput*  compressedDiff, //random read
-                                        hpatch_TDecompress* decompressPlugin,
-                                        unsigned char* temp_cache,unsigned char* temp_cache_end);
-
-//see patch_decompress()
-hpatch_inline static hpatch_BOOL
-    patch_decompress_mem(unsigned char* out_newData,unsigned char* out_newData_end,
-                         const unsigned char* oldData,const unsigned char* oldData_end,
-                         const unsigned char* compressedDiff,const unsigned char* compressedDiff_end,
-                         hpatch_TDecompress* decompressPlugin){
-        hpatch_TStreamOutput out_newStream;
-        hpatch_TStreamInput  oldStream;
-        hpatch_TStreamInput  diffStream;
-        mem_as_hStreamOutput(&out_newStream,out_newData,out_newData_end);
-        mem_as_hStreamInput(&oldStream,oldData,oldData_end);
-        mem_as_hStreamInput(&diffStream,compressedDiff,compressedDiff_end);
-        return patch_decompress(&out_newStream,&oldStream,&diffStream,decompressPlugin);
-    }
-
-
-
-
-// hpatch_TCoverList: open diffData and read coverList
-    typedef struct hpatch_TCoverList{
-        hpatch_TCovers* ICovers;
-    //private:
-        unsigned char _buf[hpatch_kStreamCacheSize*4];
-    } hpatch_TCoverList;
-
-hpatch_inline static
-void        hpatch_coverList_init(hpatch_TCoverList* coverList) {
-                                  assert(coverList!=0); memset(coverList,0,sizeof(*coverList)-sizeof(coverList->_buf)); }
-//  serializedDiff create by create_diff()
-hpatch_BOOL hpatch_coverList_open_serializedDiff(hpatch_TCoverList*         out_coverList,
-                                                 const hpatch_TStreamInput* serializedDiff);
-//  compressedDiff create by create_compressed_diff() or create_compressed_diff_stream()
-hpatch_BOOL hpatch_coverList_open_compressedDiff(hpatch_TCoverList*         out_coverList,
-                                                 const hpatch_TStreamInput* compressedDiff,
-                                                 hpatch_TDecompress*        decompressPlugin);
-hpatch_inline static
-hpatch_BOOL hpatch_coverList_close(hpatch_TCoverList* coverList) {
-                                   hpatch_BOOL result=hpatch_TRUE;
-                                   if ((coverList!=0)&&(coverList->ICovers)){
-                                       result=coverList->ICovers->close(coverList->ICovers);
-                                       hpatch_coverList_init(coverList); } return result; }
-
-
-
-
-//patch singleCompressedDiff with listener
-//	used (stepMemSize memory) + (I/O cache memory) + (decompress buffer*1)
-//  every byte in singleCompressedDiff will only be read once in order
-//  singleCompressedDiff create by create_single_compressed_diff() or create_single_compressed_diff_stream()
-//  you can download&patch diffData at the same time, without saving it to disk
-//  same as call getSingleCompressedDiffInfo() + listener->onDiffInfo() + patch_single_compressed_diff()
-hpatch_BOOL patch_single_stream(sspatch_listener_t* listener, //call back when got diffInfo
-                                const hpatch_TStreamOutput* out_newData,          //sequential write
-                                const hpatch_TStreamInput*  oldData,              //random read
-                                const hpatch_TStreamInput*  singleCompressedDiff, //sequential read every byte
-                                hpatch_StreamPos_t  diffInfo_pos, //default 0, begin pos in singleCompressedDiff
-                                sspatch_coversListener_t* coversListener //default NULL, call by on got covers
-                                );
-static hpatch_inline hpatch_BOOL
-    patch_single_stream_mem(sspatch_listener_t* listener,
-                            unsigned char* out_newData,unsigned char* out_newData_end,
-                            const unsigned char* oldData,const unsigned char* oldData_end,
-                            const unsigned char* diff,const unsigned char* diff_end,
-                            sspatch_coversListener_t* coversListener){
-        hpatch_TStreamOutput out_newStream;
-        hpatch_TStreamInput  oldStream;
-        hpatch_TStreamInput  diffStream;
-        mem_as_hStreamOutput(&out_newStream,out_newData,out_newData_end);
-        mem_as_hStreamInput(&oldStream,oldData,oldData_end);
-        mem_as_hStreamInput(&diffStream,diff,diff_end);
-        return patch_single_stream(listener,&out_newStream,&oldStream,&diffStream,0,coversListener);
-    }
-
-//get singleCompressedDiff info
-//  singleCompressedDiff create by create_single_compressed_diff() or create_single_compressed_diff_stream()
-hpatch_BOOL getSingleCompressedDiffInfo(hpatch_singleCompressedDiffInfo* out_diffInfo,
-                                        const hpatch_TStreamInput*  singleCompressedDiff,   //sequential read
-                                        hpatch_StreamPos_t diffInfo_pos//default 0, begin pos in singleCompressedDiff
-                                        );
-hpatch_inline static hpatch_BOOL
-    getSingleCompressedDiffInfo_mem(hpatch_singleCompressedDiffInfo* out_diffInfo,
-                                    const unsigned char* singleCompressedDiff,
-                                    const unsigned char* singleCompressedDiff_end){
-        hpatch_TStreamInput  diffStream;
-        mem_as_hStreamInput(&diffStream,singleCompressedDiff,singleCompressedDiff_end);
-        return getSingleCompressedDiffInfo(out_diffInfo,&diffStream,0);            
-    }
-
-//patch singleCompressedDiff with diffInfo
-//	used (stepMemSize memory) + (I/O cache memory) + (decompress buffer*1)
-//	note: (I/O cache memory) >= hpatch_kStreamCacheSize*3
-//  temp_cache_end-temp_cache == stepMemSize + (I/O cache memory)
-//  singleCompressedDiff create by create_single_compressed_diff() or create_single_compressed_diff_stream()
-//  decompressPlugin can null when no compressed data in singleCompressedDiff
-//  same as call compressed_stream_as_uncompressed() + patch_single_stream_diff()
-hpatch_BOOL patch_single_compressed_diff(const hpatch_TStreamOutput* out_newData,          //sequential write
-                                         const hpatch_TStreamInput*  oldData,              //random read
-                                         const hpatch_TStreamInput*  singleCompressedDiff, //sequential read
-                                         hpatch_StreamPos_t          diffData_pos, //diffData begin pos in singleCompressedDiff
-                                         hpatch_StreamPos_t          uncompressedSize,
-                                         hpatch_StreamPos_t          compressedSize,
-                                         hpatch_TDecompress*         decompressPlugin,
-                                         hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
-                                         unsigned char* temp_cache,unsigned char* temp_cache_end,
-                                         sspatch_coversListener_t* coversListener //default NULL, call by on got covers
-                                         );
-
-hpatch_BOOL compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream,hpatch_StreamPos_t uncompressedSize,
-                                                hpatch_TDecompress* decompressPlugin,const hpatch_TStreamInput* compressedStream,
-                                                hpatch_StreamPos_t compressed_pos,hpatch_StreamPos_t compressed_end);
-void close_compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream);
-
-hpatch_BOOL patch_single_stream_diff(const hpatch_TStreamOutput*  out_newData,          //sequential write
-                                     const hpatch_TStreamInput*   oldData,              //random read
-                                     const hpatch_TStreamInput*   uncompressedDiffData, //sequential read
-                                     hpatch_StreamPos_t           diffData_pos,//diffData begin pos in uncompressedDiffData
-                                     hpatch_StreamPos_t           diffData_posEnd,//diffData end pos in uncompressedDiffData
-                                     hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
-                                     unsigned char* temp_cache,unsigned char* temp_cache_end,
-                                     sspatch_coversListener_t* coversListener);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 208
hpatch/HPatch/patch_private.h

@@ -1,208 +0,0 @@
-//  patch_private.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2018 HouSisong
- 
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- 
- The above copyright notice and this permission notice shall be
- included in all copies of the Software.
- 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef HPatch_patch_private_h
-#define HPatch_patch_private_h
-
-#include "patch_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-    
-//byte rle type , ctrl code: high 2bit + packedLen(6bit+...)
-typedef enum TByteRleType{
-    kByteRleType_rle0  = 0,    //00 rle 0  , data code:0 byte
-    kByteRleType_rle255= 1,    //01 rle 255, data code:0 byte
-    kByteRleType_rle   = 2,    //10 rle x(1--254), data code:1 byte (save x)
-    kByteRleType_unrle = 3     //11 n byte data, data code:n byte(save no rle data)
-} TByteRleType;
-    
-static const hpatch_uint kByteRleType_bit=2;
-    
-
-typedef struct _THDiffzHead{
-    hpatch_StreamPos_t coverCount;
-    
-    hpatch_StreamPos_t cover_buf_size;
-    hpatch_StreamPos_t compress_cover_buf_size;
-    hpatch_StreamPos_t rle_ctrlBuf_size;
-    hpatch_StreamPos_t compress_rle_ctrlBuf_size;
-    hpatch_StreamPos_t rle_codeBuf_size;
-    hpatch_StreamPos_t compress_rle_codeBuf_size;
-    hpatch_StreamPos_t newDataDiff_size;
-    hpatch_StreamPos_t compress_newDataDiff_size;
-    
-    hpatch_StreamPos_t typesEndPos;
-    hpatch_StreamPos_t compressSizeBeginPos;
-    hpatch_StreamPos_t headEndPos;
-    hpatch_StreamPos_t coverEndPos;
-} _THDiffzHead;
-    
-hpatch_BOOL read_diffz_head(hpatch_compressedDiffInfo* out_diffInfo,_THDiffzHead* out_head,
-                            const hpatch_TStreamInput* compressedDiff);
-
-// Stream Clip cache
-typedef struct TStreamCacheClip{
-    hpatch_StreamPos_t          streamPos;
-    hpatch_StreamPos_t          streamPos_end;
-    const hpatch_TStreamInput*  srcStream;
-    unsigned char*  cacheBuf;
-    hpatch_size_t   cacheBegin;
-    hpatch_size_t   cacheEnd;
-} TStreamCacheClip;
-
-hpatch_inline static
-void _TStreamCacheClip_init(TStreamCacheClip* sclip,const hpatch_TStreamInput* srcStream,
-                            hpatch_StreamPos_t streamPos,hpatch_StreamPos_t streamPos_end,
-                            unsigned char* aCache,hpatch_size_t cacheSize){
-    assert((streamPos<=streamPos_end)&&(streamPos_end<=(srcStream?srcStream->streamSize:0)));
-    sclip->streamPos=streamPos;
-    sclip->streamPos_end=streamPos_end;
-    sclip->srcStream=srcStream;
-    sclip->cacheBuf=aCache;
-    sclip->cacheBegin=cacheSize;
-    sclip->cacheEnd=cacheSize;
-}
-    
-#define _TStreamCacheClip_isFinish(sclip)     ( 0==_TStreamCacheClip_leaveSize(sclip) )
-#define _TStreamCacheClip_isCacheEmpty(sclip) ( (sclip)->cacheBegin==(sclip)->cacheEnd )
-#define _TStreamCacheClip_cachedSize(sclip)   ( (hpatch_size_t)((sclip)->cacheEnd-(sclip)->cacheBegin) )
-#define _TStreamCacheClip_leaveSize(sclip)   \
-            (  (hpatch_StreamPos_t)((sclip)->streamPos_end-(sclip)->streamPos)  \
-                + (hpatch_StreamPos_t)_TStreamCacheClip_cachedSize(sclip)  )
-#define _TStreamCacheClip_readPosOfSrcStream(sclip) ( \
-            (sclip)->streamPos - _TStreamCacheClip_cachedSize(sclip) )
-    
-hpatch_BOOL _TStreamCacheClip_updateCache(TStreamCacheClip* sclip);
-    
-hpatch_inline static //error return 0
-unsigned char* _TStreamCacheClip_accessData(TStreamCacheClip* sclip,hpatch_size_t readSize){
-    //assert(readSize<=sclip->cacheEnd);
-    if (readSize>_TStreamCacheClip_cachedSize(sclip)){
-        if (!_TStreamCacheClip_updateCache(sclip)) return 0;
-        if (readSize>_TStreamCacheClip_cachedSize(sclip)) return 0;
-    }
-    return &sclip->cacheBuf[sclip->cacheBegin];
-}
-
-#define _TStreamCacheClip_skipData_noCheck(sclip,skipSize) ((sclip)->cacheBegin+=skipSize)
-hpatch_BOOL _TStreamCacheClip_skipData(TStreamCacheClip* sclip,hpatch_StreamPos_t skipLongSize);
-    
-hpatch_inline static //error return 0
-unsigned char* _TStreamCacheClip_readData(TStreamCacheClip* sclip,hpatch_size_t readSize){
-    unsigned char* result=_TStreamCacheClip_accessData(sclip,readSize);
-    _TStreamCacheClip_skipData_noCheck(sclip,readSize);
-    return result;
-}
-
-hpatch_BOOL _TStreamCacheClip_readDataTo(TStreamCacheClip* sclip,
-                                         unsigned char* out_buf,unsigned char* bufEnd);
-hpatch_BOOL _TStreamCacheClip_addDataTo(TStreamCacheClip* self,unsigned char* dst,hpatch_size_t addLen);
-
-hpatch_BOOL _TStreamCacheClip_unpackUIntWithTag(TStreamCacheClip* sclip,
-                                                hpatch_StreamPos_t* result,const hpatch_uint kTagBit);
-
-hpatch_BOOL _TStreamCacheClip_readType_end(TStreamCacheClip* sclip,unsigned char endTag,
-                                           char out_type[hpatch_kMaxPluginTypeLength+1]);
-
-// Stream Clip cache
-typedef struct {
-    hpatch_StreamPos_t           writeToPos;
-    const hpatch_TStreamOutput*  dstStream;
-    unsigned char*  cacheBuf;
-    hpatch_size_t   cacheCur;
-    hpatch_size_t   cacheEnd;
-} _TOutStreamCache;
-
-static hpatch_inline void _TOutStreamCache_init(_TOutStreamCache* self,const hpatch_TStreamOutput*  dstStream,
-                                                unsigned char* aCache,hpatch_size_t aCacheSize){
-    self->writeToPos=0;
-    self->cacheCur=0;
-    self->dstStream=dstStream;
-    self->cacheBuf=aCache;
-    self->cacheEnd=aCacheSize;
-}
-hpatch_inline static
-void _TOutStreamCache_resetCache(_TOutStreamCache* self,unsigned char* aCache,hpatch_size_t aCacheSize){
-    assert(0==self->cacheCur);
-    self->cacheBuf=aCache;
-    self->cacheEnd=aCacheSize;
-}
-
-static hpatch_inline hpatch_StreamPos_t _TOutStreamCache_leaveSize(const _TOutStreamCache* self){
-    return self->dstStream->streamSize-self->writeToPos;
-}
-static hpatch_inline hpatch_BOOL _TOutStreamCache_isFinish(const _TOutStreamCache* self){
-    return self->writeToPos==self->dstStream->streamSize;
-}
-static hpatch_inline hpatch_size_t _TOutStreamCache_cachedDataSize(const _TOutStreamCache* self){
-    return self->cacheCur;
-}
-hpatch_BOOL _TOutStreamCache_flush(_TOutStreamCache* self);
-hpatch_BOOL _TOutStreamCache_write(_TOutStreamCache* self,const unsigned char* data,hpatch_size_t dataSize);
-hpatch_BOOL _TOutStreamCache_fill(_TOutStreamCache* self,hpatch_byte fillValue,hpatch_StreamPos_t fillLength);
-
-hpatch_BOOL _TOutStreamCache_copyFromClip(_TOutStreamCache* self,TStreamCacheClip* src,hpatch_StreamPos_t copyLength);
-hpatch_BOOL _TOutStreamCache_copyFromStream(_TOutStreamCache* self,const hpatch_TStreamInput* src,
-                                            hpatch_StreamPos_t srcPos,hpatch_StreamPos_t copyLength);
-hpatch_BOOL _TOutStreamCache_copyFromSelf(_TOutStreamCache* self,hpatch_StreamPos_t aheadLength,hpatch_StreamPos_t copyLength);
-
-
-    typedef struct _TDecompressInputStream{
-        hpatch_TStreamInput         IInputStream;
-        hpatch_TDecompress*         decompressPlugin;
-        hpatch_decompressHandle     decompressHandle;
-    } _TDecompressInputStream;
-    
-hpatch_BOOL getStreamClip(TStreamCacheClip* out_clip,_TDecompressInputStream* out_stream,
-                          hpatch_StreamPos_t dataSize,hpatch_StreamPos_t compressedSize,
-                          const hpatch_TStreamInput* stream,hpatch_StreamPos_t* pCurStreamPos,
-                          hpatch_TDecompress* decompressPlugin,unsigned char* aCache,hpatch_size_t cacheSize);
-    
-
-#define _TDiffToSingleStream_kBufSize hpatch_kStreamCacheSize
-typedef struct {
-    hpatch_TStreamInput         base;
-    const hpatch_TStreamInput*  diffStream;
-    hpatch_StreamPos_t          readedSize;
-    hpatch_size_t               cachedBufBegin;
-    hpatch_BOOL                 isInSingleStream;
-    unsigned char               buf[_TDiffToSingleStream_kBufSize];
-} TDiffToSingleStream;
-
-void TDiffToSingleStream_init(TDiffToSingleStream* self,const hpatch_TStreamInput* diffStream);
-hpatch_inline static 
-void TDiffToSingleStream_setInSingleStream(TDiffToSingleStream* self,hpatch_StreamPos_t singleStreamPos){
-    self->isInSingleStream=hpatch_TRUE; }
-
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 334
hpatch/HPatch/patch_types.h

@@ -1,334 +0,0 @@
-//  patch_types.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2012-2018 HouSisong
- 
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- 
- The above copyright notice and this permission notice shall be
- included in all copies of the Software.
- 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef HPatch_patch_types_h
-#define HPatch_patch_types_h
-
-#include <string.h> //for size_t memset memcpy memmove
-#include <assert.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HDIFFPATCH_VERSION_MAJOR    4
-#define HDIFFPATCH_VERSION_MINOR    6
-#define HDIFFPATCH_VERSION_RELEASE  6
-
-#define _HDIFFPATCH_VERSION          HDIFFPATCH_VERSION_MAJOR.HDIFFPATCH_VERSION_MINOR.HDIFFPATCH_VERSION_RELEASE
-#define _HDIFFPATCH_QUOTE(str) #str
-#define _HDIFFPATCH_EXPAND_AND_QUOTE(str) _HDIFFPATCH_QUOTE(str)
-#define HDIFFPATCH_VERSION_STRING   _HDIFFPATCH_EXPAND_AND_QUOTE(_HDIFFPATCH_VERSION)
-
-#ifndef hpatch_int
-    typedef int                 hpatch_int;
-#endif
-#ifndef hpatch_uint
-    typedef unsigned int        hpatch_uint;
-#endif
-#ifndef hpatch_size_t
-    typedef size_t              hpatch_size_t;
-#endif
-#ifndef hpatch_uint32_t
-#ifdef _MSC_VER
-#   if (_MSC_VER >= 1300)
-    typedef unsigned __int32    hpatch_uint32_t;
-#   else
-    typedef unsigned int        hpatch_uint32_t;
-#   endif
-#else
-    typedef unsigned int        hpatch_uint32_t;
-#endif
-#endif
-#ifndef hpatch_uint64_t
-#ifdef _MSC_VER
-    typedef unsigned __int64    hpatch_uint64_t;
-#else
-    typedef unsigned long long  hpatch_uint64_t;
-#endif
-#endif
-#ifndef hpatch_StreamPos_t
-    typedef hpatch_uint64_t     hpatch_StreamPos_t; // file size type
-#endif
-#define hpatch_kNullStreamPos   (~(hpatch_StreamPos_t)0)
-
-#ifndef hpatch_BOOL
-    typedef int                 hpatch_BOOL;
-#endif
-#define     hpatch_FALSE    0
-#define     hpatch_TRUE     ((hpatch_BOOL)(!hpatch_FALSE))
-    
-#ifndef hpatch_byte
-    typedef unsigned char       hpatch_byte;
-#endif
-
-#if (_HPATCH_IS_USED_errno)
-typedef    int          hpatch_FileError_t;// 0: no error; other: saved errno value;
-#else
-typedef    hpatch_BOOL  hpatch_FileError_t;// 0: no error; other: error;
-#endif
-
-#ifdef _MSC_VER
-#   define hpatch_inline _inline
-#else
-#   define hpatch_inline inline
-#endif
-
-//PRIu64 for printf type hpatch_StreamPos_t
-#ifndef PRIu64
-#   ifdef _MSC_VER
-#       define PRIu64 "I64u"
-#   else
-#       define PRIu64 "llu"
-#   endif
-#endif
-
-#ifdef ANDROID
-#   include <android/log.h>
-#   define LOG_ERR(...) __android_log_print(ANDROID_LOG_ERROR, "hpatch", __VA_ARGS__)
-#else
-#   include <stdio.h>  //for stderr
-#   define LOG_ERR(...) fprintf(stderr,__VA_ARGS__)
-#endif
-#ifndef _HPATCH_IS_USED_errno
-#   define  _HPATCH_IS_USED_errno 1
-#endif
-#define _hpatch_import_system_tag "call import system api"
-#if (_HPATCH_IS_USED_errno)
-#   define  LOG_ERRNO(_err_no) \
-        LOG_ERR(_hpatch_import_system_tag" error! errno: %d, errmsg: %s.\n",_err_no,strerror(_err_no))
-#else
-#   define  LOG_ERRNO(_err_no) LOG_ERR(_hpatch_import_system_tag" error!\n")
-#endif
-    
-#define _hpatch_align_type_lower(uint_type,p,align2pow) (((uint_type)(p)) & (~(uint_type)((align2pow)-1)))
-#define _hpatch_align_lower(p,align2pow) _hpatch_align_type_lower(hpatch_size_t,p,align2pow)
-#define _hpatch_align_upper(p,align2pow) _hpatch_align_lower(((hpatch_size_t)(p))+((align2pow)-1),align2pow)
-    
-    typedef void* hpatch_TStreamInputHandle;
-    typedef void* hpatch_TStreamOutputHandle;
-    
-    typedef struct hpatch_TStreamInput{
-        void*            streamImport;
-        hpatch_StreamPos_t streamSize; //stream size,max readable range;
-        //read() must read (out_data_end-out_data), otherwise error return hpatch_FALSE
-        hpatch_BOOL            (*read)(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
-                                       unsigned char* out_data,unsigned char* out_data_end);
-        void*        _private_reserved;
-    } hpatch_TStreamInput;
-    
-    typedef struct hpatch_TStreamOutput{
-        void*            streamImport;
-        hpatch_StreamPos_t streamSize; //stream size,max writable range; not is write pos!
-        //read_writed for ReadWriteIO, can null!
-        hpatch_BOOL     (*read_writed)(const struct hpatch_TStreamOutput* stream,hpatch_StreamPos_t readFromPos,
-                                       unsigned char* out_data,unsigned char* out_data_end);
-        //write() must wrote (out_data_end-out_data), otherwise error return hpatch_FALSE
-        hpatch_BOOL           (*write)(const struct hpatch_TStreamOutput* stream,hpatch_StreamPos_t writeToPos,
-                                       const unsigned char* data,const unsigned char* data_end);
-    } hpatch_TStreamOutput;
-    
-    //default once I/O (read/write) byte size
-    #ifndef hpatch_kStreamCacheSize
-    #   define hpatch_kStreamCacheSize      (1024*4)
-    #endif
-    #ifndef hpatch_kFileIOBufBetterSize
-    #   define hpatch_kFileIOBufBetterSize  (1024*64)
-    #endif
-    
-    #ifndef hpatch_kMaxPluginTypeLength
-    #   define hpatch_kMaxPluginTypeLength   259
-    #endif
-
-    typedef struct hpatch_compressedDiffInfo{
-        hpatch_StreamPos_t  newDataSize;
-        hpatch_StreamPos_t  oldDataSize;
-        hpatch_uint         compressedCount;//need open hpatch_decompressHandle number
-        char                compressType[hpatch_kMaxPluginTypeLength+1]; //ascii cstring 
-    } hpatch_compressedDiffInfo;
-    
-    typedef void*  hpatch_decompressHandle;
-    typedef enum{
-        hpatch_dec_ok=0,
-        hpatch_dec_mem_error,
-        hpatch_dec_open_error,
-        hpatch_dec_error,
-        hpatch_dec_close_error,
-    } hpatch_dec_error_t;
-    typedef struct hpatch_TDecompress{
-        hpatch_BOOL        (*is_can_open)(const char* compresseType);
-        //error return 0.
-        hpatch_decompressHandle   (*open)(struct hpatch_TDecompress* decompressPlugin,
-                                          hpatch_StreamPos_t dataSize,
-                                          const struct hpatch_TStreamInput* codeStream,
-                                          hpatch_StreamPos_t code_begin,
-                                          hpatch_StreamPos_t code_end);//codeSize==code_end-code_begin
-        hpatch_BOOL              (*close)(struct hpatch_TDecompress* decompressPlugin,
-                                          hpatch_decompressHandle decompressHandle);
-        //decompress_part() must out (out_part_data_end-out_part_data), otherwise error return hpatch_FALSE
-        hpatch_BOOL    (*decompress_part)(hpatch_decompressHandle decompressHandle,
-                                          unsigned char* out_part_data,unsigned char* out_part_data_end);
-        //reset_code add new compressed data; for support vcpatch, can NULL
-        hpatch_BOOL         (*reset_code)(hpatch_decompressHandle decompressHandle,
-                                          hpatch_StreamPos_t dataSize,
-                                          const struct hpatch_TStreamInput* codeStream,
-                                          hpatch_StreamPos_t code_begin,
-                                          hpatch_StreamPos_t code_end);
-        volatile hpatch_dec_error_t decError; //if you used decError value, once patch must used it's own hpatch_TDecompress
-    } hpatch_TDecompress;
-    #define _hpatch_update_decError(decompressPlugin,errorCode) \
-        do { if ((decompressPlugin)->decError==hpatch_dec_ok)   \
-                (decompressPlugin)->decError=errorCode;     } while(0)
-    
-    
-    const hpatch_TStreamInput* mem_as_hStreamInput(hpatch_TStreamInput* out_stream,
-                                                   const unsigned char* mem,const unsigned char* mem_end);
-    const hpatch_TStreamOutput* mem_as_hStreamOutput(hpatch_TStreamOutput* out_stream,
-                                                     unsigned char* mem,unsigned char* mem_end);
-    
-    hpatch_BOOL hpatch_deccompress_mem(hpatch_TDecompress* decompressPlugin,
-                                       const unsigned char* code,const unsigned char* code_end,
-                                       unsigned char* out_data,unsigned char* out_data_end);
-    
-    typedef struct{
-        hpatch_TStreamInput         base;
-        const hpatch_TStreamInput*  srcStream;
-        hpatch_StreamPos_t          clipBeginPos;
-    } TStreamInputClip;
-    //clip srcStream from clipBeginPos to clipEndPos as a new StreamInput;
-    void TStreamInputClip_init(TStreamInputClip* self,const hpatch_TStreamInput*  srcStream,
-                               hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos);
-    typedef struct{
-        hpatch_TStreamOutput        base;
-        const hpatch_TStreamOutput* srcStream;
-        hpatch_StreamPos_t          clipBeginPos;
-    } TStreamOutputClip;
-    //clip srcStream from clipBeginPos to clipEndPos as a new StreamInput;
-    void TStreamOutputClip_init(TStreamOutputClip* self,const hpatch_TStreamOutput*  srcStream,
-                                hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos);
-
-    
-    #define  hpatch_kMaxPackedUIntBytes ((sizeof(hpatch_StreamPos_t)*8+6)/7+1)
-    hpatch_BOOL hpatch_packUIntWithTag(unsigned char** out_code,unsigned char* out_code_end,
-                                       hpatch_StreamPos_t uValue,hpatch_uint highTag,const hpatch_uint kTagBit);
-    hpatch_uint hpatch_packUIntWithTag_size(hpatch_StreamPos_t uValue,const hpatch_uint kTagBit);
-    #define hpatch_packUInt(out_code,out_code_end,uValue) \
-                hpatch_packUIntWithTag(out_code,out_code_end,uValue,0,0)
-    #define hpatch_packUInt_size(uValue) hpatch_packUIntWithTag_size(uValue,0)
-    
-    hpatch_BOOL hpatch_unpackUIntWithTag(const unsigned char** src_code,const unsigned char* src_code_end,
-                                         hpatch_StreamPos_t* result,const hpatch_uint kTagBit);
-    #define hpatch_unpackUInt(src_code,src_code_end,result) \
-                hpatch_unpackUIntWithTag(src_code,src_code_end,result,0)
-
-    
-    typedef struct hpatch_TCover{
-        hpatch_StreamPos_t oldPos;
-        hpatch_StreamPos_t newPos;
-        hpatch_StreamPos_t length;
-    } hpatch_TCover;
-    typedef struct hpatch_TCover32{
-        hpatch_uint32_t oldPos;
-        hpatch_uint32_t newPos;
-        hpatch_uint32_t length;
-    } hpatch_TCover32;
-    typedef struct hpatch_TCover_sz{
-        size_t oldPos;
-        size_t newPos;
-        size_t length;
-    } hpatch_TCover_sz;
-
-    //opened input covers
-    typedef struct hpatch_TCovers{
-        hpatch_StreamPos_t (*leave_cover_count)(const struct hpatch_TCovers* covers);
-        //read out a cover,and to next cover pos; if error then return false
-        hpatch_BOOL               (*read_cover)(struct hpatch_TCovers* covers,hpatch_TCover* out_cover);
-        hpatch_BOOL                (*is_finish)(const struct hpatch_TCovers* covers);
-        hpatch_BOOL                    (*close)(struct hpatch_TCovers* covers);
-    } hpatch_TCovers;
-    
-    //output covers
-    typedef struct hpatch_TOutputCovers{
-        hpatch_BOOL (*push_cover)(struct hpatch_TOutputCovers* out_covers,const hpatch_TCover* cover); 
-        void (*collate_covers)(struct hpatch_TOutputCovers* out_covers); // for support search covers by muti-thread
-    } hpatch_TOutputCovers;
-    
-    typedef struct{
-        hpatch_StreamPos_t  newDataSize;
-        hpatch_StreamPos_t  oldDataSize;
-        hpatch_StreamPos_t  uncompressedSize;
-        hpatch_StreamPos_t  compressedSize;
-        hpatch_StreamPos_t  diffDataPos;
-        hpatch_StreamPos_t  coverCount;
-        hpatch_StreamPos_t  stepMemSize;
-        char                compressType[hpatch_kMaxPluginTypeLength+1]; //ascii cstring
-    } hpatch_singleCompressedDiffInfo;
-    
-    typedef struct sspatch_listener_t{ 
-        void*         import;   
-        hpatch_BOOL (*onDiffInfo)(struct sspatch_listener_t* listener,
-                                  const hpatch_singleCompressedDiffInfo* info,
-                                  hpatch_TDecompress** out_decompressPlugin,//find decompressPlugin by info->compressType
-                                  unsigned char** out_temp_cache,    //*out_temp_cacheEnd-*out_temp_cache == info->stepMemSize + (I/O cache memory)
-                                  unsigned char** out_temp_cacheEnd);//  note: (I/O cache memory) >= hpatch_kStreamCacheSize*3
-        void        (*onPatchFinish)(struct sspatch_listener_t* listener, //onPatchFinish can null
-                                     unsigned char* temp_cache, unsigned char* temp_cacheEnd);
-    } sspatch_listener_t;
-
-    typedef struct{
-        hpatch_TStreamInput     base;
-        hpatch_TDecompress*     _decompressPlugin;
-        hpatch_decompressHandle _decompressHandle;
-    } hpatch_TUncompresser_t;
-
-    typedef struct sspatch_coversListener_t{
-        void*         import;
-        void        (*onStepCoversReset)(struct sspatch_coversListener_t* listener,hpatch_StreamPos_t leaveCoverCount);//can NULL, data(in covers_cache) will invalid
-        void        (*onStepCovers)(struct sspatch_coversListener_t* listener,
-                                    const unsigned char* covers_cache,const unsigned char* covers_cacheEnd);
-    } sspatch_coversListener_t;
-    
-    typedef struct{
-        const unsigned char* covers_cache;
-        const unsigned char* covers_cacheEnd;
-        hpatch_StreamPos_t   lastOldEnd;
-        hpatch_StreamPos_t   lastNewEnd;
-        hpatch_TCover        cover;
-    } sspatch_covers_t;
-
-    hpatch_inline static void sspatch_covers_init(sspatch_covers_t* self) { memset(self,0,sizeof(*self)); }
-    hpatch_inline static void sspatch_covers_setCoversCache(sspatch_covers_t* self,const unsigned char* covers_cache,const unsigned char* covers_cacheEnd){
-                                    self->covers_cache=covers_cache; self->covers_cacheEnd=covers_cacheEnd; }
-    hpatch_inline static hpatch_BOOL sspatch_covers_isHaveNextCover(const sspatch_covers_t* self) { return (self->covers_cache!=(self)->covers_cacheEnd); }
-
-    hpatch_BOOL sspatch_covers_nextCover(sspatch_covers_t* self);
-    
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 210
hpatch/HPatchLite/hpatch_lite.c

@@ -1,210 +0,0 @@
-// hpatch_lite.c
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2020-2022 HouSisong All Rights Reserved.
-*/
-#include "hpatch_lite.h"
-#include "hpatch_lite_input_cache.h"
-
-#define _hpi_FALSE hpi_FALSE
-// hpi_size_t __debug_check_false_x=0; //for debug
-// #define _hpi_FALSE (1/__debug_check_false_x)
-
-#if (_IS_RUN_MEM_SAFE_CHECK)
-#define __RUN_MEM_SAFE_CHECK
-#endif
-
-#define _CHECK(code)                    \
-    {                                   \
-        if (!(code)) return _hpi_FALSE; \
-    }
-
-#ifdef __RUN_MEM_SAFE_CHECK
-#define _SAFE_CHECK(checkv) _CHECK(checkv)
-#else
-#define _SAFE_CHECK(checkv)
-#endif
-
-#define _TInputCache          _hpi_TInputCache
-#define _cache_read_1byte     _hpi_cache_read_1byte
-#define _cache_update         _hpi_cache_update
-#define _cache_success_finish _hpi_cache_success_finish
-
-hpi_BOOL _cache_update(struct _TInputCache *self)
-{
-    //    [                    cache  buf                        ]
-    hpi_size_t len = self->cache_end;
-    assert(len == self->cache_begin); // empty
-    if (!self->read_code(self->inputStream, self->cache_buf, &len))
-        len = 0;
-    //    |                                   len|               |
-    self->cache_begin = 0;
-    self->cache_end   = len;
-    return len != 0;
-}
-
-hpi_fast_uint8 _cache_read_1byte(struct _TInputCache *self)
-{
-    if (self->cache_begin != self->cache_end)
-    {
-    __cache_read_1byte:
-        return self->cache_buf[self->cache_begin++];
-    }
-    if (_cache_update(self))
-        goto __cache_read_1byte;
-    else
-        return 0;
-}
-
-static hpi_pos_t _cache_unpackUInt(_TInputCache *self, hpi_pos_t v, hpi_fast_uint8 isNext)
-{
-    while (isNext)
-    {
-        hpi_fast_uint8 b = _cache_read_1byte(self);
-        v                = (v << 7) | (b & 127);
-        isNext           = b >> 7;
-    }
-    return v;
-}
-
-static hpi_BOOL _patch_copy_diff(hpatchi_listener_t *out_newData,
-                                 _TInputCache *diff, hpi_pos_t copyLength)
-{
-    while (copyLength > 0)
-    {
-        hpi_size_t decodeStep = diff->cache_end - diff->cache_begin;
-        if (decodeStep == 0)
-        {
-            _CHECK(_cache_update(diff));
-            decodeStep = diff->cache_end - diff->cache_begin;
-        }
-        if (decodeStep > copyLength)
-            decodeStep = (hpi_size_t)copyLength;
-        _CHECK(out_newData->write_new(out_newData, diff->cache_buf + diff->cache_begin, decodeStep));
-        diff->cache_begin += decodeStep;
-        copyLength -= (hpi_pos_t)decodeStep;
-    }
-    return hpi_TRUE;
-}
-
-static hpi_force_inline void addData(hpi_byte *dst, const hpi_byte *src, hpi_size_t length)
-{
-    while (length--) { *dst++ += *src++; }
-}
-
-static hpi_BOOL _patch_add_old_withClip(hpatchi_listener_t *old_and_new, _TInputCache *diff, hpi_BOOL isNotNeedSubDiff,
-                                        hpi_size_t oldPos, hpi_size_t addLength, hpi_byte *temp_cache)
-{
-    while (addLength > 0)
-    {
-        hpi_size_t decodeStep = diff->cache_end;
-        if (!isNotNeedSubDiff)
-        {
-            decodeStep -= diff->cache_begin;
-            if (decodeStep == 0)
-            {
-                _cache_update(diff);
-                decodeStep = diff->cache_end - diff->cache_begin;
-            }
-        }
-        _CHECK(decodeStep > 0);
-        if (decodeStep > addLength)
-            decodeStep = (hpi_size_t)addLength;
-        _CHECK(old_and_new->read_old(old_and_new, oldPos, temp_cache, (hpi_pos_t)decodeStep));
-        if (!isNotNeedSubDiff)
-        {
-            addData(temp_cache, diff->cache_buf + diff->cache_begin, decodeStep);
-            diff->cache_begin += decodeStep;
-        }
-        _CHECK(old_and_new->write_new(old_and_new, temp_cache, decodeStep));
-        oldPos += decodeStep;
-        addLength -= decodeStep;
-    }
-    return hpi_TRUE;
-}
-
-static hpi_pos_t _hpi_readSize(const hpi_byte *buf, hpi_size_t len)
-{
-    hpi_pos_t v = 0;
-    while (len--)
-    {
-        v = (v << 8) | (hpi_pos_t)buf[len];
-    }
-    return v;
-}
-
-hpi_BOOL hpatch_lite_open(hpi_TInputStreamHandle diff_data, hpi_TInputStream_read read_diff,
-                          hpi_compressType *out_compress_type, hpi_pos_t *out_newSize, hpi_pos_t *out_uncompressSize)
-{
-#define kHPatchLite_versionCode 1
-    hpi_size_t lenn = hpi_kHeadSize;
-    hpi_size_t lenu;
-    hpi_byte buf[hpi_kHeadSize > sizeof(hpi_pos_t) ? hpi_kHeadSize : sizeof(hpi_pos_t)];
-
-    _CHECK(read_diff(diff_data, buf, &lenn));
-    // HPatchLite type tag 2byte, version code(high 2bit)
-    lenu = buf[3];
-    _SAFE_CHECK((lenn == hpi_kHeadSize) & (buf[0] == 'h') & (buf[1] == 'I') & ((lenu >> 6) == kHPatchLite_versionCode));
-    *out_compress_type = (hpi_compressType)buf[2]; // compress type
-    lenn               = lenu & 7;                 // newSize bytes(low 3bit)
-    lenu               = (lenu >> 3) & 7;          // uncompressSize bytes(mid 3bit)
-
-    _SAFE_CHECK((lenn <= sizeof(hpi_pos_t)) & (lenu <= sizeof(hpi_pos_t)));
-    _CHECK(read_diff(diff_data, buf, &lenn));
-    *out_newSize = _hpi_readSize(buf, lenn);
-    _CHECK(read_diff(diff_data, buf, &lenu));
-    *out_uncompressSize = _hpi_readSize(buf, lenu);
-    return hpi_TRUE;
-}
-
-hpi_BOOL hpatch_lite_patch(hpatchi_listener_t *listener, hpi_pos_t newSize,
-                           hpi_byte *temp_cache, hpi_size_t temp_cache_size)
-{
-    _TInputCache diff;
-    hpi_pos_t coverCount;
-    hpi_pos_t newPosBack = 0;
-    hpi_pos_t oldPosBack = 0;
-    {
-        assert(temp_cache);
-        _SAFE_CHECK(temp_cache_size >= hpi_kMinCacheSize);
-        temp_cache_size >>= 1;
-        diff.cache_begin = temp_cache_size;
-        diff.cache_end   = temp_cache_size;
-        diff.cache_buf   = temp_cache + temp_cache_size;
-        diff.inputStream = listener->diff_data;
-        diff.read_code   = listener->read_diff;
-    }
-    coverCount = _cache_unpackUInt(&diff, 0, hpi_TRUE);
-
-    while (coverCount--)
-    {
-        hpi_pos_t cover_oldPos;
-        hpi_pos_t cover_newPos;
-        hpi_pos_t cover_length;
-        hpi_BOOL isNotNeedSubDiff;
-        { // read cover
-            cover_length = _cache_unpackUInt(&diff, 0, hpi_TRUE);
-            {
-                hpi_fast_uint8 tag = _cache_read_1byte(&diff);
-                cover_oldPos       = _cache_unpackUInt(&diff, tag & 31, tag & (1 << 5));
-                isNotNeedSubDiff   = (tag >> 7);
-                if (tag & (1 << 6))
-                    cover_oldPos = oldPosBack - cover_oldPos;
-                else
-                    cover_oldPos += oldPosBack;
-            }
-            cover_newPos = _cache_unpackUInt(&diff, 0, hpi_TRUE);
-            cover_newPos += newPosBack;
-        }
-
-        _SAFE_CHECK(cover_newPos >= newPosBack);
-        if (newPosBack < cover_newPos)
-            _CHECK(_patch_copy_diff(listener, &diff, cover_newPos - newPosBack));
-        _CHECK(_patch_add_old_withClip(listener, &diff, isNotNeedSubDiff, cover_oldPos, cover_length, temp_cache));
-        newPosBack = cover_newPos + cover_length;
-        oldPosBack = cover_oldPos + cover_length;
-        _SAFE_CHECK((cover_length > 0) | (coverCount == 0));
-    }
-    return (newSize == newPosBack) & _cache_success_finish(&diff);
-}

+ 0 - 48
hpatch/HPatchLite/hpatch_lite.h

@@ -1,48 +0,0 @@
-//patch_lite.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2020-2022 HouSisong All Rights Reserved.
-*/
-
-#ifndef _hpatch_lite_h
-#define _hpatch_lite_h
-#include "hpatch_lite_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//-----------------------------------------------------------------------------------------------------------------
-// hpatch_lite by stream: hpatch_lite_open()+hpatch_lite_patch() compiled by Mbed Studio is 662 bytes
-//   hdiffpatch v4.2.3, other patcher compiled by Mbed Studio:
-//      patch_single_stream() 2356 bytes (hpatch_StreamPos_t=hpatch_uint32_t)
-//      patch_decompress_with_cache() 2846 bytes (_IS_NEED_CACHE_OLD_BY_COVERS=0,hpatch_StreamPos_t=hpatch_uint32_t)
-
-//diff_data must created by create_lite_diff()
-
-typedef struct hpatchi_listener_t{
-    hpi_TInputStreamHandle  diff_data;
-    hpi_TInputStream_read   read_diff;
-    //must read data_size data to out_data, from read_from_pos of stream; if read error return hpi_FALSE;
-    hpi_BOOL (*read_old)(struct hpatchi_listener_t* listener,hpi_pos_t read_from_pos,hpi_byte* out_data,hpi_size_t data_size);
-    //must write data_size data to sequence stream; if write error return hpi_FALSE;
-    hpi_BOOL (*write_new)(struct hpatchi_listener_t* listener,const hpi_byte* data,hpi_size_t data_size);
-} hpatchi_listener_t;
-
-//hpatch_lite open
-// read lite headinfo from diff_data
-// if diff_data uncompress(*out_compress_type==hpi_compressType_no), *out_uncompressSize==0;
-// if (*out_compress_type!=hpi_compressType_no), you need open compressed data by decompresser 
-//      (see https://github.com/sisong/HPatchLite/decompresser_demo.h & https://github.com/sisong/HPatchLite/hpatchi.c)
-hpi_BOOL hpatch_lite_open(hpi_TInputStreamHandle diff_data,hpi_TInputStream_read read_diff,
-                          hpi_compressType* out_compress_type,hpi_pos_t* out_newSize,hpi_pos_t* out_uncompressSize);
-//hpatch_lite patch
-//	used temp_cache_size memory + {decompress buffer*1}
-//  note: temp_cache_size>=hpi_kMinCacheSize
-hpi_BOOL hpatch_lite_patch(hpatchi_listener_t* listener,hpi_pos_t newSize,
-                           hpi_byte* temp_cache,hpi_size_t temp_cache_size);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_hpatch_lite_h

+ 0 - 31
hpatch/HPatchLite/hpatch_lite_input_cache.h

@@ -1,31 +0,0 @@
-//hpatch_lite_input_cache.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2020-2022 HouSisong All Rights Reserved.
-*/
-#ifndef _hpatch_lite_input_cache_h
-#define _hpatch_lite_input_cache_h
-#include "hpatch_lite_types.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct _hpi_TInputCache{
-    hpi_size_t      cache_begin;
-    hpi_size_t      cache_end;
-    hpi_byte*       cache_buf;
-    hpi_TInputStreamHandle  inputStream;
-    hpi_TInputStream_read   read_code;
-} _hpi_TInputCache;
-
-static hpi_force_inline 
-hpi_BOOL _hpi_cache_success_finish(const _hpi_TInputCache* self){ return (self->cache_end!=0); }
-
-hpi_fast_uint8 _hpi_cache_read_1byte(struct _hpi_TInputCache* self);
-hpi_BOOL       _hpi_cache_update(struct _hpi_TInputCache* self);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_hpatch_lite_input_cache_h

+ 0 - 101
hpatch/HPatchLite/hpatch_lite_types.h

@@ -1,101 +0,0 @@
-//hpatch_lite_type.h
-//
-/*
- The MIT License (MIT)
- Copyright (c) 2020-2022 HouSisong All Rights Reserved.
-*/
-
-#ifndef _hpatch_lite_type_h
-#define _hpatch_lite_type_h
-#define NDEBUG
-#ifdef NDEBUG
-# ifndef assert
-#   define  assert(expression) ((void)0)
-# endif
-#else
-#   include <assert.h> //assert
-#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef hpi_byte
-    typedef     unsigned char   hpi_byte;
-#endif
-#ifndef hpi_fast_uint8
-    typedef     unsigned int    hpi_fast_uint8; //>= 8bit uint
-#endif
-#ifndef hpi_BOOL
-    typedef     hpi_fast_uint8  hpi_BOOL;
-#endif
-#define         hpi_FALSE       0
-#define         hpi_TRUE        1
-#ifndef hpi_size_t
-    typedef     unsigned int    hpi_size_t; //memory size type
-#endif
-#ifndef hpi_pos_t
-    typedef     unsigned int    hpi_pos_t; //file size type
-#endif
-
-#ifndef hpi_inline
-#if (defined(_MSC_VER))
-#   define hpi_inline __inline
-#else
-#   define hpi_inline inline
-#endif
-#endif
-#ifndef hpi_force_inline
-#if defined(_MSC_VER)
-#   define hpi_force_inline __forceinline
-#elif defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
-#   define hpi_force_inline __attribute__((always_inline)) inline
-#elif defined(__ICCARM__)
-#   define hpi_force_inline _Pragma("inline=forced")
-#else
-#   define hpi_force_inline hpi_inline
-#endif
-#endif
-
-#ifndef hpi_try_inline
-//#   define hpi_try_inline hpi_inline
-#   define hpi_try_inline
-#endif
-
-
-#ifndef _IS_RUN_MEM_SAFE_CHECK
-#   define _IS_RUN_MEM_SAFE_CHECK 1
-#endif
-
-#ifndef hpi_TInputStreamHandle
-    typedef void*   hpi_TInputStreamHandle;
-#endif
-
-//read (*data_size) data to out_data from sequence stream; if input stream end,set *data_size readed size; if read error return hpi_FALSE;
-typedef hpi_BOOL (*hpi_TInputStream_read)(hpi_TInputStreamHandle inputStream,hpi_byte* out_data,hpi_size_t* data_size);
-
-#ifndef hpi_kHeadSize
-#   define  hpi_kHeadSize       (2+1+1) //"hI" + hpi_compressType + (versionCode+newSize bytes+uncompressSize bytes) { + newSize + uncompressSize}
-#endif
-
-#ifndef hpi_kMinCacheSize
-#   define hpi_kMinCacheSize    (1*2)
-#endif
-
-typedef enum hpi_compressType{
-    hpi_compressType_no=0,
-    hpi_compressType_tuz=1, //tinyuz
-    hpi_compressType_zlib=2, //deflate format
-    hpi_compressType_lzma=3,
-    hpi_compressType_lzma2=4,
-    hpi_compressType_zstd=5,
-    hpi_compressType_bzip2=6,
-    hpi_compressType_lz4=7,
-    hpi_compressType_brotli=8,
-    hpi_compressType_lzham=9,
-    //...
-} hpi_compressType;
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_hpatch_lite_type_h

+ 62 - 0
hpatch_conf.h

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date             Author              Notes
  * 2024-10-24       liujitong           first version
+ * 2025-09-30       wdfk_prog           add decompresser config
  */
 
 #ifndef __hpatch_conf_h__
@@ -13,6 +14,67 @@
 
 #include "rtthread.h"
 
+#ifdef PKG_HPATCHLITE_DECOMPRESSER_TUZ
+/* 启用tuz解压功能 */
+#define _CompressPlugin_tuz 1
+/* 
+ * 0 (默认): Tinyuz 将使用自己独立的一套类型定义,如 tuz_byte, tuz_BOOL, _tuz_TInputCache 等。
+ * 1: Tinyuz 将会直接使用 HPatchLite 的类型定义,例如 tuz_byte 会被 #define 成 hpi_byte,_tuz_TInputCache 会被 #define 成 _hpi_TInputCache。
+ * 当 Tinyuz 和 HPatchLite 在同一个项目中紧密集成时,将此宏设为 1 可以减少代码体积。因为两种输入缓存结构体 (_TInputCache) 的实现可以被复用,从而节省几十到上百字节的Flash空间。
+ */
+#define _IS_USED_SHARE_hpatch_lite_types 1
+
+/* 
+ * 作用: 控制 Tinyuz 是否启用一种特殊的**“原文数据块(Literal Line)”**处理模式。
+ * 1 (默认,用于解压): 启用该模式。解压器能够处理一种特殊的指令,该指令表示“接下来的一段数据是未压缩的原文,请直接复制”。这对于处理那些本身就难以压缩的数据(如已压缩的图片、加密数据)非常有效,可以避免压缩算法在这些数据上“白费力气”,甚至防止压缩后体积变大的情况。
+ * 0: 禁用该模式。解压器将不认识“原文数据块”指令。
+ * 重要联动: 压缩端和解压端的这个宏设置必须完全一致!
+ * 如果您在PC端使用 hdiffi.exe -c-tuz ... 来打包,那么您在MCU端的 tuz_isNeedLiteralLine 必须是 1。
+ * 如果您在PC端使用 hdiffi.exe -c-tuzi ... (注意后面的 i) 来打包,那么您在MCU端的 tuz_isNeedLiteralLine 必须是 0。
+ * 设置为 0 可以减少解压端的代码体积(节省大约54字节),但代价是可能降低对混合数据的压缩率。
+ */
+// #define tuz_isNeedLiteralLine 0
+
+/* 禁用tuz断言 */
+// #define NDEBUG
+
+/* 
+ * 作用: 控制是否在代码中加入运行时的内存安全检查。
+ * 1 (默认): 启用检查。代码中会包含一些 assert 或类似的检查,用于在解压过程中判断是否存在缓冲区溢出、数据损坏等风险。这会使代码更健壮,但会稍微增加一点代码体积和运行开销。
+ * 0: 禁用检查。移除所有的安全断言。可以获得极致的代码大小和性能,但牺牲了运行时的安全性。通常只在经过充分测试、准备发布最终产品时才考虑关闭它。
+ */
+// #define _IS_RUN_MEM_SAFE_CHECK 1
+
+/*  
+ * tuz_kMaxOfDictSize 和 tuz_kDictSizeSavedBytes
+ * tuz_kMaxOfDictSize:
+ * 作用: 定义了 Tinyuz 算法理论上支持的最大字典大小。它不是您实际使用的字典大小,而是一个编译时的上限。
+ * 这个值会影响 tuz_kDictSizeSavedBytes 的计算。
+ * 
+ * tuz_kDictSizeSavedBytes:
+ * 作用: 这个宏非常重要。它决定了在压缩数据流的开头,用多少个字节来存储实际的字典大小值。
+ * 计算逻辑: 它是根据 tuz_kMaxOfDictSize 的大小自动计算的。
+ * 如果 tuz_kMaxOfDictSize 在 2^8-1 (255) 以内,就用1个字节存储。
+ * 如果在 2^16-1 (65535) 以内,就用2个字节存储。
+ * ... 以此类推。
+ * 目的: 这是一种空间优化。如果知道一个系统永远不会使用超过64KB的字典,就可以通过 tuz_kMaxOfDictSize 限制它,从而使存储字典大小的头部字段更小。 
+*/
+// #define tuz_kMaxOfDictSize (1<<30)
+
+/* 
+ * 作用: 这个宏定义了 Tinyuz 算法所能接受的最小字典大小(Minimum Dictionary Size)。
+ * 默认值: 1。
+ * 目的:
+ * 参数校验: 它主要用于参数合法性检查。当 hdiffi (压缩端) 或 tuz_dec (解压端) 接收到一个字典大小参数时,会检查这个值是否大于或等于 tuz_kMinOfDictSize。如果用户试图提供一个为0或无效的字典大小,这个检查可以防止程序出错。
+ * 算法下限: 它从理论上确立了算法可以工作的最小资源条件。虽然使用只有1个字节的字典几乎没有任何压缩效果,但算法本身在这种极端情况下依然是正确和有效的 */
+// #define tuz_kMinOfDictSize 1
+#endif
+
+// Future decompressors can be added here
+// #ifdef PKG_HPATCHLITE_DECOMPRESSER_ZLIB
+// #   define _CompressPlugin_zlib 1
+// #endif
+
 #define hpi_malloc(x) rt_malloc(x)
 #define hpi_free(x)   rt_free(x)
 

+ 1 - 1
hpatch_impl.c

@@ -9,7 +9,7 @@
  */
 
 #include "hpatch_impl.h"
-#include "hpatch_conf.h"
+#include "decompresser_demo.h"
 
 hpi_patch_result_t hpi_patch(hpatchi_listener_t *listener, int patch_cache_size, int decompress_cache_size, hpi_TInputStream_read _do_read_diff, read_old_t _do_read_old, write_new_t _do_write_new)
 {

+ 1 - 1
hpatch_impl.h

@@ -11,9 +11,9 @@
 #ifndef __hpatch_impl_h__
 #define __hpatch_impl_h__
 
+#include "hpatch_conf.h"
 #include "hpatch_lite.h"
 #include "patch_types.h"
-#include "decompresser_demo.h"
 
 typedef enum hpi_patch_result_t
 {