@bravemobile/react-native-code-push 13.0.0 → 13.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CodePush.podspec +35 -3
  2. package/README.md +115 -3
  3. package/THIRD-PARTY-NOTICES +96 -0
  4. package/android/app/build.gradle +19 -0
  5. package/android/app/proguard-rules.pro +5 -0
  6. package/android/app/src/main/cpp/CMakeLists.txt +38 -0
  7. package/android/app/src/main/cpp/binarypatch_jni.c +181 -0
  8. package/android/app/src/main/java/com/microsoft/codepush/react/BinaryPatchAttempt.java +92 -0
  9. package/android/app/src/main/java/com/microsoft/codepush/react/BinaryPatchResult.java +64 -0
  10. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +1 -1
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBinaryPatch.java +293 -0
  12. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +25 -0
  13. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +12 -2
  14. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +159 -4
  15. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +13 -0
  16. package/android/app/src/main/java/com/microsoft/codepush/react/HDiffPatchNative.java +52 -0
  17. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushBinaryPatchTest.java +393 -0
  18. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerBinaryPatchTest.java +207 -0
  19. package/android/app/src/test/java/com/microsoft/codepush/react/CodePushUpdateManagerDownloadTest.java +449 -0
  20. package/android/codepush-export.gradle +115 -0
  21. package/cli/commands/bundleCommand/bundleCodePush.ts +39 -7
  22. package/cli/commands/bundleCommand/index.ts +9 -1
  23. package/cli/commands/releaseCommand/addToReleaseHistory.ts +7 -0
  24. package/cli/commands/releaseCommand/index.test.ts +118 -0
  25. package/cli/commands/releaseCommand/index.ts +20 -2
  26. package/cli/commands/releaseCommand/release.test.ts +582 -0
  27. package/cli/commands/releaseCommand/release.ts +232 -15
  28. package/cli/dist/commands/bundleCommand/bundleCodePush.js +26 -7
  29. package/cli/dist/commands/bundleCommand/index.js +5 -1
  30. package/cli/dist/commands/releaseCommand/addToReleaseHistory.js +6 -1
  31. package/cli/dist/commands/releaseCommand/index.js +8 -1
  32. package/cli/dist/commands/releaseCommand/index.test.js +96 -0
  33. package/cli/dist/commands/releaseCommand/release.js +165 -17
  34. package/cli/dist/commands/releaseCommand/release.test.js +367 -0
  35. package/cli/dist/functions/makeBinaryPatchBundle.js +248 -0
  36. package/cli/dist/functions/makeBinaryPatchBundle.test.js +321 -0
  37. package/cli/dist/functions/makeCodePushBundle.js +4 -2
  38. package/cli/dist/functions/runHermesEmitBinaryCommand.js +48 -1
  39. package/cli/dist/functions/runHermesEmitBinaryCommand.test.js +100 -0
  40. package/cli/dist/jest.globalSetup.js +38 -0
  41. package/cli/dist/utils/binaryPatch.js +86 -0
  42. package/cli/dist/utils/binaryPatch.test.js +190 -0
  43. package/cli/functions/makeBinaryPatchBundle.test.ts +410 -0
  44. package/cli/functions/makeBinaryPatchBundle.ts +367 -0
  45. package/cli/functions/makeCodePushBundle.ts +4 -2
  46. package/cli/functions/runHermesEmitBinaryCommand.test.ts +124 -0
  47. package/cli/functions/runHermesEmitBinaryCommand.ts +57 -1
  48. package/cli/jest.globalSetup.ts +43 -0
  49. package/cli/utils/binaryPatch.test.ts +234 -0
  50. package/cli/utils/binaryPatch.ts +103 -0
  51. package/cpp/binarypatch/binarypatch_zstd_decompressor.c +187 -0
  52. package/cpp/binarypatch/binarypatch_zstd_decompressor.h +47 -0
  53. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/checksum_plugin.h +52 -0
  54. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/hpatch_mt/hpatch_mt.h +147 -0
  55. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch.c +3315 -0
  56. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch.h +268 -0
  57. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch_private.h +297 -0
  58. package/cpp/binarypatch/vendor/HDiffPatch/libHDiffPatch/HPatch/patch_types.h +434 -0
  59. package/cpp/binarypatch/vendor/zstd/common/allocations.h +55 -0
  60. package/cpp/binarypatch/vendor/zstd/common/bits.h +205 -0
  61. package/cpp/binarypatch/vendor/zstd/common/bitstream.h +454 -0
  62. package/cpp/binarypatch/vendor/zstd/common/compiler.h +464 -0
  63. package/cpp/binarypatch/vendor/zstd/common/cpu.h +249 -0
  64. package/cpp/binarypatch/vendor/zstd/common/debug.c +30 -0
  65. package/cpp/binarypatch/vendor/zstd/common/debug.h +107 -0
  66. package/cpp/binarypatch/vendor/zstd/common/entropy_common.c +340 -0
  67. package/cpp/binarypatch/vendor/zstd/common/error_private.c +64 -0
  68. package/cpp/binarypatch/vendor/zstd/common/error_private.h +158 -0
  69. package/cpp/binarypatch/vendor/zstd/common/fse.h +625 -0
  70. package/cpp/binarypatch/vendor/zstd/common/fse_decompress.c +315 -0
  71. package/cpp/binarypatch/vendor/zstd/common/huf.h +277 -0
  72. package/cpp/binarypatch/vendor/zstd/common/mem.h +422 -0
  73. package/cpp/binarypatch/vendor/zstd/common/pool.c +371 -0
  74. package/cpp/binarypatch/vendor/zstd/common/pool.h +81 -0
  75. package/cpp/binarypatch/vendor/zstd/common/portability_macros.h +171 -0
  76. package/cpp/binarypatch/vendor/zstd/common/threading.c +182 -0
  77. package/cpp/binarypatch/vendor/zstd/common/threading.h +142 -0
  78. package/cpp/binarypatch/vendor/zstd/common/xxhash.c +18 -0
  79. package/cpp/binarypatch/vendor/zstd/common/xxhash.h +7094 -0
  80. package/cpp/binarypatch/vendor/zstd/common/zstd_common.c +48 -0
  81. package/cpp/binarypatch/vendor/zstd/common/zstd_deps.h +123 -0
  82. package/cpp/binarypatch/vendor/zstd/common/zstd_internal.h +324 -0
  83. package/cpp/binarypatch/vendor/zstd/common/zstd_trace.h +156 -0
  84. package/cpp/binarypatch/vendor/zstd/decompress/huf_decompress.c +1944 -0
  85. package/cpp/binarypatch/vendor/zstd/decompress/zstd_ddict.c +244 -0
  86. package/cpp/binarypatch/vendor/zstd/decompress/zstd_ddict.h +44 -0
  87. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress.c +2410 -0
  88. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_block.c +2209 -0
  89. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_block.h +73 -0
  90. package/cpp/binarypatch/vendor/zstd/decompress/zstd_decompress_internal.h +240 -0
  91. package/cpp/binarypatch/vendor/zstd/zstd.h +3206 -0
  92. package/cpp/binarypatch/vendor/zstd/zstd_errors.h +107 -0
  93. package/ios/CodePush/CodePush.h +18 -1
  94. package/ios/CodePush/CodePush.mm +16 -1
  95. package/ios/CodePush/CodePushBinaryPatch.h +80 -0
  96. package/ios/CodePush/CodePushBinaryPatch.m +473 -0
  97. package/ios/CodePush/CodePushPackage.m +183 -2
  98. package/ios/CodePush/CodePushUpdateUtils.m +49 -1
  99. package/package.json +10 -3
  100. package/scripts/binary-patch/build-hdiffpatch.sh +86 -0
  101. package/scripts/export-embedded-bundle.sh +76 -0
  102. package/src/CodePush.js +46 -3
  103. package/src/CodePush.test.js +382 -0
  104. package/src/package-mixins.js +20 -2
  105. package/typings/react-native-code-push.d.ts +77 -0
@@ -0,0 +1,3315 @@
1
+ //patch.c
2
+ //
3
+ /*
4
+ The MIT License (MIT)
5
+ Copyright (c) 2012-2018 HouSisong
6
+
7
+ Permission is hereby granted, free of charge, to any person
8
+ obtaining a copy of this software and associated documentation
9
+ files (the "Software"), to deal in the Software without
10
+ restriction, including without limitation the rights to use,
11
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the
13
+ Software is furnished to do so, subject to the following
14
+ conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
+ OTHER DEALINGS IN THE SOFTWARE.
27
+ */
28
+ #include "patch.h"
29
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
30
+ # include <stdlib.h> //qsort
31
+ #endif
32
+ #include "patch_private.h"
33
+ #include "hpatch_mt/hpatch_mt.h"
34
+ #if (_HPATCH_IS_USED_MULTITHREAD)
35
+ # include "hpatch_mt/_hcache_window_old_mt.h"
36
+ # include "hpatch_mt/_hinput_mt.h"
37
+ #endif
38
+
39
+ #ifndef _IS_RUN_MEM_SAFE_CHECK
40
+ # define _IS_RUN_MEM_SAFE_CHECK 1
41
+ #endif
42
+
43
+ #if (_IS_RUN_MEM_SAFE_CHECK)
44
+ // __RUN_MEM_SAFE_CHECK : enables bounds checking for memory access to defend against potentially corrupted or maliciously crafted data.
45
+ # define __RUN_MEM_SAFE_CHECK
46
+ #endif
47
+
48
+ #ifdef __RUN_MEM_SAFE_CHECK
49
+ # define _SAFE_CHECK_DO(code) do{ if (!(code)) return _hpatch_FALSE; }while(0)
50
+ #else
51
+ # define _SAFE_CHECK_DO(code) do{ code; }while(0)
52
+ #endif
53
+
54
+ #define _hpatch_FALSE hpatch_FALSE
55
+ //hpatch_uint __hpatch_debug_check_false_x=0; //for debug
56
+ //#define _hpatch_FALSE (1/__hpatch_debug_check_false_x)
57
+
58
+ typedef unsigned char TByte;
59
+
60
+
61
+ //Variable-length positive integer encoding scheme (x bits for additional type flags, x<=7), outputs 1--n bytes from high:
62
+ // x0* 7-x bit
63
+ // x1* 0* 7+7-x bit
64
+ // x1* 1* 0* 7+7+7-x bit
65
+ // x1* 1* 1* 0* 7+7+7+7-x bit
66
+ // x1* 1* 1* 1* 0* 7+7+7+7+7-x bit
67
+ // ......
68
+ hpatch_BOOL hpatch_packUIntWithTag(TByte** out_code,TByte* out_code_end,
69
+ hpatch_StreamPos_t uValue,hpatch_uint highTag,
70
+ const hpatch_uint kTagBit){//write out integer and advance pointer.
71
+ TByte* pcode=*out_code;
72
+ const hpatch_StreamPos_t kMaxValueWithTag=((hpatch_StreamPos_t)1<<(7-kTagBit))-1;
73
+ size_t bCount=0;
74
+ assert((0<=kTagBit)&&(kTagBit<=7));
75
+ assert((highTag>>kTagBit)==0);
76
+ while ((uValue>>(7*bCount))>kMaxValueWithTag)
77
+ ++bCount;
78
+ #ifdef __RUN_MEM_SAFE_CHECK
79
+ if ((size_t)(out_code_end-pcode)<(1+bCount)) return _hpatch_FALSE;
80
+ #endif
81
+ *pcode++=(TByte)( (TByte)(uValue>>(7*bCount)) | (highTag<<(8-kTagBit))
82
+ | (((bCount>0)?1:0)<<(7-kTagBit)) );
83
+ while (bCount>0) {
84
+ --bCount;
85
+ *pcode++=((uValue>>(7*bCount))&((1<<7)-1)) | (TByte)(((bCount>0)?1:0)<<7);
86
+ }
87
+ *out_code=pcode;
88
+ return hpatch_TRUE;
89
+ }
90
+
91
+ hpatch_uint hpatch_packUIntWithTag_size(hpatch_StreamPos_t uValue,const hpatch_uint kTagBit){
92
+ const hpatch_StreamPos_t kMaxValueWithTag=((hpatch_StreamPos_t)1<<(7-kTagBit))-1;
93
+ hpatch_uint size=0;
94
+ while (uValue>kMaxValueWithTag) {
95
+ ++size;
96
+ uValue>>=7;
97
+ }
98
+ ++size;
99
+ return size;
100
+ }
101
+
102
+ hpatch_BOOL hpatch_unpackUIntWithTag(const TByte** src_code,const TByte* src_code_end,
103
+ hpatch_StreamPos_t* result,const hpatch_uint kTagBit){//read integer and advance pointer.
104
+ #ifdef __RUN_MEM_SAFE_CHECK
105
+ //const hpatch_uint kPackMaxTagBit=7;
106
+ #endif
107
+ hpatch_StreamPos_t value;
108
+ TByte code;
109
+ const TByte* pcode=*src_code;
110
+
111
+ #ifdef __RUN_MEM_SAFE_CHECK
112
+ //assert(kTagBit<=kPackMaxTagBit);
113
+ if (src_code_end<=pcode) return _hpatch_FALSE;
114
+ #endif
115
+ code=*pcode; ++pcode;
116
+ value=code&((1<<(7-kTagBit))-1);
117
+ if ((code&(1<<(7-kTagBit)))!=0){
118
+ do {
119
+ #ifdef __RUN_MEM_SAFE_CHECK
120
+ if ((value>>(sizeof(value)*8-7))!=0) return _hpatch_FALSE;//cannot save 7bit
121
+ if (src_code_end==pcode) return _hpatch_FALSE;
122
+ #endif
123
+ code=*pcode; ++pcode;
124
+ value=(value<<7) | (code&((1<<7)-1));
125
+ } while ((code&(1<<7))!=0);
126
+ }
127
+ (*src_code)=pcode;
128
+ *result=value;
129
+ return hpatch_TRUE;
130
+ }
131
+
132
+
133
+ static hpatch_BOOL _read_mem_stream(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
134
+ unsigned char* out_data,unsigned char* out_data_end){
135
+ const unsigned char* src=(const unsigned char*)stream->streamImport;
136
+ hpatch_size_t readLen=out_data_end-out_data;
137
+ #ifdef __RUN_MEM_SAFE_CHECK
138
+ if (readFromPos>stream->streamSize) return _hpatch_FALSE;
139
+ if (readLen>(hpatch_StreamPos_t)(stream->streamSize-readFromPos)) return _hpatch_FALSE;
140
+ #endif
141
+ memcpy(out_data,src+readFromPos,readLen);
142
+ return hpatch_TRUE;
143
+ }
144
+ const hpatch_TStreamInput* mem_as_hStreamInput(hpatch_TStreamInput* out_stream,
145
+ const unsigned char* mem,const unsigned char* mem_end){
146
+ assert(mem<=mem_end);
147
+ out_stream->streamImport=(void*)mem;
148
+ out_stream->streamSize=mem_end-mem;
149
+ out_stream->read=_read_mem_stream;
150
+ return out_stream;
151
+ }
152
+
153
+ // Two-segment memory stream
154
+ typedef struct TMem2StreamImport{
155
+ const unsigned char* seg1_begin;
156
+ const unsigned char* seg1_end;
157
+ const unsigned char* seg2_begin;
158
+ const unsigned char* seg2_end;
159
+ } TMem2StreamImport;
160
+
161
+ static hpatch_BOOL _read_mem2_stream(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
162
+ unsigned char* out_data,unsigned char* out_data_end){
163
+ const TMem2StreamImport* self=(const TMem2StreamImport*)stream->streamImport;
164
+ hpatch_size_t readLen=out_data_end-out_data;
165
+ const size_t seg1Len=(size_t)(self->seg1_end-self->seg1_begin);
166
+ #ifdef __RUN_MEM_SAFE_CHECK
167
+ if (readFromPos>stream->streamSize) return _hpatch_FALSE;
168
+ if (readLen>(hpatch_StreamPos_t)(stream->streamSize-readFromPos)) return _hpatch_FALSE;
169
+ #endif
170
+ while (readLen>0){
171
+ const unsigned char* src;
172
+ size_t srcOffset;
173
+ size_t copyLen;
174
+ if ((size_t)readFromPos<seg1Len){
175
+ src =self->seg1_begin;
176
+ srcOffset=(size_t)readFromPos;
177
+ copyLen =seg1Len-srcOffset;
178
+ }else{
179
+ src =self->seg2_begin;
180
+ srcOffset=(size_t)(readFromPos-seg1Len);
181
+ copyLen =(size_t)(self->seg2_end-self->seg2_begin)-srcOffset;
182
+ }
183
+ copyLen=copyLen<=readLen?copyLen:readLen;
184
+ memcpy(out_data,src+srcOffset,copyLen);
185
+ readFromPos+=(hpatch_StreamPos_t)copyLen;
186
+ out_data+=copyLen;
187
+ readLen-=copyLen;
188
+ }
189
+ return hpatch_TRUE;
190
+ }
191
+
192
+ static hpatch_inline
193
+ const hpatch_TStreamInput* mem2_as_hStreamInput(hpatch_TStreamInput* out_stream,TMem2StreamImport* import,
194
+ const unsigned char* seg1_begin,const unsigned char* seg1_end,
195
+ const unsigned char* seg2_begin,const unsigned char* seg2_end){
196
+ assert((seg1_begin<=seg1_end)&&(seg2_begin<=seg2_end));
197
+ import->seg1_begin=seg1_begin;
198
+ import->seg1_end =seg1_end;
199
+ import->seg2_begin=seg2_begin;
200
+ import->seg2_end =seg2_end;
201
+ out_stream->streamImport=import;
202
+ out_stream->streamSize=(seg1_end-seg1_begin)+(seg2_end-seg2_begin);
203
+ out_stream->read=_read_mem2_stream;
204
+ return out_stream;
205
+ }
206
+
207
+ static hpatch_BOOL _write_mem_stream(const hpatch_TStreamOutput* stream,hpatch_StreamPos_t writeToPos,
208
+ const unsigned char* data,const unsigned char* data_end){
209
+ unsigned char* out_dst=(unsigned char*)stream->streamImport;
210
+ hpatch_size_t writeLen=data_end-data;
211
+ #ifdef __RUN_MEM_SAFE_CHECK
212
+ if (writeToPos>stream->streamSize) return _hpatch_FALSE;
213
+ if (writeLen>(hpatch_StreamPos_t)(stream->streamSize-writeToPos)) return _hpatch_FALSE;
214
+ #endif
215
+ memcpy(out_dst+writeToPos,data,writeLen);
216
+ return hpatch_TRUE;
217
+ }
218
+ typedef hpatch_BOOL (*_read_mem_stream_t)(const hpatch_TStreamOutput* stream,hpatch_StreamPos_t readFromPos,
219
+ unsigned char* out_data,unsigned char* out_data_end);
220
+ const hpatch_TStreamOutput* mem_as_hStreamOutput(hpatch_TStreamOutput* out_stream,
221
+ unsigned char* mem,unsigned char* mem_end){
222
+ out_stream->streamImport=mem;
223
+ out_stream->streamSize=mem_end-mem;
224
+ out_stream->read_writed=(_read_mem_stream_t)_read_mem_stream;
225
+ out_stream->write=_write_mem_stream;
226
+ return out_stream;
227
+ }
228
+
229
+ hpatch_BOOL hpatch_deccompress_mem(hpatch_TDecompress* decompressPlugin,
230
+ const unsigned char* code,const unsigned char* code_end,
231
+ unsigned char* out_data,unsigned char* out_data_end){
232
+ hpatch_decompressHandle dec=0;
233
+ hpatch_BOOL result,colose_rt;
234
+ hpatch_TStreamInput codeStream;
235
+ mem_as_hStreamInput(&codeStream,code,code_end);
236
+ dec=decompressPlugin->open(decompressPlugin,(out_data_end-out_data),
237
+ &codeStream,0,codeStream.streamSize);
238
+ if (dec==0) return _hpatch_FALSE;
239
+ result=decompressPlugin->decompress_part(dec,out_data,out_data_end);
240
+ colose_rt=decompressPlugin->close(decompressPlugin,dec);
241
+ assert(colose_rt);
242
+ return result;
243
+ }
244
+
245
+
246
+ ////////
247
+ //patch by memory
248
+
249
+ static const hpatch_uint kSignTagBit=1;
250
+
251
+ static hpatch_BOOL _bytesRle_load(TByte* out_data,TByte* out_dataEnd,
252
+ const TByte* rle_code,const TByte* rle_code_end);
253
+ static void addData(TByte* dst,const TByte* src,hpatch_size_t length);
254
+ hpatch_inline
255
+ static hpatch_BOOL _unpackUIntWithTag(const TByte** src_code,const TByte* src_code_end,
256
+ hpatch_size_t* result,const hpatch_uint kTagBit){
257
+ if (sizeof(hpatch_size_t)==sizeof(hpatch_StreamPos_t)){
258
+ return hpatch_unpackUIntWithTag(src_code,src_code_end,(hpatch_StreamPos_t*)result,kTagBit);
259
+ }else{
260
+ hpatch_StreamPos_t u64=0;
261
+ hpatch_BOOL rt=hpatch_unpackUIntWithTag(src_code,src_code_end,&u64,kTagBit);
262
+ hpatch_size_t u=(hpatch_size_t)u64;
263
+ *result=u;
264
+ #ifdef __RUN_MEM_SAFE_CHECK
265
+ return rt&(u==u64);
266
+ #else
267
+ return rt;
268
+ #endif
269
+ }
270
+ }
271
+
272
+ #define unpackUIntWithTagTo(puint,src_code,src_code_end,kTagBit) \
273
+ _SAFE_CHECK_DO(_unpackUIntWithTag(src_code,src_code_end,puint,kTagBit))
274
+ #define unpackUIntTo(puint,src_code,src_code_end) \
275
+ unpackUIntWithTagTo(puint,src_code,src_code_end,0)
276
+
277
+ hpatch_BOOL patch(TByte* out_newData,TByte* out_newData_end,
278
+ const TByte* oldData,const TByte* oldData_end,
279
+ const TByte* serializedDiff,const TByte* serializedDiff_end){
280
+ const TByte *code_lengths, *code_lengths_end,
281
+ *code_inc_newPos, *code_inc_newPos_end,
282
+ *code_inc_oldPos, *code_inc_oldPos_end,
283
+ *code_newDataDiff, *code_newDataDiff_end;
284
+ hpatch_size_t coverCount;
285
+
286
+ assert(out_newData<=out_newData_end);
287
+ assert(oldData<=oldData_end);
288
+ assert(serializedDiff<=serializedDiff_end);
289
+ unpackUIntTo(&coverCount,&serializedDiff, serializedDiff_end);
290
+ { //head
291
+ hpatch_size_t lengthSize,inc_newPosSize,inc_oldPosSize,newDataDiffSize;
292
+ unpackUIntTo(&lengthSize,&serializedDiff, serializedDiff_end);
293
+ unpackUIntTo(&inc_newPosSize,&serializedDiff, serializedDiff_end);
294
+ unpackUIntTo(&inc_oldPosSize,&serializedDiff, serializedDiff_end);
295
+ unpackUIntTo(&newDataDiffSize,&serializedDiff, serializedDiff_end);
296
+ #ifdef __RUN_MEM_SAFE_CHECK
297
+ if (lengthSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
298
+ #endif
299
+ code_lengths=serializedDiff; serializedDiff+=lengthSize;
300
+ code_lengths_end=serializedDiff;
301
+ #ifdef __RUN_MEM_SAFE_CHECK
302
+ if (inc_newPosSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
303
+ #endif
304
+ code_inc_newPos=serializedDiff; serializedDiff+=inc_newPosSize;
305
+ code_inc_newPos_end=serializedDiff;
306
+ #ifdef __RUN_MEM_SAFE_CHECK
307
+ if (inc_oldPosSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
308
+ #endif
309
+ code_inc_oldPos=serializedDiff; serializedDiff+=inc_oldPosSize;
310
+ code_inc_oldPos_end=serializedDiff;
311
+ #ifdef __RUN_MEM_SAFE_CHECK
312
+ if (newDataDiffSize>(hpatch_size_t)(serializedDiff_end-serializedDiff)) return _hpatch_FALSE;
313
+ #endif
314
+ code_newDataDiff=serializedDiff; serializedDiff+=newDataDiffSize;
315
+ code_newDataDiff_end=serializedDiff;
316
+ }
317
+
318
+ //decode rle ; rle data begin==cur serializedDiff;
319
+ _SAFE_CHECK_DO(_bytesRle_load(out_newData, out_newData_end, serializedDiff, serializedDiff_end));
320
+
321
+ { //patch
322
+ const hpatch_size_t newDataSize=(hpatch_size_t)(out_newData_end-out_newData);
323
+ hpatch_size_t oldPosBack=0;
324
+ hpatch_size_t newPosBack=0;
325
+ hpatch_size_t i;
326
+ for (i=0; i<coverCount; ++i){
327
+ hpatch_size_t copyLength,addLength, oldPos,inc_oldPos,inc_oldPos_sign;
328
+ unpackUIntTo(&copyLength,&code_inc_newPos, code_inc_newPos_end);
329
+ unpackUIntTo(&addLength,&code_lengths, code_lengths_end);
330
+ #ifdef __RUN_MEM_SAFE_CHECK
331
+ if (code_inc_oldPos>=code_inc_oldPos_end) return _hpatch_FALSE;
332
+ #endif
333
+ inc_oldPos_sign=(*code_inc_oldPos)>>(8-kSignTagBit);
334
+ unpackUIntWithTagTo(&inc_oldPos,&code_inc_oldPos, code_inc_oldPos_end, kSignTagBit);
335
+ if (inc_oldPos_sign==0)
336
+ oldPos=oldPosBack+inc_oldPos;
337
+ else
338
+ oldPos=oldPosBack-inc_oldPos;
339
+ if (copyLength>0){
340
+ #ifdef __RUN_MEM_SAFE_CHECK
341
+ if (copyLength>(hpatch_size_t)(newDataSize-newPosBack)) return _hpatch_FALSE;
342
+ if (copyLength>(hpatch_size_t)(code_newDataDiff_end-code_newDataDiff)) return _hpatch_FALSE;
343
+ #endif
344
+ memcpy(out_newData+newPosBack,code_newDataDiff,copyLength);
345
+ code_newDataDiff+=copyLength;
346
+ newPosBack+=copyLength;
347
+ }
348
+ #ifdef __RUN_MEM_SAFE_CHECK
349
+ if ( (addLength>(hpatch_size_t)(newDataSize-newPosBack)) ) return _hpatch_FALSE;
350
+ if ( (oldPos>(hpatch_size_t)(oldData_end-oldData)) ||
351
+ (addLength>(hpatch_size_t)(oldData_end-oldData-oldPos)) ) return _hpatch_FALSE;
352
+ #endif
353
+ addData(out_newData+newPosBack,oldData+oldPos,addLength);
354
+ oldPosBack=oldPos;
355
+ newPosBack+=addLength;
356
+ }
357
+
358
+ if (newPosBack<newDataSize){
359
+ hpatch_size_t copyLength=newDataSize-newPosBack;
360
+ #ifdef __RUN_MEM_SAFE_CHECK
361
+ if (copyLength>(hpatch_size_t)(code_newDataDiff_end-code_newDataDiff)) return _hpatch_FALSE;
362
+ #endif
363
+ memcpy(out_newData+newPosBack,code_newDataDiff,copyLength);
364
+ code_newDataDiff+=copyLength;
365
+ //newPosBack=newDataSize;
366
+ }
367
+ }
368
+
369
+ if ( (code_lengths==code_lengths_end)
370
+ &&(code_inc_newPos==code_inc_newPos_end)
371
+ &&(code_inc_oldPos==code_inc_oldPos_end)
372
+ &&(code_newDataDiff==code_newDataDiff_end))
373
+ return hpatch_TRUE;
374
+ else
375
+ return _hpatch_FALSE;
376
+ }
377
+
378
+ hpatch_inline static void addData(TByte* dst,const TByte* src,hpatch_size_t length){
379
+ while (length--) { *dst++ += *src++; }
380
+ }
381
+
382
+ static hpatch_BOOL _bytesRle_load(TByte* out_data,TByte* out_dataEnd,
383
+ const TByte* rle_code,const TByte* rle_code_end){
384
+ const TByte* ctrlBuf,*ctrlBuf_end;
385
+ hpatch_size_t ctrlSize;
386
+ unpackUIntTo(&ctrlSize,&rle_code,rle_code_end);
387
+ #ifdef __RUN_MEM_SAFE_CHECK
388
+ if (ctrlSize>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
389
+ #endif
390
+ ctrlBuf=rle_code;
391
+ rle_code+=ctrlSize;
392
+ ctrlBuf_end=rle_code;
393
+ while (ctrlBuf_end-ctrlBuf>0){
394
+ enum TByteRleType type=(enum TByteRleType)((*ctrlBuf)>>(8-kByteRleType_bit));
395
+ hpatch_size_t length;
396
+ unpackUIntWithTagTo(&length,&ctrlBuf,ctrlBuf_end,kByteRleType_bit);
397
+ #ifdef __RUN_MEM_SAFE_CHECK
398
+ if (length>=(hpatch_size_t)(out_dataEnd-out_data)) return _hpatch_FALSE;
399
+ #endif
400
+ ++length;
401
+ switch (type){
402
+ case kByteRleType_rle0:{
403
+ memset(out_data,0,length);
404
+ out_data+=length;
405
+ }break;
406
+ case kByteRleType_rle255:{
407
+ memset(out_data,255,length);
408
+ out_data+=length;
409
+ }break;
410
+ case kByteRleType_rle:{
411
+ #ifdef __RUN_MEM_SAFE_CHECK
412
+ if (1>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
413
+ #endif
414
+ memset(out_data,*rle_code,length);
415
+ ++rle_code;
416
+ out_data+=length;
417
+ }break;
418
+ case kByteRleType_unrle:{
419
+ #ifdef __RUN_MEM_SAFE_CHECK
420
+ if (length>(hpatch_size_t)(rle_code_end-rle_code)) return _hpatch_FALSE;
421
+ #endif
422
+ memcpy(out_data,rle_code,length);
423
+ rle_code+=length;
424
+ out_data+=length;
425
+ }break;
426
+ }
427
+ }
428
+
429
+ if ( (ctrlBuf==ctrlBuf_end)
430
+ &&(rle_code==rle_code_end)
431
+ &&(out_data==out_dataEnd))
432
+ return hpatch_TRUE;
433
+ else
434
+ return _hpatch_FALSE;
435
+ }
436
+
437
+ //----------------------
438
+ //patch by stream
439
+
440
+ static hpatch_BOOL _TStreamInputClip_read(const hpatch_TStreamInput* stream,
441
+ hpatch_StreamPos_t readFromPos,
442
+ unsigned char* out_data,unsigned char* out_data_end){
443
+ TStreamInputClip* self=(TStreamInputClip*)stream->streamImport;
444
+ #ifdef __RUN_MEM_SAFE_CHECK
445
+ if (readFromPos+(out_data_end-out_data)>self->base.streamSize) return _hpatch_FALSE;
446
+ #endif
447
+ return self->srcStream->read(self->srcStream,readFromPos+self->clipBeginPos,out_data,out_data_end);
448
+ }
449
+ void TStreamInputClip_init(TStreamInputClip* self,const hpatch_TStreamInput* srcStream,
450
+ hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos){
451
+ assert(self!=0);
452
+ assert(srcStream!=0);
453
+ assert(clipBeginPos<=clipEndPos);
454
+ assert(clipEndPos<=srcStream->streamSize);
455
+ self->srcStream=srcStream;
456
+ self->clipBeginPos=clipBeginPos;
457
+ self->base.streamImport=self;
458
+ self->base.streamSize=clipEndPos-clipBeginPos;
459
+ self->base.read=_TStreamInputClip_read;
460
+ }
461
+
462
+ static hpatch_BOOL _TStreamOutputClip_write(const hpatch_TStreamOutput* stream,
463
+ hpatch_StreamPos_t writePos,
464
+ const unsigned char* data,const unsigned char* data_end){
465
+ TStreamOutputClip* self=(TStreamOutputClip*)stream->streamImport;
466
+ #ifdef __RUN_MEM_SAFE_CHECK
467
+ if (writePos+(data_end-data)>self->base.streamSize) return _hpatch_FALSE;
468
+ #endif
469
+ return self->srcStream->write(self->srcStream,writePos+self->clipBeginPos,data,data_end);
470
+ }
471
+
472
+ void TStreamOutputClip_init(TStreamOutputClip* self,const hpatch_TStreamOutput* srcStream,
473
+ hpatch_StreamPos_t clipBeginPos,hpatch_StreamPos_t clipEndPos){
474
+ assert(self!=0);
475
+ assert(srcStream!=0);
476
+ assert(clipBeginPos<=clipEndPos);
477
+ assert(clipEndPos<=srcStream->streamSize);
478
+ self->srcStream=srcStream;
479
+ self->clipBeginPos=clipBeginPos;
480
+ self->base.streamImport=self;
481
+ self->base.streamSize=clipEndPos-clipBeginPos;
482
+ ((TStreamInputClip*)self)->base.read=_TStreamInputClip_read;
483
+ self->base.write=_TStreamOutputClip_write;
484
+ }
485
+
486
+
487
+
488
+ //assert(hpatch_kStreamCacheSize>=hpatch_kMaxPluginTypeLength+1);
489
+ struct __private_hpatch_check_kMaxCompressTypeLength {
490
+ char _[(hpatch_kStreamCacheSize>=(hpatch_kMaxPluginTypeLength+1))?1:-1];};
491
+
492
+ hpatch_BOOL _TStreamCacheClip_readStr_end(TStreamCacheClip* sclip,TByte endTag,
493
+ char* out_type,size_t typeBufLen){
494
+ const TByte* type_begin;
495
+ hpatch_size_t i;
496
+ hpatch_size_t readLen=typeBufLen;
497
+ if (readLen>_TStreamCacheClip_leaveSize(sclip))
498
+ readLen=(hpatch_size_t)_TStreamCacheClip_leaveSize(sclip);
499
+ type_begin=_TStreamCacheClip_accessData(sclip,readLen);
500
+ if (type_begin==0) return _hpatch_FALSE;//not found
501
+ for (i=0; i<readLen; ++i) {
502
+ if (type_begin[i]!=endTag)
503
+ continue;
504
+ else{
505
+ memcpy(out_type,type_begin,i); out_type[i]='\0';
506
+ _TStreamCacheClip_skipData_noCheck(sclip,i+1);
507
+ return hpatch_TRUE;
508
+ }
509
+ }
510
+ return _hpatch_FALSE;//not found
511
+ }
512
+
513
+ hpatch_BOOL _TStreamCacheClip_updateCache(TStreamCacheClip* sclip){
514
+ TByte* buf0=&sclip->cacheBuf[0];
515
+ const hpatch_StreamPos_t streamSize=sclip->streamPos_end-sclip->streamPos;
516
+ hpatch_size_t readSize=sclip->cacheBegin;
517
+ if (readSize>streamSize)
518
+ readSize=(hpatch_size_t)streamSize;
519
+ if (readSize==0) return hpatch_TRUE;
520
+ if (!_TStreamCacheClip_isCacheEmpty(sclip)){
521
+ memmove(buf0+(hpatch_size_t)(sclip->cacheBegin-readSize),
522
+ buf0+sclip->cacheBegin,_TStreamCacheClip_cachedSize(sclip));
523
+ }
524
+ if (!sclip->srcStream->read(sclip->srcStream,sclip->streamPos,
525
+ buf0+(sclip->cacheEnd-readSize),buf0+sclip->cacheEnd))
526
+ return _hpatch_FALSE;//read error
527
+ sclip->cacheBegin-=readSize;
528
+ sclip->streamPos+=readSize;
529
+ return hpatch_TRUE;
530
+ }
531
+
532
+ hpatch_BOOL _TStreamCacheClip_skipData(TStreamCacheClip* sclip,hpatch_StreamPos_t skipLongSize){
533
+ while (skipLongSize>0) {
534
+ hpatch_size_t len=sclip->cacheEnd;
535
+ if (len>skipLongSize)
536
+ len=(hpatch_size_t)skipLongSize;
537
+ if (_TStreamCacheClip_accessData(sclip,len)){
538
+ _TStreamCacheClip_skipData_noCheck(sclip,len);
539
+ skipLongSize-=len;
540
+ }else{
541
+ return _hpatch_FALSE;
542
+ }
543
+ }
544
+ return hpatch_TRUE;
545
+ }
546
+
547
+ //assert(hpatch_kStreamCacheSize>=hpatch_kMaxPackedUIntBytes);
548
+ struct __private_hpatch_check_hpatch_kMaxPackedUIntBytes {
549
+ char _[(hpatch_kStreamCacheSize>=hpatch_kMaxPackedUIntBytes)?1:-1]; };
550
+
551
+ hpatch_BOOL _TStreamCacheClip_unpackUIntWithTag(TStreamCacheClip* sclip,hpatch_StreamPos_t* result,const hpatch_uint kTagBit){
552
+ TByte* curCode,*codeBegin;
553
+ hpatch_size_t readSize=hpatch_kMaxPackedUIntBytes;
554
+ const hpatch_StreamPos_t dataSize=_TStreamCacheClip_leaveSize(sclip);
555
+ if (readSize>dataSize)
556
+ readSize=(hpatch_size_t)dataSize;
557
+ codeBegin=_TStreamCacheClip_accessData(sclip,readSize);
558
+ if (codeBegin==0) return _hpatch_FALSE;
559
+ curCode=codeBegin;
560
+ _SAFE_CHECK_DO(hpatch_unpackUIntWithTag((const TByte**)&curCode,codeBegin+readSize,result,kTagBit));
561
+ _TStreamCacheClip_skipData_noCheck(sclip,(hpatch_size_t)(curCode-codeBegin));
562
+ return hpatch_TRUE;
563
+ }
564
+
565
+ hpatch_BOOL _TStreamCacheClip_readDataTo(TStreamCacheClip* sclip,TByte* out_buf,TByte* bufEnd){
566
+ hpatch_size_t readLen=_TStreamCacheClip_cachedSize(sclip);
567
+ hpatch_size_t outLen=bufEnd-out_buf;
568
+ if (readLen>=outLen)
569
+ readLen=outLen;
570
+ memcpy(out_buf,&sclip->cacheBuf[sclip->cacheBegin],readLen);
571
+ sclip->cacheBegin+=readLen;
572
+ outLen-=readLen;
573
+ if (outLen){
574
+ out_buf += readLen;
575
+ if (outLen<(sclip->cacheEnd>>1)){
576
+ if (!_TStreamCacheClip_updateCache(sclip)) return _hpatch_FALSE;
577
+ #ifdef __RUN_MEM_SAFE_CHECK
578
+ if (outLen>_TStreamCacheClip_cachedSize(sclip)) return _hpatch_FALSE;
579
+ #endif
580
+ return _TStreamCacheClip_readDataTo(sclip, out_buf, bufEnd);
581
+ }else{
582
+ if (!sclip->srcStream->read(sclip->srcStream,sclip->streamPos,
583
+ out_buf,bufEnd)) return _hpatch_FALSE;
584
+ sclip->streamPos+=outLen;
585
+ }
586
+ }
587
+ return hpatch_TRUE;
588
+ }
589
+
590
+ hpatch_BOOL _TStreamCacheClip_addDataTo(TStreamCacheClip* self,unsigned char* dst,hpatch_size_t addLen){
591
+ const unsigned char* src=_TStreamCacheClip_readData(self,addLen);
592
+ if (src==0) return _hpatch_FALSE;
593
+ addData(dst,src,addLen);
594
+ return hpatch_TRUE;
595
+ }
596
+
597
+ static hpatch_BOOL _decompress_read(const hpatch_TStreamInput* stream,
598
+ const hpatch_StreamPos_t readFromPos,
599
+ TByte* out_data,TByte* out_data_end){
600
+ _TDecompressInputStream* self=(_TDecompressInputStream*)stream->streamImport;
601
+ return self->decompressPlugin->decompress_part(self->decompressHandle,out_data,out_data_end);
602
+ }
603
+ hpatch_BOOL getStreamClip(TStreamCacheClip* out_clip,_TDecompressInputStream* out_stream,
604
+ hpatch_StreamPos_t dataSize,hpatch_StreamPos_t compressedSize,
605
+ const hpatch_TStreamInput* stream,hpatch_StreamPos_t* pCurStreamPos,
606
+ hpatch_TDecompress* decompressPlugin,TByte* aCache,hpatch_size_t cacheSize){
607
+ hpatch_StreamPos_t curStreamPos=*pCurStreamPos;
608
+ if (compressedSize==0){
609
+ #ifdef __RUN_MEM_SAFE_CHECK
610
+ if ((curStreamPos+dataSize)<curStreamPos) return _hpatch_FALSE;
611
+ if ((curStreamPos+dataSize)>stream->streamSize) return _hpatch_FALSE;
612
+ #endif
613
+ if (out_clip)
614
+ _TStreamCacheClip_init(out_clip,stream,curStreamPos,curStreamPos+dataSize,aCache,cacheSize);
615
+ curStreamPos+=dataSize;
616
+ }else{
617
+ #ifdef __RUN_MEM_SAFE_CHECK
618
+ if ((curStreamPos+compressedSize)<curStreamPos) return _hpatch_FALSE;
619
+ if ((curStreamPos+compressedSize)>stream->streamSize) return _hpatch_FALSE;
620
+ #endif
621
+ if (out_clip){
622
+ out_stream->IInputStream.streamImport=out_stream;
623
+ out_stream->IInputStream.streamSize=dataSize;
624
+ out_stream->IInputStream.read=_decompress_read;
625
+ out_stream->decompressPlugin=decompressPlugin;
626
+ if (out_stream->decompressHandle==0){
627
+ out_stream->decompressHandle=decompressPlugin->open(decompressPlugin,dataSize,stream,
628
+ curStreamPos,curStreamPos+compressedSize);
629
+ if (!out_stream->decompressHandle) return _hpatch_FALSE;
630
+ }else{
631
+ if (decompressPlugin->reset_code==0) return _hpatch_FALSE;
632
+ if (!decompressPlugin->reset_code(out_stream->decompressHandle,dataSize,stream,curStreamPos,
633
+ curStreamPos+compressedSize)) return _hpatch_FALSE;
634
+ }
635
+ _TStreamCacheClip_init(out_clip,&out_stream->IInputStream,0,
636
+ out_stream->IInputStream.streamSize,aCache,cacheSize);
637
+ }
638
+ curStreamPos+=compressedSize;
639
+ }
640
+ *pCurStreamPos=curStreamPos;
641
+ return hpatch_TRUE;
642
+ }
643
+
644
+ ///////
645
+
646
+ static hpatch_force_inline hpatch_BOOL __TOutStreamCache_writeStream(_TOutStreamCache* self,const TByte* data,hpatch_size_t dataSize){
647
+ if (!self->dstStream->write(self->dstStream,self->writeToPos,data,data+dataSize))
648
+ return _hpatch_FALSE;
649
+ self->writeToPos+=dataSize;
650
+ return hpatch_TRUE;
651
+ }
652
+
653
+ hpatch_BOOL _TOutStreamCache_flush(_TOutStreamCache* self){
654
+ hpatch_size_t curSize=self->cacheCur;
655
+ if (curSize>0){
656
+ if (!__TOutStreamCache_writeStream(self,self->cacheBuf,curSize))
657
+ return _hpatch_FALSE;
658
+ self->cacheCur=0;
659
+ }
660
+ return hpatch_TRUE;
661
+ }
662
+
663
+ hpatch_BOOL _TOutStreamCache_write(_TOutStreamCache* self,const TByte* data,hpatch_size_t dataSize){
664
+ while (dataSize>0) {
665
+ hpatch_size_t copyLen;
666
+ hpatch_size_t curSize=self->cacheCur;
667
+ if ((dataSize>=self->cacheEnd)&&(curSize==0)){
668
+ return __TOutStreamCache_writeStream(self,data,dataSize);
669
+ }
670
+ copyLen=self->cacheEnd-curSize;
671
+ copyLen=(copyLen<=dataSize)?copyLen:dataSize;
672
+ memcpy(self->cacheBuf+curSize,data,copyLen);
673
+ self->cacheCur=curSize+copyLen;
674
+ data+=copyLen;
675
+ dataSize-=copyLen;
676
+ if (self->cacheCur==self->cacheEnd){
677
+ if (!_TOutStreamCache_flush(self))
678
+ return _hpatch_FALSE;
679
+ }
680
+ }
681
+ return hpatch_TRUE;
682
+ }
683
+
684
+ hpatch_BOOL _TOutStreamCache_fill(_TOutStreamCache* self,hpatch_byte fillValue,hpatch_StreamPos_t fillLength){
685
+ assert(self->cacheBuf);
686
+ if (self->cacheBuf==0) return _hpatch_FALSE;
687
+ while (fillLength>0){
688
+ hpatch_size_t curSize=self->cacheCur;
689
+ hpatch_size_t runStep=self->cacheEnd-curSize;
690
+ runStep=(runStep<=fillLength)?runStep:(hpatch_size_t)fillLength;
691
+ memset(self->cacheBuf+curSize,fillValue,runStep);
692
+ self->cacheCur=curSize+runStep;
693
+ fillLength-=runStep;
694
+ if (self->cacheCur==self->cacheEnd){
695
+ if (!_TOutStreamCache_flush(self))
696
+ return _hpatch_FALSE;
697
+ }
698
+ }
699
+ return hpatch_TRUE;
700
+ }
701
+
702
+ hpatch_BOOL _TOutStreamCache_copyFromStream(_TOutStreamCache* self,const hpatch_TStreamInput* src,
703
+ hpatch_StreamPos_t srcPos,hpatch_StreamPos_t copyLength){
704
+ assert(self->cacheBuf);
705
+ if (self->cacheBuf==0) return _hpatch_FALSE;
706
+ while (copyLength>0){
707
+ hpatch_size_t curSize=self->cacheCur;
708
+ hpatch_size_t runStep=self->cacheEnd-curSize;
709
+ hpatch_byte* buf=self->cacheBuf+curSize;
710
+ runStep=(runStep<=copyLength)?runStep:(hpatch_size_t)copyLength;
711
+ if (!src->read(src,srcPos,buf,buf+runStep))
712
+ return _hpatch_FALSE;
713
+ srcPos+=runStep;
714
+ self->cacheCur=curSize+runStep;
715
+ copyLength-=runStep;
716
+ if (self->cacheCur==self->cacheEnd){
717
+ if (!_TOutStreamCache_flush(self))
718
+ return _hpatch_FALSE;
719
+ }
720
+ }
721
+ return hpatch_TRUE;
722
+ }
723
+
724
+ hpatch_BOOL _TOutStreamCache_copyFromClip(_TOutStreamCache* self,TStreamCacheClip* src,hpatch_StreamPos_t copyLength){
725
+ while (copyLength>0){
726
+ const TByte* data;
727
+ hpatch_size_t runStep=(src->cacheEnd<=copyLength)?src->cacheEnd:(hpatch_size_t)copyLength;
728
+ data=_TStreamCacheClip_readData(src,runStep);
729
+ if (data==0)
730
+ return _hpatch_FALSE;
731
+ if (!_TOutStreamCache_write(self,data,runStep))
732
+ return _hpatch_FALSE;
733
+ copyLength-=runStep;
734
+ }
735
+ return hpatch_TRUE;
736
+ }
737
+
738
+ hpatch_BOOL _TOutStreamCache_copyFromSelf(_TOutStreamCache* self,hpatch_StreamPos_t aheadLength,hpatch_StreamPos_t copyLength){
739
+ // [ writed ]
740
+ // [ cached buf | empty buf ]
741
+ const hpatch_TStreamInput* src=(const hpatch_TStreamInput*)self->dstStream;
742
+ hpatch_StreamPos_t srcPos=self->writeToPos+self->cacheCur-aheadLength;
743
+ if (src->read==0) //can't read
744
+ return _hpatch_FALSE;
745
+ if ((aheadLength<1)||(aheadLength>self->writeToPos+self->cacheCur))
746
+ return _hpatch_FALSE;
747
+
748
+ if (srcPos+copyLength<=self->writeToPos){//copy from stream
749
+ // [ copyLength ]
750
+ __copy_in_stream:
751
+ return _TOutStreamCache_copyFromStream(self,src,srcPos,copyLength);
752
+ }else if (srcPos>=self->writeToPos){ //copy in mem
753
+ // [ copyLength ]
754
+ __copy_in_mem:
755
+ while (copyLength>0){
756
+ hpatch_byte* dstBuf=self->cacheBuf+self->cacheCur;
757
+ hpatch_byte* srcBuf=dstBuf-(hpatch_size_t)aheadLength;
758
+ hpatch_size_t runLen=(self->cacheCur+copyLength<=self->cacheEnd)?(hpatch_size_t)copyLength:(self->cacheEnd-self->cacheCur);
759
+ hpatch_size_t i;
760
+ for (i=0;i<runLen;i++)
761
+ dstBuf[i]=srcBuf[i];
762
+ copyLength-=runLen;
763
+ self->cacheCur+=runLen;
764
+ if (self->cacheCur==self->cacheEnd){
765
+ if (!_TOutStreamCache_flush(self))
766
+ return _hpatch_FALSE;
767
+ runLen=(hpatch_size_t)((aheadLength<=copyLength)?aheadLength:copyLength);
768
+ memmove(self->cacheBuf,self->cacheBuf+self->cacheEnd-(hpatch_size_t)aheadLength,runLen);
769
+ self->cacheCur=runLen;
770
+ copyLength-=runLen;
771
+ }else{
772
+ assert(copyLength==0);
773
+ }
774
+ }
775
+ return hpatch_TRUE;
776
+ }else if (self->writeToPos+self->cacheCur<=srcPos+self->cacheEnd){
777
+ // small data in stream,can as copy in mem
778
+ hpatch_byte* dstBuf=self->cacheBuf+self->cacheCur;
779
+ hpatch_size_t runLen=(hpatch_size_t)(self->writeToPos-srcPos);
780
+ if (!src->read(src,srcPos,dstBuf,dstBuf+runLen))
781
+ return _hpatch_FALSE;
782
+ //srcPos+=runLen; //not used
783
+ copyLength-=runLen;
784
+ self->cacheCur+=runLen;
785
+ if (self->cacheCur==self->cacheEnd){
786
+ while (hpatch_TRUE){
787
+ if (self->cacheCur==self->cacheEnd){
788
+ if (!_TOutStreamCache_flush(self))
789
+ return _hpatch_FALSE;
790
+ }
791
+ if (copyLength>0){
792
+ runLen=(self->cacheEnd<=copyLength)?self->cacheEnd:(hpatch_size_t)copyLength;
793
+ //srcPos+=runLen; //not used
794
+ copyLength-=runLen;
795
+ self->cacheCur=runLen;
796
+ }else{
797
+ return hpatch_TRUE;
798
+ }
799
+ }
800
+ }else{
801
+ goto __copy_in_mem;
802
+ }
803
+ }else{
804
+ goto __copy_in_stream;
805
+ }
806
+ }
807
+
808
+
809
+ typedef struct _TBytesRle_load_stream{
810
+ hpatch_StreamPos_t memCopyLength;
811
+ hpatch_StreamPos_t memSetLength;
812
+ TByte memSetValue;
813
+ TStreamCacheClip ctrlClip;
814
+ TStreamCacheClip rleCodeClip;
815
+ } _TBytesRle_load_stream;
816
+
817
+ hpatch_inline
818
+ static void _TBytesRle_load_stream_init(_TBytesRle_load_stream* loader){
819
+ loader->memSetLength=0;
820
+ loader->memSetValue=0;//nil;
821
+ loader->memCopyLength=0;
822
+ _TStreamCacheClip_init(&loader->ctrlClip,0,0,0,0,0);
823
+ _TStreamCacheClip_init(&loader->rleCodeClip,0,0,0,0,0);
824
+ }
825
+
826
+ hpatch_inline static void memSet_add(TByte* dst,const TByte src,hpatch_size_t length){
827
+ while (length--) { (*dst++) += src; }
828
+ }
829
+
830
+ static hpatch_BOOL _TBytesRle_load_stream_mem_add(_TBytesRle_load_stream* loader,
831
+ hpatch_size_t* _decodeSize,TByte** _out_data){
832
+ hpatch_size_t decodeSize=*_decodeSize;
833
+ TByte* out_data=*_out_data;
834
+ TStreamCacheClip* rleCodeClip=&loader->rleCodeClip;
835
+
836
+ hpatch_StreamPos_t memSetLength=loader->memSetLength;
837
+ if (memSetLength!=0){
838
+ hpatch_size_t memSetStep=((memSetLength<=decodeSize)?(hpatch_size_t)memSetLength:decodeSize);
839
+ const TByte byteSetValue=loader->memSetValue;
840
+ if (out_data!=0){
841
+ if (byteSetValue!=0)
842
+ memSet_add(out_data,byteSetValue,memSetStep);
843
+ out_data+=memSetStep;
844
+ }
845
+ decodeSize-=memSetStep;
846
+ loader->memSetLength=memSetLength-memSetStep;
847
+ }
848
+ while ((loader->memCopyLength>0)&&(decodeSize>0)) {
849
+ TByte* rleData;
850
+ hpatch_size_t decodeStep=rleCodeClip->cacheEnd;
851
+ if (decodeStep>loader->memCopyLength)
852
+ decodeStep=(hpatch_size_t)loader->memCopyLength;
853
+ if (decodeStep>decodeSize)
854
+ decodeStep=decodeSize;
855
+ rleData=_TStreamCacheClip_readData(rleCodeClip,decodeStep);
856
+ if (rleData==0) return _hpatch_FALSE;
857
+ if (out_data){
858
+ addData(out_data,rleData,decodeStep);
859
+ out_data+=decodeStep;
860
+ }
861
+ decodeSize-=decodeStep;
862
+ loader->memCopyLength-=decodeStep;
863
+ }
864
+ *_decodeSize=decodeSize;
865
+ *_out_data=out_data;
866
+ return hpatch_TRUE;
867
+ }
868
+
869
+ hpatch_inline
870
+ static hpatch_BOOL _TBytesRle_load_stream_isFinish(const _TBytesRle_load_stream* loader){
871
+ return(loader->memSetLength==0)
872
+ &&(loader->memCopyLength==0)
873
+ &&(_TStreamCacheClip_isFinish(&loader->rleCodeClip))
874
+ &&(_TStreamCacheClip_isFinish(&loader->ctrlClip));
875
+ }
876
+
877
+
878
+
879
+ #define _clip_unpackUIntWithTagTo(puint,sclip,kTagBit) \
880
+ { if (!_TStreamCacheClip_unpackUIntWithTag(sclip,puint,kTagBit)) return _hpatch_FALSE; }
881
+ #define _clip_unpackUIntTo(puint,sclip) _clip_unpackUIntWithTagTo(puint,sclip,0)
882
+
883
+ static hpatch_BOOL _TBytesRle_load_stream_decode_add(_TBytesRle_load_stream* loader,
884
+ TByte* out_data,hpatch_size_t decodeSize){
885
+ if (!_TBytesRle_load_stream_mem_add(loader,&decodeSize,&out_data))
886
+ return _hpatch_FALSE;
887
+
888
+ while ((decodeSize>0)&&(!_TStreamCacheClip_isFinish(&loader->ctrlClip))){
889
+ enum TByteRleType type;
890
+ hpatch_StreamPos_t length;
891
+ const TByte* pType=_TStreamCacheClip_accessData(&loader->ctrlClip,1);
892
+ if (pType==0) return _hpatch_FALSE;
893
+ type=(enum TByteRleType)((*pType)>>(8-kByteRleType_bit));
894
+ _clip_unpackUIntWithTagTo(&length,&loader->ctrlClip,kByteRleType_bit);
895
+ ++length;
896
+ switch (type){
897
+ case kByteRleType_rle0:{
898
+ loader->memSetLength=length;
899
+ loader->memSetValue=0;
900
+ }break;
901
+ case kByteRleType_rle255:{
902
+ loader->memSetLength=length;
903
+ loader->memSetValue=255;
904
+ }break;
905
+ case kByteRleType_rle:{
906
+ const TByte* pSetValue=_TStreamCacheClip_readData(&loader->rleCodeClip,1);
907
+ if (pSetValue==0) return _hpatch_FALSE;
908
+ loader->memSetValue=*pSetValue;
909
+ loader->memSetLength=length;
910
+ }break;
911
+ case kByteRleType_unrle:{
912
+ loader->memCopyLength=length;
913
+ }break;
914
+ }
915
+ if (!_TBytesRle_load_stream_mem_add(loader,&decodeSize,&out_data)) return _hpatch_FALSE;
916
+ }
917
+
918
+ if (decodeSize==0)
919
+ return hpatch_TRUE;
920
+ else
921
+ return _hpatch_FALSE;
922
+ }
923
+
924
+ #define _TBytesRle_load_stream_decode_skip(loader,decodeSize) \
925
+ _TBytesRle_load_stream_decode_add(loader,0,decodeSize)
926
+
927
+ static hpatch_BOOL _patch_add_old_with_rle(_TOutStreamCache* outCache,_TBytesRle_load_stream* rle_loader,
928
+ const hpatch_TStreamInput* old,hpatch_StreamPos_t oldPos,
929
+ hpatch_StreamPos_t addLength,TByte* aCache,hpatch_size_t aCacheSize){
930
+ while (addLength>0){
931
+ hpatch_size_t decodeStep=aCacheSize;
932
+ if (decodeStep>addLength)
933
+ decodeStep=(hpatch_size_t)addLength;
934
+ if (!old->read(old,oldPos,aCache,aCache+decodeStep)) return _hpatch_FALSE;
935
+ if (!_TBytesRle_load_stream_decode_add(rle_loader,aCache,decodeStep)) return _hpatch_FALSE;
936
+ if (!_TOutStreamCache_write(outCache,aCache,decodeStep)) return _hpatch_FALSE;
937
+ oldPos+=decodeStep;
938
+ addLength-=decodeStep;
939
+ }
940
+ return hpatch_TRUE;
941
+ }
942
+
943
+ typedef struct _TCovers{
944
+ hpatch_TCovers ICovers;
945
+ hpatch_StreamPos_t coverCount;
946
+ hpatch_StreamPos_t oldPosBack;
947
+ hpatch_StreamPos_t newPosBack;
948
+ TStreamCacheClip* code_inc_oldPosClip;
949
+ TStreamCacheClip* code_inc_newPosClip;
950
+ TStreamCacheClip* code_lengthsClip;
951
+ hpatch_BOOL isOldPosBackNeedAddLength;
952
+ } _TCovers;
953
+
954
+ static hpatch_StreamPos_t _covers_leaveCoverCount(const hpatch_TCovers* covers){
955
+ const _TCovers* self=(const _TCovers*)covers;
956
+ return self->coverCount;
957
+ }
958
+ static hpatch_BOOL _covers_close_nil(hpatch_TCovers* covers){
959
+ //empty
960
+ return hpatch_TRUE;
961
+ }
962
+
963
+ static hpatch_BOOL _read_sign_pos_byLastPos(TStreamCacheClip* clip,hpatch_StreamPos_t* pLastOldPos){
964
+ hpatch_StreamPos_t absDelta;
965
+ const TByte* pSignByte=_TStreamCacheClip_accessData(clip,1);
966
+ if (!pSignByte) return _hpatch_FALSE;
967
+ hpatch_BOOL isNeg=((*pSignByte)>>(8-kSignTagBit));
968
+ _clip_unpackUIntWithTagTo(&absDelta,clip,kSignTagBit);
969
+ if (isNeg)
970
+ *pLastOldPos-=absDelta;
971
+ else
972
+ *pLastOldPos+=absDelta;
973
+ return hpatch_TRUE;
974
+ }
975
+
976
+ static hpatch_BOOL _covers_read_cover(hpatch_TCovers* covers,hpatch_TCover* out_cover){
977
+ _TCovers* self=(_TCovers*)covers;
978
+ hpatch_StreamPos_t oldPosBack=self->oldPosBack;
979
+ hpatch_StreamPos_t newPosBack=self->newPosBack;
980
+ hpatch_StreamPos_t coverCount=self->coverCount;
981
+ if (coverCount>0)
982
+ self->coverCount=coverCount-1;
983
+ else
984
+ return _hpatch_FALSE;
985
+
986
+ {
987
+ hpatch_StreamPos_t copyLength,coverLength;
988
+ if (!_read_sign_pos_byLastPos(self->code_inc_oldPosClip,&oldPosBack))
989
+ return _hpatch_FALSE;
990
+ _clip_unpackUIntTo(&copyLength,self->code_inc_newPosClip);
991
+ _clip_unpackUIntTo(&coverLength,self->code_lengthsClip);
992
+ newPosBack+=copyLength;
993
+
994
+ out_cover->oldPos=oldPosBack;
995
+ out_cover->newPos=newPosBack;
996
+ out_cover->length=coverLength;
997
+ oldPosBack+=(self->isOldPosBackNeedAddLength)?coverLength:0;
998
+ newPosBack+=coverLength;
999
+ }
1000
+ self->oldPosBack=oldPosBack;
1001
+ self->newPosBack=newPosBack;
1002
+ return hpatch_TRUE;
1003
+ }
1004
+
1005
+ static hpatch_BOOL _covers_is_finish(const struct hpatch_TCovers* covers){
1006
+ _TCovers* self=(_TCovers*)covers;
1007
+ return _TStreamCacheClip_isFinish(self->code_lengthsClip)
1008
+ && _TStreamCacheClip_isFinish(self->code_inc_newPosClip)
1009
+ && _TStreamCacheClip_isFinish(self->code_inc_oldPosClip);
1010
+ }
1011
+
1012
+
1013
+ static void _covers_init(_TCovers* covers,hpatch_StreamPos_t coverCount,
1014
+ TStreamCacheClip* code_inc_oldPosClip,
1015
+ TStreamCacheClip* code_inc_newPosClip,
1016
+ TStreamCacheClip* code_lengthsClip,
1017
+ hpatch_BOOL isOldPosBackNeedAddLength){
1018
+ covers->ICovers.leave_cover_count=_covers_leaveCoverCount;
1019
+ covers->ICovers.read_cover=_covers_read_cover;
1020
+ covers->ICovers.is_finish=_covers_is_finish;
1021
+ covers->ICovers.close=_covers_close_nil;
1022
+ covers->coverCount=coverCount;
1023
+ covers->newPosBack=0;
1024
+ covers->oldPosBack=0;
1025
+ covers->code_inc_oldPosClip=code_inc_oldPosClip;
1026
+ covers->code_inc_newPosClip=code_inc_newPosClip;
1027
+ covers->code_lengthsClip=code_lengthsClip;
1028
+ covers->isOldPosBackNeedAddLength=isOldPosBackNeedAddLength;
1029
+ }
1030
+
1031
+ static hpatch_BOOL _rle_decode_skip(struct _TBytesRle_load_stream* rle_loader,hpatch_StreamPos_t copyLength){
1032
+ while (copyLength>0) {
1033
+ hpatch_size_t len=(~(hpatch_size_t)0);
1034
+ if (len>copyLength)
1035
+ len=(hpatch_size_t)copyLength;
1036
+ if (!_TBytesRle_load_stream_decode_skip(rle_loader,len)) return _hpatch_FALSE;
1037
+ copyLength-=len;
1038
+ }
1039
+ return hpatch_TRUE;
1040
+ }
1041
+
1042
+ static hpatch_BOOL patchByClip(_TOutStreamCache* outCache,
1043
+ const hpatch_TStreamInput* oldData,
1044
+ hpatch_TCovers* covers,
1045
+ TStreamCacheClip* code_newDataDiffClip,
1046
+ struct _TBytesRle_load_stream* rle_loader,
1047
+ TByte* temp_cache,hpatch_size_t cache_size){
1048
+ const hpatch_StreamPos_t newDataSize=_TOutStreamCache_leaveSize(outCache);
1049
+ const hpatch_StreamPos_t oldDataSize=oldData->streamSize;
1050
+ hpatch_StreamPos_t coverCount=covers->leave_cover_count(covers);
1051
+ hpatch_StreamPos_t newPosBack=0;
1052
+ assert(cache_size>=hpatch_kMaxPackedUIntBytes);
1053
+
1054
+ while (coverCount--){
1055
+ hpatch_TCover cover;
1056
+ if(!covers->read_cover(covers,&cover)) return _hpatch_FALSE;
1057
+ #ifdef __RUN_MEM_SAFE_CHECK
1058
+ if (cover.newPos<newPosBack) return _hpatch_FALSE;
1059
+ if (cover.length>(hpatch_StreamPos_t)(newDataSize-cover.newPos)) return _hpatch_FALSE;
1060
+ if (cover.oldPos>oldDataSize) return _hpatch_FALSE;
1061
+ if (cover.length>(hpatch_StreamPos_t)(oldDataSize-cover.oldPos)) return _hpatch_FALSE;
1062
+ #endif
1063
+ if (newPosBack<cover.newPos){
1064
+ hpatch_StreamPos_t copyLength=cover.newPos-newPosBack;
1065
+ if (!_TOutStreamCache_copyFromClip(outCache,code_newDataDiffClip,copyLength)) return _hpatch_FALSE;
1066
+ if (!_rle_decode_skip(rle_loader,copyLength)) return _hpatch_FALSE;
1067
+ }
1068
+ if (!_patch_add_old_with_rle(outCache,rle_loader,oldData,cover.oldPos,cover.length,
1069
+ temp_cache,cache_size)) return _hpatch_FALSE;
1070
+ newPosBack=cover.newPos+cover.length;
1071
+ }
1072
+
1073
+ if (newPosBack<newDataSize){
1074
+ hpatch_StreamPos_t copyLength=newDataSize-newPosBack;
1075
+ if (!_TOutStreamCache_copyFromClip(outCache,code_newDataDiffClip,copyLength)) return _hpatch_FALSE;
1076
+ if (!_rle_decode_skip(rle_loader,copyLength)) return _hpatch_FALSE;
1077
+ newPosBack=newDataSize;
1078
+ }
1079
+ if (!_TOutStreamCache_flush(outCache))
1080
+ return _hpatch_FALSE;
1081
+ if ( _TBytesRle_load_stream_isFinish(rle_loader)
1082
+ && covers->is_finish(covers)
1083
+ && _TOutStreamCache_isFinish(outCache)
1084
+ && _TStreamCacheClip_isFinish(code_newDataDiffClip)
1085
+ && (newPosBack==newDataSize) )
1086
+ return hpatch_TRUE;
1087
+ else
1088
+ return _hpatch_FALSE;
1089
+ }
1090
+
1091
+
1092
+ #define _kCachePatCount 8
1093
+
1094
+ #define _cache_alloc(dst,dst_type,memSize,temp_cache,temp_cache_end){ \
1095
+ if ((hpatch_size_t)(temp_cache_end-temp_cache) < \
1096
+ sizeof(hpatch_StreamPos_t)+(memSize)) return hpatch_FALSE; \
1097
+ (dst)=(dst_type*)_hpatch_align_upper(temp_cache,sizeof(hpatch_StreamPos_t));\
1098
+ temp_cache=(TByte*)(dst)+(hpatch_size_t)(memSize); \
1099
+ }
1100
+
1101
+ typedef struct _TPackedCovers{
1102
+ _TCovers base;
1103
+ TStreamCacheClip code_inc_oldPosClip;
1104
+ TStreamCacheClip code_inc_newPosClip;
1105
+ TStreamCacheClip code_lengthsClip;
1106
+ } _TPackedCovers;
1107
+
1108
+ typedef struct _THDiffHead{
1109
+ hpatch_StreamPos_t coverCount;
1110
+ hpatch_StreamPos_t lengthSize;
1111
+ hpatch_StreamPos_t inc_newPosSize;
1112
+ hpatch_StreamPos_t inc_oldPosSize;
1113
+ hpatch_StreamPos_t newDataDiffSize;
1114
+ hpatch_StreamPos_t headEndPos;
1115
+ hpatch_StreamPos_t coverEndPos;
1116
+ } _THDiffHead;
1117
+
1118
+ static hpatch_BOOL read_diff_head(_THDiffHead* out_diffHead,
1119
+ const hpatch_TStreamInput* serializedDiff){
1120
+ hpatch_StreamPos_t diffPos0;
1121
+ const hpatch_StreamPos_t diffPos_end=serializedDiff->streamSize;
1122
+ TByte temp_cache[hpatch_kStreamCacheSize];
1123
+ TStreamCacheClip diffHeadClip;
1124
+ _TStreamCacheClip_init(&diffHeadClip,serializedDiff,0,diffPos_end,temp_cache,hpatch_kStreamCacheSize);
1125
+ _clip_unpackUIntTo(&out_diffHead->coverCount,&diffHeadClip);
1126
+ _clip_unpackUIntTo(&out_diffHead->lengthSize,&diffHeadClip);
1127
+ _clip_unpackUIntTo(&out_diffHead->inc_newPosSize,&diffHeadClip);
1128
+ _clip_unpackUIntTo(&out_diffHead->inc_oldPosSize,&diffHeadClip);
1129
+ _clip_unpackUIntTo(&out_diffHead->newDataDiffSize,&diffHeadClip);
1130
+ diffPos0=(hpatch_StreamPos_t)(_TStreamCacheClip_readPosOfSrcStream(&diffHeadClip));
1131
+ out_diffHead->headEndPos=diffPos0;
1132
+ #ifdef __RUN_MEM_SAFE_CHECK
1133
+ if (out_diffHead->lengthSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
1134
+ #endif
1135
+ diffPos0+=out_diffHead->lengthSize;
1136
+ #ifdef __RUN_MEM_SAFE_CHECK
1137
+ if (out_diffHead->inc_newPosSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
1138
+ #endif
1139
+ diffPos0+=out_diffHead->inc_newPosSize;
1140
+ #ifdef __RUN_MEM_SAFE_CHECK
1141
+ if (out_diffHead->inc_oldPosSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
1142
+ #endif
1143
+ diffPos0+=out_diffHead->inc_oldPosSize;
1144
+ out_diffHead->coverEndPos=diffPos0;
1145
+ #ifdef __RUN_MEM_SAFE_CHECK
1146
+ if (out_diffHead->newDataDiffSize>(hpatch_StreamPos_t)(diffPos_end-diffPos0)) return _hpatch_FALSE;
1147
+ #endif
1148
+ return hpatch_TRUE;
1149
+ }
1150
+
1151
+ static hpatch_BOOL _packedCovers_open(_TPackedCovers** out_self,
1152
+ _THDiffHead* out_diffHead,
1153
+ const hpatch_TStreamInput* serializedDiff,
1154
+ TByte* temp_cache,TByte* temp_cache_end){
1155
+ hpatch_size_t cacheSize;
1156
+ _TPackedCovers* self=0;
1157
+ _cache_alloc(self,_TPackedCovers,sizeof(_TPackedCovers),temp_cache,temp_cache_end);
1158
+ cacheSize=(temp_cache_end-temp_cache)/3;
1159
+ {
1160
+ hpatch_StreamPos_t diffPos0;
1161
+ if (!read_diff_head(out_diffHead,serializedDiff)) return _hpatch_FALSE;
1162
+ diffPos0=out_diffHead->headEndPos;
1163
+ _TStreamCacheClip_init(&self->code_lengthsClip,serializedDiff,diffPos0,
1164
+ diffPos0+out_diffHead->lengthSize,temp_cache,cacheSize);
1165
+ temp_cache+=cacheSize;
1166
+ diffPos0+=out_diffHead->lengthSize;
1167
+ _TStreamCacheClip_init(&self->code_inc_newPosClip,serializedDiff,diffPos0,
1168
+ diffPos0+out_diffHead->inc_newPosSize,temp_cache,cacheSize);
1169
+ temp_cache+=cacheSize;
1170
+ diffPos0+=out_diffHead->inc_newPosSize;
1171
+ _TStreamCacheClip_init(&self->code_inc_oldPosClip,serializedDiff,diffPos0,
1172
+ diffPos0+out_diffHead->inc_oldPosSize,temp_cache,cacheSize);
1173
+ }
1174
+
1175
+ _covers_init(&self->base,out_diffHead->coverCount,&self->code_inc_oldPosClip,
1176
+ &self->code_inc_newPosClip,&self->code_lengthsClip,hpatch_FALSE);
1177
+ *out_self=self;
1178
+ return hpatch_TRUE;
1179
+ }
1180
+
1181
+ static hpatch_BOOL _patch_stream_with_cache(const hpatch_TStreamOutput* out_newData,
1182
+ const hpatch_TStreamInput* oldData,
1183
+ const hpatch_TStreamInput* serializedDiff,
1184
+ hpatch_TCovers* cached_covers,
1185
+ TByte* temp_cache,TByte* temp_cache_end){
1186
+ struct _THDiffHead diffHead;
1187
+ TStreamCacheClip code_newDataDiffClip;
1188
+ struct _TBytesRle_load_stream rle_loader;
1189
+ hpatch_TCovers* pcovers=0;
1190
+ hpatch_StreamPos_t diffPos0;
1191
+ const hpatch_StreamPos_t diffPos_end=serializedDiff->streamSize;
1192
+ const hpatch_size_t cacheSize=(temp_cache_end-temp_cache)/(cached_covers?(_kCachePatCount-3):_kCachePatCount);
1193
+
1194
+ assert(out_newData!=0);
1195
+ assert(out_newData->write!=0);
1196
+ assert(oldData!=0);
1197
+ assert(oldData->read!=0);
1198
+ assert(serializedDiff!=0);
1199
+ assert(serializedDiff->read!=0);
1200
+
1201
+ //covers
1202
+ if (cached_covers==0){
1203
+ struct _TPackedCovers* packedCovers;
1204
+ if (!_packedCovers_open(&packedCovers,&diffHead,serializedDiff,temp_cache+cacheSize*(_kCachePatCount-3),
1205
+ temp_cache_end)) return _hpatch_FALSE;
1206
+ pcovers=&packedCovers->base.ICovers; //not need close before return
1207
+ }else{
1208
+ pcovers=cached_covers;
1209
+ if (!read_diff_head(&diffHead,serializedDiff)) return _hpatch_FALSE;
1210
+ }
1211
+ //newDataDiff
1212
+ diffPos0=diffHead.coverEndPos;
1213
+ _TStreamCacheClip_init(&code_newDataDiffClip,serializedDiff,diffPos0,
1214
+ diffPos0+diffHead.newDataDiffSize,temp_cache,cacheSize);
1215
+ temp_cache+=cacheSize;
1216
+ diffPos0+=diffHead.newDataDiffSize;
1217
+
1218
+ {//rle
1219
+ hpatch_StreamPos_t rleCtrlSize;
1220
+ hpatch_StreamPos_t rlePos0;
1221
+ TStreamCacheClip* rleHeadClip=&rle_loader.ctrlClip;//rename, share address
1222
+ #ifdef __RUN_MEM_SAFE_CHECK
1223
+ if (cacheSize<hpatch_kMaxPackedUIntBytes) return _hpatch_FALSE;
1224
+ #endif
1225
+ _TStreamCacheClip_init(rleHeadClip,serializedDiff,diffPos0,diffPos_end,
1226
+ temp_cache,hpatch_kMaxPackedUIntBytes);
1227
+ _clip_unpackUIntTo(&rleCtrlSize,rleHeadClip);
1228
+ rlePos0=(hpatch_StreamPos_t)(_TStreamCacheClip_readPosOfSrcStream(rleHeadClip));
1229
+ #ifdef __RUN_MEM_SAFE_CHECK
1230
+ if (rleCtrlSize>(hpatch_StreamPos_t)(diffPos_end-rlePos0)) return _hpatch_FALSE;
1231
+ #endif
1232
+ _TBytesRle_load_stream_init(&rle_loader);
1233
+ _TStreamCacheClip_init(&rle_loader.ctrlClip,serializedDiff,rlePos0,rlePos0+rleCtrlSize,
1234
+ temp_cache,cacheSize);
1235
+ temp_cache+=cacheSize;
1236
+ _TStreamCacheClip_init(&rle_loader.rleCodeClip,serializedDiff,rlePos0+rleCtrlSize,diffPos_end,
1237
+ temp_cache,cacheSize);
1238
+ temp_cache+=cacheSize;
1239
+ }
1240
+ {
1241
+ _TOutStreamCache outCache;
1242
+ _TOutStreamCache_init(&outCache,out_newData,temp_cache,cacheSize);
1243
+ temp_cache+=cacheSize;
1244
+ return patchByClip(&outCache,oldData,pcovers,&code_newDataDiffClip,
1245
+ &rle_loader,temp_cache,cacheSize);
1246
+ }
1247
+ }
1248
+
1249
+
1250
+ hpatch_BOOL read_diffz_head(hpatch_compressedDiffInfo* out_diffInfo,_THDiffzHead* out_head,
1251
+ const hpatch_TStreamInput* compressedDiff){
1252
+ TStreamCacheClip _diffHeadClip;
1253
+ TStreamCacheClip* diffHeadClip=&_diffHeadClip;
1254
+ TByte temp_cache[hpatch_kStreamCacheSize];
1255
+ _TStreamCacheClip_init(&_diffHeadClip,compressedDiff,0,compressedDiff->streamSize,
1256
+ temp_cache,hpatch_kStreamCacheSize);
1257
+ {//type
1258
+ const char* kVersionType="HDIFF13";
1259
+ char* tempType=out_diffInfo->compressType;
1260
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'&',tempType)) return _hpatch_FALSE;
1261
+ if (0!=strcmp(tempType,kVersionType)) return hpatch_FALSE;
1262
+ }
1263
+ {//read compressType
1264
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'\0',
1265
+ out_diffInfo->compressType)) return _hpatch_FALSE;
1266
+ out_head->typesEndPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
1267
+ }
1268
+ _clip_unpackUIntTo(&out_diffInfo->newDataSize,diffHeadClip);
1269
+ _clip_unpackUIntTo(&out_diffInfo->oldDataSize,diffHeadClip);
1270
+ _clip_unpackUIntTo(&out_head->coverCount,diffHeadClip);
1271
+ out_head->compressSizeBeginPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
1272
+ _clip_unpackUIntTo(&out_head->cover_buf_size,diffHeadClip);
1273
+ _clip_unpackUIntTo(&out_head->compress_cover_buf_size,diffHeadClip);
1274
+ _clip_unpackUIntTo(&out_head->rle_ctrlBuf_size,diffHeadClip);
1275
+ _clip_unpackUIntTo(&out_head->compress_rle_ctrlBuf_size,diffHeadClip);
1276
+ _clip_unpackUIntTo(&out_head->rle_codeBuf_size,diffHeadClip);
1277
+ _clip_unpackUIntTo(&out_head->compress_rle_codeBuf_size,diffHeadClip);
1278
+ _clip_unpackUIntTo(&out_head->newDataDiff_size,diffHeadClip);
1279
+ _clip_unpackUIntTo(&out_head->compress_newDataDiff_size,diffHeadClip);
1280
+ out_head->headEndPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
1281
+
1282
+ out_diffInfo->compressedCount=((out_head->compress_cover_buf_size)?1:0)
1283
+ +((out_head->compress_rle_ctrlBuf_size)?1:0)
1284
+ +((out_head->compress_rle_codeBuf_size)?1:0)
1285
+ +((out_head->compress_newDataDiff_size)?1:0);
1286
+ if (out_head->compress_cover_buf_size>0)
1287
+ out_head->coverEndPos=out_head->headEndPos+out_head->compress_cover_buf_size;
1288
+ else
1289
+ out_head->coverEndPos=out_head->headEndPos+out_head->cover_buf_size;
1290
+ return hpatch_TRUE;
1291
+ }
1292
+
1293
+ hpatch_BOOL getCompressedDiffInfo(hpatch_compressedDiffInfo* out_diffInfo,
1294
+ const hpatch_TStreamInput* compressedDiff){
1295
+ _THDiffzHead head;
1296
+ assert(out_diffInfo!=0);
1297
+ assert(compressedDiff!=0);
1298
+ assert(compressedDiff->read!=0);
1299
+ return read_diffz_head(out_diffInfo,&head,compressedDiff);
1300
+ }
1301
+
1302
+ #define _clear_return(exitValue) { result=exitValue; goto clear; }
1303
+
1304
+ #define _kCacheDecCount 6
1305
+
1306
+ static
1307
+ hpatch_BOOL _patch_decompress_cache(const hpatch_TStreamOutput* out_newData,
1308
+ const hpatch_TStreamInput* oldData,
1309
+ const hpatch_TStreamInput* compressedDiff,
1310
+ hpatch_TDecompress* decompressPlugin,
1311
+ hpatch_TCovers* cached_covers,
1312
+ TByte* temp_cache, TByte* temp_cache_end){
1313
+ TStreamCacheClip coverClip;
1314
+ TStreamCacheClip code_newDataDiffClip;
1315
+ struct _TBytesRle_load_stream rle_loader;
1316
+ _THDiffzHead head;
1317
+ hpatch_compressedDiffInfo diffInfo;
1318
+ _TDecompressInputStream decompressers[4];
1319
+ hpatch_size_t i;
1320
+ hpatch_StreamPos_t coverCount;
1321
+ hpatch_BOOL result=hpatch_TRUE;
1322
+ hpatch_StreamPos_t diffPos0=0;
1323
+ const hpatch_StreamPos_t diffPos_end=compressedDiff->streamSize;
1324
+ const hpatch_size_t cacheSize=(temp_cache_end-temp_cache)/(cached_covers?(_kCacheDecCount-1):_kCacheDecCount);
1325
+ if (cacheSize<=hpatch_kMaxPluginTypeLength) return _hpatch_FALSE;
1326
+ assert(out_newData!=0);
1327
+ assert(out_newData->write!=0);
1328
+ assert(oldData!=0);
1329
+ assert(oldData->read!=0);
1330
+ assert(compressedDiff!=0);
1331
+ assert(compressedDiff->read!=0);
1332
+ {//head
1333
+ if (!read_diffz_head(&diffInfo,&head,compressedDiff)) return _hpatch_FALSE;
1334
+ if ((diffInfo.oldDataSize!=oldData->streamSize)
1335
+ ||(diffInfo.newDataSize!=out_newData->streamSize)) return _hpatch_FALSE;
1336
+
1337
+ if ((decompressPlugin==0)&&(diffInfo.compressedCount!=0)) return _hpatch_FALSE;
1338
+ if ((decompressPlugin)&&(diffInfo.compressedCount>0))
1339
+ if (!decompressPlugin->is_can_open(diffInfo.compressType)) return _hpatch_FALSE;
1340
+ diffPos0=head.headEndPos;
1341
+ }
1342
+
1343
+ for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i)
1344
+ decompressers[i].decompressHandle=0;
1345
+ _TBytesRle_load_stream_init(&rle_loader);
1346
+
1347
+ if (cached_covers){
1348
+ diffPos0=head.coverEndPos;
1349
+ }else{
1350
+ if (!getStreamClip(&coverClip,&decompressers[0],
1351
+ head.cover_buf_size,head.compress_cover_buf_size,compressedDiff,&diffPos0,
1352
+ decompressPlugin,temp_cache+cacheSize*(_kCacheDecCount-1),cacheSize)) _clear_return(_hpatch_FALSE);
1353
+ }
1354
+ if (!getStreamClip(&rle_loader.ctrlClip,&decompressers[1],
1355
+ head.rle_ctrlBuf_size,head.compress_rle_ctrlBuf_size,compressedDiff,&diffPos0,
1356
+ decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
1357
+ temp_cache+=cacheSize;
1358
+ if (!getStreamClip(&rle_loader.rleCodeClip,&decompressers[2],
1359
+ head.rle_codeBuf_size,head.compress_rle_codeBuf_size,compressedDiff,&diffPos0,
1360
+ decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
1361
+ temp_cache+=cacheSize;
1362
+ if (!getStreamClip(&code_newDataDiffClip,&decompressers[3],
1363
+ head.newDataDiff_size,head.compress_newDataDiff_size,compressedDiff,&diffPos0,
1364
+ decompressPlugin,temp_cache,cacheSize)) _clear_return(_hpatch_FALSE);
1365
+ temp_cache+=cacheSize;
1366
+ #ifdef __RUN_MEM_SAFE_CHECK
1367
+ if (diffPos0!=diffPos_end) _clear_return(_hpatch_FALSE);
1368
+ #endif
1369
+
1370
+ coverCount=head.coverCount;
1371
+ {
1372
+ _TCovers covers;
1373
+ hpatch_TCovers* pcovers=0;
1374
+ _TOutStreamCache outCache;
1375
+ _TOutStreamCache_init(&outCache,out_newData,temp_cache,cacheSize);
1376
+ temp_cache+=cacheSize;
1377
+ if (cached_covers){
1378
+ pcovers=cached_covers;
1379
+ }else{
1380
+ _covers_init(&covers,coverCount,&coverClip,&coverClip,&coverClip,hpatch_TRUE);
1381
+ pcovers=&covers.ICovers; //not need close before return
1382
+ }
1383
+ result=patchByClip(&outCache,oldData,pcovers,&code_newDataDiffClip,&rle_loader,
1384
+ temp_cache,cacheSize);
1385
+ //if ((pcovers!=cached_covers)&&(!pcovers->close(pcovers))) result=_hpatch_FALSE;
1386
+ }
1387
+ clear:
1388
+ for (i=0;i<sizeof(decompressers)/sizeof(_TDecompressInputStream);++i) {
1389
+ if (decompressers[i].decompressHandle){
1390
+ if (!decompressPlugin->close(decompressPlugin,decompressers[i].decompressHandle))
1391
+ result=_hpatch_FALSE;
1392
+ decompressers[i].decompressHandle=0;
1393
+ }
1394
+ }
1395
+ return result;
1396
+ }
1397
+
1398
+
1399
+ hpatch_inline static hpatch_BOOL _cache_load_all(const hpatch_TStreamInput* data,
1400
+ TByte* cache,TByte* cache_end){
1401
+ assert((hpatch_size_t)(cache_end-cache)==data->streamSize);
1402
+ return data->read(data,0,cache,cache_end);
1403
+ }
1404
+
1405
+ typedef struct _TCompressedCovers{
1406
+ _TCovers base;
1407
+ TStreamCacheClip coverClip;
1408
+ _TDecompressInputStream decompresser;
1409
+ } _TCompressedCovers;
1410
+
1411
+ static hpatch_BOOL _compressedCovers_close(hpatch_TCovers* covers){
1412
+ hpatch_BOOL result=hpatch_TRUE;
1413
+ _TCompressedCovers* self=(_TCompressedCovers*)covers;
1414
+ if (self){
1415
+ if (self->decompresser.decompressHandle){
1416
+ result=self->decompresser.decompressPlugin->close(self->decompresser.decompressPlugin,
1417
+ self->decompresser.decompressHandle);
1418
+ self->decompresser.decompressHandle=0;
1419
+ }
1420
+ }
1421
+ return result;
1422
+ }
1423
+
1424
+ static hpatch_BOOL _compressedCovers_open(_TCompressedCovers** out_self,
1425
+ hpatch_compressedDiffInfo* out_diffInfo,
1426
+ const hpatch_TStreamInput* compressedDiff,
1427
+ hpatch_TDecompress* decompressPlugin,
1428
+ TByte* temp_cache,TByte* temp_cache_end){
1429
+ _THDiffzHead head;
1430
+ hpatch_StreamPos_t diffPos0=0;
1431
+ _TCompressedCovers* self=0;
1432
+ _cache_alloc(self,_TCompressedCovers,sizeof(_TCompressedCovers),temp_cache,temp_cache_end);
1433
+ if (!read_diffz_head(out_diffInfo,&head,compressedDiff)) return _hpatch_FALSE;
1434
+ diffPos0=head.headEndPos;
1435
+ if (head.compress_cover_buf_size>0){
1436
+ if (decompressPlugin==0) return _hpatch_FALSE;
1437
+ if (!decompressPlugin->is_can_open(out_diffInfo->compressType)) return _hpatch_FALSE;
1438
+ }
1439
+
1440
+ _covers_init(&self->base,head.coverCount,&self->coverClip,
1441
+ &self->coverClip,&self->coverClip,hpatch_TRUE);
1442
+ self->base.ICovers.close=_compressedCovers_close;
1443
+ memset(&self->decompresser,0, sizeof(self->decompresser));
1444
+ if (!getStreamClip(&self->coverClip,&self->decompresser,
1445
+ head.cover_buf_size,head.compress_cover_buf_size,
1446
+ compressedDiff,&diffPos0,decompressPlugin,
1447
+ temp_cache,temp_cache_end-temp_cache)) {
1448
+ return _hpatch_FALSE;
1449
+ };
1450
+ *out_self=self;
1451
+ return hpatch_TRUE;
1452
+ }
1453
+
1454
+
1455
+ //kMinSkipSpaceLen: skip space of length seekTime*speed if time-efficient, otherwise sequential access;
1456
+ // SSD: 4K-64K HHD: 1M
1457
+ const hpatch_size_t kMinSkipSpaceLen =1024*256; //default 256k
1458
+
1459
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
1460
+
1461
+ typedef struct _TArrayCovers{
1462
+ hpatch_TCovers ICovers;
1463
+ void* pCCovers;
1464
+ hpatch_size_t coverCount;
1465
+ hpatch_size_t cur_index;
1466
+ hpatch_BOOL is32;
1467
+ } _TArrayCovers;
1468
+
1469
+
1470
+ typedef struct hpatch_TCCover32{
1471
+ hpatch_uint32_t oldPos;
1472
+ hpatch_uint32_t newPos;
1473
+ hpatch_uint32_t length;
1474
+ hpatch_uint32_t cachePos; //Consider moving to temporary memory and releasing after use? Logic would be more complex;
1475
+ } hpatch_TCCover32;
1476
+
1477
+ typedef struct hpatch_TCCover64{
1478
+ hpatch_StreamPos_t oldPos;
1479
+ hpatch_StreamPos_t newPos;
1480
+ hpatch_StreamPos_t length;
1481
+ hpatch_StreamPos_t cachePos;
1482
+ } hpatch_TCCover64;
1483
+
1484
+ #define _arrayCovers_get(self,i,item) (((self)->is32)? \
1485
+ ((const hpatch_uint32_t*)(self)->pCCovers)[(i)*4+(item)]:\
1486
+ ((const hpatch_StreamPos_t*)(self)->pCCovers)[(i)*4+(item)])
1487
+ #define _arrayCovers_get_oldPos(self,i) _arrayCovers_get(self,i,0)
1488
+ #define _arrayCovers_get_len(self,i) _arrayCovers_get(self,i,2)
1489
+ #define _arrayCovers_get_cachePos(self,i) _arrayCovers_get(self,i,3)
1490
+
1491
+ #define _arrayCovers_set(self,i,item,v) { if ((self)->is32){ \
1492
+ ((hpatch_uint32_t*)(self)->pCCovers)[(i)*4+(item)]=(hpatch_uint32_t)(v); }else{ \
1493
+ ((hpatch_StreamPos_t*)(self)->pCCovers)[(i)*4+(item)]=(v); } }
1494
+ #define _arrayCovers_set_cachePos(self,i,v) _arrayCovers_set(self,i,3,v)
1495
+
1496
+ hpatch_inline static hpatch_StreamPos_t arrayCovers_memSize(hpatch_StreamPos_t coverCount,hpatch_BOOL is32){
1497
+ return coverCount*(is32?sizeof(hpatch_TCCover32):sizeof(hpatch_TCCover64));
1498
+ }
1499
+
1500
+ static hpatch_BOOL _arrayCovers_is_finish(const hpatch_TCovers* covers){
1501
+ const _TArrayCovers* self=(const _TArrayCovers*)covers;
1502
+ return (self->coverCount==self->cur_index);
1503
+ }
1504
+ static hpatch_StreamPos_t _arrayCovers_leaveCoverCount(const hpatch_TCovers* covers){
1505
+ const _TArrayCovers* self=(const _TArrayCovers*)covers;
1506
+ return self->coverCount-self->cur_index;
1507
+ }
1508
+ static hpatch_BOOL _arrayCovers_read_cover(struct hpatch_TCovers* covers,hpatch_TCover* out_cover){
1509
+ _TArrayCovers* self=(_TArrayCovers*)covers;
1510
+ hpatch_size_t i=self->cur_index;
1511
+ if (i<self->coverCount){
1512
+ if (self->is32){
1513
+ const hpatch_TCCover32* pCover=((const hpatch_TCCover32*)self->pCCovers)+i;
1514
+ out_cover->oldPos=pCover->oldPos;
1515
+ out_cover->newPos=pCover->newPos;
1516
+ out_cover->length=pCover->length;
1517
+ }else{
1518
+ const hpatch_TCCover64* pCover=((const hpatch_TCCover64*)self->pCCovers)+i;
1519
+ out_cover->oldPos=pCover->oldPos;
1520
+ out_cover->newPos=pCover->newPos;
1521
+ out_cover->length=pCover->length;
1522
+ }
1523
+ self->cur_index=i+1;
1524
+ return hpatch_TRUE;
1525
+ }else{
1526
+ return _hpatch_FALSE;
1527
+ }
1528
+ }
1529
+
1530
+ static hpatch_force_inline void _arrayCovers_push_cover(_TArrayCovers* self,const hpatch_TCover* cover){
1531
+ hpatch_size_t i=self->coverCount;
1532
+ if (self->is32){
1533
+ hpatch_TCCover32* pCover=((hpatch_TCCover32*)self->pCCovers)+i;
1534
+ pCover->oldPos=(hpatch_uint32_t)cover->oldPos;
1535
+ pCover->newPos=(hpatch_uint32_t)cover->newPos;
1536
+ pCover->length=(hpatch_uint32_t)cover->length;
1537
+ }else{
1538
+ hpatch_TCCover64* pCover=((hpatch_TCCover64*)self->pCCovers)+i;
1539
+ pCover->oldPos=cover->oldPos;
1540
+ pCover->newPos=cover->newPos;
1541
+ pCover->length=cover->length;
1542
+ }
1543
+ self->coverCount=i+1;
1544
+ }
1545
+
1546
+ static hpatch_BOOL _arrayCovers_load(_TArrayCovers** out_self,hpatch_TCovers* src_covers,
1547
+ hpatch_BOOL isUsedCover32,hpatch_BOOL* out_isReadError,
1548
+ TByte** ptemp_cache,TByte* temp_cache_end){
1549
+ TByte* temp_cache=*ptemp_cache;
1550
+ hpatch_StreamPos_t _coverCount=src_covers->leave_cover_count(src_covers);
1551
+ hpatch_StreamPos_t memSize=arrayCovers_memSize(_coverCount,isUsedCover32);
1552
+ hpatch_size_t i;
1553
+ void* pCovers;
1554
+ _TArrayCovers* self=0;
1555
+ hpatch_size_t coverCount=(hpatch_size_t)_coverCount;
1556
+
1557
+ *out_isReadError=hpatch_FALSE;
1558
+ if (coverCount!=_coverCount) return hpatch_FALSE;
1559
+
1560
+ _cache_alloc(self,_TArrayCovers,sizeof(_TArrayCovers),temp_cache,temp_cache_end);
1561
+ _cache_alloc(pCovers,void,memSize,temp_cache,temp_cache_end);
1562
+ if (isUsedCover32){
1563
+ hpatch_TCCover32* pdst=(hpatch_TCCover32*)pCovers;
1564
+ for (i=0;i<coverCount;++i,++pdst) {
1565
+ hpatch_TCover cover;
1566
+ if (!src_covers->read_cover(src_covers,&cover))
1567
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1568
+ pdst->oldPos=(hpatch_uint32_t)cover.oldPos;
1569
+ pdst->newPos=(hpatch_uint32_t)cover.newPos;
1570
+ pdst->length=(hpatch_uint32_t)cover.length;
1571
+ }
1572
+ }else{
1573
+ hpatch_TCCover64* pdst=(hpatch_TCCover64*)pCovers;
1574
+ for (i=0;i<coverCount;++i,++pdst) {
1575
+ if (!src_covers->read_cover(src_covers,(hpatch_TCover*)pdst))
1576
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1577
+ }
1578
+ }
1579
+ if (!src_covers->is_finish(src_covers))
1580
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1581
+
1582
+ self->pCCovers=pCovers;
1583
+ self->is32=isUsedCover32;
1584
+ self->coverCount=coverCount;
1585
+ self->cur_index=0;
1586
+ self->ICovers.close=_covers_close_nil;
1587
+ self->ICovers.is_finish=_arrayCovers_is_finish;
1588
+ self->ICovers.leave_cover_count=_arrayCovers_leaveCoverCount;
1589
+ self->ICovers.read_cover=_arrayCovers_read_cover;
1590
+ *out_self=self;
1591
+ *ptemp_cache=temp_cache;
1592
+ return hpatch_TRUE;
1593
+ }
1594
+
1595
+ #define _arrayCovers_comp(_uint_t,_x,_y,item){ \
1596
+ _uint_t x=((const _uint_t*)_x)[item]; \
1597
+ _uint_t y=((const _uint_t*)_y)[item]; \
1598
+ return (x<y)?(-1):((x>y)?1:0); \
1599
+ }
1600
+ #ifdef _MSC_VER
1601
+ # define __CALL_BACK_C __cdecl
1602
+ #else
1603
+ # define __CALL_BACK_C
1604
+ #endif
1605
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_old_32(const void* _x, const void *_y){
1606
+ _arrayCovers_comp(hpatch_uint32_t,_x,_y,0);
1607
+ }
1608
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_old(const void* _x, const void *_y){
1609
+ _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,0);
1610
+ }
1611
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_new_32(const void* _x, const void *_y){
1612
+ _arrayCovers_comp(hpatch_uint32_t,_x,_y,1);
1613
+ }
1614
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_new(const void* _x, const void *_y){
1615
+ _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,1);
1616
+ }
1617
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_len_32(const void* _x, const void *_y){
1618
+ _arrayCovers_comp(hpatch_uint32_t,_x,_y,2);
1619
+ }
1620
+ static hpatch_int __CALL_BACK_C _arrayCovers_comp_by_len(const void* _x, const void *_y){
1621
+ _arrayCovers_comp(hpatch_StreamPos_t,_x,_y,2);
1622
+ }
1623
+
1624
+ hpatch_force_inline
1625
+ static void _arrayCovers_sort_by_old(_TArrayCovers* self){
1626
+ if (self->is32)
1627
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_old_32);
1628
+ else
1629
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_old);
1630
+ }
1631
+ hpatch_force_inline
1632
+ static void _arrayCovers_sort_by_new(_TArrayCovers* self){
1633
+ if (self->is32)
1634
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_new_32);
1635
+ else
1636
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_new);
1637
+ }
1638
+ hpatch_force_inline
1639
+ static void _arrayCovers_sort_by_len(_TArrayCovers* self){
1640
+ if (self->is32)
1641
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover32),_arrayCovers_comp_by_len_32);
1642
+ else
1643
+ qsort(self->pCCovers,self->coverCount,sizeof(hpatch_TCCover64),_arrayCovers_comp_by_len);
1644
+ }
1645
+
1646
+ static hpatch_StreamPos_t _getCacheSumLen(const _TArrayCovers* src_covers,hpatch_StreamPos_t maxCachedLen){
1647
+ const hpatch_size_t coverCount=src_covers->coverCount;
1648
+ hpatch_StreamPos_t sumLen=0;
1649
+ hpatch_size_t i;
1650
+ for (i=0; i<coverCount;++i) {
1651
+ hpatch_StreamPos_t mlen=_arrayCovers_get_len(src_covers,i);
1652
+ sumLen+=(mlen<=maxCachedLen)?mlen:0;
1653
+ }
1654
+ return sumLen;
1655
+ }
1656
+
1657
+ static hpatch_size_t _getMaxCachedLen(_TArrayCovers* arrayCovers,hpatch_size_t cacheSize){
1658
+ const hpatch_size_t kMaxCachedLen =(~((hpatch_size_t)0))/2;//max allowed length for a single cached data item;
1659
+ hpatch_StreamPos_t mlen=0;
1660
+ hpatch_StreamPos_t sum=0;
1661
+ const hpatch_size_t coverCount=arrayCovers->coverCount;
1662
+ hpatch_size_t i;
1663
+ _arrayCovers_sort_by_len(arrayCovers);
1664
+
1665
+ for (i=0; i<coverCount;++i) {
1666
+ mlen=_arrayCovers_get_len(arrayCovers,i);
1667
+ sum+=mlen;
1668
+ if (sum<=cacheSize){
1669
+ continue;
1670
+ }else{
1671
+ --mlen;
1672
+ break;
1673
+ }
1674
+ }
1675
+ if (mlen>kMaxCachedLen)
1676
+ mlen=kMaxCachedLen;
1677
+ _arrayCovers_sort_by_new(arrayCovers);
1678
+ return (hpatch_size_t)mlen;
1679
+ }
1680
+
1681
+ static hpatch_size_t _set_cache_pos(_TArrayCovers* covers,hpatch_size_t maxCachedLen,
1682
+ hpatch_StreamPos_t* poldPosBegin,hpatch_StreamPos_t* poldPosEnd,
1683
+ hpatch_size_t kMinCacheCoverCount){
1684
+ const hpatch_size_t coverCount=covers->coverCount;
1685
+ hpatch_StreamPos_t oldPosBegin=hpatch_kNullStreamPos;
1686
+ hpatch_StreamPos_t oldPosEnd=0;
1687
+ hpatch_size_t cacheCoverCount=0;
1688
+ hpatch_size_t sum=0;//result
1689
+ hpatch_size_t i;
1690
+ for (i=0; i<coverCount;++i) {
1691
+ hpatch_StreamPos_t clen=_arrayCovers_get_len(covers,i);
1692
+ if (clen<=maxCachedLen){
1693
+ hpatch_StreamPos_t oldPos;
1694
+ _arrayCovers_set_cachePos(covers,i,sum);
1695
+ sum+=(hpatch_size_t)clen;
1696
+ ++cacheCoverCount;
1697
+
1698
+ oldPos=_arrayCovers_get_oldPos(covers,i);
1699
+ if (oldPos<oldPosBegin) oldPosBegin=oldPos;
1700
+ if (oldPos+clen>oldPosEnd) oldPosEnd=oldPos+clen;
1701
+ }
1702
+ }
1703
+ if (cacheCoverCount<kMinCacheCoverCount)
1704
+ return 0;//fail
1705
+ *poldPosBegin=oldPosBegin;
1706
+ *poldPosEnd=oldPosEnd;
1707
+ return sum;
1708
+ }
1709
+
1710
+ //a simple caching strategy:
1711
+ // 1. select a batch of shortest cover lines to cache based on buffer size limit;
1712
+ // 2. sequentially access the oldData file once to fill these caches;
1713
+ // 3. skip large intermediate regions that are useless for caching during sequential access;
1714
+
1715
+ static hpatch_BOOL _cache_old_load(const hpatch_TStreamInput*oldData,
1716
+ hpatch_StreamPos_t oldPos,hpatch_StreamPos_t oldPosAllEnd,
1717
+ _TArrayCovers* arrayCovers,hpatch_size_t maxCachedLen,hpatch_size_t sumCacheLen,
1718
+ TByte* old_cache,TByte* old_cache_end,TByte* cache_buf_end){
1719
+ const hpatch_size_t kAccessPageSize=4096;//disk page-aligned access (affects only speed, but impact is minimal);
1720
+ hpatch_BOOL result=hpatch_TRUE;
1721
+ hpatch_size_t cur_i=0,i;
1722
+ const hpatch_size_t coverCount=arrayCovers->coverCount;
1723
+ TByte* cache_buf=old_cache_end;
1724
+ assert((hpatch_size_t)(old_cache_end-old_cache)>=sumCacheLen);
1725
+
1726
+ if ((hpatch_size_t)(cache_buf_end-cache_buf)>=kAccessPageSize*2){
1727
+ cache_buf=(TByte*)_hpatch_align_upper(cache_buf,kAccessPageSize);
1728
+ if ((hpatch_size_t)(cache_buf_end-cache_buf)>=(kMinSkipSpaceLen>>1))
1729
+ cache_buf_end=cache_buf+(kMinSkipSpaceLen>>1);
1730
+ else
1731
+ cache_buf_end=(TByte*)_hpatch_align_lower(cache_buf_end,kAccessPageSize);
1732
+ }
1733
+ oldPos=_hpatch_align_type_lower(hpatch_StreamPos_t,oldPos,kAccessPageSize);
1734
+ if (oldPos<kMinSkipSpaceLen) oldPos=0;
1735
+
1736
+ _arrayCovers_sort_by_old(arrayCovers);
1737
+ while ((oldPos<oldPosAllEnd)&&(cur_i<coverCount)) {
1738
+ hpatch_StreamPos_t oldPosEnd;
1739
+ hpatch_size_t readLen=(cache_buf_end-cache_buf);
1740
+ if (readLen>(oldPosAllEnd-oldPos)) readLen=(hpatch_size_t)(oldPosAllEnd-oldPos);
1741
+ if (!oldData->read(oldData,oldPos,cache_buf,
1742
+ cache_buf+readLen)) { result=_hpatch_FALSE; break; } //error
1743
+ oldPosEnd=oldPos+readLen;
1744
+ for (i=cur_i;i<coverCount;++i){
1745
+ hpatch_StreamPos_t ioldPos,ioldPosEnd;
1746
+ hpatch_StreamPos_t ilen=_arrayCovers_get_len(arrayCovers,i);
1747
+ if (ilen>maxCachedLen){//cover line too long to cache, proceed to next cover line;
1748
+ if (i==cur_i)
1749
+ ++cur_i;
1750
+ continue;
1751
+ }
1752
+ ioldPos=_arrayCovers_get_oldPos(arrayCovers,i);
1753
+ ioldPosEnd=ioldPos+ilen;
1754
+ if (ioldPosEnd>oldPos){
1755
+ // [oldPos oldPosEnd]
1756
+ // ioldPosEnd]----or----]
1757
+ if (ioldPos<oldPosEnd){//intersection exists, needs cache
1758
+ // [----or----[ioldPos ioldPosEnd]----or----]
1759
+ hpatch_StreamPos_t from;
1760
+ hpatch_size_t copyLen;
1761
+ hpatch_StreamPos_t dstPos=_arrayCovers_get_cachePos(arrayCovers,i);
1762
+ //assert(dstPos<=(hpatch_size_t)(old_cache_end-old_cache));
1763
+ if (ioldPos>=oldPos){
1764
+ // [ioldPos ioldPosEnd]----or----]
1765
+ from=ioldPos;
1766
+ }else{
1767
+ // [ioldPos ioldPosEnd]----or----]
1768
+ from=oldPos;
1769
+ dstPos+=(oldPos-ioldPos);
1770
+ }
1771
+ copyLen=(hpatch_size_t)(((ioldPosEnd<=oldPosEnd)?ioldPosEnd:oldPosEnd)-from);
1772
+ //assert(dstPos+copyLen<=(hpatch_size_t)(old_cache_end-old_cache));
1773
+ //assert(sumCacheLen>=copyLen);
1774
+ memcpy(old_cache+(hpatch_size_t)dstPos,cache_buf+(from-oldPos),copyLen);
1775
+ sumCacheLen-=copyLen;
1776
+ if ((i==cur_i)&&(oldPosEnd>=ioldPosEnd))
1777
+ ++cur_i;
1778
+ }else{//no more intersections with current data for following cover lines, move to next data block;
1779
+ // [oldPos oldPosEnd]
1780
+ // [ioldPos ioldPosEnd]
1781
+ if ((i==cur_i)&&(ioldPos-oldPosEnd>=kMinSkipSpaceLen))
1782
+ oldPosEnd=_hpatch_align_type_lower(hpatch_StreamPos_t,ioldPos,kAccessPageSize);
1783
+ break;
1784
+ }
1785
+ }else{//current cover line is behind current data, proceed to next cover line;
1786
+ // [oldPos oldPosEnd]
1787
+ // [ioldPos ioldPosEnd]
1788
+ if (i==cur_i)
1789
+ ++cur_i;
1790
+ }
1791
+ }
1792
+ oldPos=oldPosEnd;
1793
+ }
1794
+ _arrayCovers_sort_by_new(arrayCovers);
1795
+ assert(sumCacheLen==0);
1796
+ return result;
1797
+ }
1798
+
1799
+ typedef struct _cache_old_TStreamInput{
1800
+ _TArrayCovers arrayCovers;
1801
+ hpatch_BOOL isInHitCache;
1802
+ hpatch_size_t maxCachedLen;
1803
+ hpatch_StreamPos_t readFromPos;
1804
+ hpatch_StreamPos_t readFromPosEnd;
1805
+ const TByte* caches;
1806
+ const TByte* cachesEnd;
1807
+ const hpatch_TStreamInput* oldData;
1808
+ void* _cacheImport;
1809
+ hpatch_BOOL (*_doUpdateCacheCovers)(void* _cacheImport);
1810
+ } _cache_old_TStreamInput;
1811
+
1812
+ static hpatch_BOOL _cache_old_StreamInput_read(const hpatch_TStreamInput* stream,
1813
+ hpatch_StreamPos_t readFromPos,
1814
+ unsigned char* out_data,unsigned char* out_data_end){
1815
+ _cache_old_TStreamInput* self=(_cache_old_TStreamInput*)stream->streamImport;
1816
+ hpatch_size_t readLen;
1817
+ hpatch_StreamPos_t dataLen=(hpatch_size_t)(self->readFromPosEnd-self->readFromPos);
1818
+ if (dataLen==0){//next cover
1819
+ hpatch_StreamPos_t oldPos;
1820
+ hpatch_size_t i=self->arrayCovers.cur_index++;
1821
+ if (i>=self->arrayCovers.coverCount){
1822
+ if ((self->_doUpdateCacheCovers)&&(self->_doUpdateCacheCovers(self->_cacheImport))){
1823
+ i=self->arrayCovers.cur_index++;
1824
+ if (i>=self->arrayCovers.coverCount)
1825
+ return _hpatch_FALSE;//update error;
1826
+ }else
1827
+ return _hpatch_FALSE;//error;
1828
+ }
1829
+ oldPos=_arrayCovers_get_oldPos(&self->arrayCovers,i);
1830
+ dataLen=_arrayCovers_get_len(&self->arrayCovers,i);
1831
+ self->isInHitCache=(dataLen<=self->maxCachedLen);
1832
+ self->readFromPos=oldPos;
1833
+ self->readFromPosEnd=oldPos+dataLen;
1834
+ }
1835
+ readLen=out_data_end-out_data;
1836
+ if ((readLen>dataLen)||(self->readFromPos!=readFromPos)) return _hpatch_FALSE; //error
1837
+ self->readFromPos=readFromPos+readLen;
1838
+ if (self->isInHitCache){
1839
+ assert(readLen<=(hpatch_size_t)(self->cachesEnd-self->caches));
1840
+ memcpy(out_data,self->caches,readLen);
1841
+ self->caches+=readLen;
1842
+ return hpatch_TRUE;
1843
+ }else{
1844
+ return self->oldData->read(self->oldData,readFromPos,out_data,out_data_end);
1845
+ }
1846
+ }
1847
+
1848
+ static hpatch_BOOL _cache_old(hpatch_TStreamInput** out_cachedOld,const hpatch_TStreamInput* oldData,
1849
+ _TArrayCovers* arrayCovers,hpatch_BOOL* out_isReadError,
1850
+ TByte* temp_cache,TByte** ptemp_cache_end,TByte* cache_buf_end){
1851
+ _cache_old_TStreamInput* self;
1852
+ TByte* temp_cache_end=*ptemp_cache_end;
1853
+ hpatch_StreamPos_t oldPosBegin;
1854
+ hpatch_StreamPos_t oldPosEnd;
1855
+ hpatch_size_t sumCacheLen;
1856
+ hpatch_size_t maxCachedLen;
1857
+ const hpatch_size_t kMinCacheCoverCount=arrayCovers->coverCount/8+1; //control min cache count, otherwise caching becomes ineffective;
1858
+ *out_isReadError=hpatch_FALSE;
1859
+ _cache_alloc(*out_cachedOld,hpatch_TStreamInput,sizeof(hpatch_TStreamInput),
1860
+ temp_cache,temp_cache_end);
1861
+ _cache_alloc(self,_cache_old_TStreamInput,sizeof(_cache_old_TStreamInput),
1862
+ temp_cache,temp_cache_end);
1863
+
1864
+ maxCachedLen=_getMaxCachedLen(arrayCovers,temp_cache_end-temp_cache);
1865
+ if (maxCachedLen==0) return hpatch_FALSE;
1866
+ sumCacheLen=_set_cache_pos(arrayCovers,maxCachedLen,&oldPosBegin,&oldPosEnd,kMinCacheCoverCount);
1867
+ if (sumCacheLen==0) return hpatch_FALSE;
1868
+ temp_cache_end=temp_cache+sumCacheLen;
1869
+
1870
+ if (!_cache_old_load(oldData,oldPosBegin,oldPosEnd,arrayCovers,maxCachedLen,sumCacheLen,
1871
+ temp_cache,temp_cache_end,cache_buf_end))
1872
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1873
+
1874
+ {//out
1875
+ self->arrayCovers=*arrayCovers;
1876
+ self->arrayCovers.cur_index=0;
1877
+ self->isInHitCache=hpatch_FALSE;
1878
+ self->maxCachedLen=maxCachedLen;
1879
+ self->caches=temp_cache;
1880
+ self->cachesEnd=temp_cache_end;
1881
+ self->readFromPos=0;
1882
+ self->readFromPosEnd=0;
1883
+ self->oldData=oldData;
1884
+ (*out_cachedOld)->streamImport=self;
1885
+ (*out_cachedOld)->streamSize=oldData->streamSize;
1886
+ (*out_cachedOld)->read=_cache_old_StreamInput_read;
1887
+ *ptemp_cache_end=temp_cache_end;
1888
+ }
1889
+ return hpatch_TRUE;
1890
+ }
1891
+
1892
+ #endif //_IS_NEED_CACHE_OLD_BY_COVERS
1893
+
1894
+ #if (_IS_NEED_CACHE_OLD_ALL)
1895
+ hpatch_BOOL _patch_cache_all_old(const hpatch_TStreamInput** poldData,size_t kMinTempCacheSize,
1896
+ TByte** ptemp_cache,TByte** ptemp_cache_end,hpatch_BOOL* out_isReadError){
1897
+ const hpatch_TStreamInput* oldData=*poldData;
1898
+ TByte* temp_cache=*ptemp_cache;
1899
+ TByte* temp_cache_end=*ptemp_cache_end;
1900
+ *out_isReadError=hpatch_FALSE;
1901
+ if (_patch_is_can_cache_all_old(oldData->streamSize,kMinTempCacheSize,temp_cache_end-temp_cache)){//load all oldData
1902
+ hpatch_TStreamInput* replace_oldData=0;
1903
+ _cache_alloc(replace_oldData,hpatch_TStreamInput,sizeof(hpatch_TStreamInput),
1904
+ temp_cache,temp_cache_end);
1905
+ if (!_cache_load_all(oldData,temp_cache_end-oldData->streamSize,
1906
+ temp_cache_end)){ *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1907
+
1908
+ mem_as_hStreamInput(replace_oldData,temp_cache_end-oldData->streamSize,temp_cache_end);
1909
+ temp_cache_end-=oldData->streamSize;
1910
+ // [ patch cache | oldData cache ]
1911
+ // [ (cacheSize-oldData->streamSize) | (oldData->streamSize) ]
1912
+ *poldData=replace_oldData;
1913
+ *ptemp_cache=temp_cache;
1914
+ *ptemp_cache_end=temp_cache_end;
1915
+ return hpatch_TRUE;
1916
+ }
1917
+ return hpatch_FALSE;
1918
+ }
1919
+ #endif //_IS_NEED_CACHE_OLD_ALL
1920
+
1921
+ static hpatch_BOOL _patch_cache(hpatch_TCovers** out_covers,
1922
+ const hpatch_TStreamInput** poldData,hpatch_StreamPos_t newDataSize,
1923
+ const hpatch_TStreamInput* diffData,hpatch_BOOL isCompressedDiff,
1924
+ hpatch_TDecompress* decompressPlugin,size_t kCacheCount,
1925
+ TByte** ptemp_cache,TByte** ptemp_cache_end,hpatch_BOOL* out_isReadError){
1926
+ const hpatch_TStreamInput* oldData=*poldData;
1927
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
1928
+ const hpatch_size_t kBestACacheSize=hpatch_kFileIOBufBetterSize; //optimal hpatch_kStreamCacheSize value when sufficient memory is available;
1929
+ const hpatch_size_t _minActiveSize=(1<<20)*3+kBestACacheSize*kCacheCount*2;
1930
+ const hpatch_StreamPos_t _betterActiveSize=oldData->streamSize/16+kBestACacheSize*kCacheCount*2;
1931
+ const hpatch_size_t kActiveCacheOldMemorySize = //min memory threshold for attempting to activate CacheOld functionality;
1932
+ (_minActiveSize>_betterActiveSize)?_minActiveSize:(hpatch_size_t)_betterActiveSize;
1933
+ #endif //_IS_NEED_CACHE_OLD_BY_COVERS
1934
+ TByte* temp_cache=*ptemp_cache;
1935
+ TByte* temp_cache_end=*ptemp_cache_end;
1936
+ *out_covers=0;
1937
+ if (_patch_cache_all_old(poldData,kCacheCount*hpatch_kStreamCacheSize,ptemp_cache,ptemp_cache_end,out_isReadError))
1938
+ return hpatch_TRUE;//cache all oldData
1939
+ if (*out_isReadError) return hpatch_FALSE;
1940
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
1941
+ if ((hpatch_size_t)(temp_cache_end-temp_cache)>=kActiveCacheOldMemorySize) {// try cache part of oldData
1942
+ hpatch_BOOL isUsedCover32;
1943
+ TByte* temp_cache_end_back=temp_cache_end;
1944
+ _TArrayCovers* arrayCovers=0;
1945
+ assert((hpatch_size_t)(temp_cache_end-temp_cache)>kBestACacheSize*kCacheCount);
1946
+ assert(kBestACacheSize>sizeof(_TCompressedCovers)+sizeof(_TPackedCovers));
1947
+ if (isCompressedDiff){
1948
+ hpatch_compressedDiffInfo diffInfo;
1949
+ _TCompressedCovers* compressedCovers=0;
1950
+ if (!_compressedCovers_open(&compressedCovers,&diffInfo,diffData,decompressPlugin,
1951
+ temp_cache_end-kBestACacheSize-sizeof(_TCompressedCovers),temp_cache_end))
1952
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1953
+ if ((oldData->streamSize!=diffInfo.oldDataSize)||(newDataSize!=diffInfo.newDataSize))
1954
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1955
+ temp_cache_end-=kBestACacheSize+sizeof(_TCompressedCovers);
1956
+ // [ ... | compressedCovers cache ]
1957
+ // [ (cacheSize-kBestACacheSize) | (kBestACacheSize) ]
1958
+ *out_covers=&compressedCovers->base.ICovers;
1959
+ isUsedCover32=(diffInfo.oldDataSize|diffInfo.newDataSize)<((hpatch_uint64_t)1<<32);
1960
+ }else{
1961
+ _TPackedCovers* packedCovers=0;
1962
+ _THDiffHead diffHead;
1963
+ hpatch_StreamPos_t oldDataSize=oldData->streamSize;
1964
+ if (!_packedCovers_open(&packedCovers,&diffHead,diffData,
1965
+ temp_cache_end-kBestACacheSize*3-sizeof(_TPackedCovers),temp_cache_end))
1966
+ { *out_isReadError=hpatch_TRUE; return _hpatch_FALSE; }
1967
+ temp_cache_end-=kBestACacheSize*3+sizeof(_TPackedCovers);
1968
+ // [ ... | packedCovers cache ]
1969
+ // [ (cacheSize-kBestACacheSize*3) | (kBestACacheSize*3) ]
1970
+ *out_covers=&packedCovers->base.ICovers;
1971
+ isUsedCover32=(oldDataSize|newDataSize)<((hpatch_uint64_t)1<<32);
1972
+ }
1973
+
1974
+ if (!_arrayCovers_load(&arrayCovers,*out_covers,isUsedCover32,
1975
+ out_isReadError,&temp_cache,temp_cache_end-kBestACacheSize)){
1976
+ if (*out_isReadError) return _hpatch_FALSE;
1977
+ // [ patch cache | *edCovers cache ]
1978
+ // [ (cacheSize-kBestACacheSize*?) | (kBestACacheSize*?) ]
1979
+ *ptemp_cache=temp_cache;
1980
+ *ptemp_cache_end=temp_cache_end;
1981
+ return hpatch_FALSE;
1982
+ }else{
1983
+ // [ arrayCovers cache | ... ]
1984
+ // [((new temp_cache)-(old temp_cache))| (cacheSize-(arrayCovers cache size)) ]
1985
+ TByte* old_cache_end;
1986
+ hpatch_TStreamInput* replace_oldData=0;
1987
+ assert(!(*out_isReadError));
1988
+ if (!((*out_covers)->close(*out_covers))) return _hpatch_FALSE;
1989
+ *out_covers=&arrayCovers->ICovers;
1990
+ temp_cache_end=temp_cache_end_back; //free compressedCovers or packedCovers memory
1991
+ old_cache_end=temp_cache_end-kBestACacheSize*kCacheCount;
1992
+ // [ arrayCovers cache | ... | patch reserve cache ]
1993
+ // [ | ... | (kBestACacheSize*kCacheCount) ]
1994
+ if (((hpatch_size_t)(temp_cache_end-temp_cache)<=kBestACacheSize*kCacheCount)
1995
+ ||(!_cache_old(&replace_oldData,oldData,arrayCovers,out_isReadError,
1996
+ temp_cache,&old_cache_end,temp_cache_end))){
1997
+ if (*out_isReadError) return _hpatch_FALSE;
1998
+ // [ arrayCovers cache | patch cache ]
1999
+ *ptemp_cache=temp_cache;
2000
+ *ptemp_cache_end=temp_cache_end;
2001
+ return hpatch_FALSE;
2002
+ }else{
2003
+ // [ arrayCovers cache | oldData cache | patch cache ]
2004
+ // [ | |(temp_cache_end-(new old_cache_end))]
2005
+ assert(!(*out_isReadError));
2006
+ assert((hpatch_size_t)(temp_cache_end-old_cache_end)>=kBestACacheSize*kCacheCount);
2007
+ temp_cache=old_cache_end;
2008
+
2009
+ *poldData=replace_oldData;
2010
+ *ptemp_cache=temp_cache;
2011
+ *ptemp_cache_end=temp_cache_end;
2012
+ return hpatch_TRUE;
2013
+ }
2014
+ }
2015
+ }
2016
+ #endif//_IS_NEED_CACHE_OLD_BY_COVERS
2017
+ return hpatch_FALSE;//not cache oldData
2018
+ }
2019
+
2020
+ hpatch_BOOL patch_stream_with_cache(const struct hpatch_TStreamOutput* out_newData,
2021
+ const struct hpatch_TStreamInput* oldData,
2022
+ const struct hpatch_TStreamInput* serializedDiff,
2023
+ TByte* temp_cache,TByte* temp_cache_end){
2024
+ hpatch_BOOL result;
2025
+ hpatch_TCovers* covers=0;//not need close before return
2026
+ hpatch_BOOL isReadError=hpatch_FALSE;
2027
+ _patch_cache(&covers,&oldData,out_newData->streamSize,serializedDiff,hpatch_FALSE,0,
2028
+ _kCachePatCount,&temp_cache,&temp_cache_end,&isReadError);
2029
+ if (isReadError) return _hpatch_FALSE;
2030
+ result=_patch_stream_with_cache(out_newData,oldData,serializedDiff,covers,
2031
+ temp_cache,temp_cache_end);
2032
+ //if ((covers!=0)&&(!covers->close(covers))) result=_hpatch_FALSE;
2033
+ return result;
2034
+ }
2035
+
2036
+ hpatch_BOOL patch_stream(const hpatch_TStreamOutput* out_newData,
2037
+ const hpatch_TStreamInput* oldData,
2038
+ const hpatch_TStreamInput* serializedDiff){
2039
+ TByte temp_cache[hpatch_kStreamCacheSize*_kCachePatCount];
2040
+ return _patch_stream_with_cache(out_newData,oldData,serializedDiff,0,
2041
+ temp_cache,temp_cache+sizeof(temp_cache)/sizeof(TByte));
2042
+ }
2043
+
2044
+ hpatch_BOOL patch_decompress_with_cache(const hpatch_TStreamOutput* out_newData,
2045
+ const hpatch_TStreamInput* oldData,
2046
+ const hpatch_TStreamInput* compressedDiff,
2047
+ hpatch_TDecompress* decompressPlugin,
2048
+ TByte* temp_cache,TByte* temp_cache_end){
2049
+ hpatch_BOOL result=hpatch_TRUE;
2050
+ hpatch_TCovers* covers=0; //need close before return
2051
+ hpatch_BOOL isReadError=hpatch_FALSE;
2052
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2053
+ hinput_mt_safe_t _safeDiff;
2054
+ hpatch_TStreamInput* psafeDiff=0;
2055
+ if (decompressPlugin && (decompressPlugin->dec_threadNum>1)){
2056
+ psafeDiff=hinput_mt_safe_open(&_safeDiff,compressedDiff);
2057
+ if (!psafeDiff){ result=_hpatch_FALSE; goto _clear; }
2058
+ compressedDiff=psafeDiff;
2059
+ }
2060
+ #endif
2061
+ _patch_cache(&covers,&oldData,out_newData->streamSize,compressedDiff,hpatch_TRUE,
2062
+ decompressPlugin,_kCacheDecCount,&temp_cache,&temp_cache_end,&isReadError);
2063
+ if (isReadError){ result=_hpatch_FALSE; goto _clear; }
2064
+ result=_patch_decompress_cache(out_newData,oldData,compressedDiff,decompressPlugin,
2065
+ covers,temp_cache,temp_cache_end);
2066
+ _clear:
2067
+ if ((covers!=0)&&(!covers->close(covers))) result=_hpatch_FALSE;
2068
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2069
+ if (psafeDiff) hinput_mt_safe_close(psafeDiff);
2070
+ #endif
2071
+ return result;
2072
+ }
2073
+
2074
+ hpatch_BOOL patch_decompress(const hpatch_TStreamOutput* out_newData,
2075
+ const hpatch_TStreamInput* oldData,
2076
+ const hpatch_TStreamInput* compressedDiff,
2077
+ hpatch_TDecompress* decompressPlugin){
2078
+ TByte temp_cache[hpatch_kStreamCacheSize*_kCacheDecCount];
2079
+ return _patch_decompress_cache(out_newData,oldData,compressedDiff,decompressPlugin,
2080
+ 0,temp_cache,temp_cache+sizeof(temp_cache)/sizeof(TByte));
2081
+ }
2082
+
2083
+ hpatch_BOOL hpatch_coverList_open_serializedDiff(hpatch_TCoverList* out_coverList,
2084
+ const hpatch_TStreamInput* serializedDiff){
2085
+ TByte* temp_cache;
2086
+ TByte* temp_cache_end;
2087
+ _TPackedCovers* packedCovers=0;
2088
+ _THDiffHead diffHead;
2089
+ assert((out_coverList!=0)&&(out_coverList->ICovers==0));
2090
+ temp_cache=out_coverList->_buf;
2091
+ temp_cache_end=temp_cache+sizeof(out_coverList->_buf);
2092
+ if (!_packedCovers_open(&packedCovers,&diffHead,serializedDiff,
2093
+ temp_cache,temp_cache_end))
2094
+ return _hpatch_FALSE;
2095
+ out_coverList->ICovers=&packedCovers->base.ICovers;
2096
+ return hpatch_TRUE;
2097
+ }
2098
+
2099
+ hpatch_BOOL hpatch_coverList_open_compressedDiff(hpatch_TCoverList* out_coverList,
2100
+ const hpatch_TStreamInput* compressedDiff,
2101
+ hpatch_TDecompress* decompressPlugin){
2102
+ TByte* temp_cache;
2103
+ TByte* temp_cache_end;
2104
+ _TCompressedCovers* compressedCovers=0;
2105
+ hpatch_compressedDiffInfo diffInfo;
2106
+ assert((out_coverList!=0)&&(out_coverList->ICovers==0));
2107
+ temp_cache=out_coverList->_buf;
2108
+ temp_cache_end=temp_cache+sizeof(out_coverList->_buf);
2109
+ if (!_compressedCovers_open(&compressedCovers,&diffInfo,compressedDiff,decompressPlugin,
2110
+ temp_cache,temp_cache_end))
2111
+ return _hpatch_FALSE;
2112
+ out_coverList->ICovers=&compressedCovers->base.ICovers;
2113
+ return hpatch_TRUE;
2114
+ }
2115
+
2116
+ //
2117
+
2118
+ hpatch_BOOL _patch_single_compressed_diff_mt(const hpatch_TStreamOutput* out_newData,
2119
+ const hpatch_TStreamInput* oldData,
2120
+ const hpatch_TStreamInput* singleCompressedDiff,
2121
+ hpatch_StreamPos_t diffData_pos,
2122
+ hpatch_StreamPos_t uncompressedSize,
2123
+ hpatch_StreamPos_t compressedSize,
2124
+ hpatch_TDecompress* decompressPlugin,
2125
+ hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
2126
+ unsigned char* temp_cache,unsigned char* temp_cache_end,
2127
+ sspatch_coversListener_t* coversListener,
2128
+ size_t maxThreadNum,hpatchMTSets_t hpatchMTSets){
2129
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2130
+ struct hpatch_mt_manager_t* hpatch_mt_manager=0;
2131
+ hpatchMTSets_t mtsets=hpatch_getMTSets(out_newData->streamSize,oldData->streamSize,singleCompressedDiff->streamSize-diffData_pos,
2132
+ compressedSize?decompressPlugin:0,_kCacheSgCount,stepMemSize,
2133
+ temp_cache_end-temp_cache,maxThreadNum,hpatchMTSets);
2134
+ #endif
2135
+ hpatch_BOOL result;
2136
+ hpatch_BOOL isNeedOutCache=hpatch_TRUE;
2137
+ size_t kCacheCount=_kCacheSgCount;
2138
+ hpatch_TUncompresser_t uncompressedStream={0};
2139
+ hpatch_StreamPos_t diffData_posEnd;
2140
+ if (compressedSize==0){
2141
+ decompressPlugin=0;
2142
+ }else{
2143
+ if (decompressPlugin==0) return _hpatch_FALSE;
2144
+ }
2145
+ diffData_posEnd=(decompressPlugin?compressedSize:uncompressedSize)+diffData_pos;
2146
+ if (diffData_posEnd>singleCompressedDiff->streamSize) return _hpatch_FALSE;
2147
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2148
+ if (_hpatchMTSets_threadNum(mtsets)>1){
2149
+ isNeedOutCache=!mtsets.writeNew_isMT;
2150
+ kCacheCount=_kCacheSgCount-(isNeedOutCache?0:1);
2151
+ hpatch_mt_manager=hpatch_mt_manager_open(&out_newData,&oldData,&singleCompressedDiff,
2152
+ &diffData_pos,&diffData_posEnd,uncompressedSize,&decompressPlugin,
2153
+ stepMemSize,&temp_cache,&temp_cache_end,&coversListener,hpatch_TRUE,
2154
+ kCacheCount,mtsets);
2155
+ if (!hpatch_mt_manager) return _hpatch_FALSE;
2156
+ }
2157
+ #endif
2158
+ if (decompressPlugin){
2159
+ if (!compressed_stream_as_uncompressed(&uncompressedStream,uncompressedSize,decompressPlugin,singleCompressedDiff,
2160
+ diffData_pos,diffData_posEnd)) return _hpatch_FALSE;
2161
+ singleCompressedDiff=&uncompressedStream.base;
2162
+ diffData_pos=0;
2163
+ diffData_posEnd=singleCompressedDiff->streamSize;
2164
+ }
2165
+
2166
+ result=patch_single_stream_diff(out_newData,oldData,singleCompressedDiff,diffData_pos,diffData_posEnd,
2167
+ coverCount,stepMemSize,temp_cache,temp_cache_end,coversListener,isNeedOutCache);
2168
+
2169
+ if (decompressPlugin)
2170
+ close_compressed_stream_as_uncompressed(&uncompressedStream);
2171
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2172
+ if (hpatch_mt_manager){
2173
+ if (!hpatch_mt_manager_close(hpatch_mt_manager,!result))
2174
+ result=_hpatch_FALSE;
2175
+ hpatch_mt_manager=0;
2176
+ }
2177
+ #endif
2178
+ return result;
2179
+ }
2180
+
2181
+ static const size_t _kStepMemSizeSafeLimit =(1<<20)*4;
2182
+ hpatch_BOOL getSingleCompressedDiffInfo(hpatch_singleCompressedDiffInfo* out_diffInfo,
2183
+ const hpatch_TStreamInput* singleCompressedDiff,
2184
+ hpatch_StreamPos_t diffInfo_pos){
2185
+ TStreamCacheClip _diffHeadClip;
2186
+ TStreamCacheClip* diffHeadClip=&_diffHeadClip;
2187
+ TByte temp_cache[hpatch_kStreamCacheSize];
2188
+ _TStreamCacheClip_init(&_diffHeadClip,singleCompressedDiff,diffInfo_pos,singleCompressedDiff->streamSize,
2189
+ temp_cache,hpatch_kStreamCacheSize);
2190
+ {//type
2191
+ const char* kVersionType="HDIFFSF20";
2192
+ char* tempType=out_diffInfo->compressType;
2193
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'&',tempType)) return _hpatch_FALSE;
2194
+ if (0!=strcmp(tempType,kVersionType)) return _hpatch_FALSE;
2195
+ }
2196
+ {//read compressType
2197
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'\0',
2198
+ out_diffInfo->compressType)) return _hpatch_FALSE;
2199
+ }
2200
+ _clip_unpackUIntTo(&out_diffInfo->newDataSize,diffHeadClip);
2201
+ _clip_unpackUIntTo(&out_diffInfo->oldDataSize,diffHeadClip);
2202
+ _clip_unpackUIntTo(&out_diffInfo->coverCount,diffHeadClip);
2203
+ _clip_unpackUIntTo(&out_diffInfo->stepMemSize,diffHeadClip);
2204
+ _clip_unpackUIntTo(&out_diffInfo->uncompressedSize,diffHeadClip);
2205
+ _clip_unpackUIntTo(&out_diffInfo->compressedSize,diffHeadClip);
2206
+ out_diffInfo->diffDataPos=_TStreamCacheClip_readPosOfSrcStream(diffHeadClip)-diffInfo_pos;
2207
+ if (out_diffInfo->compressedSize>out_diffInfo->uncompressedSize)
2208
+ return _hpatch_FALSE;
2209
+ if (out_diffInfo->stepMemSize>(out_diffInfo->newDataSize+_kStepMemSizeSafeLimit))
2210
+ return _hpatch_FALSE;
2211
+ if (out_diffInfo->stepMemSize>out_diffInfo->uncompressedSize+_kStepMemSizeSafeLimit)
2212
+ return _hpatch_FALSE;
2213
+ return hpatch_TRUE;
2214
+ }
2215
+
2216
+ static hpatch_BOOL _TUncompresser_read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
2217
+ unsigned char* out_data,unsigned char* out_data_end){
2218
+ hpatch_TUncompresser_t* self=(hpatch_TUncompresser_t*)stream->streamImport;
2219
+ return self->_decompressPlugin->decompress_part(self->_decompressHandle,out_data,out_data_end);
2220
+ }
2221
+
2222
+ hpatch_BOOL compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream,hpatch_StreamPos_t uncompressedSize,
2223
+ hpatch_TDecompress* decompressPlugin,const hpatch_TStreamInput* compressedStream,
2224
+ hpatch_StreamPos_t compressed_pos,hpatch_StreamPos_t compressed_end){
2225
+ hpatch_TUncompresser_t* self=uncompressedStream;
2226
+ assert(decompressPlugin!=0);
2227
+ assert(self->_decompressHandle==0);
2228
+ self->_decompressHandle=decompressPlugin->open(decompressPlugin,uncompressedSize,compressedStream,
2229
+ compressed_pos,compressed_end);
2230
+ if (self->_decompressHandle==0) return _hpatch_FALSE;
2231
+ self->_decompressPlugin=decompressPlugin;
2232
+
2233
+ self->base.streamImport=self;
2234
+ self->base.streamSize=uncompressedSize;
2235
+ self->base.read=_TUncompresser_read;
2236
+ return hpatch_TRUE;
2237
+ }
2238
+
2239
+ void close_compressed_stream_as_uncompressed(hpatch_TUncompresser_t* uncompressedStream){
2240
+ hpatch_TUncompresser_t* self=uncompressedStream;
2241
+ if (self==0) return;
2242
+ if (self->_decompressHandle==0) return;
2243
+ self->_decompressPlugin->close(self->_decompressPlugin,self->_decompressHandle);
2244
+ self->_decompressHandle=0;
2245
+ }
2246
+
2247
+ typedef struct{
2248
+ const unsigned char* code;
2249
+ const unsigned char* code_end;
2250
+ hpatch_size_t len0;
2251
+ hpatch_size_t lenv;
2252
+ hpatch_BOOL isNeedDecode0;
2253
+ } rle0_decoder_t;
2254
+
2255
+ static void _rle0_decoder_init(rle0_decoder_t* self,const unsigned char* code,const unsigned char* code_end){
2256
+ self->code=code;
2257
+ self->code_end=code_end;
2258
+ self->len0=0;
2259
+ self->lenv=0;
2260
+ self->isNeedDecode0=hpatch_TRUE;
2261
+ }
2262
+
2263
+ static hpatch_BOOL _rle0_decoder_add(rle0_decoder_t* self,TByte* out_data,hpatch_size_t decodeSize){
2264
+ if (self->len0){
2265
+ _0_process:
2266
+ if (self->len0>=decodeSize){
2267
+ self->len0-=decodeSize;
2268
+ return hpatch_TRUE;
2269
+ }else{
2270
+ decodeSize-=self->len0;
2271
+ out_data+=self->len0;
2272
+ self->len0=0;
2273
+ goto _decode_v_process;
2274
+ }
2275
+ }
2276
+
2277
+ if (self->lenv){
2278
+ _v_process:
2279
+ if (self->lenv>=decodeSize){
2280
+ addData(out_data,self->code,decodeSize);
2281
+ self->code+=decodeSize;
2282
+ self->lenv-=decodeSize;
2283
+ return hpatch_TRUE;
2284
+ }else{
2285
+ addData(out_data,self->code,self->lenv);
2286
+ out_data+=self->lenv;
2287
+ decodeSize-=self->lenv;
2288
+ self->code+=self->lenv;
2289
+ self->lenv=0;
2290
+ goto _decode_0_process;
2291
+ }
2292
+ }
2293
+
2294
+ assert(decodeSize>0);
2295
+ if (self->isNeedDecode0){
2296
+ hpatch_StreamPos_t len0;
2297
+ _decode_0_process:
2298
+ self->isNeedDecode0=hpatch_FALSE;
2299
+ if (!hpatch_unpackUInt(&self->code,self->code_end,&len0)) return _hpatch_FALSE;
2300
+ if (len0!=(hpatch_size_t)len0) return _hpatch_FALSE;
2301
+ self->len0=(hpatch_size_t)len0;
2302
+ goto _0_process;
2303
+ }else{
2304
+ hpatch_StreamPos_t lenv;
2305
+ _decode_v_process:
2306
+ self->isNeedDecode0=hpatch_TRUE;
2307
+ if (!hpatch_unpackUInt(&self->code,self->code_end,&lenv)) return _hpatch_FALSE;
2308
+ if (lenv>(size_t)(self->code_end-self->code)) return _hpatch_FALSE;
2309
+ self->lenv=(hpatch_size_t)lenv;
2310
+ goto _v_process;
2311
+ }
2312
+ }
2313
+
2314
+
2315
+ static hpatch_BOOL _patch_add_old_with_rle0(_TOutStreamCache* outCache,rle0_decoder_t* rle0_decoder,
2316
+ const hpatch_TStreamInput* old,hpatch_StreamPos_t oldPos,
2317
+ hpatch_StreamPos_t addLength,TByte* aCache,hpatch_size_t aCacheSize){
2318
+ while (addLength>0){
2319
+ hpatch_size_t decodeStep=aCacheSize;
2320
+ if (decodeStep>addLength)
2321
+ decodeStep=(hpatch_size_t)addLength;
2322
+ if (!old->read(old,oldPos,aCache,aCache+decodeStep)) return _hpatch_FALSE;
2323
+ if (!_rle0_decoder_add(rle0_decoder,aCache,decodeStep)) return _hpatch_FALSE;
2324
+ if (!_TOutStreamCache_write(outCache,aCache,decodeStep)) return _hpatch_FALSE;
2325
+ oldPos+=decodeStep;
2326
+ addLength-=decodeStep;
2327
+ }
2328
+ return hpatch_TRUE;
2329
+ }
2330
+
2331
+ hpatch_BOOL sspatch_covers_nextCover(sspatch_covers_t* self){
2332
+ hpatch_BOOL inc_oldPos_sign=(*(self->covers_cache))>>(8-1);
2333
+ self->lastOldEnd=self->cover.oldPos+self->cover.length;
2334
+ self->lastNewEnd=self->cover.newPos+self->cover.length;
2335
+ if (!hpatch_unpackUIntWithTag(&self->covers_cache,self->covers_cacheEnd,&self->cover.oldPos,1)) return _hpatch_FALSE;
2336
+ if (inc_oldPos_sign==0)
2337
+ self->cover.oldPos+=self->lastOldEnd;
2338
+ else
2339
+ self->cover.oldPos=self->lastOldEnd-self->cover.oldPos;
2340
+ if (!hpatch_unpackUInt(&self->covers_cache,self->covers_cacheEnd,&self->cover.newPos)) return _hpatch_FALSE;
2341
+ self->cover.newPos+=self->lastNewEnd;
2342
+ if (!hpatch_unpackUInt(&self->covers_cache,self->covers_cacheEnd,&self->cover.length)) return _hpatch_FALSE;
2343
+ return hpatch_TRUE;
2344
+ }
2345
+
2346
+
2347
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2348
+
2349
+ #define _kMaxCachedLen_min (32*1024) // 1M is big value, 256k is middle value, 32k is small value
2350
+ #define _kMaxCachedLen_max (32*_kMaxCachedLen_min)
2351
+ #define _kMemForReadOldSize (hpatch_kFileIOBufBetterSize*2)
2352
+
2353
+ typedef struct{
2354
+ _cache_old_TStreamInput cache_old;
2355
+ hpatch_TStreamInput base;
2356
+ sspatch_covers_t covers;
2357
+ hpatch_BOOL isHaveACover;
2358
+ hpatch_size_t sumCacheLen;
2359
+ hpatch_byte* cache_buf_end;
2360
+ const hpatch_byte* covers_cache;
2361
+ const hpatch_byte* covers_cacheEnd;
2362
+ } _step_cache_old_t;
2363
+
2364
+ static hpatch_force_inline hpatch_size_t _step_cache_old_sumBufSize(const _step_cache_old_t* self){
2365
+ return self->cache_old.cachesEnd-(const hpatch_byte*)self->cache_old.arrayCovers.pCCovers; }
2366
+ static hpatch_force_inline hpatch_size_t _step_cache_old_coverBufSize(const _step_cache_old_t* self){
2367
+ return (hpatch_size_t)arrayCovers_memSize(self->cache_old.arrayCovers.coverCount,self->cache_old.arrayCovers.is32); }
2368
+ static hpatch_force_inline hpatch_StreamPos_t _step_cache_old_incCoverBufSize(const _step_cache_old_t* self){
2369
+ return arrayCovers_memSize(self->cache_old.arrayCovers.coverCount+1,self->cache_old.arrayCovers.is32); }
2370
+
2371
+
2372
+ static hpatch_BOOL _step_cache_old_addCover(_step_cache_old_t* self,const hpatch_TCover* cover){
2373
+ const hpatch_StreamPos_t _incCoverBufSize=_step_cache_old_incCoverBufSize(self);
2374
+ while (hpatch_TRUE){
2375
+ const hpatch_size_t _addCachedLen=(cover->length<=self->cache_old.maxCachedLen)?(hpatch_size_t)cover->length:0;
2376
+ if (_incCoverBufSize+self->sumCacheLen+_addCachedLen<=_step_cache_old_sumBufSize(self)){
2377
+ self->sumCacheLen+=_addCachedLen;
2378
+ _arrayCovers_push_cover(&self->cache_old.arrayCovers,cover);
2379
+ return hpatch_TRUE;
2380
+ }else{
2381
+ assert(self->cache_old.maxCachedLen>=_kMaxCachedLen_min);
2382
+ if (self->cache_old.maxCachedLen==_kMaxCachedLen_min) return hpatch_FALSE;
2383
+ self->cache_old.maxCachedLen/=2;
2384
+ self->sumCacheLen=(hpatch_size_t)_getCacheSumLen(&self->cache_old.arrayCovers,self->cache_old.maxCachedLen);
2385
+ }
2386
+ }
2387
+ }
2388
+
2389
+ static hpatch_BOOL _patch_step_cache_old_update(void* _self){
2390
+ _step_cache_old_t* self=(_step_cache_old_t*)_self;
2391
+ hpatch_StreamPos_t oldPosBegin;
2392
+ hpatch_StreamPos_t oldPosEnd;
2393
+ const hpatch_size_t kMinCacheCoverCount=0; //no limit
2394
+ assert(self->cache_old.arrayCovers.coverCount<=self->cache_old.arrayCovers.cur_index);
2395
+ assert(self->cache_old.caches==self->cache_old.cachesEnd);
2396
+ self->sumCacheLen=0;
2397
+ self->cache_old.arrayCovers.coverCount=0;
2398
+ self->cache_old.arrayCovers.cur_index=0;
2399
+ self->cache_old.cachesEnd=self->cache_buf_end-_kMemForReadOldSize; //limit covers + cached data 's size
2400
+ self->cache_old.maxCachedLen=_kMaxCachedLen_max;
2401
+ while ((self->cache_old.maxCachedLen>=_step_cache_old_sumBufSize(self))&&(self->cache_old.maxCachedLen>_kMaxCachedLen_min))
2402
+ self->cache_old.maxCachedLen/=2;
2403
+
2404
+ //read some cover from self->covers to self->cache_old.arrayCovers
2405
+ if (self->isHaveACover){
2406
+ self->isHaveACover=hpatch_FALSE;
2407
+ assert(self->covers.cover.length>0);
2408
+ if (!_step_cache_old_addCover(self,&self->covers.cover)) assert(hpatch_FALSE);
2409
+ }
2410
+ while (sspatch_covers_isHaveNextCover(&self->covers)){
2411
+ if (!sspatch_covers_nextCover(&self->covers))
2412
+ return hpatch_FALSE;
2413
+ if (self->covers.cover.length>0){
2414
+ if (_step_cache_old_addCover(self,&self->covers.cover)){
2415
+ //ok
2416
+ }else{
2417
+ self->isHaveACover=hpatch_TRUE;
2418
+ break; //arrayCovers full
2419
+ }
2420
+ }
2421
+ }
2422
+
2423
+ self->cache_old.maxCachedLen=_getMaxCachedLen(&self->cache_old.arrayCovers,_step_cache_old_sumBufSize(self)-_step_cache_old_coverBufSize(self));
2424
+ assert(self->cache_old.maxCachedLen>0);
2425
+ self->sumCacheLen=_set_cache_pos(&self->cache_old.arrayCovers,self->cache_old.maxCachedLen,&oldPosBegin,&oldPosEnd,kMinCacheCoverCount);
2426
+ self->cache_old.caches=((hpatch_byte*)self->cache_old.arrayCovers.pCCovers)+_step_cache_old_coverBufSize(self);
2427
+ self->cache_old.cachesEnd=self->cache_old.caches+self->sumCacheLen;
2428
+ if (self->sumCacheLen>0){
2429
+ if (!_cache_old_load(self->cache_old.oldData,oldPosBegin,oldPosEnd,&self->cache_old.arrayCovers,
2430
+ self->cache_old.maxCachedLen,self->sumCacheLen, (hpatch_byte*)self->cache_old.caches,
2431
+ (hpatch_byte*)self->cache_old.cachesEnd,self->cache_buf_end))
2432
+ return _hpatch_FALSE;
2433
+ }
2434
+ return hpatch_TRUE;
2435
+ }
2436
+
2437
+ static hpatch_inline
2438
+ void _patch_step_cache_old_init(_step_cache_old_t* self,hpatch_size_t canUsedMemSize,
2439
+ const hpatch_TStreamInput* oldData,hpatch_BOOL isUsedCover32){
2440
+ memset(self,0,sizeof(*self));
2441
+ assert(canUsedMemSize>=_kMemForReadOldSize*2);
2442
+ self->base.streamImport=&self->cache_old;
2443
+ self->base.streamSize=oldData->streamSize;
2444
+ self->base.read=_cache_old_StreamInput_read;
2445
+ //todo: _cache_old_StreamInput_read call back
2446
+ self->cache_old.oldData=oldData;
2447
+ self->cache_old._cacheImport=self;
2448
+ self->cache_old._doUpdateCacheCovers=_patch_step_cache_old_update;
2449
+ self->cache_buf_end=((hpatch_byte*)self) + canUsedMemSize;
2450
+
2451
+ self->cache_old.arrayCovers.is32=isUsedCover32;
2452
+ self->cache_old.arrayCovers.pCCovers=(void*)_hpatch_align_upper((self+1),sizeof(hpatch_StreamPos_t));
2453
+ self->cache_old.arrayCovers.ICovers.leave_cover_count=_arrayCovers_leaveCoverCount;
2454
+ self->cache_old.arrayCovers.ICovers.read_cover=_arrayCovers_read_cover;
2455
+ }
2456
+
2457
+
2458
+ hpatch_BOOL _patch_step_cache_old_onStepCovers(const hpatch_TStreamInput* _self,const unsigned char* covers_cache,const unsigned char* covers_cacheEnd){
2459
+ _step_cache_old_t* self=(_step_cache_old_t*)_self->streamImport;
2460
+ assert(!sspatch_covers_isHaveNextCover(&self->covers));
2461
+ assert(!self->isHaveACover);
2462
+ self->covers_cache=covers_cache;
2463
+ self->covers_cacheEnd=covers_cacheEnd;
2464
+ sspatch_covers_setCoversCache(&self->covers,covers_cache,covers_cacheEnd);
2465
+ return covers_cache?_patch_step_cache_old_update(self):hpatch_TRUE;
2466
+ }
2467
+
2468
+
2469
+ hpatch_size_t _patch_step_cache_old_canUsedSize(hpatch_size_t stepCoversMemSize,hpatch_size_t kMinTempCacheSize,hpatch_size_t tempCacheSize){
2470
+ const hpatch_size_t kActiveCacheOldMemorySize=(1<<20)*3+_kMemForReadOldSize*2;
2471
+ hpatch_size_t cacheStepSize,multiple;
2472
+ if (tempCacheSize<kActiveCacheOldMemorySize+stepCoversMemSize+kMinTempCacheSize)
2473
+ return 0;
2474
+ cacheStepSize=tempCacheSize-(stepCoversMemSize+kMinTempCacheSize+sizeof(hpatch_StreamPos_t));
2475
+ multiple=cacheStepSize/((kActiveCacheOldMemorySize+kMinTempCacheSize+_kMemForReadOldSize)/4);
2476
+ cacheStepSize-=(hpatch_size_t)((hpatch_StreamPos_t)(kMinTempCacheSize+_kMemForReadOldSize)*((multiple>4)?(hpatch_size_t)(multiple-4):0)/8);
2477
+ return cacheStepSize;
2478
+ }
2479
+
2480
+ hpatch_BOOL _patch_step_cache_old(const hpatch_TStreamInput** poldData,hpatch_StreamPos_t newDataSize,size_t stepCoversMemSize,
2481
+ size_t kMinTempCacheSize,hpatch_byte** ptemp_cache,hpatch_byte** ptemp_cache_end){
2482
+ const hpatch_TStreamInput* oldData=*poldData;
2483
+ _step_cache_old_t* self;
2484
+ const hpatch_BOOL isUsedCover32=(oldData->streamSize|newDataSize)<((hpatch_uint64_t)1<<32);
2485
+ hpatch_byte* temp_cache=*ptemp_cache;
2486
+ hpatch_byte* const temp_cache_end=*ptemp_cache_end;
2487
+
2488
+ hpatch_size_t canUsedMemSize=_patch_step_cache_old_canUsedSize(stepCoversMemSize,kMinTempCacheSize,temp_cache_end-temp_cache);
2489
+ if (canUsedMemSize==0)
2490
+ return hpatch_FALSE; //not enough memory for cache part of oldData
2491
+ _cache_alloc(self,_step_cache_old_t,canUsedMemSize,temp_cache,temp_cache_end);
2492
+ _patch_step_cache_old_init(self,canUsedMemSize,oldData,isUsedCover32);
2493
+
2494
+ *poldData=&self->base;
2495
+ *ptemp_cache=temp_cache;
2496
+ return hpatch_TRUE;
2497
+ }
2498
+
2499
+ #endif // _IS_NEED_CACHE_OLD_BY_COVERS
2500
+
2501
+
2502
+ hpatch_size_t _patch_is_can_cache_window_old_canUsedSize(hpatch_size_t windowOldBufSize,hpatch_size_t stepCoversMemSize,
2503
+ hpatch_size_t kMinTempCacheSize,hpatch_size_t tempCacheSize,hpatch_StreamPos_t oldDataSize){
2504
+ hpatch_size_t result=(windowOldBufSize*2<oldDataSize)?windowOldBufSize*2:(hpatch_size_t)oldDataSize;
2505
+ const hpatch_size_t mt_needSize=result+stepCoversMemSize+kMinTempCacheSize;
2506
+ hpatch_size_t cacheStepSize;
2507
+ if ((windowOldBufSize==0)||(tempCacheSize<mt_needSize))
2508
+ return 0;
2509
+ cacheStepSize=tempCacheSize-mt_needSize;
2510
+ if (cacheStepSize<=kMinTempCacheSize)
2511
+ return result;
2512
+ result+=(cacheStepSize-kMinTempCacheSize)*1/2;
2513
+ return (result<oldDataSize)?result:(hpatch_size_t)oldDataSize;
2514
+ }
2515
+
2516
+ static hpatch_BOOL _patch_single_stream_loop(TStreamCacheClip* inClip,_TOutStreamCache* outCache,
2517
+ const hpatch_TStreamInput* oldData,hpatch_StreamPos_t coverCount,
2518
+ hpatch_size_t stepMemSize,unsigned char* step_cache,
2519
+ unsigned char* temp_cache,hpatch_size_t cache_size,
2520
+ sspatch_coversListener_t* coversListener
2521
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2522
+ ,hpatch_BOOL isCachedOldByStep
2523
+ #endif
2524
+ ){
2525
+ sspatch_covers_t covers;
2526
+ sspatch_covers_init(&covers);
2527
+ if (coversListener) assert(coversListener->onStepCovers);
2528
+
2529
+ while (coverCount){
2530
+ rle0_decoder_t rle0_decoder;
2531
+ {//read step info
2532
+ unsigned char* covers_cacheEnd;
2533
+ unsigned char* bufRle_cache_end;
2534
+ {
2535
+ hpatch_StreamPos_t bufCover_size;
2536
+ hpatch_StreamPos_t bufRle_size;
2537
+ _clip_unpackUIntTo(&bufCover_size,inClip);
2538
+ _clip_unpackUIntTo(&bufRle_size,inClip);
2539
+ #ifdef __RUN_MEM_SAFE_CHECK
2540
+ if ((bufCover_size>stepMemSize)||(bufRle_size>stepMemSize)||
2541
+ (bufCover_size+bufRle_size>stepMemSize)) return _hpatch_FALSE;
2542
+ #endif
2543
+ covers_cacheEnd=step_cache+(size_t)bufCover_size;
2544
+ bufRle_cache_end=covers_cacheEnd+(size_t)bufRle_size;
2545
+ }
2546
+ if (coversListener&&coversListener->onStepCoversReset)
2547
+ coversListener->onStepCoversReset(coversListener,coverCount);
2548
+ if (!_TStreamCacheClip_readDataTo(inClip,step_cache,bufRle_cache_end))
2549
+ return _hpatch_FALSE;
2550
+ if (coversListener)
2551
+ coversListener->onStepCovers(coversListener,step_cache,covers_cacheEnd);
2552
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2553
+ if (isCachedOldByStep)
2554
+ _patch_step_cache_old_onStepCovers(oldData,step_cache,covers_cacheEnd);
2555
+ #endif
2556
+ sspatch_covers_setCoversCache(&covers,step_cache,covers_cacheEnd);
2557
+ _rle0_decoder_init(&rle0_decoder,covers_cacheEnd,bufRle_cache_end);
2558
+ }
2559
+ while (sspatch_covers_isHaveNextCover(&covers)){
2560
+ if (!sspatch_covers_nextCover(&covers))
2561
+ return _hpatch_FALSE;
2562
+ if (covers.cover.newPos>covers.lastNewEnd){
2563
+ if (!_TOutStreamCache_copyFromClip(outCache,inClip,covers.cover.newPos-covers.lastNewEnd))
2564
+ return _hpatch_FALSE;
2565
+ }
2566
+
2567
+ --coverCount;
2568
+ if (covers.cover.length){
2569
+ #ifdef __RUN_MEM_SAFE_CHECK
2570
+ if ((covers.cover.oldPos>oldData->streamSize)||
2571
+ (covers.cover.length>(hpatch_StreamPos_t)(oldData->streamSize-covers.cover.oldPos))) return _hpatch_FALSE;
2572
+ #endif
2573
+ if (!_patch_add_old_with_rle0(outCache,&rle0_decoder,oldData,covers.cover.oldPos,covers.cover.length,
2574
+ temp_cache,cache_size)) return _hpatch_FALSE;
2575
+ }else{
2576
+ #ifdef __RUN_MEM_SAFE_CHECK
2577
+ if (coverCount!=0) return _hpatch_FALSE;
2578
+ #endif
2579
+ }
2580
+ }
2581
+ }
2582
+ if (coversListener){
2583
+ if (coversListener->onStepCoversReset)
2584
+ coversListener->onStepCoversReset(coversListener,0);
2585
+ coversListener->onStepCovers(coversListener,0,0);
2586
+ }
2587
+
2588
+ return hpatch_TRUE;
2589
+ }
2590
+
2591
+
2592
+ hpatch_BOOL patch_single_stream_diff(const hpatch_TStreamOutput* out_newData,
2593
+ const hpatch_TStreamInput* oldData,
2594
+ const hpatch_TStreamInput* uncompressedDiffData,
2595
+ hpatch_StreamPos_t diffData_pos,
2596
+ hpatch_StreamPos_t diffData_posEnd,
2597
+ hpatch_StreamPos_t coverCount,hpatch_size_t stepMemSize,
2598
+ unsigned char* temp_cache,unsigned char* temp_cache_end,
2599
+ sspatch_coversListener_t* coversListener,hpatch_BOOL isNeedOutCache){
2600
+ unsigned char* step_cache;
2601
+ hpatch_size_t cache_size;
2602
+ TStreamCacheClip inClip;
2603
+ _TOutStreamCache outCache;
2604
+ const size_t kCacheCount=_kCacheSgCount-(isNeedOutCache?0:1);
2605
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2606
+ hpatch_BOOL isCachedOldByStep=hpatch_FALSE;
2607
+ #endif
2608
+
2609
+ step_cache=temp_cache;
2610
+ assert(diffData_posEnd<=uncompressedDiffData->streamSize);
2611
+ if (coversListener) assert(coversListener->onStepCovers);
2612
+ {//cache
2613
+ hpatch_BOOL isCachedAllOld;
2614
+ hpatch_BOOL isReadError=hpatch_FALSE;
2615
+ if ((size_t)(temp_cache_end-temp_cache)<stepMemSize+hpatch_kStreamCacheSize*kCacheCount) return _hpatch_FALSE;
2616
+ temp_cache+=stepMemSize;
2617
+ isCachedAllOld=_patch_cache_all_old(&oldData,kCacheCount*hpatch_kStreamCacheSize,&temp_cache,&temp_cache_end,&isReadError);
2618
+ if (isReadError) return _hpatch_FALSE;
2619
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2620
+ if (!isCachedAllOld)
2621
+ isCachedOldByStep=_patch_step_cache_old(&oldData,out_newData->streamSize,stepMemSize,
2622
+ kCacheCount*hpatch_kFileIOBufBetterSize,&temp_cache,&temp_cache_end);
2623
+ #endif
2624
+ cache_size=(temp_cache_end-temp_cache)/kCacheCount;
2625
+ _TStreamCacheClip_init(&inClip,uncompressedDiffData,diffData_pos,diffData_posEnd,
2626
+ temp_cache,cache_size);
2627
+ temp_cache+=cache_size;
2628
+ _TOutStreamCache_init(&outCache,out_newData,isNeedOutCache?temp_cache:0,isNeedOutCache?cache_size:0);
2629
+ if (isNeedOutCache) temp_cache+=cache_size;
2630
+ }
2631
+
2632
+ if (!_patch_single_stream_loop(&inClip,&outCache,oldData,coverCount,stepMemSize,
2633
+ step_cache,temp_cache,cache_size,coversListener
2634
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
2635
+ ,isCachedOldByStep
2636
+ #endif
2637
+ ))
2638
+ return _hpatch_FALSE;
2639
+
2640
+ if (!_TOutStreamCache_flush(&outCache))
2641
+ return _hpatch_FALSE;
2642
+ if (_TStreamCacheClip_isFinish(&inClip)&&_TOutStreamCache_isFinish(&outCache))
2643
+ return hpatch_TRUE;
2644
+ else
2645
+ return _hpatch_FALSE;
2646
+ }
2647
+
2648
+
2649
+ static hpatch_BOOL _TDiffToSingleStream_read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
2650
+ unsigned char* out_data,unsigned char* out_data_end){
2651
+ //[ |readedSize ]
2652
+ // [ |cachedBufBegin _TDiffToSingleStream_kBufSize]
2653
+ // readFromPos[out_data out_data_end]
2654
+ TDiffToSingleStream* self=(TDiffToSingleStream*)stream->streamImport;
2655
+ hpatch_StreamPos_t readedSize=self->readedSize;
2656
+ while (1){
2657
+ size_t rLen=out_data_end-out_data;
2658
+ if (readFromPos==readedSize){
2659
+ hpatch_BOOL result=self->diffStream->read(self->diffStream,readedSize,out_data,out_data_end);
2660
+ self->readedSize=readedSize+rLen;
2661
+ if ((self->isInSingleStream)||(rLen>_TDiffToSingleStream_kBufSize)){
2662
+ self->cachedBufBegin=_TDiffToSingleStream_kBufSize;
2663
+ }else{
2664
+ //cache
2665
+ if (rLen>=_TDiffToSingleStream_kBufSize){
2666
+ memcpy(self->buf,out_data_end-_TDiffToSingleStream_kBufSize,_TDiffToSingleStream_kBufSize);
2667
+ self->cachedBufBegin = 0;
2668
+ }else{
2669
+ size_t new_cachedBufBegin;
2670
+ if (self->cachedBufBegin>=rLen){
2671
+ new_cachedBufBegin=self->cachedBufBegin-rLen;
2672
+ memmove(self->buf+new_cachedBufBegin,self->buf+self->cachedBufBegin,_TDiffToSingleStream_kBufSize-self->cachedBufBegin);
2673
+ }else{
2674
+ new_cachedBufBegin=0;
2675
+ memmove(self->buf,self->buf+rLen,_TDiffToSingleStream_kBufSize-rLen);
2676
+ }
2677
+ memcpy(self->buf+(_TDiffToSingleStream_kBufSize-rLen),out_data,rLen);
2678
+ self->cachedBufBegin=new_cachedBufBegin;
2679
+ }
2680
+ }
2681
+ return result;
2682
+ }else{
2683
+ size_t cachedSize=_TDiffToSingleStream_kBufSize-self->cachedBufBegin;
2684
+ size_t bufSize=(size_t)(readedSize-readFromPos);
2685
+ if ((readFromPos<readedSize)&&(bufSize<=cachedSize)){
2686
+ if (rLen>bufSize)
2687
+ rLen=bufSize;
2688
+ memcpy(out_data,self->buf+(_TDiffToSingleStream_kBufSize-bufSize),rLen);
2689
+ out_data+=rLen;
2690
+ readFromPos+=rLen;
2691
+ if (out_data==out_data_end)
2692
+ return hpatch_TRUE;
2693
+ else
2694
+ continue;
2695
+ }else{
2696
+ return _hpatch_FALSE;
2697
+ }
2698
+ }
2699
+ }
2700
+ }
2701
+ void TDiffToSingleStream_init(TDiffToSingleStream* self,const hpatch_TStreamInput* diffStream){
2702
+ self->base.streamImport=self;
2703
+ self->base.streamSize=diffStream->streamSize;
2704
+ self->base.read=_TDiffToSingleStream_read;
2705
+ self->base._private_reserved=0;
2706
+ self->diffStream=diffStream;
2707
+ self->readedSize=0;
2708
+ self->cachedBufBegin=_TDiffToSingleStream_kBufSize;
2709
+ self->isInSingleStream=hpatch_FALSE;
2710
+ }
2711
+
2712
+ hpatch_BOOL _patch_single_stream_mt(sspatch_listener_t* listener,
2713
+ const hpatch_TStreamOutput* __out_newData,
2714
+ const hpatch_TStreamInput* oldData,
2715
+ const hpatch_TStreamInput* singleCompressedDiff,
2716
+ hpatch_StreamPos_t diffInfo_pos,
2717
+ sspatch_coversListener_t* coversListener,
2718
+ size_t maxThreadNum,hpatchMTSets_t hpatchMTSets){
2719
+ hpatch_BOOL result=hpatch_TRUE;
2720
+ hpatch_TDecompress* decompressPlugin=0;
2721
+ unsigned char* temp_cache=0;
2722
+ unsigned char* temp_cacheEnd=0;
2723
+ hpatch_singleCompressedDiffInfo diffInfo;
2724
+ hpatch_TStreamOutput _out_newData=*__out_newData;
2725
+ hpatch_TStreamOutput* out_newData=&_out_newData;
2726
+ TDiffToSingleStream _toSStream;
2727
+ assert((listener)&&(listener->onDiffInfo));
2728
+ TDiffToSingleStream_init(&_toSStream,singleCompressedDiff);
2729
+ singleCompressedDiff=&_toSStream.base;
2730
+
2731
+ if (!getSingleCompressedDiffInfo(&diffInfo,singleCompressedDiff,diffInfo_pos))
2732
+ return _hpatch_FALSE;
2733
+ if (diffInfo.newDataSize>out_newData->streamSize)
2734
+ return _hpatch_FALSE;
2735
+ out_newData->streamSize=diffInfo.newDataSize;
2736
+ if (diffInfo.oldDataSize!=oldData->streamSize)
2737
+ return _hpatch_FALSE;
2738
+ if (!listener->onDiffInfo(listener,&diffInfo,&decompressPlugin,&temp_cache,&temp_cacheEnd))
2739
+ return _hpatch_FALSE;
2740
+
2741
+ if ((temp_cache==0)||(temp_cache>=temp_cacheEnd))
2742
+ result=_hpatch_FALSE;
2743
+ if (result){
2744
+ result=_patch_single_compressed_diff_mt(out_newData,oldData,singleCompressedDiff,diffInfo.diffDataPos,
2745
+ diffInfo.uncompressedSize,diffInfo.compressedSize,decompressPlugin,
2746
+ diffInfo.coverCount,(size_t)diffInfo.stepMemSize,
2747
+ temp_cache,temp_cacheEnd,coversListener,maxThreadNum,hpatchMTSets);
2748
+ }
2749
+ if (listener->onPatchFinish)
2750
+ listener->onPatchFinish(listener,temp_cache,temp_cacheEnd);
2751
+ return result;
2752
+ }
2753
+
2754
+
2755
+ static hpatch_BOOL _getWindowDiffInfo(hpatch_windowDiffInfo* out_diffInfo,
2756
+ const hpatch_TStreamInput* windowDiff,hpatch_StreamPos_t diffInfo_pos,
2757
+ unsigned char* headBuf, // [hpatch_kWindowDiffHeadMaxSize]
2758
+ hpatch_size_t* headSize){ // in headBuf size, out headData size
2759
+ const char* kVersionType="HDIFFW26";
2760
+ const size_t kVersionLen=strlen(kVersionType);
2761
+ const size_t kHeadPrefixSize=kVersionLen+2;
2762
+ hpatch_size_t headRemainingSize;
2763
+ hpatch_TStreamInput headMemStream;
2764
+ TStreamCacheClip _headClip;
2765
+ TStreamCacheClip* diffHeadClip=&_headClip;
2766
+ TByte _temp_cache[hpatch_kMaxPluginTypeLength];
2767
+ assert(out_diffInfo!=0);
2768
+ assert(windowDiff!=0);
2769
+ assert(windowDiff->read!=0);
2770
+ assert(headBuf!=0);
2771
+ assert(headSize!=0);
2772
+
2773
+ //read "HDIFFW26" + headRemainingSize
2774
+ if (kHeadPrefixSize>(*headSize)) return _hpatch_FALSE;
2775
+ if (!windowDiff->read(windowDiff,diffInfo_pos,headBuf,headBuf+kHeadPrefixSize))
2776
+ return _hpatch_FALSE;
2777
+ if (0!=memcmp(headBuf,"HDIFFW26",kVersionLen))
2778
+ return _hpatch_FALSE;
2779
+ headRemainingSize=(hpatch_size_t)headBuf[kVersionLen] | ((hpatch_size_t)headBuf[kVersionLen+1]<<8);
2780
+ if (headRemainingSize+kHeadPrefixSize>(*headSize))
2781
+ return _hpatch_FALSE;
2782
+
2783
+ //read remaining head data
2784
+ if (!windowDiff->read(windowDiff,diffInfo_pos+kHeadPrefixSize,
2785
+ headBuf+kHeadPrefixSize,headBuf+kHeadPrefixSize+headRemainingSize))
2786
+ return _hpatch_FALSE;
2787
+ *headSize=kHeadPrefixSize+headRemainingSize;
2788
+ out_diffInfo->windowDataPos=kHeadPrefixSize+headRemainingSize;
2789
+
2790
+ //parse from headBuf (skip version+size, parse type string + packUInts)
2791
+ mem_as_hStreamInput(&headMemStream,headBuf+kHeadPrefixSize,headBuf+kHeadPrefixSize+headRemainingSize);
2792
+ _TStreamCacheClip_init(diffHeadClip,&headMemStream,0,headRemainingSize,_temp_cache,sizeof(_temp_cache));
2793
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'&',out_diffInfo->compressType))
2794
+ return _hpatch_FALSE;
2795
+ if (!_TStreamCacheClip_readType_end(diffHeadClip,'\0',out_diffInfo->checksumType))
2796
+ return _hpatch_FALSE;
2797
+
2798
+ //read header fields
2799
+ _clip_unpackUIntTo(&out_diffInfo->compressedSize,diffHeadClip);
2800
+ out_diffInfo->_headFixedInfoPos=kHeadPrefixSize+_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
2801
+ _clip_unpackUIntTo(&out_diffInfo->uncompressedSize,diffHeadClip);
2802
+ _clip_unpackUIntTo(&out_diffInfo->newDataSize,diffHeadClip);
2803
+ _clip_unpackUIntTo(&out_diffInfo->oldDataSize,diffHeadClip);
2804
+ _clip_unpackUIntTo(&out_diffInfo->coverCount,diffHeadClip);
2805
+ _clip_unpackUIntTo(&out_diffInfo->windowCount,diffHeadClip);
2806
+ _clip_unpackUIntTo(&out_diffInfo->windowMetaCount,diffHeadClip);
2807
+ _clip_unpackUIntTo(&out_diffInfo->maxStepMemSize,diffHeadClip);
2808
+ _clip_unpackUIntTo(&out_diffInfo->maxSubCoverCount,diffHeadClip);
2809
+ _clip_unpackUIntTo(&out_diffInfo->maxWindowOldSize,diffHeadClip);
2810
+ _clip_unpackUIntTo(&out_diffInfo->checksumByteSize,diffHeadClip);
2811
+ _clip_unpackUIntTo(&out_diffInfo->extraDataSize,diffHeadClip);
2812
+
2813
+ out_diffInfo->otherInfoPos=kHeadPrefixSize+_TStreamCacheClip_readPosOfSrcStream(diffHeadClip);
2814
+ if (out_diffInfo->otherInfoPos+out_diffInfo->checksumByteSize*3>out_diffInfo->windowDataPos)
2815
+ return _hpatch_FALSE;
2816
+ out_diffInfo->otherInfoEndPos=out_diffInfo->windowDataPos-out_diffInfo->checksumByteSize*3;
2817
+
2818
+ if ((out_diffInfo->windowMetaCount>hpatch_kMaxWindowMetaCount)||(out_diffInfo->windowMetaCount<2))
2819
+ return _hpatch_FALSE;
2820
+ if ((out_diffInfo->windowMetaCount&(out_diffInfo->windowMetaCount-1))!=0) //2^N
2821
+ return _hpatch_FALSE;
2822
+ if (((out_diffInfo->checksumType[0]==0)&&(out_diffInfo->checksumByteSize!=0))
2823
+ ||((out_diffInfo->checksumType[0]!=0)&&(out_diffInfo->checksumByteSize==0)))
2824
+ return _hpatch_FALSE;
2825
+ if (out_diffInfo->maxWindowOldSize>out_diffInfo->oldDataSize)
2826
+ return _hpatch_FALSE;
2827
+ if ((out_diffInfo->maxWindowOldSize>0)&&(out_diffInfo->windowCount==0))
2828
+ return _hpatch_FALSE;
2829
+ if (out_diffInfo->compressedSize>out_diffInfo->uncompressedSize)
2830
+ return _hpatch_FALSE;
2831
+ if (out_diffInfo->maxStepMemSize>(out_diffInfo->newDataSize+_kStepMemSizeSafeLimit))
2832
+ return _hpatch_FALSE;
2833
+ if (out_diffInfo->maxStepMemSize>out_diffInfo->uncompressedSize+_kStepMemSizeSafeLimit)
2834
+ return _hpatch_FALSE;
2835
+ return hpatch_TRUE;
2836
+ }
2837
+
2838
+ hpatch_BOOL getWindowDiffInfo(hpatch_windowDiffInfo* out_diffInfo,const hpatch_TStreamInput* windowDiff,
2839
+ hpatch_StreamPos_t diffInfo_pos){
2840
+ TByte headBuf[hpatch_kWindowDiffHeadMaxSize];
2841
+ hpatch_size_t headSize=sizeof(headBuf);
2842
+ return _getWindowDiffInfo(out_diffInfo,windowDiff,diffInfo_pos,headBuf,&headSize);
2843
+ }
2844
+
2845
+ static const size_t _kWindowCacheCount=_kCacheSgCount;
2846
+
2847
+ static hpatch_BOOL _cache_load_window_old(const hpatch_TStreamInput* oldData,unsigned char* oldBuf,
2848
+ hpatch_StreamPos_t windowOldPos,hpatch_StreamPos_t windowOldLength,
2849
+ hpatch_StreamPos_t* pLastOldPos,hpatch_StreamPos_t* pLastOldEnd){
2850
+ const hpatch_StreamPos_t lastOldPos=*pLastOldPos;
2851
+ const hpatch_StreamPos_t lastOldEnd=*pLastOldEnd;
2852
+ const hpatch_StreamPos_t windowOldEnd=windowOldPos+windowOldLength;
2853
+ hpatch_StreamPos_t reuseLen,reuseOff,noOverlapLeft;
2854
+ _compute_window_overlap(lastOldPos,lastOldEnd,windowOldPos,windowOldEnd,&reuseLen,&reuseOff,&noOverlapLeft);
2855
+ memmove(oldBuf+(size_t)noOverlapLeft,oldBuf+(size_t)reuseOff,(size_t)reuseLen);
2856
+ if ((noOverlapLeft>0)&&(!oldData->read(oldData,windowOldPos,oldBuf,oldBuf+(size_t)noOverlapLeft)))
2857
+ return _hpatch_FALSE;
2858
+ if ((noOverlapLeft+reuseLen<windowOldLength)&&(!oldData->read(oldData,windowOldPos+noOverlapLeft+reuseLen,
2859
+ oldBuf+(size_t)(noOverlapLeft+reuseLen),oldBuf+(size_t)windowOldLength)))
2860
+ return _hpatch_FALSE;
2861
+ *pLastOldPos=windowOldPos;
2862
+ *pLastOldEnd=windowOldPos+windowOldLength;
2863
+ return hpatch_TRUE;
2864
+ }
2865
+
2866
+ static hpatch_BOOL _read_meta_batch(TStreamCacheClip* clip,hpatch_StreamPos_t* pLastOldPos,
2867
+ hpatch_StreamPos_t maxWindowOldSize,hpatch_StreamPos_t oldSize,
2868
+ _oldwin_info_t* winInfos,hpatch_size_t writeIdx,hpatch_size_t batchSize){
2869
+ hpatch_StreamPos_t lastOldPos=*pLastOldPos;
2870
+ hpatch_size_t i;
2871
+ for (i=0;i<batchSize;++i){
2872
+ hpatch_StreamPos_t len;
2873
+ _clip_unpackUIntTo(&len,clip);
2874
+ if (!_read_sign_pos_byLastPos(clip,&lastOldPos)) return _hpatch_FALSE;
2875
+ #if (defined __RUN_MEM_SAFE_CHECK)
2876
+ if (len>maxWindowOldSize) return _hpatch_FALSE;
2877
+ if (len!=(hpatch_StreamPos_t)(hpatch_size_t)len) return _hpatch_FALSE;
2878
+ if (lastOldPos>oldSize) return _hpatch_FALSE;
2879
+ if (lastOldPos+len>oldSize) return _hpatch_FALSE;
2880
+ #endif
2881
+ winInfos[writeIdx+i].len=len;
2882
+ winInfos[writeIdx+i].oldPos=lastOldPos;
2883
+ lastOldPos+=len;
2884
+ }
2885
+ *pLastOldPos=lastOldPos;
2886
+ return hpatch_TRUE;
2887
+ }
2888
+
2889
+ static hpatch_BOOL _readForSkipStream(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readPos,
2890
+ hpatch_StreamPos_t readEndPos,unsigned char* temp_cache,unsigned char* temp_cacheEnd){
2891
+ while (readPos<readEndPos){
2892
+ hpatch_StreamPos_t rlen=readEndPos-readPos;
2893
+ rlen=(rlen<(size_t)(temp_cacheEnd-temp_cache))?rlen:(size_t)(temp_cacheEnd-temp_cache);
2894
+ if (!stream->read(stream,readPos,temp_cache,temp_cache+(size_t)rlen))
2895
+ return _hpatch_FALSE;
2896
+ readPos+=rlen;
2897
+ }
2898
+ return hpatch_TRUE;
2899
+ }
2900
+
2901
+ static hpatch_inline hpatch_BOOL _read_sub_cover_count(TStreamCacheClip* clip,
2902
+ hpatch_StreamPos_t maxSubCoverCount,hpatch_StreamPos_t* out_subCoverCount){
2903
+ _clip_unpackUIntTo(out_subCoverCount,clip);
2904
+ #if (defined __RUN_MEM_SAFE_CHECK)
2905
+ if ((*out_subCoverCount)>maxSubCoverCount) return _hpatch_FALSE;
2906
+ #endif
2907
+ return hpatch_TRUE;
2908
+ }
2909
+
2910
+ static hpatch_BOOL _patch_window_diff(const hpatch_TStreamOutput* out_newData,const hpatch_TStreamInput* oldData,
2911
+ const hpatch_TStreamInput* diffStream,hpatch_StreamPos_t diffData_pos,
2912
+ const hpatch_windowDiffInfo* diffInfo,hpatch_TDecompress* decompressPlugin,
2913
+ hpatch_TChecksum* checksumPlugin,hpatch_checksumHandle checksumHandle_old,
2914
+ unsigned char* temp_cache,unsigned char* temp_cache_end,
2915
+ size_t maxThreadNum,hpatchMTSets_t hpatchMTSets){
2916
+ const hpatch_size_t windowOldBufSize=(hpatch_size_t)diffInfo->maxWindowOldSize;
2917
+ const hpatch_size_t stepMemSize=(hpatch_size_t)diffInfo->maxStepMemSize;
2918
+ const hpatch_StreamPos_t windowCount=diffInfo->windowCount;
2919
+ const hpatch_StreamPos_t metaCount=diffInfo->windowMetaCount;
2920
+ unsigned char* oldBuf;
2921
+ TStreamCacheClip mainClip;
2922
+ _TOutStreamCache outCache;
2923
+ hpatch_StreamPos_t lastOldPos=0;
2924
+ hpatch_StreamPos_t lastOldEnd=0;
2925
+ hpatch_StreamPos_t lastOldPosForMeta=0; // running oldPos for delta decoding
2926
+ hpatch_StreamPos_t loadedMetaEnd=0;
2927
+ _oldwin_info_t winInfos[hpatch_kMaxWindowMetaCount];
2928
+ hpatch_StreamPos_t wi;
2929
+ hpatch_BOOL result=hpatch_TRUE;
2930
+
2931
+ hpatch_BOOL isNeedOutCache=hpatch_TRUE;
2932
+ size_t kCacheCount=_kWindowCacheCount;
2933
+ hpatch_size_t cacheSize;
2934
+ hpatch_TUncompresser_t uncompressedStream={0};
2935
+ hpatch_StreamPos_t diffData_posEnd;
2936
+
2937
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2938
+ struct hpatch_mt_manager_win_t* hpatch_mt_manager=0;
2939
+ struct hcache_window_old_mt_t* oldCache_mt=0;
2940
+ hpatchMTSets_t mtsets;
2941
+ TMem2StreamImport mem2Import;
2942
+ #endif
2943
+ assert(out_newData!=0);
2944
+ assert(out_newData->write!=0);
2945
+ assert(oldData!=0);
2946
+ assert(oldData->read!=0);
2947
+ assert(diffStream!=0);
2948
+ assert(diffStream->read!=0);
2949
+ assert(diffInfo!=0);
2950
+ assert(((checksumHandle_old==0)&&(checksumPlugin==0))||((checksumHandle_old!=0)&&(checksumPlugin!=0)));
2951
+ #if (defined __RUN_MEM_SAFE_CHECK)
2952
+ if (diffInfo->maxWindowOldSize!=(hpatch_StreamPos_t)(hpatch_size_t)diffInfo->maxWindowOldSize) return _hpatch_FALSE;
2953
+ if (diffInfo->maxStepMemSize!=(hpatch_StreamPos_t)(hpatch_size_t)diffInfo->maxStepMemSize) return _hpatch_FALSE;
2954
+ #endif
2955
+
2956
+ if (diffInfo->compressedSize==0){
2957
+ decompressPlugin=0;
2958
+ }else{
2959
+ if (decompressPlugin==0) return _hpatch_FALSE;
2960
+ }
2961
+ diffData_posEnd=(decompressPlugin?diffInfo->compressedSize:diffInfo->uncompressedSize)+diffData_pos;
2962
+ #if (defined __RUN_MEM_SAFE_CHECK)
2963
+ if (diffData_posEnd>diffStream->streamSize) return _hpatch_FALSE;
2964
+ #endif
2965
+ #if (_HPATCH_IS_USED_MULTITHREAD)
2966
+ mtsets=hpatch_getMTSets_win(out_newData->streamSize,oldData->streamSize,diffStream->streamSize-diffData_pos,
2967
+ decompressPlugin,_kWindowCacheCount,windowOldBufSize,stepMemSize,
2968
+ (temp_cache_end-temp_cache),maxThreadNum,hpatchMTSets);
2969
+ if (_hpatchMTSets_threadNum(mtsets)>1){
2970
+ isNeedOutCache=!mtsets.writeNew_isMT;
2971
+ kCacheCount=_kWindowCacheCount-(isNeedOutCache?0:1);
2972
+ hpatch_mt_manager=hpatch_mt_manager_win_open(&out_newData,&oldData,&diffStream,&diffData_pos,&diffData_posEnd,
2973
+ diffInfo->uncompressedSize,&decompressPlugin,windowCount,windowOldBufSize,
2974
+ stepMemSize,&temp_cache,&temp_cache_end,kCacheCount,mtsets);
2975
+ if (!hpatch_mt_manager) { result=_hpatch_FALSE; goto _clear; }
2976
+ oldCache_mt=hpatch_mt_manager_win_oldCache(hpatch_mt_manager);
2977
+ }
2978
+ if (oldCache_mt==0)
2979
+ #endif
2980
+ {// Single-threaded: allocate fixed-size oldBuf
2981
+ assert((size_t)(temp_cache_end-temp_cache)>=windowOldBufSize+stepMemSize+hpatch_kStreamCacheSize*kCacheCount);
2982
+ oldBuf=temp_cache; temp_cache+=windowOldBufSize;
2983
+ }
2984
+ #if (defined __RUN_MEM_SAFE_CHECK)
2985
+ if ((size_t)(temp_cache_end-temp_cache)<stepMemSize+hpatch_kStreamCacheSize*kCacheCount) { result=_hpatch_FALSE; goto _clear; }
2986
+ #endif
2987
+ if (decompressPlugin){
2988
+ if (!compressed_stream_as_uncompressed(&uncompressedStream,diffInfo->uncompressedSize,decompressPlugin,diffStream,
2989
+ diffData_pos,diffData_posEnd)) { result=_hpatch_FALSE; goto _clear; }
2990
+ diffStream=&uncompressedStream.base;
2991
+ diffData_pos=0;
2992
+ diffData_posEnd=diffStream->streamSize;
2993
+ }
2994
+
2995
+ if (!_readForSkipStream(diffStream,diffData_pos, //skip extraData
2996
+ diffData_pos+diffInfo->extraDataSize,temp_cache,temp_cache_end))
2997
+ { result=_hpatch_FALSE; goto _clear; }
2998
+ diffData_pos+=diffInfo->extraDataSize;
2999
+
3000
+ #if (defined __RUN_MEM_SAFE_CHECK)
3001
+ if (diffData_pos>diffData_posEnd) { result=_hpatch_FALSE; goto _clear; }
3002
+ if (diffData_posEnd>diffStream->streamSize) { result=_hpatch_FALSE; goto _clear; }
3003
+ #endif
3004
+
3005
+ // Remaining temp_cache for stream caches
3006
+ cacheSize=(hpatch_size_t)((temp_cache_end-temp_cache)-stepMemSize)/kCacheCount;
3007
+ if (cacheSize<hpatch_kStreamCacheSize) { result=_hpatch_FALSE; goto _clear; }
3008
+
3009
+ // Initialize mainClip for reading window data
3010
+ _TStreamCacheClip_init(&mainClip,diffStream,diffData_pos,diffData_posEnd,temp_cache,cacheSize);
3011
+ temp_cache+=cacheSize;
3012
+ //init output cache
3013
+ _TOutStreamCache_init(&outCache,out_newData,isNeedOutCache?temp_cache:0,isNeedOutCache?cacheSize:0);
3014
+ if (isNeedOutCache) temp_cache+=cacheSize;
3015
+
3016
+ //process each window
3017
+ for (wi=0; wi<windowCount; ++wi){
3018
+ hpatch_StreamPos_t subCoverCount;
3019
+ hpatch_StreamPos_t windowOldPos;
3020
+ hpatch_StreamPos_t windowOldLength;
3021
+ hpatch_TStreamInput oldMemStream;
3022
+
3023
+ //after each (metaCount>>1) windows, read next metadata batch
3024
+ if ((((wi)&((metaCount>>1)-1))==0) && (loadedMetaEnd<windowCount)){
3025
+ hpatch_StreamPos_t savedMetaCount=(wi==0)?metaCount:(metaCount>>1);
3026
+ hpatch_size_t writeIdx=(hpatch_size_t)(loadedMetaEnd & (metaCount-1));
3027
+ hpatch_StreamPos_t batchSize=windowCount-loadedMetaEnd;
3028
+ if (batchSize>savedMetaCount) batchSize=savedMetaCount;
3029
+ if (!_read_meta_batch(&mainClip,&lastOldPosForMeta,diffInfo->maxWindowOldSize,oldData->streamSize,
3030
+ winInfos,writeIdx,(hpatch_size_t)batchSize))
3031
+ { result=_hpatch_FALSE; goto _clear; }
3032
+ #if (_HPATCH_IS_USED_MULTITHREAD)
3033
+ if (oldCache_mt)
3034
+ hcache_window_old_prepareBatch(oldCache_mt,(hpatch_size_t)batchSize,winInfos,writeIdx,(hpatch_size_t)metaCount-1);
3035
+ #endif
3036
+ loadedMetaEnd+=batchSize;
3037
+ }
3038
+
3039
+ if (!_read_sub_cover_count(&mainClip,diffInfo->maxSubCoverCount,&subCoverCount))
3040
+ { result=_hpatch_FALSE; goto _clear; }
3041
+ {//look up oldPos/oldLength from ring buffer
3042
+ hpatch_size_t metaIdx=(hpatch_size_t)(wi & (metaCount-1));
3043
+ windowOldPos =winInfos[metaIdx].oldPos;
3044
+ windowOldLength=winInfos[metaIdx].len;
3045
+ }
3046
+
3047
+ // Load old window data
3048
+ #if (_HPATCH_IS_USED_MULTITHREAD)
3049
+ if (oldCache_mt){
3050
+ unsigned char *seg1, *seg1End, *seg2, *seg2End;
3051
+ if (!hcache_window_old_getWindow(oldCache_mt,windowOldPos,windowOldLength,
3052
+ &seg1,&seg1End,&seg2,&seg2End))
3053
+ { result=_hpatch_FALSE; goto _clear; }
3054
+ mem2_as_hStreamInput(&oldMemStream,&mem2Import,seg1,seg1End,seg2,seg2End);
3055
+ if (checksumHandle_old!=0){
3056
+ checksumPlugin->append(checksumHandle_old,seg1,seg1End);
3057
+ checksumPlugin->append(checksumHandle_old,seg2,seg2End);
3058
+ }
3059
+ } else
3060
+ #endif
3061
+ {
3062
+ if (!_cache_load_window_old(oldData,oldBuf,windowOldPos,windowOldLength, &lastOldPos,&lastOldEnd))
3063
+ { result=_hpatch_FALSE; goto _clear; }
3064
+ if (checksumHandle_old!=0)
3065
+ checksumPlugin->append(checksumHandle_old,oldBuf,oldBuf+(hpatch_size_t)windowOldLength);
3066
+ mem_as_hStreamInput(&oldMemStream,oldBuf,oldBuf+(hpatch_size_t)windowOldLength);
3067
+ }
3068
+
3069
+ if (!_patch_single_stream_loop(&mainClip,&outCache,&oldMemStream,subCoverCount,stepMemSize,
3070
+ temp_cache,temp_cache+stepMemSize,cacheSize, 0//no coversListener
3071
+ #if (_IS_NEED_CACHE_OLD_BY_COVERS)
3072
+ ,hpatch_FALSE
3073
+ #endif
3074
+ ))
3075
+ { result=_hpatch_FALSE; goto _clear; }
3076
+
3077
+ #if (_HPATCH_IS_USED_MULTITHREAD)
3078
+ if (oldCache_mt){
3079
+ hcache_window_old_finishWindow(oldCache_mt);
3080
+ }
3081
+ #endif
3082
+ }
3083
+
3084
+ //flush and verify
3085
+ if ((!_TOutStreamCache_flush(&outCache))
3086
+ ||(!_TOutStreamCache_isFinish(&outCache))
3087
+ ||(!_TStreamCacheClip_isFinish(&mainClip)))
3088
+ { result=_hpatch_FALSE; goto _clear; }
3089
+
3090
+ _clear:
3091
+ if (decompressPlugin)
3092
+ close_compressed_stream_as_uncompressed(&uncompressedStream);
3093
+ #if (_HPATCH_IS_USED_MULTITHREAD)
3094
+ if (hpatch_mt_manager){
3095
+ if (!hpatch_mt_manager_win_close(hpatch_mt_manager,!result))
3096
+ result=_hpatch_FALSE;
3097
+ hpatch_mt_manager=0;
3098
+ }
3099
+ #endif
3100
+ return result;
3101
+ }
3102
+
3103
+
3104
+ //checksum stream wrappers
3105
+ typedef struct _TChecksumInputStream{
3106
+ hpatch_TStreamInput base;
3107
+ const hpatch_TStreamInput* realIn;
3108
+ hpatch_TChecksum* checksumPlugin;
3109
+ hpatch_checksumHandle checksumHandle;
3110
+ hpatch_StreamPos_t readedEndPos;
3111
+ } _TChecksumInputStream;
3112
+
3113
+ static hpatch_BOOL _TChecksumInputStream_read(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
3114
+ unsigned char* out_data,unsigned char* out_data_end){
3115
+ _TChecksumInputStream* self=(_TChecksumInputStream*)stream->streamImport;
3116
+ if (!self->realIn->read(self->realIn,readFromPos,out_data,out_data_end))
3117
+ return _hpatch_FALSE;
3118
+ self->checksumPlugin->append(self->checksumHandle,out_data,out_data_end);
3119
+ self->readedEndPos=readFromPos+(out_data_end-out_data);
3120
+ return hpatch_TRUE;
3121
+ }
3122
+
3123
+ static void _TChecksumInputStream_init(_TChecksumInputStream* self,const hpatch_TStreamInput* realIn,
3124
+ hpatch_TChecksum* checksumPlugin,hpatch_checksumHandle checksumHandle){
3125
+ assert(self);
3126
+ assert(realIn);
3127
+ assert(checksumPlugin);
3128
+ assert(checksumHandle);
3129
+ self->realIn=realIn;
3130
+ self->checksumPlugin=checksumPlugin;
3131
+ self->checksumHandle=checksumHandle;
3132
+ self->readedEndPos=0;
3133
+ self->base.streamImport=self;
3134
+ self->base.streamSize=realIn->streamSize;
3135
+ self->base.read=_TChecksumInputStream_read;
3136
+ }
3137
+
3138
+ typedef struct _TChecksumOutputStream{
3139
+ hpatch_TStreamOutput base;
3140
+ const hpatch_TStreamOutput* realOut;
3141
+ hpatch_TChecksum* checksumPlugin;
3142
+ hpatch_checksumHandle checksumHandle;
3143
+ hpatch_StreamPos_t writedEndPos;
3144
+ } _TChecksumOutputStream;
3145
+
3146
+ static hpatch_BOOL _TChecksumOutputStream_write(const hpatch_TStreamOutput* stream,
3147
+ hpatch_StreamPos_t writeToPos,
3148
+ const unsigned char* data,const unsigned char* data_end){
3149
+ _TChecksumOutputStream* self=(_TChecksumOutputStream*)stream->streamImport;
3150
+ if (!self->realOut->write(self->realOut,writeToPos,data,data_end))
3151
+ return _hpatch_FALSE;
3152
+ self->checksumPlugin->append(self->checksumHandle,data,data_end);
3153
+ self->writedEndPos=writeToPos+(data_end-data);
3154
+ return hpatch_TRUE;
3155
+ }
3156
+
3157
+ static void _TChecksumOutputStream_init(_TChecksumOutputStream* self,const hpatch_TStreamOutput* realOut,
3158
+ hpatch_TChecksum* checksumPlugin,hpatch_checksumHandle checksumHandle){
3159
+ assert(self);
3160
+ assert(realOut);
3161
+ assert(checksumPlugin);
3162
+ assert(checksumHandle);
3163
+ self->realOut=realOut;
3164
+ self->checksumPlugin=checksumPlugin;
3165
+ self->checksumHandle=checksumHandle;
3166
+ self->writedEndPos=0;
3167
+ self->base.streamImport=self;
3168
+ self->base.streamSize=realOut->streamSize;
3169
+ self->base.write=_TChecksumOutputStream_write;
3170
+ self->base.read_writed=0;
3171
+ }
3172
+
3173
+ TWindowPatchResult patch_window_diff(winpatch_listener_t* listener,
3174
+ const hpatch_TStreamOutput* __out_newData,
3175
+ const hpatch_TStreamInput* oldData,
3176
+ const hpatch_TStreamInput* windowDiff,
3177
+ hpatch_StreamPos_t diffInfo_pos,size_t threadNum){
3178
+ TWindowPatchResult result=kWindowPatch_ok;
3179
+ hpatch_BOOL patch_result;
3180
+ hpatch_windowDiffInfo diffInfo;
3181
+ hpatch_TDecompress* decompressPlugin=0;
3182
+ hpatch_TChecksum* checksumPlugin=0;
3183
+ unsigned char* temp_cache_back=0;
3184
+ unsigned char* temp_cache=0;
3185
+ unsigned char* temp_cacheEnd=0;
3186
+ hpatch_BOOL isChecksumNew;
3187
+ hpatch_BOOL isChecksumOld=hpatch_FALSE;
3188
+ hpatch_BOOL isChecksumDiff=hpatch_FALSE;
3189
+ hpatch_checksumHandle checksumHandle_old=0;
3190
+ hpatch_checksumHandle checksumHandle_new=0;
3191
+ hpatch_checksumHandle checksumHandle_diff=0;
3192
+ hpatch_size_t checksumByteSize;
3193
+ const hpatch_TStreamInput* effectiveDiffStream;
3194
+ _TChecksumInputStream checksumDiffInput;
3195
+ _TChecksumOutputStream checksumNewOutput;
3196
+ const hpatch_TStreamOutput* effectiveOutNew;
3197
+ hpatch_TStreamOutput _out_newData=*__out_newData;
3198
+ hpatch_TStreamOutput* out_newData=&_out_newData;
3199
+ hpatch_byte headerCache[hpatch_kWindowDiffHeadMaxSize];
3200
+ hpatch_size_t headerSize=sizeof(headerCache);
3201
+
3202
+ assert(listener!=0);
3203
+ assert(listener->onDiffInfo!=0);
3204
+ assert(out_newData->write!=0);
3205
+ assert(oldData!=0);
3206
+ assert(oldData->read!=0);
3207
+ assert(windowDiff!=0);
3208
+ assert(windowDiff->read!=0);
3209
+
3210
+ if (!_getWindowDiffInfo(&diffInfo,windowDiff,diffInfo_pos,headerCache,&headerSize))//parse header
3211
+ return kWindowPatch_load_head_error;
3212
+ if (diffInfo.newDataSize>out_newData->streamSize)//check output limit
3213
+ return kWindowPatch_new_size_error;
3214
+ out_newData->streamSize=diffInfo.newDataSize;//adjust output stream size
3215
+
3216
+ isChecksumNew=(diffInfo.checksumByteSize>0);
3217
+ if (!listener->onDiffInfo(listener,&diffInfo,&decompressPlugin,&checksumPlugin,
3218
+ &isChecksumNew,&isChecksumOld,&isChecksumDiff,&temp_cache,&temp_cacheEnd))
3219
+ return kWindowPatch_onDiffInfo_error;
3220
+ if ((temp_cache==0)||(temp_cache>=temp_cacheEnd))
3221
+ return kWindowPatch_temp_mem_error;
3222
+ if (diffInfo.maxWindowOldSize+diffInfo.maxStepMemSize+hpatch_kStreamCacheSize*_kWindowCacheCount>(size_t)(temp_cacheEnd-temp_cache))
3223
+ return kWindowPatch_temp_mem_error;
3224
+ temp_cache_back=temp_cache;
3225
+
3226
+ if ((diffInfo.checksumByteSize>0)&&(isChecksumNew||isChecksumOld||isChecksumDiff)){
3227
+ if ((!checksumPlugin)||(diffInfo.checksumByteSize!=checksumPlugin->checksumByteSize()))
3228
+ return kWindowPatch_checksum_plugin_error;
3229
+ checksumByteSize=(size_t)diffInfo.checksumByteSize;
3230
+ }else{
3231
+ checksumByteSize=0; checksumPlugin=0;
3232
+ isChecksumNew=hpatch_FALSE; isChecksumOld=hpatch_FALSE; isChecksumDiff=hpatch_FALSE;
3233
+ }
3234
+
3235
+ if (isChecksumOld){
3236
+ checksumHandle_old=checksumPlugin->open(checksumPlugin);
3237
+ if (!checksumHandle_old) { result=kWindowPatch_checksum_open_error; goto clear; }
3238
+ checksumPlugin->begin(checksumHandle_old);
3239
+ }
3240
+ if (isChecksumNew){
3241
+ checksumHandle_new=checksumPlugin->open(checksumPlugin);
3242
+ if (!checksumHandle_new) { result=kWindowPatch_checksum_open_error; goto clear; }
3243
+ checksumPlugin->begin(checksumHandle_new);
3244
+ }
3245
+ if (isChecksumDiff){
3246
+ checksumHandle_diff=checksumPlugin->open(checksumPlugin);
3247
+ if (!checksumHandle_diff) { result=kWindowPatch_checksum_open_error; goto clear; }
3248
+ checksumPlugin->begin(checksumHandle_diff);
3249
+ }
3250
+
3251
+ if (isChecksumDiff){//wrap diff stream input for checksum
3252
+ _TChecksumInputStream_init(&checksumDiffInput,windowDiff,checksumPlugin,checksumHandle_diff);
3253
+ effectiveDiffStream=&checksumDiffInput.base;
3254
+ }else{
3255
+ effectiveDiffStream=windowDiff;
3256
+ }
3257
+
3258
+ if (isChecksumNew){//wrap new stream output for checksum
3259
+ _TChecksumOutputStream_init(&checksumNewOutput,out_newData,checksumPlugin,checksumHandle_new);
3260
+ effectiveOutNew=&checksumNewOutput.base;
3261
+ }else{
3262
+ effectiveOutNew=out_newData;
3263
+ }
3264
+
3265
+ patch_result=_patch_window_diff(effectiveOutNew,oldData,effectiveDiffStream,diffInfo_pos+diffInfo.windowDataPos,
3266
+ &diffInfo,decompressPlugin,checksumHandle_old?checksumPlugin:0,checksumHandle_old,
3267
+ temp_cache,temp_cacheEnd, threadNum,hpatchMTSets_full);
3268
+
3269
+ {//verify checksums
3270
+ hpatch_byte* storedChecksumOld=headerCache+diffInfo.windowDataPos-3*checksumByteSize;
3271
+ hpatch_byte* storedChecksumNew=storedChecksumOld+checksumByteSize;
3272
+ hpatch_byte* storedChecksumDiff=storedChecksumNew+checksumByteSize;
3273
+ hpatch_byte* computedChecksum=temp_cache; temp_cache+=checksumByteSize; assert(temp_cache<temp_cacheEnd);
3274
+ hpatch_BOOL isChecksumNew_and_eq=hpatch_FALSE;
3275
+ if (isChecksumNew){//verify new data checksum
3276
+ checksumPlugin->end(checksumHandle_new,computedChecksum,computedChecksum+checksumByteSize);
3277
+ isChecksumNew_and_eq=(0==memcmp(computedChecksum,storedChecksumNew,checksumByteSize));
3278
+ if (isChecksumNew_and_eq){
3279
+ //assert(patch_result); //why fail?
3280
+ patch_result=hpatch_TRUE;//note: if patch failed, but new data checksum is correct, we can consider it as success.
3281
+ }
3282
+ }
3283
+ if (!isChecksumNew_and_eq){
3284
+ if (isChecksumDiff){//verify diff checksum
3285
+ //read to diffData end for checksum
3286
+ if (!_readForSkipStream(&checksumDiffInput.base,checksumDiffInput.readedEndPos,
3287
+ checksumDiffInput.base.streamSize,temp_cache,temp_cacheEnd))
3288
+ { result=kWindowPatch_patch_error; goto clear; }
3289
+ checksumPlugin->append(checksumHandle_diff,headerCache,headerCache+headerSize-checksumByteSize);//checksum head
3290
+ checksumPlugin->end(checksumHandle_diff,computedChecksum,computedChecksum+checksumByteSize);
3291
+ if (0!=memcmp(computedChecksum,storedChecksumDiff,checksumByteSize))
3292
+ { result=kWindowPatch_checksum_diff_error; goto clear; }
3293
+ }
3294
+ if ((!patch_result)&&(diffInfo.oldDataSize!=oldData->streamSize))
3295
+ { result=kWindowPatch_old_size_error; goto clear; }
3296
+ if ((patch_result||(isChecksumNew&&(checksumNewOutput.writedEndPos==diffInfo.newDataSize)))//all old's data checked
3297
+ &&isChecksumOld){//verify old data checksum
3298
+ checksumPlugin->end(checksumHandle_old,computedChecksum,computedChecksum+checksumByteSize);
3299
+ if (0!=memcmp(computedChecksum,storedChecksumOld,checksumByteSize))
3300
+ { result=kWindowPatch_checksum_old_error; goto clear; }
3301
+ }
3302
+ if (isChecksumNew) { result=kWindowPatch_checksum_new_error; goto clear; }
3303
+ }
3304
+ }
3305
+ if (!patch_result) { result=kWindowPatch_patch_error; goto clear; }
3306
+
3307
+ clear:
3308
+ if (checksumHandle_old!=0) checksumPlugin->close(checksumPlugin,checksumHandle_old);
3309
+ if (checksumHandle_new!=0) checksumPlugin->close(checksumPlugin,checksumHandle_new);
3310
+ if (checksumHandle_diff!=0) checksumPlugin->close(checksumPlugin,checksumHandle_diff);
3311
+ if (listener->onPatchFinish)
3312
+ listener->onPatchFinish(listener,temp_cache_back,temp_cacheEnd);
3313
+ return result;
3314
+ }
3315
+