· 6 years ago · May 20, 2019, 09:12 AM
1Index: Contrib/Modern UI 2/Interface.nsh
2===================================================================
3--- Contrib/Modern UI 2/Interface.nsh (revision 7070)
4+++ Contrib/Modern UI 2/Interface.nsh (working copy)
5@@ -213,13 +213,13 @@
6 !ifdef MUI_HEADERIMAGE_${UN}BITMAP_RTL
7 ${if} $(^RTL) == 1
8
9- File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}"
10+ StubFile "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}"
11 !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "_RTL" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp"
12
13 ${else}
14 !endif
15
16- File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP}"
17+ StubFile "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP}"
18 !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp"
19
20 !ifdef MUI_HEADERIMAGE_${UN}BITMAP_RTL
21Index: Contrib/Modern UI 2/Pages/Welcome.nsh
22===================================================================
23--- Contrib/Modern UI 2/Pages/Welcome.nsh (revision 7070)
24+++ Contrib/Modern UI 2/Pages/Welcome.nsh (working copy)
25@@ -42,7 +42,7 @@
26 Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomePage.GUIInit
27
28 InitPluginsDir
29- File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
30+ StubFile "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
31
32 !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT
33 Call "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT}"
34Index: Docs/src/attributes.but
35===================================================================
36--- Docs/src/attributes.but (revision 7070)
37+++ Docs/src/attributes.but (working copy)
38@@ -327,6 +327,20 @@
39
40 Specifies the output file that the MakeNSIS should write the installer to. This is just the file that MakeNSIS writes, it doesn't affect the contents of the installer.
41
42+\S2{aoutfilemode} OutFileMode
43+
44+\c \\<b\\>auto\\</b\\>|aio|data|stub
45+
46+Specifies the output file mode that makensis writes.
47+
48+'aio' is the same as classic nsis, which creates single file installers up to the exe limit of 4GB.
49+
50+'data' writes the install data to a separate file, which allows installers over 4GB to be created (both the .exe and the .nsisbin must exist together for the installer to run).
51+
52+'stub' is a specialized version of the 'data' mode, designed for web downloads. The .exe can be run on its own and plugins can be used to download the main .nsisbin file. If the .nsisbin file is not found use \R{verifyexternalfile}{VerifyExternalFile} to check and use the .nsisbin file. Plugins called directly (ie plugin::function) are automatically added to the exehead and not the main install block.
53+
54+'auto' is the default, and it chooses between 'aio' and 'data' modes based on the amount of data added (the 'aio' limit is 4GB).
55+
56 \S2{arequestexecutionlevel} RequestExecutionLevel
57
58 \c none|user|highest|\\<b\\>admin\\</b\\>
59Index: Docs/src/basic.but
60===================================================================
61--- Docs/src/basic.but (revision 7070)
62+++ Docs/src/basic.but (working copy)
63@@ -109,6 +109,10 @@
64
65 When adding \e{\\*.*}, it will be used as the matching condition and \e{something} will be used as the directory to search. When only \e{something} is specified, the current directory will be recursively searched for every file and directory named \e{something} and \e{another\\something} will be matched.
66
67+\S2{stubfile} StubFile
68+
69+When \R{aoutfilemode}{OutFileMode} is set to 'stub', files are added to the exehead stub instead of the main install block. Otherwise is identical to \R{file}{File}. Useful for files required for the installer ie bitmaps.
70+
71 \S2{rename} Rename
72
73 \c [/REBOOTOK] source_file dest_file
74@@ -133,6 +137,12 @@
75
76 See \R{file}{File} for more information about the parameters.
77
78+\S2{reservestubfile} ReserveStubFile
79+
80+Reserves a file in the data block for later use. When \R{aoutfilemode}{OutFileMode} is set to 'stub', files are added to the exehead stub instead of the main install block. Otherwise is identical to \R{reservefile}{ReserveFile}.
81+
82+See \R{file}{File} for more information about the parameters.
83+
84 \S2{rmdir} RMDir
85
86 \c [/r] [/REBOOTOK] directory_name
87@@ -171,3 +181,9 @@
88
89 \c SetOutPath $INSTDIR
90 \c File program.exe
91+
92+\S2{verifyexternalfile} VerifyExternalFile
93+
94+\c [path_to_data_file]
95+
96+When \R{aoutfilemode}{OutFileMode} is set to 'stub', this checks and uses the .nsisbin file, if it can't be found when the installer first runs. If no path is specified, the default path is used (the installer path and name with .nsisbin instead of .exe). Sets the error flag if the check fails.
97Index: SCons/config.py
98===================================================================
99--- SCons/config.py (revision 7070)
100+++ SCons/config.py (working copy)
101@@ -94,6 +94,14 @@
102
103 cfg.Add(
104 BoolVariable(
105+ 'NSIS_CONFIG_EXTERNAL_FILE_SUPPORT',
106+ 'enables support for making installers that can use an external file for storing install data. Useful for installers that exceed the 4GB limit of standard "all-in-one" installers.',
107+ 'yes'
108+ )
109+)
110+
111+cfg.Add(
112+ BoolVariable(
113 'NSIS_CONFIG_COMPRESSION_SUPPORT',
114 'enables support for making installers that use compression (recommended).',
115 'yes'
116@@ -461,6 +469,7 @@
117 AddBoolDefine('NSIS_CONFIG_SILENT_SUPPORT')
118 AddBoolDefine('NSIS_CONFIG_VISIBLE_SUPPORT')
119 AddBoolDefine('NSIS_CONFIG_ENHANCEDUI_SUPPORT')
120+AddBoolDefine('NSIS_CONFIG_EXTERNAL_FILE_SUPPORT')
121 AddBoolDefine('NSIS_CONFIG_COMPRESSION_SUPPORT')
122 AddBoolDefine('NSIS_COMPRESS_BZIP2_SMALLMODE')
123
124Index: SConstruct
125===================================================================
126--- SConstruct (revision 7070)
127+++ SConstruct (working copy)
128@@ -2,6 +2,7 @@
129
130 stubs = [
131 'bzip2',
132+ 'lz4',
133 'lzma',
134 'zlib'
135 ]
136Index: Source/Plugins.cpp
137===================================================================
138--- Source/Plugins.cpp (revision 7070)
139+++ Source/Plugins.cpp (working copy)
140@@ -25,6 +25,7 @@
141 #include "Platform.h"
142 #include "util.h"
143 #include "ResourceEditor.h"
144+#include "growbuf64.h"
145
146 #include "dirreader.h"
147
148@@ -195,27 +196,38 @@
149 }
150 }
151
152-int Plugins::GetDllDataHandle(bool uninst, const tstring& command) const
153+IGrowBuf64::size_type Plugins::GetDllDataHandle(bool uninst, const tstring& command) const
154 {
155 const tstring dllname = GetDllName(command);
156 if (uninst)
157- return get_paired_value(m_dllname_to_unst_datahandle, dllname, -1);
158+ return get_paired_value(m_dllname_to_unst_datahandle, dllname, (IGrowBuf64::size_type)-1);
159 else
160- return get_paired_value(m_dllname_to_inst_datahandle, dllname, -1);
161+ return get_paired_value(m_dllname_to_inst_datahandle, dllname, (IGrowBuf64::size_type)-1);
162 }
163
164-void Plugins::SetDllDataHandle(bool uninst, tstring&canoniccmd, int dataHandle)
165+crc32_t Plugins::GetDllCRCValue(bool uninst, const tstring& command) const
166 {
167+ const tstring dllname = GetDllName(command);
168+ if (uninst)
169+ return get_paired_value(m_dllname_to_unst_crc, dllname, -1);
170+ else
171+ return get_paired_value(m_dllname_to_inst_crc, dllname, -1);
172+}
173+
174+void Plugins::SetDllDataHandle(bool uninst, tstring&canoniccmd, IGrowBuf64::size_type dataHandle, crc32_t crc)
175+{
176 const tstring dllname = GetDllName(canoniccmd);
177 if (uninst)
178- m_dllname_to_unst_datahandle[dllname] = dataHandle;
179+ m_dllname_to_unst_datahandle[dllname] = dataHandle,
180+ m_dllname_to_unst_crc[dllname] = crc;
181 else
182- m_dllname_to_inst_datahandle[dllname] = dataHandle;
183+ m_dllname_to_inst_datahandle[dllname] = dataHandle,
184+ m_dllname_to_inst_crc[dllname] = crc;
185 }
186
187 bool Plugins::DllHasDataHandle(const tstring& dllnamelowercase) const
188 {
189- int h = GetDllDataHandle(false, dllnamelowercase);
190+ IGrowBuf64::size_type h = GetDllDataHandle(false, dllnamelowercase);
191 if (-1 == h) h = GetDllDataHandle(true, dllnamelowercase);
192 return -1 != h;
193 }
194Index: Source/Plugins.h
195===================================================================
196--- Source/Plugins.h (revision 7070)
197+++ Source/Plugins.h (working copy)
198@@ -21,6 +21,8 @@
199 #include <map>
200 #include <set>
201 #include "tstring.h"
202+#include "growbuf64.h"
203+#include "crc32.h"
204
205 namespace STL
206 {
207@@ -54,8 +56,9 @@
208 bool IsPluginCommand(const tstring& command) const;
209 bool IsKnownPlugin(const tstring& token) const;
210 bool GetCommandInfo(const tstring&command, tstring&canoniccmd, tstring&dllPath);
211- int GetDllDataHandle(bool uninst, const tstring& command) const;
212- void SetDllDataHandle(bool uninst, tstring&canoniccmd, int dataHandle);
213+ IGrowBuf64::size_type GetDllDataHandle(bool uninst, const tstring& command) const;
214+ crc32_t GetDllCRCValue(bool uninst, const tstring& command) const;
215+ void SetDllDataHandle(bool uninst, tstring&canoniccmd, IGrowBuf64::size_type dataHandle, crc32_t crc);
216 static bool IsPluginCallSyntax(const tstring& token);
217 void PrintPluginDirs();
218
219@@ -66,8 +69,10 @@
220 private: // data members
221 std::set<tstring, strnocasecmp> m_commands;
222 std::map<tstring, tstring, strnocasecmp> m_dllname_to_path;
223- std::map<tstring, int, strnocasecmp> m_dllname_to_inst_datahandle;
224- std::map<tstring, int, strnocasecmp> m_dllname_to_unst_datahandle;
225+ std::map<tstring, IGrowBuf64::size_type, strnocasecmp> m_dllname_to_inst_datahandle;
226+ std::map<tstring, IGrowBuf64::size_type, strnocasecmp> m_dllname_to_unst_datahandle;
227+ std::map<tstring, crc32_t, strnocasecmp> m_dllname_to_inst_crc;
228+ std::map<tstring, crc32_t, strnocasecmp> m_dllname_to_unst_crc;
229 std::set<tstring, strnocasecmp> m_dllname_conflicts;
230 bool m_initialized;
231 };
232Index: Source/SConscript
233===================================================================
234--- Source/SConscript (revision 7070)
235+++ Source/SConscript (working copy)
236@@ -10,6 +10,7 @@
237 dirreader.cpp
238 fileform.cpp
239 growbuf.cpp
240+ growbuf64.cpp
241 icon.cpp
242 lang.cpp
243 lineparse.cpp
244@@ -30,6 +31,7 @@
245 util.cpp
246 winchar.cpp
247 writer.cpp
248+ xxhash.c
249 """)
250
251 bzip2_files = Split("""
252@@ -39,6 +41,12 @@
253 bzip2/huffman.c
254 """)
255
256+lz4_files = Split("""
257+ lz4/lz4common.c
258+ lz4/lz4compress.c
259+ lz4/lz4hccompress.c
260+""")
261+
262 lzma_files = Split("""
263 7zip/7zGuids.cpp
264 7zip/7zip/Common/OutBuffer.cpp
265@@ -90,7 +98,7 @@
266
267 ##### Compile makensis
268
269-files = makensis_files + bzip2_files + lzma_files
270+files = makensis_files + bzip2_files + lzma_files + lz4_files
271
272 makensis = env.Program(target, files)
273
274Index: Source/build.cpp
275===================================================================
276--- Source/build.cpp (revision 7070)
277+++ Source/build.cpp (working copy)
278@@ -28,6 +28,7 @@
279 #include "fileform.h"
280 #include "writer.h"
281 #include "crc32.h"
282+#include "xxhash.h"
283 #include "manifest.h"
284 #include "icon.h"
285 #include "utf.h" // For NStream
286@@ -128,10 +129,7 @@
287 definedlist.add(_T("NSIS_VERSION"), NSIS_VERSION);
288 definedlist.add(_T("NSIS_PACKEDVERSION"), NSIS_PACKEDVERSION);
289
290- m_target_type=TARGET_X86ANSI;
291-#ifdef _WIN32
292- if (sizeof(void*) > 4) m_target_type = TARGET_AMD64; // BUGBUG: scons 'TARGET_ARCH' should specify the default
293-#endif
294+ m_target_type=TARGET_X86UNICODE;
295 #ifdef _M_ARM64
296 m_target_type = TARGET_ARM64; // BUGBUG: scons 'TARGET_ARCH' should specify the default
297 #endif
298@@ -155,6 +153,9 @@
299 if (sizeof(void*) > 4) definedlist.add(_T("NSIS_MAKENSIS64"));
300
301 db_opt_save=db_opt_save_u=db_full_size=db_full_size_u=0;
302+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
303+ db_full_size_s=0;
304+#endif
305 db_comp_save=db_comp_save_u=0;
306
307 // Added by Amir Szekely 31st July 2002
308@@ -225,6 +226,9 @@
309 #endif
310 memset(&build_header.blocks,0,sizeof(build_header.blocks));
311
312+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
313+ datablock_mode=0;
314+#endif
315 uninstall_mode=0;
316 uninstall_size_full=0;
317 uninstall_size=-1;
318@@ -251,6 +255,10 @@
319
320 uninstaller_writes_used=0;
321
322+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
323+ build_external_file = OFM_AUTO;
324+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
325+
326 build_strlist.addemptystring();
327 ubuild_strlist.addemptystring();
328
329@@ -419,7 +427,7 @@
330 }
331
332
333-int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); }
334+IGrowBuf64::size_type CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); }
335
336
337 void CEXEBuild::init_shellconstantvalues()
338@@ -730,9 +738,9 @@
339 // the datablock as necessary). Reduces overhead if you want to add files to a couple places.
340 // Woo, an optimizing installer generator, now we're styling.
341
342-int CEXEBuild::datablock_optimize(int start_offset, int first_int)
343+IGrowBuf64::size_type CEXEBuild::datablock_optimize(IGrowBuf64::size_type start_offset, int first_int)
344 {
345- int this_len = cur_datablock->getlen() - start_offset;
346+ int this_len = truncate_cast(int, (size_t)(cur_datablock->getlen() - start_offset));
347
348 cached_db_size this_size = {first_int, start_offset};
349 this->cur_datablock_cache->add(&this_size, sizeof(cached_db_size));
350@@ -747,14 +755,14 @@
351 db->setro(TRUE);
352
353 cached_db_size *db_sizes = (cached_db_size *) this->cur_datablock_cache->get();
354- int db_sizes_num = this->cur_datablock_cache->getlen() / sizeof(cached_db_size);
355+ IGrowBuf64::size_type db_sizes_num = this->cur_datablock_cache->getlen() / sizeof(cached_db_size);
356 db_sizes_num--; // don't compare with the one we just added
357
358- for (int i = 0; i < db_sizes_num; i++)
359+ for (IGrowBuf64::size_type i = 0; i < db_sizes_num; i++)
360 {
361 if (db_sizes[i].first_int == first_int)
362 {
363- int pos = db_sizes[i].start_offset;
364+ IGrowBuf64::size_type pos = db_sizes[i].start_offset;
365 int left = this_len;
366 while (left > 0)
367 {
368@@ -787,7 +795,7 @@
369 return start_offset;
370 }
371
372-bool CEXEBuild::datablock_finddata(IMMap&mmap, int mmstart, int size, int*ofs)
373+bool CEXEBuild::datablock_finddata(IMMap&mmap, IGrowBuf64::size_type mmstart, int size, IGrowBuf64::size_type*ofs)
374 {
375 const int first_int = size;
376 size &= ~ 0x80000000;
377@@ -796,11 +804,12 @@
378 #endif
379 MMapBuf *db = static_cast<MMapBuf*>(cur_datablock);
380 cached_db_size *db_sizes = (cached_db_size *) this->cur_datablock_cache->get();
381- int db_sizes_num = this->cur_datablock_cache->getlen() / sizeof(cached_db_size);
382- for (int i = 0; i < db_sizes_num; i++)
383+ IGrowBuf64::size_type db_sizes_num = this->cur_datablock_cache->getlen() / sizeof(cached_db_size);
384+ for (IGrowBuf64::size_type i = 0; i < db_sizes_num; i++)
385 {
386 if (db_sizes[i].first_int != first_int) continue;
387- int left = size, oldpos = db_sizes[i].start_offset;
388+ int left = size;
389+ IGrowBuf64::size_type oldpos = db_sizes[i].start_offset;
390 while (left > 0)
391 {
392 int cbCmp = min(left, build_filebuflen);
393@@ -820,8 +829,27 @@
394 return false;
395 }
396
397-int CEXEBuild::add_db_data(IMMap *mmap) // returns offset
398+#ifdef NSIS_CONFIG_CRC_SUPPORT
399+bool CEXEBuild::datablock_crcdata(IMMap *in, IGrowBuf64::size_type start, int len, crc32_t *ex_crc)
400 {
401+ int left = len;
402+ crc32_t crc = 0;
403+
404+ if (!in || len < 0 || !ex_crc) return false;
405+ while (left > 0)
406+ {
407+ int l = min(build_filebuflen, left);
408+ crc = CRC32(crc, (unsigned char *)in->get(start + len - left, l), l);
409+ in->release();
410+ left -= l;
411+ }
412+ *ex_crc = crc;
413+ return true;
414+}
415+#endif //NSIS_CONFIG_CRC_SUPPORT
416+
417+IGrowBuf64::size_type CEXEBuild::add_db_data(IMMap *mmap, crc32_t *ex_crc) // returns offset
418+{
419 build_compressor_set = true;
420
421 int done = 0;
422@@ -832,7 +860,7 @@
423 return -1;
424 }
425
426- int length = mmap->getsize();
427+ int length = mmap->getsize() > (int)(INT_MAX - sizeof(int)) ? -1 : (int)mmap->getsize();
428
429 if (length < 0)
430 {
431@@ -844,7 +872,7 @@
432 // most likely to point to a MMapBuf type right now so it works.
433 MMapBuf *db = (MMapBuf *) this->cur_datablock;
434
435- int st = db->getlen();
436+ IGrowBuf64::size_type st = db->getlen();
437
438 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
439 if (length && !build_compress_whole && build_compress)
440@@ -851,9 +879,9 @@
441 {
442 // grow datablock so that there is room to compress into
443 int bufferlen = length + 1024 + length / 4; // give a nice 25% extra space
444- if (st+bufferlen+(signed)sizeof(int) < 0) // we've hit a signed integer overflow (file is over 1.6 GB)
445- bufferlen = INT_MAX-st-sizeof(int); // so maximize compressor room and hope the file compresses well
446- db->resize(st + bufferlen + sizeof(int));
447+ if (bufferlen+(signed)sizeof(int) < 0) // we've hit a signed integer overflow (file is over 1.6 GB)
448+ bufferlen = INT_MAX-sizeof(int); // so maximize compressor room and hope the file compresses well
449+ db->resize(st + bufferlen + sizeof(int));
450
451 int n = compressor->Init(build_compress_level, build_compress_dict_size);
452 if (n != C_OK)
453@@ -928,8 +956,14 @@
454
455 *(int*)db->get(st, sizeof(int)) = FIX_ENDIAN_INT32(used | 0x80000000);
456 db->release();
457+#ifdef NSIS_CONFIG_CRC_SUPPORT
458+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
459+ if (build_external_file != OFM_STUB || build_external_file != OFM_AIO)
460+ datablock_crcdata(db, st + sizeof(int), used, ex_crc);
461+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
462+#endif //NSIS_CONFIG_CRC_SUPPORT
463
464- int nst = datablock_optimize(st, used | 0x80000000);
465+ IGrowBuf64::size_type nst = datablock_optimize(st, used | 0x80000000);
466 if (nst == st) db_comp_save += length - used;
467 else st = nst;
468 }
469@@ -945,7 +979,7 @@
470 // because datablock_optimize() happens too late. Let's try to find a dupe early.
471 if (this->build_optimize_datablock && st + length < 0)
472 {
473- int oldst;
474+ IGrowBuf64::size_type oldst;
475 if (datablock_finddata(*mmap, 0, length, &oldst))
476 return (db_full_size += length, db_opt_save += length, oldst);
477 }
478@@ -966,6 +1000,12 @@
479 mmap->release();
480 left -= l;
481 }
482+#ifdef NSIS_CONFIG_CRC_SUPPORT
483+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
484+ if (build_external_file != OFM_STUB || build_external_file != OFM_AIO)
485+ datablock_crcdata(db, st + sizeof(int), length, ex_crc);
486+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
487+#endif //NSIS_CONFIG_CRC_SUPPORT
488
489 st = datablock_optimize(st, length);
490 }
491@@ -974,11 +1014,11 @@
492 return st;
493 }
494
495-int CEXEBuild::add_db_data(const char *data, int length) // returns offset
496+IGrowBuf64::size_type CEXEBuild::add_db_data(const char *data, int length, crc32_t *ex_crc) // returns offset
497 {
498 MMapFake fakemap;
499 fakemap.set(data, length);
500- return add_db_data(&fakemap);
501+ return add_db_data(&fakemap, ex_crc);
502 }
503
504 int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // returns offset
505@@ -1369,7 +1409,7 @@
506 return PS_OK;
507 }
508
509-int CEXEBuild::add_entry_direct(int which, int o0, int o1, int o2, int o3, int o4, int o5 /*o#=0*/)
510+int CEXEBuild::add_entry_direct(int which, int o0, int o1, int o2, int o3, int o4, int o5, int o6, int o7 /*o#=0*/)
511 {
512 entry ent;
513 ent.which = which;
514@@ -1379,6 +1419,8 @@
515 ent.offsets[3] = o3;
516 ent.offsets[4] = o4;
517 ent.offsets[5] = o5;
518+ ent.offsets[6] = o6;
519+ ent.offsets[7] = o7;
520 return add_entry(&ent);
521 }
522
523@@ -2631,7 +2673,7 @@
524
525 build_optimize_datablock=0;
526
527- int data_block_size_before_uninst = build_datablock.getlen();
528+ IGrowBuf64::size_type data_block_size_before_uninst = build_datablock.getlen();
529
530 RET_UNLESS_OK( uninstall_generate() );
531
532@@ -2652,17 +2694,19 @@
533 }
534 }
535
536- FILE *fp = FOPEN(build_output_filename,("w+b"));
537- if (!fp)
538+ FileWriter fp;
539+ if (!fp.Fopen(build_output_filename))
540 {
541 ERROR_MSG(_T("Can't open output file\n"));
542 return PS_ERROR;
543 }
544-
545- if (fwrite(m_exehead,1,m_exehead_size,fp) != m_exehead_size)
546+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
547+ FileWriter fp_ex;
548+ XXH32_hash_t hash_ex = 0;
549+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
550+ if (fp.Fwrite(m_exehead,1,m_exehead_size) != m_exehead_size)
551 {
552 ERROR_MSG(_T("Error: can't write %d bytes to output\n"),m_exehead_size);
553- fclose(fp);
554 return PS_ERROR;
555 }
556
557@@ -2687,6 +2731,10 @@
558 #ifdef NSIS_CONFIG_SILENT_SUPPORT
559 if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT;
560 #endif
561+ fh.flags |= FH_FLAGS_LONG_DB_OFFSET;
562+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
563+ fh.flags |= FH_FLAGS_EXTERNAL_FILE_SUPPORT;
564+#endif
565 fh.siginfo=FH_SIG;
566
567 int installinfo_compressed;
568@@ -2719,13 +2767,94 @@
569 }
570
571 if (!build_compress_whole)
572- fh.length_of_all_following_data=ihd.getlen()+build_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
573+ {
574+ // this first line is just to check if the installer data can fit
575+ // into an 'all in one' installer, doesn't need to be completely
576+ // accurate because it will be modified later
577+ IGrowBuf64::size_type length_of_all_following_data = ihd.getlen()+build_datablock.getlen()+sizeof(firstheader)+(build_crcchk?sizeof(crc32_t)+sizeof(XXH32_hash_t):0);
578+ int is_exe_sized = m_exehead_size + length_of_all_following_data < 0xffffffff;
579+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
580+ if (build_datablock.getlen() > IGrowBuf64::getlimit())
581+ {
582+ ERROR_MSG(_T("Error: can't continue, datablock bigger than current NSIS limit (8EB).\n"));
583+ return PS_ERROR;
584+ }
585+ build_stub_installer_size = 0;
586+ if (build_external_file <= OFM_AUTO)
587+ // this resets to either AIO or DATA, based on the size of the datablock
588+ build_external_file = is_exe_sized ? OFM_AIO : OFM_DATA;
589+ else
590+ {
591+ if (build_external_file == OFM_STUB && build_datablock_stub.getlen())
592+ {
593+ if (0xffffffff >= (m_exehead_size+ihd.getlen()+build_datablock_stub.getlen()+sizeof(firstheader)+(build_crcchk?(build_datablock.getlen()?sizeof(crc32_t)+sizeof(XXH32_hash_t):sizeof(crc32_t)):0)))
594+ {
595+ DB_OFFSET off;
596+ off.quad_part = build_datablock_stub.getlen();
597+ build_stub_installer_size = off.low_part;
598+ fh.flags |= FH_FLAGS_IS_STUB_INSTALLER;
599+ length_of_all_following_data = ihd.getlen()+build_datablock_stub.getlen()+sizeof(firstheader)+(build_crcchk?(build_datablock.getlen()?sizeof(crc32_t)+sizeof(XXH32_hash_t):sizeof(crc32_t)):0);
600+ }
601+ else
602+ {
603+ ERROR_MSG(_T("Error: can't continue, exehead datablock bigger than current NSIS limit (4GB).\n"));
604+ return PS_ERROR;
605+ }
606+ }
607+ else
608+ {
609+ // don't write a stub or external file if there is no data
610+ build_external_file = build_datablock.getlen() && build_external_file ? OFM_DATA : OFM_AIO;
611+ }
612+ }
613+ if (build_external_file == OFM_DATA || build_external_file == OFM_STUB)
614+ {
615+ if (build_datablock.getlen())
616+ {
617+ tstring full_path_ex = remove_file_extension(get_full_path(build_output_filename));
618+ full_path_ex += _T(".nsisbin");
619+ my_strncpy(build_output_external_filename, full_path_ex.c_str(), 1024);
620+ INFO_MSG(_T("Output: \"%") NPRIs _T("\"\n"), build_output_external_filename);
621+ if (!fp_ex.Fopen(build_output_external_filename))
622+ {
623+ ERROR_MSG(_T("Can't open output file (data)\n"));
624+ return PS_ERROR;
625+ }
626+ }
627+ DB_OFFSET db_size_off;
628+ fh.length_of_all_following_data=ihd.getlen()+sizeof(firstheader)+build_stub_installer_size+(build_crcchk?(build_stub_installer_size?sizeof(crc32_t)+sizeof(XXH32_hash_t):sizeof(crc32_t)):0);
629+ db_size_off.quad_part = build_datablock.getlen();
630+ fh.datablock_lowpart = db_size_off.low_part;
631+ fh.datablock_highpart = db_size_off.high_part;
632+ if (build_datablock.getlen()) fh.flags |= FH_FLAGS_HAS_EXTERNAL_FILE;
633+ }
634+ else
635+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
636+ {
637+ if (!is_exe_sized)
638+ {
639+ ERROR_MSG(_T("Error: can't continue, exehead datablock bigger than current NSIS limit (4GB).\n"));
640+ return PS_ERROR;
641+ }
642+ length_of_all_following_data = ihd.getlen()+build_datablock.getlen()+sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
643+ DB_OFFSET following_data_off;
644+ following_data_off.quad_part = length_of_all_following_data;
645+ fh.length_of_all_following_data=following_data_off.low_part;
646+ }
647+ }
648 else
649- fd_start=ftell(fp);
650+ {
651+ if (m_exehead_size+ihd.getlen()+build_datablock.getlen()+sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0) > 0x7fffffff)
652+ {
653+ ERROR_MSG(_T("Error: can't continue, exehead datablock bigger than current NSIS compress whole limit (2GB).\n"));
654+ return PS_ERROR;
655+ }
656+ fd_start=fp.Ftell();
657+ }
658
659 try
660 {
661- file_writer_sink sink(fp, mk_writer_target_info());
662+ file_writer_sink sink(fp.GetHandle(), mk_writer_target_info());
663 firstheader_writer w(&sink);
664 w.write(&fh);
665 }
666@@ -2732,25 +2861,21 @@
667 catch (...)
668 {
669 ERROR_MSG(_T("Error: can't write %d bytes to output\n"),sizeof(fh));
670- fclose(fp);
671 return PS_ERROR;
672 }
673
674 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
675- if (build_compress_whole) {
676- if (deflateToFile(fp,(char*)ihd.get(),ihd.getlen()))
677- {
678- fclose(fp);
679+ if (build_compress_whole)
680+ {
681+ if (deflateToFile(fp.GetHandle(),(char*)ihd.get(),ihd.getlen()))
682 return PS_ERROR;
683- }
684 }
685 else
686 #endif
687 {
688- if (fwrite(ihd.get(),1,ihd.getlen(),fp) != (unsigned int)ihd.getlen())
689+ if (fp.Fwrite(ihd.get(),1,ihd.getlen()) != (unsigned int)ihd.getlen())
690 {
691 ERROR_MSG(_T("Error: can't write %d bytes to output\n"),ihd.getlen());
692- fclose(fp);
693 return PS_ERROR;
694 }
695 #ifdef NSIS_CONFIG_CRC_SUPPORT
696@@ -2826,7 +2951,7 @@
697
698 if (db_opt_save)
699 {
700- size_t total_out_size_estimate=
701+ IGrowBuf64::size_type total_out_size_estimate=
702 m_exehead_size+sizeof(fh)+build_datablock.getlen()+(build_crcchk?sizeof(crc32_t):0);
703 int pc=(int)((db_opt_save*1000)/(db_opt_save+total_out_size_estimate));
704 FriendlySize fs(db_opt_save);
705@@ -2839,6 +2964,9 @@
706 #endif
707
708 unsigned int total_usize=(unsigned int) m_exehead_original_size;
709+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
710+ IGrowBuf64::size_type total_usize_ex = 0;
711+#endif
712
713 INFO_MSG(_T("EXE header size: %10u / %u bytes\n"),m_exehead_size,m_exehead_original_size);
714
715@@ -2855,25 +2983,86 @@
716 total_usize+=sizeof(fh)+fh.length_of_header;
717
718 {
719- unsigned int dbsize;
720+ IGrowBuf64::size_type dbsize = build_datablock.getlen();
721 UINT64 dbsizeu;
722- dbsize = build_datablock.getlen();
723- if (uninstall_size>0) dbsize -= uninstall_size;
724-
725+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
726+ IGrowBuf64::size_type dbsize_s = build_datablock_stub.getlen();
727+ UINT64 dbsize_su = 0;
728+ if (!build_compress_whole) dbsize += dbsize_s;
729+
730+ if (uninstall_size>0)
731+ {
732+ if (build_external_file == OFM_STUB)
733+ dbsize_s -= uninstall_size;
734+ else
735+ dbsize -= uninstall_size;
736+ }
737+#else
738+ if (uninstall_size>0) { dbsize -= uninstall_size; }
739+#endif
740 if (build_compress_whole) {
741 dbsizeu = dbsize;
742- INFO_MSG(_T("Install data: (%u bytes)\n"),dbsize); // dbsize==dbsizeu and is easy to print
743+ INFO_MSG(_T("Install data: (%u bytes)\n"),(DWORD)dbsizeu); // dbsize==dbsizeu and is easy to print
744 }
745- else {
746+ else
747+ {
748+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
749+ if (build_external_file == OFM_STUB)
750+ {
751+ dbsizeu = db_full_size;
752+ dbsize_su = db_full_size_s - uninstall_size_full;
753+ }
754+ else
755+ {
756+ dbsizeu = db_full_size - uninstall_size_full;
757+ dbsize_su = db_full_size_s;
758+ }
759+ dbsizeu += dbsize_su;
760+#else
761 dbsizeu = db_full_size - uninstall_size_full;
762+#endif
763 FriendlySize us(dbsizeu, GFSF_BYTESIFPOSSIBLE); // uncompressed installer size
764 FriendlySize cs(dbsize, GFSF_BYTESIFPOSSIBLE | (us.UInt()==dbsizeu ? GFSF_HIDEBYTESCALE : 0)); // compressed installer size
765 INFO_MSG(_T("Install data: %10u%") NPRIs _T(" / %u%") NPRIs _T("\n"),
766 cs.UInt(),cs.Scale(),us.UInt(),us.Scale()); // "123 / 456 bytes" or "123 KiB / 456 MiB"
767 }
768- UINT future = (build_crcchk ? sizeof(int) : 0) + (uninstall_size > 0 ? uninstall_size_full : 0);
769- UINT maxsize = (~(UINT)0) - (total_usize + future), totsizadd = dbsizeu < maxsize ? (UINT)dbsizeu : maxsize;
770- total_usize += totsizadd; // Might not be accurate, it is more important to not overflow the additions coming up
771+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
772+ if (!build_compress_whole)
773+ {
774+ dbsize -= dbsize_s;
775+ dbsizeu -= dbsize_su;
776+ }
777+ if (build_external_file == OFM_DATA)
778+ {
779+ UINT future = (build_crcchk ? sizeof(crc32_t) : 0) + (uninstall_size > 0 ? uninstall_size_full : 0);
780+ IGrowBuf64::size_type maxsize = (~(IGrowBuf64::size_type)0) - (total_usize + future), totsizadd = dbsizeu < (UINT64)maxsize ? dbsize_s : maxsize;
781+ total_usize += (DWORD)totsizadd; // Might not be accurate, it is more important to not overflow the additions coming up
782+
783+ if (build_datablock.getlen())
784+ {
785+ IGrowBuf64::size_type maxsize_ex = (~(IGrowBuf64::size_type)0) - total_usize_ex, totsizadd_ex = dbsizeu < (UINT64)maxsize_ex ? dbsizeu : maxsize_ex;
786+ total_usize_ex += totsizadd_ex; // Might not be accurate, it is more important to not overflow the additions coming up
787+ }
788+ }
789+ else if (build_external_file == OFM_STUB)
790+ {
791+ UINT future = (build_crcchk ? sizeof(crc32_t) + sizeof(XXH32_hash_t): 0) + (uninstall_size > 0 ? uninstall_size_full : 0);
792+ IGrowBuf64::size_type maxsize = (~(IGrowBuf64::size_type)0) - (total_usize + future), totsizadd = dbsize_su < (UINT64)maxsize ? dbsize_su : maxsize;
793+ total_usize += (DWORD)totsizadd; // Might not be accurate, it is more important to not overflow the additions coming up
794+
795+ if (build_datablock.getlen())
796+ {
797+ IGrowBuf64::size_type maxsize_ex = (~(IGrowBuf64::size_type)0) - total_usize_ex, totsizadd_ex = dbsizeu < (UINT64)maxsize_ex ? dbsizeu : maxsize_ex;
798+ total_usize_ex += totsizadd_ex; // Might not be accurate, it is more important to not overflow the additions coming up
799+ }
800+ }
801+ else
802+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
803+ {
804+ UINT future = (build_crcchk ? sizeof(int) : 0) + (uninstall_size > 0 ? uninstall_size_full : 0);
805+ IGrowBuf64::size_type maxsize = (~(IGrowBuf64::size_type)0) - (total_usize + future), totsizadd = dbsizeu < (UINT64)maxsize ? dbsizeu : maxsize;
806+ total_usize += (DWORD)totsizadd; // Might not be accurate, it is more important to not overflow the additions coming up
807+ }
808 }
809
810 if (uninstall_size>=0)
811@@ -2882,7 +3071,12 @@
812 INFO_MSG(_T("Uninstall code+data: (%d bytes)\n"),uninstall_size_full);
813 else
814 INFO_MSG(_T("Uninstall code+data: %6d / %d bytes\n"),uninstall_size,uninstall_size_full);
815- total_usize += uninstall_size_full;
816+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
817+ if (build_external_file == OFM_DATA)
818+ total_usize_ex += uninstall_size_full;
819+ else
820+#endif
821+ total_usize += uninstall_size_full;
822 }
823
824 if (build_compress_whole) {
825@@ -2892,65 +3086,115 @@
826 if (build_datablock.getlen())
827 {
828 build_datablock.setro(TRUE);
829- int dbl = build_datablock.getlen();
830- int left = dbl;
831+ IGrowBuf64::size_type left, dbl = build_datablock.getlen();
832+ left = dbl;
833+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
834+#ifdef NSIS_CONFIG_CRC_SUPPORT
835+ XXH32_state_t state;
836+ XXH32_reset(&state, 0);
837+#endif
838+#endif
839 while (left > 0)
840 {
841- int l = min(build_filebuflen, left);
842+ int l = min(build_filebuflen, left > 0x7fffffff ? (int)0x7fffffff : (int)left);
843 char *dbptr = (char *) build_datablock.get(dbl - left, l);
844 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
845 if (build_compress_whole)
846 {
847- if (deflateToFile(fp,dbptr,l))
848- {
849- fclose(fp);
850+ if (deflateToFile(fp.GetHandle(),dbptr,l))
851 return PS_ERROR;
852- }
853 }
854 else
855 #endif
856 {
857+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
858+ if (build_external_file == OFM_DATA || build_external_file == OFM_STUB)
859+ {
860 #ifdef NSIS_CONFIG_CRC_SUPPORT
861- crc=CRC32(crc,(unsigned char *)dbptr,l);
862+ if (build_stub_installer_size)
863+ XXH32_update(&state, dbptr, l);
864 #endif
865- if ((int)fwrite(dbptr,1,l,fp) != l)
866+ if ((int)fp_ex.Fwrite(dbptr,1,l) != l)
867+ {
868+ ERROR_MSG(_T("Error: can't write %d bytes to output\n"),l);
869+ return PS_ERROR;
870+ }
871+ fp_ex.Fflush();
872+ }
873+ else
874+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
875 {
876- ERROR_MSG(_T("Error: can't write %d bytes to output\n"),l);
877- fclose(fp);
878- return PS_ERROR;
879+#ifdef NSIS_CONFIG_CRC_SUPPORT
880+ crc=CRC32(crc,(unsigned char *)dbptr,l);
881+#endif
882+ if ((int)fp.Fwrite(dbptr,1,l) != l)
883+ {
884+ ERROR_MSG(_T("Error: can't write %d bytes to output\n"),l);
885+ return PS_ERROR;
886+ }
887+ fp.Fflush();
888 }
889- fflush(fp);
890 }
891 build_datablock.release();
892 left -= l;
893 }
894+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
895+#ifdef NSIS_CONFIG_CRC_SUPPORT
896+ if ((build_external_file == OFM_DATA || build_external_file == OFM_STUB) && build_stub_installer_size)
897+ hash_ex = XXH32_digest(&state);
898+#endif
899+#endif
900 build_datablock.setro(FALSE);
901 build_datablock.clear();
902 }
903+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
904+ if (build_datablock_stub.getlen())
905+ {
906+ build_datablock_stub.setro(TRUE);
907+ IGrowBuf64::size_type dbl = build_stub_installer_size;
908+ IGrowBuf64::size_type left = dbl;
909+ while (left > 0)
910+ {
911+ int l = min(build_filebuflen, left > 0x7fffffff ? (int)0x7fffffff : (int)left);
912+ char *dbptr = (char *) build_datablock_stub.get(dbl - left, l);
913+#ifdef NSIS_CONFIG_CRC_SUPPORT
914+ crc=CRC32(crc,(unsigned char *)dbptr,l);
915+#endif
916+ if ((int)fp.Fwrite(dbptr,1,l) != l)
917+ {
918+ ERROR_MSG(_T("Error: can't write %d bytes to output\n"),l);
919+ return PS_ERROR;
920+ }
921+ fp.Fflush();
922+ build_datablock_stub.release();
923+ left -= l;
924+ }
925+ build_datablock_stub.setro(FALSE);
926+ build_datablock_stub.clear();
927+ }
928+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
929 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
930 if (build_compress_whole)
931 {
932- if (deflateToFile(fp,NULL,0))
933- {
934- fclose(fp);
935+ if (deflateToFile(fp.GetHandle(),NULL,0))
936 return PS_ERROR;
937- }
938+
939 compressor->End();
940
941- unsigned fend = ftell(fp);
942+ UINT64 fend = fp.Ftell64();
943
944- fh.length_of_all_following_data=ftell(fp)-fd_start+(build_crcchk?sizeof(crc32_t):0);
945+ fh.length_of_all_following_data=(DWORD)(fend-fd_start+(build_crcchk?sizeof(crc32_t):0));
946 INFO_MSG(
947- _T("%10d / %d bytes\n"),
948- ftell(fp) - fd_start,
949- data_block_size_before_uninst + fh.length_of_header + sizeof(firstheader) + uninstall_size_full
950+ _T("%10u / %u bytes\n"),
951+ (DWORD)(fend - fd_start),
952+ (DWORD)((UINT64)(data_block_size_before_uninst + fh.length_of_header + sizeof(firstheader) + uninstall_size_full))
953 );
954
955- fseek(fp,fd_start,SEEK_SET);
956+ fp.Fseek(fd_start,SEEK_SET);
957
958 try
959 {
960- file_writer_sink sink(fp, mk_writer_target_info());
961+ file_writer_sink sink(fp.GetHandle(), mk_writer_target_info());
962 firstheader_writer w(&sink);
963 w.write(&fh);
964 }
965@@ -2957,7 +3201,6 @@
966 catch (...)
967 {
968 ERROR_MSG(_T("Error: can't write %d bytes to output\n"),sizeof(fh));
969- fclose(fp);
970 return PS_ERROR;
971 }
972
973@@ -2965,40 +3208,74 @@
974 if (build_crcchk)
975 {
976 // check rest of CRC
977- fseek(fp,fd_start,SEEK_SET);
978+ fp.Fseek(fd_start,SEEK_SET);
979 for (;;)
980 {
981 char buf[32768];
982- unsigned int l=(unsigned int)fread(buf,1,sizeof(buf),fp);
983+ size_t l=fp.Fread(buf,1,sizeof(buf));
984 if (!l) break;
985 crc=CRC32(crc,(unsigned char *)buf,l);
986 }
987 }
988 #endif
989- fseek(fp,fend,SEEK_SET); // reset eof flag
990+ fp.Fseek64(fend,SEEK_SET); // reset eof flag
991 }
992 #endif
993
994 if (build_crcchk)
995 {
996+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
997+ if (build_stub_installer_size && build_external_file == OFM_STUB)
998+ {
999+ total_usize+=sizeof(int);
1000+ XXH32_hash_t rhash = FIX_ENDIAN_INT32(hash_ex);
1001+#ifdef NSIS_CONFIG_CRC_SUPPORT
1002+ crc=CRC32(crc,(unsigned char *)&rhash,sizeof(XXH32_hash_t));
1003+#endif //NSIS_CONFIG_CRC_SUPPORT
1004+ if (fp.Fwrite(&rhash,1,sizeof(XXH32_hash_t)) != sizeof(XXH32_hash_t))
1005+ {
1006+ ERROR_MSG(_T("Error: can't write %d bytes to output\n"),sizeof(XXH32_hash_t));
1007+ return PS_ERROR;
1008+ }
1009+ if (build_datablock.getlen()) INFO_MSG(_T("Hash ExFile (0x%08X): 4 / 4 bytes\n"),hash_ex);
1010+ }
1011+#endif
1012 total_usize+=sizeof(int);
1013 int rcrc = FIX_ENDIAN_INT32(crc);
1014- if (fwrite(&rcrc,1,sizeof(crc32_t),fp) != sizeof(crc32_t))
1015+ if (fp.Fwrite(&rcrc,1,sizeof(crc32_t)) != sizeof(crc32_t))
1016 {
1017 ERROR_MSG(_T("Error: can't write %d bytes to output\n"),sizeof(crc32_t));
1018- fclose(fp);
1019 return PS_ERROR;
1020 }
1021 INFO_MSG(_T("CRC (0x%08X): 4 / 4 bytes\n"),crc);
1022 }
1023 INFO_MSG(_T("\n"));
1024+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1025+ if ((build_external_file == OFM_DATA || build_external_file == OFM_STUB) && build_datablock.getlen())
1026 {
1027- long fileend = ftell(fp);
1028+ UINT64 fileend = fp.Ftell64();
1029 UINT pc=(UINT)(((UINT64)fileend*1000)/(total_usize));
1030+ INFO_MSG(_T("Totals:\n"));
1031+ INFO_MSG(_T("Exe size: %10u / %u bytes (%u.%u%%)\n"),
1032+ (DWORD)fileend,(DWORD)total_usize,pc/10,pc%10);
1033+
1034+ FriendlySize us(total_usize_ex, GFSF_BYTESIFPOSSIBLE); // uncompressed installer size
1035+ FriendlySize cs(fp_ex.Ftell64(), GFSF_BYTESIFPOSSIBLE | (us.UInt()==total_usize_ex ? GFSF_HIDEBYTESCALE : 0)); // compressed installer size
1036+
1037+ INFO_MSG(_T("Bin size: %18u%") NPRIs _T(" / %u%") NPRIs _T("\n"),
1038+ cs.UInt(),cs.Scale(),us.UInt(),us.Scale());
1039+
1040+ fp_ex.Fclose();
1041+ }
1042+ else
1043+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1044+ {
1045+ UINT64 fileend = fp.Ftell64();
1046+ UINT pc=(UINT)(((UINT64)fileend*1000)/(total_usize));
1047 INFO_MSG(_T("Total size: %10u / %u bytes (%u.%u%%)\n"),
1048- fileend,total_usize,pc/10,pc%10);
1049+ (DWORD)fileend,(DWORD)total_usize,pc/10,pc%10);
1050 }
1051- fclose(fp);
1052+ fp.Fclose();
1053 RET_UNLESS_OK(run_postbuild_cmds(postbuild_cmds, build_output_filename, _T("Finalize")));
1054 print_warnings();
1055 return PS_OK;
1056@@ -3086,25 +3363,25 @@
1057
1058 int ents = build_header.blocks[NB_ENTRIES].num;
1059 int uns = uninstaller_writes_used;
1060- int uninstdata_offset = build_datablock.getlen();
1061- while (ents--)
1062+ crc32_t crc_ico = 0;
1063+ IGrowBuf64::size_type uninstdata_offset;
1064+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1065+ set_datablock_mode(build_external_file == OFM_STUB);
1066+ if (build_external_file == OFM_STUB)
1067+ uninstdata_offset = build_datablock_stub.getlen();
1068+ else
1069+#endif
1070 {
1071- if (ent->which == EW_WRITEUNINSTALLER)
1072- {
1073- ent->offsets[1] = uninstdata_offset;
1074- ent->offsets[2] = (int) m_unicon_size;
1075- uns--;
1076- if (!uns)
1077- break;
1078- }
1079- ent++;
1080+ uninstdata_offset = build_datablock.getlen();
1081 }
1082-
1083- if (add_db_data((char *)unicon_data,m_unicon_size) < 0)
1084+ if (add_db_data((char *)unicon_data,m_unicon_size,&crc_ico) < 0)
1085 {
1086 delete [] unicon_data;
1087 return PS_ERROR;
1088 }
1089+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1090+ set_datablock_mode(0);
1091+#endif
1092
1093 #ifdef NSIS_CONFIG_CRC_SUPPORT
1094 {
1095@@ -3149,12 +3426,12 @@
1096 #endif
1097 fh.siginfo=FH_SIG;
1098 fh.length_of_all_following_data=
1099- uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
1100+ uhd.getlen()+truncate_cast(int, (size_t)(ubuild_datablock.getlen())+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0));
1101
1102 MMapBuf udata;
1103
1104 {
1105- growbuf_writer_sink sink(&udata, mk_writer_target_info());
1106+ growbuf64_writer_sink sink(&udata, mk_writer_target_info());
1107 firstheader_writer w(&sink);
1108 w.write(&fh);
1109 }
1110@@ -3184,10 +3461,10 @@
1111 }
1112 }
1113
1114- int avail_in = ubuild_datablock.getlen();
1115+ IGrowBuf64::size_type avail_in = ubuild_datablock.getlen();
1116 int in_pos = 0;
1117 while (avail_in > 0) {
1118- int l = min(avail_in, build_filebuflen);
1119+ int l = min(avail_in > INT_MAX ? INT_MAX : (int)avail_in, build_filebuflen);
1120
1121 char *p = (char*)ubuild_datablock.get(in_pos, l);
1122 compressor->SetNextIn(p, l);
1123@@ -3218,7 +3495,7 @@
1124 }
1125
1126 firstheader *_fh=(firstheader *)udata.get(0, sizeof(firstheader));
1127- _fh->length_of_all_following_data=FIX_ENDIAN_INT32(udata.getlen()+(build_crcchk?sizeof(crc32_t):0));
1128+ _fh->length_of_all_following_data=FIX_ENDIAN_INT32(truncate_cast(int, (size_t)(udata.getlen())+(build_crcchk?sizeof(crc32_t):0)));
1129 udata.release();
1130 }
1131 else
1132@@ -3226,13 +3503,13 @@
1133 {
1134 udata.add(uhd.get(), uhd.getlen());
1135
1136- int st = udata.getlen();
1137- int length = ubuild_datablock.getlen();
1138- int left = length;
1139+ IGrowBuf64::size_type st = udata.getlen();
1140+ IGrowBuf64::size_type length = ubuild_datablock.getlen();
1141+ IGrowBuf64::size_type left = length;
1142 udata.resize(st + left);
1143 while (left > 0)
1144 {
1145- int l = min(build_filebuflen, left);
1146+ int l = min(build_filebuflen, left > INT_MAX ? INT_MAX : (int)left);
1147 void *p = ubuild_datablock.get(length - left, l);
1148 memcpy(udata.get(st + length - left, l), p, l);
1149 udata.flush(l);
1150@@ -3250,10 +3527,10 @@
1151 if (build_crcchk)
1152 {
1153 int pos = 0;
1154- int left = udata.getlen();
1155+ IGrowBuf64::size_type left = udata.getlen();
1156 while (left > 0)
1157 {
1158- int l = min(build_filebuflen, left);
1159+ int l = min(build_filebuflen, left > INT_MAX ? INT_MAX : (int)left);
1160 crc = CRC32(crc, (unsigned char *) udata.get(pos, l), l);
1161 udata.release();
1162 pos += l;
1163@@ -3266,9 +3543,34 @@
1164 }
1165 #endif
1166
1167- if (add_db_data(&udata) < 0)
1168+ crc32_t crc_undata = 0;
1169+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1170+ set_datablock_mode(build_external_file == OFM_STUB);
1171+#endif
1172+ if (add_db_data(&udata, &crc_undata) < 0)
1173 return PS_ERROR;
1174+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1175+ set_datablock_mode(0);
1176+#endif
1177
1178+ while (ents--)
1179+ {
1180+ if (ent->which == EW_WRITEUNINSTALLER)
1181+ {
1182+ DB_OFFSET off;
1183+ off.quad_part = uninstdata_offset;
1184+ ent->offsets[1] = off.low_part;
1185+ ent->offsets[2] = off.high_part;
1186+ ent->offsets[3] = (int) m_unicon_size;
1187+ ent->offsets[5] = FIX_ENDIAN_INT32(crc_ico);
1188+ ent->offsets[6] = FIX_ENDIAN_INT32(crc_undata);
1189+ uns--;
1190+ if (!uns)
1191+ break;
1192+ }
1193+ ent++;
1194+ }
1195+
1196 udata.clear();
1197
1198 //uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int);
1199@@ -3275,7 +3577,16 @@
1200 uninstall_size_full=fh.length_of_all_following_data+(int)m_unicon_size;
1201
1202 // compressed size
1203- uninstall_size=build_datablock.getlen()-uninstdata_offset;
1204+ DB_OFFSET following_data_off;
1205+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1206+ if (build_external_file == OFM_STUB)
1207+ following_data_off.quad_part = build_datablock_stub.getlen()-uninstdata_offset;
1208+ else
1209+#endif
1210+ {
1211+ following_data_off.quad_part = build_datablock.getlen()-uninstdata_offset;
1212+ }
1213+ uninstall_size=following_data_off.low_part;
1214
1215 SCRIPT_MSG(_T("Done!\n"));
1216 }
1217@@ -3285,6 +3596,28 @@
1218
1219 #define SWAP(x,y,i) { i _ii; _ii=x; x=y; y=_ii; }
1220
1221+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1222+void CEXEBuild::set_datablock_mode(int stub)
1223+{
1224+ if (uninstall_mode) return;
1225+ if (stub != datablock_mode)
1226+ {
1227+ datablock_mode=stub;
1228+ if (stub)
1229+ {
1230+ cur_datablock=&build_datablock_stub;
1231+ cur_datablock_cache=&build_datablock_stub_cache;
1232+ }
1233+ else
1234+ {
1235+ cur_datablock=&build_datablock;
1236+ cur_datablock_cache=&build_datablock_cache;
1237+ }
1238+ SWAP(db_full_size_s,db_full_size,UINT64);
1239+ }
1240+}
1241+#endif
1242+
1243 void CEXEBuild::set_uninstall_mode(int un)
1244 {
1245 if (un != uninstall_mode)
1246@@ -3309,8 +3642,13 @@
1247 }
1248 else
1249 {
1250+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1251+ cur_datablock=datablock_mode?&build_datablock_stub:&build_datablock;
1252+ cur_datablock_cache=datablock_mode?&build_datablock_stub_cache:&build_datablock_cache;
1253+#else
1254 cur_datablock=&build_datablock;
1255 cur_datablock_cache=&build_datablock_cache;
1256+#endif
1257 cur_entries=&build_entries;
1258 cur_instruction_entry_map=&build_instruction_entry_map;
1259 cur_functions=&build_functions;
1260@@ -3327,7 +3665,11 @@
1261
1262 SWAP(db_opt_save_u,db_opt_save,UINT64);
1263 SWAP(db_comp_save_u,db_comp_save,int);
1264+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1265+ SWAP(db_full_size_u,datablock_mode?db_full_size_s:db_full_size,UINT64);
1266+#else
1267 SWAP(db_full_size_u,db_full_size,UINT64);
1268+#endif
1269 }
1270 }
1271
1272Index: Source/build.h
1273===================================================================
1274--- Source/build.h (revision 7070)
1275+++ Source/build.h (working copy)
1276@@ -51,6 +51,7 @@
1277 #include "czlib.h"
1278 #include "cbzip2.h"
1279 #include "clzma.h"
1280+#include "clz4.h"
1281 #endif //~ NSIS_CONFIG_COMPRESSION_SUPPORT
1282
1283 #ifdef NSIS_CONFIG_PLUGIN_SUPPORT
1284@@ -108,10 +109,12 @@
1285 DW_ATTRIBUTE_OVERLONGSTRING = 7060,
1286 DW_PARSE_BADNUMBER = 7070,
1287 DW_PARSE_LNK_HK = 7075,
1288+ DW_PARSE_SETEXOUTFILE_DEPRECATED = 7950,
1289 DW_PARSE_REGPATHPREFIX = 7999,
1290 DW_INSTFILESPAGE_NOT_USED = 8000, // reserved ..8019
1291 DW_COMP_FINAL = 8020, // reserved ..8059
1292 DW_COMP_WHOLE_IGNORE_OFF = 8021,
1293+ DW_COMP_WHOLE_IGNORE = 8022,
1294 DW_COMP_LEVEL_IGNORE = 8025,
1295 DW_COMP_DICT_IGNORE = 8026,
1296 DW_COMP_DICTWHOLE = 8030,
1297@@ -327,12 +330,12 @@
1298 int doCommand(int which_token, LineParser &line);
1299 TCHAR m_templinebuf[MAX_LINELENGTH]; // Buffer used by parseScript() & doCommand(), not recursion safe!
1300
1301- int do_add_file(const TCHAR *lgss, int attrib, int recurse, int *total_files, const TCHAR
1302- *name_override=0, int generatecode=1, int *data_handle=0,
1303- const std::set<tstring>& excluded=std::set<tstring>(),
1304+ int do_add_file(const TCHAR *lgss, int attrib, int recurse, int *total_files, const TCHAR
1305+ *name_override=0, int generatecode=1, IGrowBuf64::size_type *data_handle=0, crc32_t *pcrc=0,
1306+ const std::set<tstring>& excluded=std::set<tstring>(),
1307 const tstring& basedir=tstring(_T("")), bool dir_created=false);
1308- int add_file(const tstring& dir, const tstring& file, int attrib, const TCHAR
1309- *name_override, int generatecode, int *data_handle);
1310+ int add_file(const tstring& dir, const tstring& file, int attrib, const TCHAR *name_override, int
1311+ generatecode, IGrowBuf64::size_type *data_handle, crc32_t *pcrc, const TCHAR *which_token_str);
1312 int do_add_file_create_dir(const tstring& local_dir, const tstring& dir, int attrib=0);
1313
1314 GrowBuf m_linebuild; // used for concatenating lines
1315@@ -382,7 +385,7 @@
1316 int set_target_architecture_data();
1317 int change_target_architecture(TARGETTYPE tt);
1318 void set_code_type_predefines(const TCHAR *value = NULL);
1319- int getcurdbsize();
1320+ IGrowBuf64::size_type getcurdbsize();
1321 int add_section(const TCHAR *secname, const TCHAR *defname, int expand=0);
1322 int section_end();
1323 int add_function(const TCHAR *funname);
1324@@ -394,10 +397,10 @@
1325 int page_end();
1326 int add_label(const TCHAR *name);
1327 int add_entry(const entry *ent);
1328- int add_entry_direct(int which, int o0=0, int o1=0, int o2=0, int o3=0, int o4=0, int o5=0);
1329- int add_db_data(IMMap *map); // returns offset
1330- int add_db_data(const char *data, int length); // returns offset
1331- int add_db_data(const char *data, size_t length) { assert(length <= 0x7FFFFFFF); return add_db_data(data, (int)length); }
1332+ int add_entry_direct(int which, int o0=0, int o1=0, int o2=0, int o3=0, int o4=0, int o5=0, int o6=0, int o7=0);
1333+ IGrowBuf64::size_type add_db_data(IMMap *map, crc32_t *ex_crc); // returns offset
1334+ IGrowBuf64::size_type add_db_data(const char *data, int length, crc32_t *ex_crc); // returns offset
1335+ IGrowBuf64::size_type add_db_data(const char *data, size_t length, crc32_t *ex_crc) { assert(length <= 0x7FFFFFFF); return add_db_data(data, (int)length, ex_crc); }
1336 int add_data(const char *data, int length, IGrowBuf *dblock); // returns offset
1337 int add_string(const TCHAR *string, int process=1, UINT codepage=-2); // returns offset (in string table)
1338 int add_asciistring(const TCHAR *string, int process=1); // For hardcoded 7bit/ASCII strings
1339@@ -417,8 +420,11 @@
1340 #endif //NSIS_CONFIG_PLUGIN_SUPPORT
1341
1342 // build.cpp functions used mostly within build.cpp
1343- int datablock_optimize(int start_offset, int first_int);
1344- bool datablock_finddata(IMMap&mmap, int mmstart, int size, int*ofs);
1345+ IGrowBuf64::size_type datablock_optimize(IGrowBuf64::size_type start_offset, int first_int);
1346+ bool datablock_finddata(IMMap&mmap, IGrowBuf64::size_type mmstart, int size, IGrowBuf64::size_type*ofs);
1347+#ifdef NSIS_CONFIG_CRC_SUPPORT
1348+ bool datablock_crcdata(IMMap *in, IGrowBuf64::size_type start, int len, crc32_t *ex_crc);
1349+#endif //NSIS_CONFIG_CRC_SUPPORT
1350 void printline(int l);
1351 int process_jump(LineParser &line, int wt, int *offs);
1352
1353@@ -442,6 +448,13 @@
1354 void warninghelper(DIAGCODE dc, bool fl, const TCHAR *fmt, va_list args);
1355 DiagState diagstate;
1356
1357+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1358+ /** Are we defining a stub installer version?
1359+ * @param stub Use like a boolean to define whether in stub mode.
1360+ */
1361+ void set_datablock_mode(int stub);
1362+#endif
1363+
1364 /** Are we defining an uninstall version of the code?
1365 * @param un Use like a boolean to define whether in uninstall mode.
1366 */
1367@@ -563,6 +576,7 @@
1368 CZlib zlib_compressor;
1369 CBzip2 bzip2_compressor;
1370 CLZMA lzma_compressor;
1371+ CLZ4 lz4_compressor;
1372 #endif
1373 bool build_compressor_set;
1374 bool build_compressor_final;
1375@@ -595,6 +609,9 @@
1376 build_allowskipfiles; // Added by ramon 23 May 2003
1377
1378 header build_header, build_uninst, *cur_header;
1379+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1380+ int datablock_mode;
1381+#endif
1382 int uninstall_mode; // Are we in uninstall mode? Acts like a bool.
1383 int uninstall_size,uninstall_size_full;
1384 int uninstaller_writes_used;
1385@@ -601,6 +618,18 @@
1386
1387 TCHAR build_output_filename[1024];
1388
1389+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1390+ enum {
1391+ OFM_AUTO = -1,
1392+ OFM_AIO,
1393+ OFM_DATA,
1394+ OFM_STUB
1395+ };
1396+ int build_external_file;
1397+ unsigned int build_stub_installer_size;
1398+ TCHAR build_output_external_filename[1024];
1399+#endif
1400+
1401 int build_include_depth;
1402
1403 // Added by ramon 6 jun 2003
1404@@ -615,6 +644,9 @@
1405 GrowBuf m_macros;
1406
1407 UINT64 db_opt_save, db_opt_save_u, db_full_size, db_full_size_u;
1408+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1409+ UINT64 db_full_size_s;
1410+#endif
1411 int db_comp_save, db_comp_save_u;
1412
1413 FastStringList include_dirs;
1414@@ -643,12 +675,16 @@
1415 // don't forget to update the cache after updating the datablock
1416 // see datablock_optimize for an example
1417 MMapBuf build_datablock, ubuild_datablock;
1418- TinyGrowBuf build_datablock_cache, ubuild_datablock_cache;
1419- IGrowBuf *cur_datablock, *cur_datablock_cache;
1420+ TinyGrowBuf64 build_datablock_cache, ubuild_datablock_cache;
1421+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1422+ MMapBuf build_datablock_stub;
1423+ TinyGrowBuf64 build_datablock_stub_cache;
1424+#endif
1425+ IGrowBuf64 *cur_datablock, *cur_datablock_cache;
1426 struct cached_db_size
1427 {
1428 int first_int; // size | (compressed ? 0x80000000 : 0)
1429- int start_offset;
1430+ IGrowBuf64::size_type start_offset;
1431 };
1432
1433 int build_filebuflen;
1434Index: Source/clz4.h
1435===================================================================
1436--- Source/clz4.h (revision 0)
1437+++ Source/clz4.h (working copy)
1438@@ -0,0 +1,86 @@
1439+/*
1440+ * clz4.h
1441+ *
1442+ * This file is a part of NSIS.
1443+ *
1444+ * Copyright (C) 2016-2017 Nullsoft and Contributors
1445+ *
1446+ * Licensed under the zlib/libpng license (the "License");
1447+ * you may not use this file except in compliance with the License.
1448+ *
1449+ * Licence details can be found in the file COPYING.
1450+ *
1451+ * This software is provided 'as-is', without any express or implied
1452+ * warranty.
1453+ */
1454+
1455+#ifndef __CLZ4_H__
1456+#define __CLZ4_H__
1457+
1458+#include "lz4/lz4compress.h"
1459+
1460+class CLZ4 : public ICompressor {
1461+ public:
1462+ virtual ~CLZ4() {}
1463+
1464+ virtual int Init(int level, unsigned int dict_size) {
1465+ return LZ4_Init(&stream, level, dict_size);
1466+ }
1467+
1468+ virtual int End() {
1469+ return LZ4_End(&stream);
1470+ }
1471+
1472+ virtual int Compress(bool finish) {
1473+ return LZ4_Compress(&stream, finish);
1474+ }
1475+
1476+ virtual void SetNextIn(char *in, unsigned int size) {
1477+ stream.next_in = in;
1478+ stream.avail_in = size;
1479+ }
1480+
1481+ virtual void SetNextOut(char *out, unsigned int size) {
1482+ stream.next_out = out;
1483+ stream.avail_out = size;
1484+ }
1485+
1486+ virtual char* GetNextOut() {
1487+ return stream.next_out;
1488+ }
1489+
1490+ virtual unsigned int GetAvailIn() {
1491+ return stream.avail_in;
1492+ }
1493+
1494+ virtual unsigned int GetAvailOut() {
1495+ return stream.avail_out;
1496+ }
1497+
1498+ virtual const TCHAR* GetName() {
1499+ return _T("lz4");
1500+ }
1501+
1502+ virtual const TCHAR* GetErrStr(int err) {
1503+ switch (err)
1504+ {
1505+ case Z_STREAM_ERROR:
1506+ return _T("invalid stream - bad call");
1507+ case Z_DATA_ERROR:
1508+ return _T("data error");
1509+ case Z_MEM_ERROR:
1510+ return _T("not enough memory");
1511+ case Z_BUF_ERROR:
1512+ return _T("buffer error - bad call");
1513+ case Z_VERSION_ERROR:
1514+ return _T("version error");
1515+ default:
1516+ return _T("unknown error");
1517+ }
1518+ }
1519+
1520+ private:
1521+ lz4_compstream stream;
1522+};
1523+
1524+#endif
1525Index: Source/exehead/Main.c
1526===================================================================
1527--- Source/exehead/Main.c (revision 7070)
1528+++ Source/exehead/Main.c (working copy)
1529@@ -434,6 +434,13 @@
1530 CloseHandle(g_db_hFile);
1531 g_db_hFile = INVALID_HANDLE_VALUE;
1532 }
1533+#ifdef NSIS_EXTERNAL_FILE_SUPPORT
1534+ if (g_dbex_hFile != INVALID_HANDLE_VALUE)
1535+ {
1536+ CloseHandle(g_dbex_hFile);
1537+ g_dbex_hFile = INVALID_HANDLE_VALUE;
1538+ }
1539+#endif
1540 #ifdef NSIS_COMPRESS_WHOLE
1541 if (dbd_hFile != INVALID_HANDLE_VALUE)
1542 {
1543Index: Source/exehead/SConscript
1544===================================================================
1545--- Source/exehead/SConscript (revision 7070)
1546+++ Source/exehead/SConscript (working copy)
1547@@ -8,6 +8,7 @@
1548 Ui.c
1549 util.c
1550 #Source/crc32.c
1551+ #Source/xxhash.c
1552 """)
1553
1554 resources = Split("""
1555@@ -26,6 +27,11 @@
1556 #Source/bzip2/huffman.c
1557 """)
1558
1559+lz4_files = Split("""
1560+ #Source/lz4/lz4common.c
1561+ #Source/lz4/lz4decompress.c
1562+""")
1563+
1564 lzma_files = Split("""
1565 #Source/7zip/LZMADecode.c
1566 """)
1567@@ -66,6 +72,9 @@
1568 if compression == 'bzip2':
1569 env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_BZIP2'])
1570 files += bzip2_files
1571+elif compression == 'lz4':
1572+ env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_LZ4'])
1573+ files += lz4_files
1574 elif compression == 'lzma':
1575 env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_LZMA'])
1576 env.Append(CPPDEFINES = ['LZMACALL=__fastcall'])
1577Index: Source/exehead/config.h
1578===================================================================
1579--- Source/exehead/config.h (revision 7070)
1580+++ Source/exehead/config.h (working copy)
1581@@ -79,7 +79,9 @@
1582 #ifndef NSIS_COMPRESS_USE_ZLIB
1583 #ifndef NSIS_COMPRESS_USE_BZIP2
1584 #ifndef NSIS_COMPRESS_USE_LZMA
1585- #error compression is enabled but zlib, bzip2 and lzma are disabled.
1586+ #ifndef NSIS_COMPRESS_USE_LZ4
1587+ #error compression is enabled but zlib, bzip2, lzma and lz4 are disabled.
1588+ #endif
1589 #endif
1590 #endif
1591 #endif
1592@@ -92,12 +94,23 @@
1593 #ifdef NSIS_COMPRESS_USE_LZMA
1594 #error both zlib and lzma are enabled.
1595 #endif
1596+ #ifdef NSIS_COMPRESS_USE_LZ4
1597+ #error both zlib and lz4 are enabled.
1598+ #endif
1599 #endif
1600 #ifdef NSIS_COMPRESS_USE_BZIP2
1601 #ifdef NSIS_COMPRESS_USE_LZMA
1602 #error both bzip2 and lzma are enabled.
1603 #endif
1604+ #ifdef NSIS_COMPRESS_USE_LZ4
1605+ #error both bzip2 and lz4 are enabled.
1606+ #endif
1607 #endif
1608+ #ifdef NSIS_COMPRESS_USE_LZMA
1609+ #ifdef NSIS_COMPRESS_USE_LZ4
1610+ #error both lzma and lz4 are enabled.
1611+ #endif
1612+ #endif
1613
1614 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
1615 #ifdef NSIS_COMPRESS_WHOLE
1616Index: Source/exehead/exec.c
1617===================================================================
1618--- Source/exehead/exec.c (revision 7070)
1619+++ Source/exehead/exec.c (working copy)
1620@@ -59,6 +59,10 @@
1621 HRESULT g_hres;
1622 #endif
1623
1624+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1625+extern LARGE_INTEGER g_ex_length;
1626+#endif
1627+
1628 static int NSISCALL ExecuteEntry(entry *entry_);
1629
1630 /**
1631@@ -252,6 +256,8 @@
1632 #define parm3 (lent.offsets[3])
1633 #define parm4 (lent.offsets[4])
1634 #define parm5 (lent.offsets[5])
1635+#define parm6 (lent.offsets[6])
1636+#define parm7 (lent.offsets[7])
1637
1638 var0 = g_usrvars[parm0];
1639 var1 = g_usrvars[parm1];
1640@@ -481,6 +487,9 @@
1641 break;
1642 #endif
1643 #ifdef NSIS_SUPPORT_FILE
1644+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1645+ case EW_EXTRACTSTUBFILE:
1646+#endif
1647 case EW_EXTRACTFILE:
1648 {
1649 HANDLE hOut;
1650@@ -503,7 +512,7 @@
1651 int cmp=0;
1652 if (ffd)
1653 {
1654- cmp=CompareFileTime(&ffd->ftLastWriteTime, (FILETIME*)(lent.offsets + 3));
1655+ cmp=CompareFileTime(&ffd->ftLastWriteTime, (FILETIME*)(lent.offsets + 4));
1656 }
1657 overwriteflag=!(cmp & (0x80000000 | (overwriteflag - 3)));
1658 }
1659@@ -526,7 +535,7 @@
1660
1661 mystrcpy(buf2,g_usrvars[0]); // save $0
1662 mystrcpy(g_usrvars[0],buf0); // copy file name to $0
1663- GetNSISString(buf1,parm5); // use $0
1664+ GetNSISString(buf1,parm6); // use $0
1665 mystrcpy(g_usrvars[0],buf2); // restore $0
1666
1667 // Modified by ramon 23 May 2003
1668@@ -548,15 +557,25 @@
1669
1670 update_status_text(LANG_EXTRACT,buf3);
1671 {
1672+ LARGE_INTEGER offset;
1673+ offset.LowPart = parm2;
1674+ offset.HighPart = parm3;
1675 g_exec_flags.status_update++;
1676- ret=GetCompressedDataFromDataBlock(parm2,hOut);
1677+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1678+ if (which == EW_EXTRACTSTUBFILE)
1679+ ret=GetCompressedDataFromExeHead(offset.QuadPart,hOut,parm7);
1680+ else
1681+#endif
1682+ {
1683+ ret=GetCompressedDataFromDataBlock(offset.QuadPart,hOut,parm7);
1684+ }
1685 g_exec_flags.status_update--;
1686 }
1687
1688 log_printf3(_T("File: wrote %d to \"%s\""),ret,buf0);
1689
1690- if (parm3 != 0xffffffff || parm4 != 0xffffffff)
1691- SetFileTime(hOut,(FILETIME*)(lent.offsets+3),NULL,(FILETIME*)(lent.offsets+3));
1692+ if (parm4 != 0xffffffff || parm5 != 0xffffffff)
1693+ SetFileTime(hOut,(FILETIME*)(lent.offsets+4),NULL,(FILETIME*)(lent.offsets+4));
1694
1695 CloseHandle(hOut);
1696
1697@@ -577,6 +596,67 @@
1698 }
1699 }
1700 break;
1701+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1702+ case EW_VERIFYEXTERNALFILE:
1703+ {
1704+ exec_error++;
1705+ if (g_dbex_hFile != INVALID_HANDLE_VALUE && g_is_stub_installer && g_has_external_file)
1706+ exec_error--;
1707+ else if (g_is_stub_installer && g_has_external_file)
1708+ {
1709+ TCHAR *buf0 = GetStringFromParm(0x00);
1710+
1711+ if (!validpathspec(buf0))
1712+ {
1713+ mystrcpy(buf1, state_exe_path);
1714+ mystrcpy(buf1, trimextension(buf1));
1715+ wsprintf(buf0, _T("%s.nsisbin"), buf1);
1716+ }
1717+ validate_filename(buf0);
1718+ g_dbex_hFile = myOpenFile(buf0, GENERIC_READ, OPEN_EXISTING);
1719+ if (g_dbex_hFile != INVALID_HANDLE_VALUE)
1720+ {
1721+#ifdef NSIS_CONFIG_CRC_SUPPORT
1722+ XXH32_hash_t fhash = 0;
1723+ XXH32_state_t state;
1724+ UINT64 left;
1725+ ULARGE_INTEGER size;
1726+
1727+ if (!g_do_hash)
1728+ {
1729+ exec_error--;
1730+ return 0;
1731+ }
1732+#ifdef NSIS_CONFIG_CRC_ANAL
1733+ size.LowPart = GetFileSize(g_dbex_hFile, &size.HighPart);
1734+ if (INVALID_FILE_SIZE == size.LowPart || GetLastError())
1735+ return 0;
1736+#else
1737+ size.QuadPart = g_ex_length.QuadPart;
1738+#endif
1739+ XXH32_reset(&state, 0);
1740+ left = size.QuadPart;
1741+ while (left > 0)
1742+ {
1743+ static char temp[32768];
1744+ DWORD l = (DWORD)(min(left, 32768));
1745+ if (!ReadExternalFile(temp, l)) break;
1746+ XXH32_update(&state, temp, l);
1747+ left -= l;
1748+ }
1749+ fhash = XXH32_digest(&state);
1750+ if (fhash == g_hash)
1751+#endif
1752+ exec_error--;
1753+#ifdef NSIS_CONFIG_CRC_SUPPORT
1754+ else
1755+ CloseHandle(g_dbex_hFile), g_dbex_hFile = INVALID_HANDLE_VALUE;
1756+#endif
1757+ }
1758+ }
1759+ }
1760+ break;
1761+#endif//NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1762 #endif//NSIS_SUPPORT_FILE
1763 #ifdef NSIS_SUPPORT_DELETE
1764 case EW_DELETEFILE:
1765@@ -1246,7 +1326,7 @@
1766 case EW_WRITEREG: // write registry value
1767 {
1768 HKEY hKey;
1769- int rootkey=parm0, type=parm4, rtype=parm5;
1770+ int rootkey=parm0, type=parm5, rtype=parm6;
1771 TCHAR *buf0=GetStringFromParm(0x02);
1772 TCHAR *buf1=GetStringFromParm(0x11);
1773 const TCHAR *rkn UNUSED=RegKeyHandleToName((HKEY)rootkey);
1774@@ -1281,8 +1361,18 @@
1775 TCHAR binbuf[128];
1776 LPCTSTR logf = rtype==REG_NONE?_T("WriteRegNone"):rtype==REG_MULTI_SZ?_T("WriteRegMultiStr"):_T("WriteRegBin");
1777 #endif
1778+ LARGE_INTEGER offset;
1779+ offset.LowPart = parm3;
1780+ offset.HighPart = parm4;
1781+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1782 // use buf2, buf3 and buf4
1783- size = GetCompressedDataFromDataBlockToMemory(parm3, data, (3 * NSIS_MAX_STRLEN)*sizeof(TCHAR));
1784+ if (g_is_stub_installer)
1785+ size = GetCompressedDataFromExeHeadToMemory(offset.QuadPart, data, (3 * NSIS_MAX_STRLEN)*sizeof(TCHAR), parm7);
1786+ else
1787+#endif
1788+ {
1789+ size = GetCompressedDataFromDataBlockToMemory(offset.QuadPart, data, (3 * NSIS_MAX_STRLEN)*sizeof(TCHAR), parm7);
1790+ }
1791 LogData2Hex(binbuf, COUNTOF(binbuf), data, size);
1792 log_printf6(_T("%s: \"%s\\%s\" \"%s\"=\"%s\""),logf,rkn,buf1,buf0,binbuf);
1793 }
1794@@ -1558,7 +1648,7 @@
1795 TCHAR *buf1=GetStringFromParm(-0x10);
1796
1797 if (!validpathspec(buf1))
1798- GetStringFromParm(-0x13);
1799+ GetStringFromParm(-0x14);
1800
1801 remove_ro_attr(buf1);
1802 hFile=myOpenFile(buf1,GENERIC_WRITE,CREATE_ALWAYS);
1803@@ -1572,12 +1662,25 @@
1804 SetSelfFilePointer(0);
1805 ReadSelfFile((char*)filebuf,filehdrsize);
1806 {
1807- // parm1 = uninstdata_offset
1808- // parm2 = m_unicon_size
1809+ // parm1 = low_uninstdata_offset
1810+ // parm2 = high_uninstdata_offset
1811+ // parm3 = m_unicon_size
1812+ // parm5 = icon crc
1813+ // parm6 = data crc
1814 unsigned char* seeker;
1815- unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2);
1816+ unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm3);
1817 if (unicon_data) {
1818- GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2);
1819+ LARGE_INTEGER offset;
1820+ offset.LowPart = parm1;
1821+ offset.HighPart = parm2;
1822+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1823+ if (g_is_stub_installer)
1824+ GetCompressedDataFromExeHeadToMemory(offset.QuadPart,unicon_data,parm3,parm5);
1825+ else
1826+#endif
1827+ {
1828+ GetCompressedDataFromDataBlockToMemory(offset.QuadPart,unicon_data,parm3,parm5);
1829+ }
1830 while (*seeker) {
1831 struct icondata {
1832 DWORD dwSize;
1833@@ -1592,7 +1695,16 @@
1834 }
1835 myWriteFile(hFile,(char*)filebuf,filehdrsize);
1836 GlobalFree(filebuf);
1837- ret=GetCompressedDataFromDataBlock(-1,hFile);
1838+ {
1839+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1840+ if (g_is_stub_installer)
1841+ ret=GetCompressedDataFromExeHead(-1,hFile,parm6);
1842+ else
1843+#endif
1844+ {
1845+ ret=GetCompressedDataFromDataBlock(-1,hFile,parm6);
1846+ }
1847+ }
1848 }
1849 CloseHandle(hFile);
1850 }
1851Index: Source/exehead/fileform.c
1852===================================================================
1853--- Source/exehead/fileform.c (revision 7070)
1854+++ Source/exehead/fileform.c (working copy)
1855@@ -25,6 +25,7 @@
1856 #include "ui.h"
1857 #include "exec.h"
1858 #include "../crc32.h"
1859+#include "../xxhash.h"
1860 #include "../tchar.h"
1861
1862 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
1863@@ -32,6 +33,16 @@
1864 #include "../zlib/ZLIB.H"
1865 #endif
1866
1867+#ifdef NSIS_COMPRESS_USE_LZ4
1868+#include "../lz4/lz4decompress.h"
1869+#define z_stream lz4_decstream
1870+#define inflateInit(x) lz4Init(x)
1871+#define inflateReset(x) lz4Init(x)
1872+#define inflate(x) lz4Decode(x)
1873+#define Z_OK LZ4_OK
1874+#define Z_STREAM_END LZ4_STREAM_END
1875+#endif
1876+
1877 #ifdef NSIS_COMPRESS_USE_LZMA
1878 #include "../7zip/LZMADecode.h"
1879 #define z_stream lzma_stream
1880@@ -60,18 +71,35 @@
1881 int g_flags;
1882 int g_filehdrsize;
1883 int g_is_uninstaller;
1884+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1885+int g_has_external_file;
1886+int g_is_stub_installer;
1887+//int _fltused = 0;
1888+#ifdef NSIS_CONFIG_CRC_SUPPORT
1889+XXH32_hash_t g_hash;
1890+int g_do_hash;
1891+#endif //NSIS_CONFIG_CRC_SUPPORT
1892+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1893
1894 HANDLE g_db_hFile=INVALID_HANDLE_VALUE;
1895+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1896+HANDLE g_dbex_hFile=INVALID_HANDLE_VALUE;
1897+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1898
1899 #if defined(NSIS_CONFIG_COMPRESSION_SUPPORT) && defined(NSIS_COMPRESS_WHOLE)
1900 HANDLE dbd_hFile=INVALID_HANDLE_VALUE;
1901-static int dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen;
1902+static DWORD dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen;
1903 #endif//NSIS_COMPRESS_WHOLE
1904
1905-static int m_length;
1906-static int m_pos;
1907+static DWORD m_length;
1908+static DWORD m_pos;
1909+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1910+static LARGE_INTEGER m_ex_length;
1911+LARGE_INTEGER g_ex_length;
1912+static LARGE_INTEGER m_ex_pos;
1913+#endif
1914
1915-#define _calc_percent() (MulDiv(min(m_pos,m_length),100,m_length))
1916+#define _calc_percent() (MulDiv(min(m_pos>>1,m_length>>1),100,m_length>>1))
1917 #ifdef NSIS_COMPRESS_WHOLE
1918 static int NSISCALL calc_percent()
1919 {
1920@@ -78,8 +106,36 @@
1921 return _calc_percent();
1922 }
1923 #else
1924-#define calc_percent() _calc_percent()
1925+static int NSISCALL calc_percent()
1926+{
1927+ int ret;
1928+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1929+ if (m_pos >= m_length - sizeof(crc32_t))
1930+ {
1931+ DWORD this_pos, this_len;
1932+
1933+ if (m_ex_length.HighPart)
1934+ {
1935+ this_len = (DWORD)(m_ex_length.HighPart << 6);
1936+ this_len |= (DWORD)(m_ex_length.LowPart >> 26);
1937+ this_pos = (DWORD)(m_ex_pos.HighPart << 6);
1938+ this_pos |= (DWORD)(m_ex_pos.LowPart >> 26);
1939+ }
1940+ else
1941+ {
1942+ this_len = m_ex_length.LowPart;
1943+ this_pos = m_ex_pos.LowPart;
1944+ }
1945+ ret = MulDiv(min(this_pos>>1,this_len>>1),100,this_len>>1);
1946+ }
1947+ else
1948 #endif
1949+ {
1950+ ret = MulDiv(min(m_pos>>1,m_length>>1),100,m_length>>1);
1951+ }
1952+ return ret;
1953+}
1954+#endif
1955
1956 #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
1957 #if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_COMPRESS_WHOLE)
1958@@ -159,7 +215,7 @@
1959
1960 const TCHAR * NSISCALL loadHeaders(int cl_flags)
1961 {
1962- int left;
1963+ DWORD length_of_all_following_data, left;
1964 #ifdef NSIS_CONFIG_CRC_SUPPORT
1965 crc32_t crc = 0;
1966 int do_crc = 0;
1967@@ -172,7 +228,11 @@
1968 HANDLE db_hFile;
1969
1970 #ifdef C_ASSERT
1971+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1972+{C_ASSERT(sizeof(firstheader) == sizeof(int) * 9);}
1973+#else
1974 {C_ASSERT(sizeof(firstheader) == sizeof(int) * 7);}
1975+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1976 {C_ASSERT(sizeof(struct block_header) == sizeof(UINT_PTR) + sizeof(int));}
1977 #endif
1978
1979@@ -182,6 +242,13 @@
1980 #endif
1981 #endif//NSIS_CONFIG_CRC_SUPPORT
1982
1983+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1984+ g_has_external_file = 0;
1985+#ifdef NSIS_CONFIG_CRC_SUPPORT
1986+ g_do_hash = 0;
1987+#endif//NSIS_CONFIG_CRC_SUPPORT
1988+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
1989+
1990 GetModuleFileName(NULL, state_exe_path, NSIS_MAX_STRLEN);
1991
1992 g_db_hFile = db_hFile = myOpenFile(state_exe_path, GENERIC_READ, OPEN_EXISTING);
1993@@ -193,11 +260,11 @@
1994 mystrcpy(state_exe_directory, state_exe_path);
1995 mystrcpy(state_exe_file, trimslashtoend(state_exe_directory));
1996
1997- left = m_length = GetFileSize(db_hFile,NULL);
1998+ left = m_length = GetFileSize(db_hFile, NULL);
1999 while (left > 0)
2000 {
2001 static char temp[32768];
2002- DWORD l = min(left, (g_filehdrsize ? 32768 : 512));
2003+ DWORD l = min(left, (DWORD)(g_filehdrsize ? 32768 : 512));
2004 if (!ReadSelfFile(temp, l))
2005 {
2006 #if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT)
2007@@ -227,7 +294,8 @@
2008 g_exec_flags.silent |= cl_flags & FH_FLAGS_SILENT;
2009 #endif
2010
2011- if (h.length_of_all_following_data > left)
2012+ length_of_all_following_data = (DWORD)h.length_of_all_following_data;
2013+ if (length_of_all_following_data > left)
2014 return _LANG_INVALIDCRC;
2015
2016 #ifdef NSIS_CONFIG_CRC_SUPPORT
2017@@ -238,15 +306,17 @@
2018 }
2019
2020 do_crc++;
2021-
2022+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2023+ g_do_hash++;
2024+#endif
2025 #ifndef NSIS_CONFIG_CRC_ANAL
2026- left = h.length_of_all_following_data - 4;
2027+ left = length_of_all_following_data - 4;
2028 // end crc checking at crc :) this means you can tack stuff on the end and it'll still work.
2029 #else //!NSIS_CONFIG_CRC_ANAL
2030 left -= 4;
2031 #endif//NSIS_CONFIG_CRC_ANAL
2032 // this is in case the end part is < 512 bytes.
2033- if (l > (DWORD)left) l=(DWORD)left;
2034+ if (l > left) l = left;
2035
2036 #else//!NSIS_CONFIG_CRC_SUPPORT
2037 // no crc support, no need to keep on reading
2038@@ -275,6 +345,35 @@
2039 m_pos += l;
2040 left -= l;
2041 }
2042+#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
2043+ if (h.flags & FH_FLAGS_UNINSTALL)
2044+ g_is_uninstaller++;
2045+#endif
2046+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2047+ if (h.flags & FH_FLAGS_HAS_EXTERNAL_FILE)
2048+ g_has_external_file++;
2049+
2050+ if (h.flags & FH_FLAGS_IS_STUB_INSTALLER)
2051+ g_is_stub_installer++;
2052+
2053+ if (g_has_external_file && !g_is_uninstaller)
2054+ {
2055+ TCHAR path_ext[NSIS_MAX_STRLEN];
2056+ LARGE_INTEGER off;
2057+
2058+ off.LowPart = h.datablock_lowpart;
2059+ off.HighPart = h.datablock_highpart;
2060+ g_ex_length.QuadPart = off.QuadPart;
2061+
2062+ mystrcpy(path_ext, state_exe_path);
2063+ mystrcpy(path_ext, trimextension(path_ext));
2064+ wsprintf(path_ext, _T("%s.nsisbin"), path_ext);
2065+ g_dbex_hFile = myOpenFile(path_ext, GENERIC_READ, OPEN_EXISTING);
2066+ if (g_dbex_hFile == INVALID_HANDLE_VALUE && !g_is_stub_installer)
2067+ return _LANG_INVALIDCRC;
2068+ }
2069+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2070+
2071 #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
2072 #ifdef NSIS_CONFIG_CRC_SUPPORT
2073 handle_ver_dlg(TRUE);
2074@@ -286,10 +385,64 @@
2075 #ifdef NSIS_CONFIG_CRC_SUPPORT
2076 if (do_crc)
2077 {
2078- crc32_t fcrc;
2079- SetSelfFilePointer(m_pos);
2080- if (!ReadSelfFile(&fcrc, sizeof(crc32_t)) || crc != fcrc)
2081- return _LANG_INVALIDCRC;
2082+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2083+ if (g_has_external_file && g_is_stub_installer && !g_is_uninstaller)
2084+ {
2085+ SetSelfFilePointer(m_pos - sizeof(XXH32_hash_t));
2086+ if (!ReadSelfFile(&g_hash, sizeof(XXH32_hash_t)))
2087+ return _LANG_INVALIDCRC;
2088+
2089+ if (g_dbex_hFile != INVALID_HANDLE_VALUE)
2090+ {
2091+ XXH32_hash_t ehash = 0;
2092+ XXH32_state_t state;
2093+ UINT64 left;
2094+
2095+#ifdef NSIS_CONFIG_CRC_ANAL
2096+ {
2097+ ULARGE_INTEGER size;
2098+ size.LowPart = GetFileSize(g_dbex_hFile, &size.HighPart);
2099+ if (INVALID_FILE_SIZE == size.LowPart || GetLastError())
2100+ return _LANG_INVALIDCRC;
2101+ left = m_ex_length.QuadPart = size.QuadPart;
2102+ }
2103+#else
2104+ left = m_ex_length.QuadPart = g_ex_length.QuadPart;
2105+#endif//NSIS_CONFIG_CRC_ANAL
2106+ XXH32_reset(&state, 0);
2107+ while (left > 0)
2108+ {
2109+ static char temp[32768];
2110+ DWORD l = (DWORD)(min(left, 32768));
2111+ if (!ReadExternalFile(temp, l))
2112+ return _LANG_INVALIDCRC;
2113+#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
2114+#ifdef NSIS_CONFIG_SILENT_SUPPORT
2115+ if ((cl_flags & FH_FLAGS_SILENT) == 0)
2116+#endif//NSIS_CONFIG_SILENT_SUPPORT
2117+ {
2118+ handle_ver_dlg(FALSE);
2119+ }
2120+#endif//NSIS_CONFIG_VISIBLE_SUPPORT
2121+ XXH32_update(&state, temp, l);
2122+ m_ex_pos.QuadPart += l;
2123+ left -= l;
2124+ }
2125+#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
2126+ handle_ver_dlg(TRUE);
2127+#endif//NSIS_CONFIG_VISIBLE_SUPPORT
2128+ ehash = XXH32_digest(&state);
2129+ if (g_hash != ehash)
2130+ return _LANG_INVALIDCRC;
2131+ }
2132+ }
2133+#endif//NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2134+ {
2135+ crc32_t fcrc;
2136+ SetSelfFilePointer(m_pos);
2137+ if (!ReadSelfFile(&fcrc, sizeof(crc32_t)) || crc != fcrc)
2138+ return _LANG_INVALIDCRC;
2139+ }
2140 }
2141 #endif//NSIS_CONFIG_CRC_SUPPORT
2142
2143@@ -315,20 +468,13 @@
2144 SetSelfFilePointer(g_filehdrsize + sizeof(firstheader));
2145 #endif//NSIS_COMPRESS_WHOLE
2146
2147- if (GetCompressedDataFromDataBlockToMemory(-1, data, h.length_of_header) != h.length_of_header)
2148- {
2149+ if (GetCompressedDataFromExeHeadToMemory(-1, data, h.length_of_header, 0) != h.length_of_header)
2150 return _LANG_INVALIDCRC;
2151- }
2152
2153 header = g_header = data;
2154
2155 g_flags = header->flags;
2156
2157-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
2158- if (h.flags & FH_FLAGS_UNINSTALL)
2159- g_is_uninstaller++;
2160-#endif
2161-
2162 // set offsets to real memory offsets rather than installer's header offset
2163 left = BLOCKS_NUM;
2164 while (left--)
2165@@ -343,7 +489,7 @@
2166 #ifdef NSIS_COMPRESS_WHOLE
2167 header->blocks[NB_DATA].offset = dbd_pos;
2168 #else
2169- header->blocks[NB_DATA].offset = SetFilePointer(db_hFile,0,NULL,FILE_CURRENT);
2170+ header->blocks[NB_DATA].offset = (UINT_PTR)((UINT64)SetFilePointer64(db_hFile, 0, FILE_CURRENT));
2171 #endif
2172
2173 mini_memcpy(&g_blocks, &header->blocks, sizeof(g_blocks));
2174@@ -358,8 +504,39 @@
2175
2176 #if !defined(NSIS_COMPRESS_WHOLE) || !defined(NSIS_CONFIG_COMPRESSION_SUPPORT)
2177
2178+int myReadFileData(LPVOID buffer, const int len, const int exehead_only)
2179+{
2180+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2181+ if (g_has_external_file && !exehead_only)
2182+ {
2183+ if (!ReadExternalFile(buffer, len)) return 0;
2184+ }
2185+ else
2186+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2187+ {
2188+ if (!ReadSelfFile(buffer, len)) return 0;
2189+ }
2190+ return 1;
2191+}
2192+
2193+void mySetFilePointer(INT64 offset, int exehead_only)
2194+{
2195+ if (offset < 0) return;
2196+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2197+ if (g_has_external_file && !exehead_only)
2198+ {
2199+ SetExternalFilePointer(offset);
2200+ }
2201+ else
2202+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2203+ {
2204+ offset += g_blocks[NB_DATA].offset;
2205+ SetSelfFilePointer64(offset);
2206+ }
2207+}
2208+
2209 // Decompress data.
2210-int NSISCALL _dodecomp(int offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen)
2211+int NSISCALL _dodecomp(int exehead_only, INT64 offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen, crc32_t ex_crc)
2212 {
2213 static char inbuffer[IBUFSIZE+OBUFSIZE];
2214 char *outbuffer;
2215@@ -366,21 +543,17 @@
2216 int outbuffer_len=outbuf?outbuflen:OBUFSIZE;
2217 int retval=0;
2218 int input_len;
2219+#ifdef NSIS_CONFIG_CRC_SUPPORT
2220+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2221+ crc32_t crc = 0;
2222+#endif
2223+#endif
2224
2225 outbuffer = outbuf?(char*)outbuf:(inbuffer+IBUFSIZE);
2226
2227- if (offset>=0)
2228- {
2229- UINT_PTR datofs=g_blocks[NB_DATA].offset+offset;
2230-#if (NSIS_MAX_EXESIZE+0) > 0x7fffffff
2231-#error "SetFilePointer is documented to only support signed 32-bit offsets in lDistanceToMove"
2232-#endif
2233- const int pos=(int)datofs;
2234- SetSelfFilePointer(pos);
2235- }
2236+ mySetFilePointer(offset, exehead_only);
2237+ if (!myReadFileData((LPVOID)&input_len, sizeof(int), exehead_only)) return -3;
2238
2239- if (!ReadSelfFile((LPVOID)&input_len,sizeof(int))) return -3;
2240-
2241 #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
2242 if (input_len & 0x80000000) // compressed
2243 {
2244@@ -396,9 +569,12 @@
2245 int l=min(input_len,IBUFSIZE);
2246 int err;
2247
2248- if (!ReadSelfFile((LPVOID)inbuffer,l))
2249- return -3;
2250-
2251+ if (!myReadFileData((LPVOID)inbuffer,l,exehead_only)) return -3;
2252+#ifdef NSIS_CONFIG_CRC_SUPPORT
2253+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2254+ if (!exehead_only && g_has_external_file && !g_is_stub_installer) crc = CRC32(crc, (unsigned char*)inbuffer, l);
2255+#endif
2256+#endif
2257 g_inflate_stream.next_in = (unsigned char*) inbuffer;
2258 g_inflate_stream.avail_in = l;
2259 input_len-=l;
2260@@ -439,7 +615,15 @@
2261 outbuffer_len-=u;
2262 outbuffer=(char*)g_inflate_stream.next_out;
2263 }
2264- if (err==Z_STREAM_END) return retval;
2265+ if (err==Z_STREAM_END)
2266+ {
2267+#ifdef NSIS_CONFIG_CRC_SUPPORT
2268+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2269+ if (!exehead_only && g_has_external_file && !g_is_stub_installer && crc != ex_crc) return -3;
2270+#endif
2271+#endif
2272+ return retval;
2273+ }
2274 }
2275 }
2276 }
2277@@ -451,7 +635,12 @@
2278 while (input_len > 0)
2279 {
2280 DWORD l=min(input_len,outbuffer_len);
2281- if (!ReadSelfFile((LPVOID)inbuffer,l)) return -3;
2282+ if (!myReadFileData((LPVOID)inbuffer,l,exehead_only)) return -3;
2283+#ifdef NSIS_CONFIG_CRC_SUPPORT
2284+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2285+ if (!exehead_only && g_has_external_file && !g_is_stub_installer) crc = CRC32(crc, (unsigned char*)inbuffer, l);
2286+#endif
2287+#endif
2288 if (!myWriteFile(hFileOut,inbuffer,l)) return -2;
2289 retval+=l;
2290 input_len-=l;
2291@@ -460,10 +649,20 @@
2292 else
2293 {
2294 int l=min(input_len,outbuflen);
2295- if (!ReadSelfFile((LPVOID)outbuf,l)) return -3;
2296+ if (!myReadFileData((LPVOID)outbuf,l,exehead_only)) return -3;
2297+#ifdef NSIS_CONFIG_CRC_SUPPORT
2298+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2299+ if (!exehead_only && g_has_external_file && !g_is_stub_installer) crc = CRC32(crc, outbuf, l);
2300+#endif
2301+#endif
2302 retval=l;
2303 }
2304 }
2305+#ifdef NSIS_CONFIG_CRC_SUPPORT
2306+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2307+ if (!exehead_only && g_has_external_file && !g_is_stub_installer && crc != ex_crc) return -3;
2308+#endif
2309+#endif
2310 return retval;
2311 }
2312 #else//NSIS_COMPRESS_WHOLE
2313@@ -470,11 +669,11 @@
2314
2315 static char _inbuffer[IBUFSIZE];
2316 static char _outbuffer[OBUFSIZE];
2317-extern int m_length;
2318-extern int m_pos;
2319+extern DWORD m_length;
2320+extern DWORD m_pos;
2321 extern INT_PTR CALLBACK verProc(HWND, UINT, WPARAM, LPARAM);
2322 extern INT_PTR CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
2323-static int NSISCALL __ensuredata(int amount)
2324+static int NSISCALL __ensuredata(DWORD amount)
2325 {
2326 int needed=amount-(dbd_size-dbd_pos);
2327 #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
2328@@ -482,14 +681,14 @@
2329 #endif
2330 if (needed>0)
2331 {
2332- SetSelfFilePointer(dbd_srcpos);
2333- SetFilePointer(dbd_hFile,dbd_size,NULL,FILE_BEGIN);
2334+ SetSelfFilePointer64(dbd_srcpos);
2335+ SetFilePointer64(dbd_hFile, dbd_size, FILE_BEGIN);
2336 m_length=needed;
2337 m_pos=0;
2338 for (;;)
2339 {
2340 int err;
2341- int l=min(IBUFSIZE,dbd_fulllen-dbd_srcpos);
2342+ DWORD l=min(IBUFSIZE,dbd_fulllen-dbd_srcpos);
2343 if (!ReadSelfFile((LPVOID)_inbuffer,l)) return -1;
2344 dbd_srcpos+=l;
2345 g_inflate_stream.next_in=(unsigned char*)_inbuffer;
2346@@ -528,9 +727,9 @@
2347 else break;
2348 }
2349 while (g_inflate_stream.avail_in);
2350- if (amount-(dbd_size-dbd_pos) <= 0) break;
2351+ if ((int)(amount-(dbd_size-dbd_pos)) <= 0) break;
2352 }
2353- SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN);
2354+ SetFilePointer64(dbd_hFile, dbd_pos, FILE_BEGIN);
2355 }
2356 #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
2357 handle_ver_dlg(TRUE);
2358@@ -539,19 +738,19 @@
2359 }
2360
2361
2362-int NSISCALL _dodecomp(int offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen)
2363+int NSISCALL _dodecomp(int exehead_only, INT64 offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen, crc32_t ex_crc)
2364 {
2365 DWORD r;
2366 int input_len;
2367 int retval;
2368- if (offset>=0)
2369+ if (offset >= 0)
2370 {
2371- UINT_PTR datofs=g_blocks[NB_DATA].offset+offset;
2372+ INT64 datofs = g_blocks[NB_DATA].offset+offset;
2373 #if (NSIS_MAX_EXESIZE+0) > 0x7fffffff
2374 #error "SetFilePointer is documented to only support signed 32-bit offsets in lDistanceToMove"
2375 #endif
2376- dbd_pos=(int)datofs;
2377- SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN);
2378+ dbd_pos=(DWORD)datofs;
2379+ SetFilePointer64(dbd_hFile, datofs, FILE_BEGIN);
2380 }
2381 retval=__ensuredata(sizeof(int));
2382 if (retval<0) return retval;
2383@@ -589,7 +788,37 @@
2384 return myReadFile(g_db_hFile,lpBuffer,nNumberOfBytesToRead);
2385 }
2386
2387+INT64 NSISCALL SetFilePointer64(HANDLE handle, INT64 lDistanceToMove, DWORD flags)
2388+{
2389+ LARGE_INTEGER liDistanceToMove;
2390+ liDistanceToMove.QuadPart = lDistanceToMove;
2391+ liDistanceToMove.LowPart = SetFilePointer(handle, liDistanceToMove.LowPart, &liDistanceToMove.HighPart, flags);
2392+ if (liDistanceToMove.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
2393+ {
2394+ liDistanceToMove.QuadPart = -1;
2395+ }
2396+ return liDistanceToMove.QuadPart;
2397+}
2398+
2399 DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove)
2400 {
2401- return SetFilePointer(g_db_hFile,lDistanceToMove,NULL,FILE_BEGIN);
2402+ LARGE_INTEGER liDistanceToMove;
2403+ liDistanceToMove.QuadPart = SetFilePointer64(g_db_hFile, lDistanceToMove, FILE_BEGIN);
2404+ return liDistanceToMove.LowPart;
2405 }
2406+INT64 NSISCALL SetSelfFilePointer64(INT64 lDistanceToMove)
2407+{
2408+ return SetFilePointer64(g_db_hFile, lDistanceToMove, FILE_BEGIN);
2409+}
2410+
2411+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2412+BOOL NSISCALL ReadExternalFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead)
2413+{
2414+ return myReadFile(g_dbex_hFile, lpBuffer, nNumberOfBytesToRead);
2415+}
2416+
2417+INT64 NSISCALL SetExternalFilePointer(INT64 lDistanceToMove)
2418+{
2419+ return SetFilePointer64(g_dbex_hFile, lDistanceToMove, FILE_BEGIN);
2420+}
2421+#endif
2422Index: Source/exehead/fileform.h
2423===================================================================
2424--- Source/exehead/fileform.h (revision 7070)
2425+++ Source/exehead/fileform.h (working copy)
2426@@ -18,6 +18,8 @@
2427
2428 #include "config.h"
2429 #include "../Platform.h"
2430+#include "../crc32.h"
2431+#include "../xxhash.h"
2432
2433 #ifndef _FILEFORM_H_
2434 #define _FILEFORM_H_
2435@@ -41,9 +43,8 @@
2436 // headers + datablock is at least 512 bytes if CRC enabled
2437
2438
2439-#define MAX_ENTRY_OFFSETS 6
2440+#define MAX_ENTRY_OFFSETS 8
2441
2442-
2443 // if you want people to not be able to decompile your installers as easily,
2444 // reorder the lines following EW_INVALID_OPCODE randomly.
2445
2446@@ -75,9 +76,14 @@
2447 EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir]
2448 #endif
2449 #ifdef NSIS_SUPPORT_FILE
2450- EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]
2451+ EW_EXTRACTFILE, // File to extract: 8 [overwriteflag, output filename, compressed filedata low, compressed filedata high, filedatetimelow, filedatetimehigh, allow ignore, crc]
2452 // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
2453+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2454+ EW_EXTRACTSTUBFILE, // File to extract: 8 [overwriteflag, output filename, compressed filedata low, compressed filedata high, filedatetimelow, filedatetimehigh, allow ignore, crc]
2455+ // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
2456+ EW_VERIFYEXTERNALFILE,// VerifyExternalFile: 1 [path_to_file]
2457 #endif
2458+#endif
2459 #ifdef NSIS_SUPPORT_DELETE
2460 EW_DELETEFILE, // Delete File: 2, [filename, rebootok]
2461 #endif
2462@@ -156,7 +162,7 @@
2463
2464 #ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
2465 EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, ActionAndFlags(DELREG*)]
2466- EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]
2467+ EW_WRITEREG, // Write Registry value: 7, [RootKey(int),KeyName,ItemName,ItemDataLow,[ItemDataHigh],typelen,[crc]]
2468 // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str
2469 EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]
2470 EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]
2471@@ -177,7 +183,7 @@
2472 #endif
2473
2474 #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
2475- EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size]
2476+ EW_WRITEUNINSTALLER, // WriteUninstaller: 6 [name, offsetlow, offsethigh, icon_size, crc icons, crc data]
2477 #endif
2478
2479 #ifdef NSIS_CONFIG_LOG
2480@@ -211,7 +217,11 @@
2481
2482 #pragma pack(push, 1) // fileform.cpp assumes no padding/alignment
2483
2484-#define FH_FLAGS_MASK 15
2485+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2486+# define FH_FLAGS_MASK 255
2487+#else
2488+# define FH_FLAGS_MASK 31
2489+#endif
2490 #define FH_FLAGS_UNINSTALL 1
2491 #ifdef NSIS_CONFIG_SILENT_SUPPORT
2492 # define FH_FLAGS_SILENT 2
2493@@ -220,6 +230,12 @@
2494 # define FH_FLAGS_NO_CRC 4
2495 # define FH_FLAGS_FORCE_CRC 8
2496 #endif
2497+#define FH_FLAGS_LONG_DB_OFFSET 16
2498+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2499+# define FH_FLAGS_EXTERNAL_FILE_SUPPORT 32
2500+# define FH_FLAGS_HAS_EXTERNAL_FILE 64
2501+# define FH_FLAGS_IS_STUB_INSTALLER 128
2502+#endif
2503
2504 #define FH_SIG 0xDEADBEEF
2505
2506@@ -240,6 +256,13 @@
2507
2508 // this specifies the length of all the data (including the firstheader and CRC)
2509 int length_of_all_following_data;
2510+
2511+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2512+ // this specifies the length of the datablock
2513+ // nsisbi versions before 3.04.1 stored the external flag in the top bit of the high part
2514+ int datablock_lowpart;
2515+ int datablock_highpart;
2516+#endif
2517 } firstheader;
2518
2519 // Flags for common_header.flags
2520@@ -583,22 +606,47 @@
2521 // (or m_uninstheader)
2522 const TCHAR * NSISCALL loadHeaders(int cl_flags);
2523
2524-int NSISCALL _dodecomp(int offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen);
2525+int NSISCALL _dodecomp(int exehead_only, INT64 offset, HANDLE hFileOut, unsigned char *outbuf, int outbuflen, crc32_t ex_crc);
2526
2527-#define GetCompressedDataFromDataBlock(offset, hFileOut) _dodecomp(offset,hFileOut,NULL,0)
2528-#define GetCompressedDataFromDataBlockToMemory(offset, out, out_len) _dodecomp(offset,NULL,out,out_len)
2529+enum {
2530+ DATALOC_DATABLOCK = 0,
2531+ DATALOC_EXEHEAD,
2532+};
2533
2534+#define GetCompressedDataFromDataBlock(offset, hFileOut, crc) _dodecomp(DATALOC_DATABLOCK,offset,hFileOut,NULL,0,crc)
2535+#define GetCompressedDataFromDataBlockToMemory(offset, out, out_len, crc) _dodecomp(DATALOC_DATABLOCK,offset,NULL,out,out_len, crc)
2536+#define GetCompressedDataFromExeHead(offset, hFileOut, crc) _dodecomp(DATALOC_EXEHEAD,offset,hFileOut,NULL,0,crc)
2537+#define GetCompressedDataFromExeHeadToMemory(offset, out, out_len, crc) _dodecomp(DATALOC_EXEHEAD,offset,NULL,out,out_len,crc)
2538+
2539 extern HANDLE g_db_hFile;
2540+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2541+extern HANDLE g_dbex_hFile;
2542+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2543 extern int g_quit_flag;
2544
2545 BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead);
2546+INT64 NSISCALL SetFilePointer64(HANDLE handle, INT64 lDistanceToMove, DWORD flags);
2547 DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove);
2548+INT64 NSISCALL SetSelfFilePointer64(INT64 lDistanceToMove);
2549
2550+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2551+BOOL NSISCALL ReadExternalFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead);
2552+INT64 NSISCALL SetExternalFilePointer(INT64 lDistanceToMove);
2553+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2554+
2555 extern struct block_header g_blocks[BLOCKS_NUM];
2556 extern header *g_header;
2557 extern int g_flags;
2558 extern int g_filehdrsize;
2559 extern int g_is_uninstaller;
2560+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2561+extern int g_has_external_file;
2562+extern int g_is_stub_installer;
2563+#ifdef NSIS_CONFIG_CRC_SUPPORT
2564+extern XXH32_hash_t g_hash;
2565+extern int g_do_hash;
2566+#endif //NSIS_CONFIG_CRC_SUPPORT
2567+#endif //NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2568
2569 #define g_pages ( (page*) g_blocks[NB_PAGES].offset )
2570 #define g_sections ( (section*) g_blocks[NB_SECTIONS].offset )
2571Index: Source/exehead/util.c
2572===================================================================
2573--- Source/exehead/util.c (revision 7070)
2574+++ Source/exehead/util.c (working copy)
2575@@ -347,6 +347,27 @@
2576 return p + 1;
2577 }
2578
2579+// Removes the extension off a filename.
2580+TCHAR * NSISCALL trimextension(TCHAR *buf)
2581+{
2582+ TCHAR *p = buf + mystrlen(buf);
2583+ do
2584+ {
2585+ if (*p == _T('.'))
2586+ break;
2587+ if (*p == _T('\\') || *p == _T('/'))
2588+ {
2589+ p = buf + mystrlen(buf); // security measure, stays in the current directory
2590+ break;
2591+ }
2592+ p = CharPrev(buf, p);
2593+ } while (p > buf);
2594+
2595+ *p = 0;
2596+
2597+ return buf;
2598+}
2599+
2600 int NSISCALL validpathspec(TCHAR *ubuf)
2601 {
2602 TCHAR dl = ubuf[0] | 0x20; // convert alleged drive letter to lower case
2603Index: Source/exehead/util.h
2604===================================================================
2605--- Source/exehead/util.h (revision 7070)
2606+++ Source/exehead/util.h (working copy)
2607@@ -122,6 +122,7 @@
2608 HANDLE NSISCALL myOpenFile(const TCHAR *fn, DWORD da, DWORD cd);
2609 int NSISCALL validpathspec(TCHAR *ubuf);
2610 TCHAR * NSISCALL addtrailingslash(TCHAR *str);
2611+TCHAR * NSISCALL trimextension(TCHAR *buf);
2612 //TCHAR NSISCALL lastchar(const TCHAR *str);
2613 #define lastchar(str) *CharPrev(str,str+mystrlen(str))
2614 TCHAR * NSISCALL findchar(TCHAR *str, TCHAR c);
2615Index: Source/fileform.cpp
2616===================================================================
2617--- Source/fileform.cpp (revision 7070)
2618+++ Source/fileform.cpp (working copy)
2619@@ -31,6 +31,10 @@
2620 m_sink->write_int_array(data->nsinst, 3);
2621 m_sink->write_int(data->length_of_header);
2622 m_sink->write_int(data->length_of_all_following_data);
2623+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
2624+ m_sink->write_int(data->datablock_lowpart);
2625+ m_sink->write_int(data->datablock_highpart);
2626+#endif
2627 }
2628
2629 void block_header_writer::write(const block_header *data, const writer_target_info&ti)
2630Index: Source/growbuf64.cpp
2631===================================================================
2632--- Source/growbuf64.cpp (revision 0)
2633+++ Source/growbuf64.cpp (working copy)
2634@@ -0,0 +1,110 @@
2635+/*
2636+ * growbuf64.cpp
2637+ *
2638+ * This file is a part of NSIS.
2639+ *
2640+ * Copyright (C) 1999-2018 Nullsoft and Contributors
2641+ *
2642+ * Licensed under the zlib/libpng license (the "License");
2643+ * you may not use this file except in compliance with the License.
2644+ *
2645+ * Licence details can be found in the file COPYING.
2646+ *
2647+ * This software is provided 'as-is', without any express or implied
2648+ * warranty.
2649+ *
2650+ * Unicode support and Doxygen comments by Jim Park -- 07/31/2007
2651+ */
2652+
2653+#include "Platform.h"
2654+#include "growbuf64.h"
2655+
2656+#include <cstdlib> // for malloc/free
2657+#include <cstring> // for memcpy
2658+#include <cstdio> // for f*
2659+#include <algorithm> // for std::min
2660+#include "tchar.h"
2661+#include "util.h"
2662+
2663+
2664+using namespace std;
2665+
2666+// Default constructor
2667+GrowBuf64::GrowBuf64() { m_alloc=m_used=0, m_zero=false, m_s=NULL, m_bs=32768; }
2668+
2669+// Destructor
2670+GrowBuf64::~GrowBuf64() { free(m_s); }
2671+
2672+void GrowBuf64::set_zeroing(bool zero) { m_zero=zero; }
2673+
2674+GrowBuf64::size_type GrowBuf64::add(const void *data, int len)
2675+{
2676+ if (len<=0) return 0; // BUGBUG: Why is this returning 0? It should return m_used?
2677+ resize(m_used+len);
2678+ memcpy((BYTE*)m_s+m_used-len,data,len);
2679+ return m_used-len;
2680+}
2681+
2682+void GrowBuf64::resize(GrowBuf64::size_type newlen)
2683+{
2684+ const size_type orgalloc=m_alloc;
2685+ const size_type orgused=m_used;
2686+
2687+ m_used=newlen;
2688+ if (newlen > m_alloc)
2689+ {
2690+ void *newstor;
2691+
2692+ // Jim Park: Not sure why we don't just add m_bs. Multiplying by 2
2693+ // makes m_bs meaningless after a few resizes. So TinyGrowBuf
2694+ // isn't very tiny.
2695+ m_alloc = newlen*2 + m_bs;
2696+ newstor = realloc(m_s, (size_t)m_alloc);
2697+ if (!newstor)
2698+ {
2699+ extern int g_display_errors;
2700+ if (g_display_errors)
2701+ {
2702+ PrintColorFmtMsg_ERR(_T("\nack! realloc(%d) failed, trying malloc(%d)!\n"),m_alloc,newlen);
2703+ }
2704+ m_alloc=newlen; // try to malloc the minimum needed
2705+ newstor=malloc((size_t)m_alloc);
2706+ if (!newstor)
2707+ {
2708+ extern void quit();
2709+ if (g_display_errors)
2710+ {
2711+ PrintColorFmtMsg_ERR(_T("\nInternal compiler error #12345: GrowBuf realloc/malloc(%d) failed.\n"),m_alloc);
2712+ }
2713+ quit();
2714+ }
2715+ memcpy(newstor,m_s,(size_t)min(newlen,orgalloc));
2716+ free(m_s);
2717+ }
2718+ m_s=newstor;
2719+ }
2720+
2721+ // Zero out the new buffer area
2722+ if (m_zero && m_used > orgused)
2723+ memset((BYTE*)m_s + orgused, 0, (size_t)(m_used - orgused));
2724+
2725+ if (!m_used && m_alloc > 2*m_bs) // only free if you resize to 0 and we're > 64k or
2726+ // 2K in the case of TinyGrowBuf
2727+ {
2728+ m_alloc=0;
2729+ free(m_s);
2730+ m_s=NULL;
2731+ }
2732+}
2733+
2734+GrowBuf64::size_type GrowBuf64::getlen() const { return m_used; }
2735+void *GrowBuf64::get() const { return m_s; }
2736+
2737+void GrowBuf64::swap(GrowBuf64&other)
2738+{
2739+ std::swap(m_s, other.m_s);
2740+ std::swap(m_alloc, other.m_alloc);
2741+ std::swap(m_used, other.m_used);
2742+ std::swap(m_zero, other.m_zero);
2743+ std::swap(m_bs, other.m_bs);
2744+}
2745Index: Source/growbuf64.h
2746===================================================================
2747--- Source/growbuf64.h (revision 0)
2748+++ Source/growbuf64.h (working copy)
2749@@ -0,0 +1,131 @@
2750+/*
2751+ * growbuf64.h
2752+ *
2753+ * This file is a part of NSIS.
2754+ *
2755+ * Copyright (C) 1999-2018 Nullsoft and Contributors
2756+ *
2757+ * Licensed under the zlib/libpng license (the "License");
2758+ * you may not use this file except in compliance with the License.
2759+ *
2760+ * Licence details can be found in the file COPYING.
2761+ *
2762+ * This software is provided 'as-is', without any express or implied
2763+ * warranty.
2764+ *
2765+ * Unicode support by Jim Park -- 08/22/2007
2766+ */
2767+
2768+#ifndef __GROWBUF64_H_
2769+#define __GROWBUF64_H_
2770+
2771+#include "Platform.h"
2772+
2773+/**
2774+ * IGrowBuf64 is the interface to a buffer that grows as you
2775+ * add to the buffer.
2776+ */
2777+class IGrowBuf64
2778+{
2779+ public:
2780+ typedef INT64 size_type;
2781+ static size_type getlimit() { return (size_type)0x7fffffffffffffff; }
2782+ virtual ~IGrowBuf64() {}
2783+
2784+ /**
2785+ * Add data to the buffer.
2786+ * @param data Pointer to the data to be stored.
2787+ * @param len Size of the data in bytes.
2788+ * @return the previous logical size in bytes before the addition.
2789+ */
2790+ virtual size_type add(const void *data, int len)=0;
2791+
2792+ /**
2793+ * Resizes the buffer to hold the number of bytes specified.
2794+ * @param newlen the desired logical size of the buffer.
2795+ */
2796+ virtual void resize(size_type newlen)=0;
2797+
2798+ /**
2799+ * Get the length of the logical buffer in bytes.
2800+ * @return the length in bytes
2801+ */
2802+ virtual size_type getlen() const=0;
2803+
2804+ /**
2805+ * Get the buffer itself.
2806+ * @return Void pointer to the buffer.
2807+ */
2808+ virtual void *get() const=0;
2809+};
2810+
2811+/**
2812+ * GrowBuf64 implements IGrowBuf64 and grows in 32K chunks.
2813+ */
2814+class GrowBuf64 : public IGrowBuf64
2815+{
2816+ private: // don't copy instances
2817+ GrowBuf64(const GrowBuf64&);
2818+ void operator=(const GrowBuf64&);
2819+
2820+ public:
2821+ GrowBuf64();
2822+ virtual ~GrowBuf64();
2823+
2824+ /**
2825+ * Set whether to zero out buffer
2826+ * @param zero A boolean value.
2827+ */
2828+ void set_zeroing(bool zero);
2829+
2830+ /**
2831+ * Add data to the buffer.
2832+ * @param data Pointer to the data to be stored.
2833+ * @param len Size of the data in bytes.
2834+ * @return the previous logical size in bytes before the addition.
2835+ */
2836+ size_type add(const void *data, int len);
2837+
2838+ /**
2839+ * Resizes the buffer to hold the number of bytes specified.
2840+ * Setting the newlen to 0 will cause the buffer to be at most
2841+ * 2*m_bs bytes long. (It will free the buffer if > 2*m_bs.)
2842+ * @param newlen the desired logical size of the buffer.
2843+ */
2844+ void resize(size_type newlen);
2845+
2846+ /**
2847+ * Get the length of the logical buffer in bytes.
2848+ * @return the length in bytes
2849+ */
2850+ size_type getlen() const;
2851+
2852+ /**
2853+ * Get the buffer itself.
2854+ * @return Void pointer to the buffer.
2855+ */
2856+ void *get() const;
2857+
2858+ void swap(GrowBuf64&other);
2859+
2860+ private:
2861+ void *m_s; /* the storage buffer */
2862+ size_type m_alloc; /* allocated bytes */
2863+ size_type m_used; /* how many bytes of the buffer is used? */
2864+ bool m_zero; /* should storage be zeroed out? */
2865+
2866+ protected:
2867+ unsigned short m_bs; // byte-size to grow by
2868+};
2869+
2870+/**
2871+ * TinyGrowBuf64 is a derived class that grows the buffer
2872+ * in tiny increments.
2873+ */
2874+class TinyGrowBuf64 : public GrowBuf64 {
2875+ public:
2876+ TinyGrowBuf64() : GrowBuf64() { m_bs=1024; }
2877+};
2878+
2879+#endif
2880+
2881Index: Source/lz4/lz4common.c
2882===================================================================
2883--- Source/lz4/lz4common.c (revision 0)
2884+++ Source/lz4/lz4common.c (working copy)
2885@@ -0,0 +1,319 @@
2886+/*
2887+ LZ4 - Fast LZ compression algorithm
2888+ Copyright (C) 2011-2015, Yann Collet.
2889+
2890+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
2891+
2892+ Redistribution and use in source and binary forms, with or without
2893+ modification, are permitted provided that the following conditions are
2894+ met:
2895+
2896+ * Redistributions of source code must retain the above copyright
2897+ notice, this list of conditions and the following disclaimer.
2898+ * Redistributions in binary form must reproduce the above
2899+ copyright notice, this list of conditions and the following disclaimer
2900+ in the documentation and/or other materials provided with the
2901+ distribution.
2902+
2903+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2904+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2905+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2906+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2907+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2908+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2909+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2910+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2911+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2912+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2913+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2914+
2915+ You can contact the author at :
2916+ - LZ4 source repository : https://github.com/Cyan4973/lz4
2917+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
2918+*/
2919+
2920+/*
2921+ * lz4common.c
2922+ *
2923+ * This file is a part of the LZ4 compression module for NSIS.
2924+ *
2925+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
2926+ *
2927+ * Licensed under the zlib/libpng license (the "License");
2928+ * you may not use this file except in compliance with the License.
2929+ *
2930+ * Licence details can be found in the file COPYING.
2931+ *
2932+ * This software is provided 'as-is', without any express or implied
2933+ * warranty.
2934+ */
2935+
2936+#include "lz4common.h"
2937+
2938+/**************************************
2939+* Compiler Options
2940+**************************************/
2941+#ifdef _MSC_VER /* Visual Studio */
2942+# define FORCE_INLINE static __forceinline
2943+# include <intrin.h>
2944+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
2945+# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
2946+#else
2947+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
2948+# if defined(__GNUC__) || defined(__clang__)
2949+# define FORCE_INLINE static inline __attribute__((always_inline))
2950+# else
2951+# define FORCE_INLINE static inline
2952+# endif
2953+# else
2954+# define FORCE_INLINE static
2955+# endif /* __STDC_VERSION__ */
2956+#endif /* _MSC_VER */
2957+
2958+
2959+#ifdef EXEHEAD
2960+void *MEM_INIT(void *mem, int c, size_t len)
2961+{
2962+ /*
2963+ ** Prevent MSVC 14.00.40310.41-AMD64 from generating a recursive call to memset
2964+ **
2965+ ** #pragma optimize("", off) + #pragma optimize("ty", on) can also
2966+ ** be used but it generates a lot more code.
2967+ */
2968+#if defined(_MSC_VER) && _MSC_VER > 1200 && _MSC_FULL_VER <= 140040310
2969+ volatile
2970+#endif
2971+ char *p=(char*)mem;
2972+ while (len-- > 0)
2973+ {
2974+ *p++=c;
2975+ }
2976+ return mem;
2977+}
2978+void *MEM_CPY(void *out, const void *in, size_t len)
2979+{
2980+ char *c_out=(char*)out;
2981+ char *c_in=(char *)in;
2982+ while (len-- > 0)
2983+ {
2984+ *c_out++=*c_in++;
2985+ }
2986+ return out;
2987+}
2988+void *MEM_MOVE(void *out, const void *in, size_t len)
2989+{
2990+ char *c_out=(char*)out + len;
2991+ char *c_in=(char *)in + len;
2992+ while (len-- > 0)
2993+ {
2994+ *c_out-- = *c_in--;
2995+ }
2996+ return out;
2997+}
2998+#endif
2999+
3000+#if defined(WIN32) && defined(EXEHEAD)
3001+#ifndef _aullshr
3002+int _aullshr = 0;
3003+#endif
3004+#ifndef _allmul
3005+int _allmul = 0;
3006+#endif
3007+#ifndef _chkstk
3008+int _chkstk = 0;
3009+#endif
3010+#endif
3011+
3012+int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
3013+
3014+
3015+/**************************************
3016+* Reading and writing into memory
3017+**************************************/
3018+
3019+unsigned LZ4_64bits(void) { return sizeof(void*)==8; }
3020+
3021+unsigned LZ4_isLittleEndian(void)
3022+{
3023+ const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
3024+ return one.c[0];
3025+}
3026+
3027+
3028+U16 LZ4_read16(const void* memPtr)
3029+{
3030+ U16 val16;
3031+ MEM_CPY(&val16, memPtr, 2);
3032+ return val16;
3033+}
3034+
3035+U16 LZ4_readLE16(const void* memPtr)
3036+{
3037+ if (LZ4_isLittleEndian())
3038+ {
3039+ return LZ4_read16(memPtr);
3040+ }
3041+ else
3042+ {
3043+ const BYTE* p = (const BYTE*)memPtr;
3044+ return (U16)((U16)p[0] + (p[1]<<8));
3045+ }
3046+}
3047+
3048+void LZ4_writeLE16(void* memPtr, U16 value)
3049+{
3050+ if (LZ4_isLittleEndian())
3051+ {
3052+ MEM_CPY(memPtr, &value, 2);
3053+ }
3054+ else
3055+ {
3056+ BYTE* p = (BYTE*)memPtr;
3057+ p[0] = (BYTE) value;
3058+ p[1] = (BYTE)(value>>8);
3059+ }
3060+}
3061+
3062+U32 LZ4_read32(const void* memPtr)
3063+{
3064+ U32 val32;
3065+ MEM_CPY(&val32, memPtr, 4);
3066+ return val32;
3067+}
3068+
3069+U64 LZ4_read64(const void* memPtr)
3070+{
3071+ U64 val64;
3072+ MEM_CPY(&val64, memPtr, 8);
3073+ return val64;
3074+}
3075+
3076+size_t LZ4_read_ARCH(const void* p)
3077+{
3078+ if (LZ4_64bits())
3079+ return (size_t)LZ4_read64(p);
3080+ else
3081+ return (size_t)LZ4_read32(p);
3082+}
3083+
3084+void LZ4_copy4(void* dstPtr, const void* srcPtr)
3085+{
3086+ MEM_CPY(dstPtr, srcPtr, 4);
3087+}
3088+
3089+void LZ4_copy8(void* dstPtr, const void* srcPtr)
3090+{
3091+ MEM_CPY(dstPtr, srcPtr, 8);
3092+}
3093+
3094+/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
3095+void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
3096+{
3097+ BYTE* d = (BYTE*)dstPtr;
3098+ const BYTE* s = (const BYTE*)srcPtr;
3099+ BYTE* e = (BYTE*)dstEnd;
3100+ do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
3101+}
3102+
3103+
3104+/**************************************
3105+* Common functions
3106+**************************************/
3107+unsigned LZ4_NbCommonBytes (register size_t val)
3108+{
3109+ if (LZ4_isLittleEndian())
3110+ {
3111+ if (LZ4_64bits())
3112+ {
3113+# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
3114+ unsigned long r = 0;
3115+ _BitScanForward64( &r, (U64)val );
3116+ return (int)(r>>3);
3117+# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
3118+ return (__builtin_ctzll((U64)val) >> 3);
3119+# else
3120+ static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
3121+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
3122+# endif
3123+ }
3124+ else /* 32 bits */
3125+ {
3126+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
3127+ unsigned long r;
3128+ _BitScanForward( &r, (U32)val );
3129+ return (int)(r>>3);
3130+# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
3131+ return (__builtin_ctz((U32)val) >> 3);
3132+# else
3133+ static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
3134+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
3135+# endif
3136+ }
3137+ }
3138+ else /* Big Endian CPU */
3139+ {
3140+ if (LZ4_64bits())
3141+ {
3142+# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
3143+ unsigned long r = 0;
3144+ _BitScanReverse64( &r, val );
3145+ return (unsigned)(r>>3);
3146+# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
3147+ return (__builtin_clzll((U64)val) >> 3);
3148+# else
3149+ unsigned r;
3150+ unsigned long long valshift = val;
3151+ if (!(valshift>>32)) { r=4; } else { r=0; val>>=16, val>>=16; }
3152+ if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
3153+ r += (!val);
3154+ return r;
3155+# endif
3156+ }
3157+ else /* 32 bits */
3158+ {
3159+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
3160+ unsigned long r = 0;
3161+ _BitScanReverse( &r, (unsigned long)val );
3162+ return (unsigned)(r>>3);
3163+# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
3164+ return (__builtin_clz((U32)val) >> 3);
3165+# else
3166+ unsigned r;
3167+ if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
3168+ r += (!val);
3169+ return r;
3170+# endif
3171+ }
3172+ }
3173+}
3174+
3175+unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
3176+{
3177+ const BYTE* const pStart = pIn;
3178+
3179+ while (likely(pIn<pInLimit-(STEPSIZE-1)))
3180+ {
3181+ size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
3182+ if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
3183+ pIn += LZ4_NbCommonBytes(diff);
3184+ return (unsigned)(pIn - pStart);
3185+ }
3186+
3187+ if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
3188+ if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
3189+ if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
3190+ return (unsigned)(pIn - pStart);
3191+}
3192+
3193+
3194+#ifndef LZ4_COMMONDEFS_ONLY
3195+/**************************************
3196+* Local Utils
3197+**************************************/
3198+int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
3199+
3200+#endif
3201+
3202+
3203+
3204+
3205Index: Source/lz4/lz4common.h
3206===================================================================
3207--- Source/lz4/lz4common.h (revision 0)
3208+++ Source/lz4/lz4common.h (working copy)
3209@@ -0,0 +1,292 @@
3210+/*
3211+ LZ4 - Fast LZ compression algorithm
3212+ Copyright (C) 2011-2015, Yann Collet.
3213+
3214+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
3215+
3216+ Redistribution and use in source and binary forms, with or without
3217+ modification, are permitted provided that the following conditions are
3218+ met:
3219+
3220+ * Redistributions of source code must retain the above copyright
3221+ notice, this list of conditions and the following disclaimer.
3222+ * Redistributions in binary form must reproduce the above
3223+ copyright notice, this list of conditions and the following disclaimer
3224+ in the documentation and/or other materials provided with the
3225+ distribution.
3226+
3227+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3228+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3229+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3230+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3231+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3232+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3233+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3234+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3235+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3236+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3237+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3238+
3239+ You can contact the author at :
3240+ - LZ4 source repository : https://github.com/Cyan4973/lz4
3241+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
3242+*/
3243+
3244+/*
3245+ * lz4common.h
3246+ *
3247+ * This file is a part of the LZ4 compression module for NSIS.
3248+ *
3249+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
3250+ *
3251+ * Licensed under the zlib/libpng license (the "License");
3252+ * you may not use this file except in compliance with the License.
3253+ *
3254+ * Licence details can be found in the file COPYING.
3255+ *
3256+ * This software is provided 'as-is', without any express or implied
3257+ * warranty.
3258+ */
3259+
3260+#ifndef __LZ4COMMON_H
3261+#define __LZ4COMMON_H
3262+
3263+#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
3264+#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
3265+
3266+#define LZ4_STREAM_END 1
3267+#define LZ4_OK 0
3268+#define LZ4_DATA_ERROR -2
3269+/* we don't really care what the problem is... */
3270+#define LZ4_NOT_ENOUGH_MEM -2
3271+
3272+#define LZ4_BLOCK_HEADER_SIZE 3
3273+#define LZ4_BLOCK_DATA_SIZE (65536)
3274+#if LZ4_BLOCK_DATA_SIZE > (65536)
3275+ #error Block sizes bigger than 65536 are not supported at this time.
3276+#endif
3277+#define LZ4_BLOCK_SIZE (LZ4_BLOCK_HEADER_SIZE + LZ4_BLOCK_DATA_SIZE)
3278+#define LZ4_BLOCK_BUF_SIZE (LZ4_COMPRESSBOUND(LZ4_BLOCK_DATA_SIZE + 2)) /* Add 2 to prevent rounding down errors */
3279+#define LZ4_RING_BUFC_SIZE (LZ4_BLOCK_DATA_SIZE * 3)
3280+#define LZ4_RING_BUFD_SIZE (LZ4_BLOCK_DATA_SIZE * 3)
3281+
3282+//#define _LZ4_STREAM
3283+//#define _LZ4_STREAMDICT
3284+
3285+#if defined(_LZ4_STREAM) || defined(_LZ4_STREAMDICT)
3286+// #define _LZ4_RINGBUFFER
3287+#else
3288+ #define _LZ4_BLOCKONLY
3289+#endif
3290+
3291+
3292+/**************************************
3293+* Version
3294+**************************************/
3295+#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
3296+#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
3297+#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
3298+#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
3299+int LZ4_versionNumber (void);
3300+
3301+
3302+/**************************************
3303+* Tuning parameter
3304+**************************************/
3305+/*
3306+ * LZ4_MEMORY_USAGE :
3307+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
3308+ * Increasing memory usage improves compression ratio
3309+ * Reduced memory usage can improve speed, due to cache effect
3310+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
3311+ */
3312+#define LZ4_MEMORY_USAGE 14
3313+
3314+
3315+#include <stdlib.h> /* malloc, calloc, free */
3316+#ifdef EXEHEAD
3317+#include <windows.h>
3318+#define ALLOCATOR(n,s) GlobalAlloc(GPTR, ((n)*(s)))
3319+#define FREEMEM GlobalFree
3320+#else
3321+#define ALLOCATOR(n,s) calloc(n,s)
3322+#define FREEMEM free
3323+#endif
3324+#include <string.h> /* memset, memcpy */
3325+#ifdef EXEHEAD
3326+#ifndef MEM_INIT
3327+void *MEM_INIT(void *mem, int c, size_t len);
3328+#endif
3329+#ifndef MEM_CPY
3330+void *MEM_CPY(void *out, const void *in, size_t len);
3331+#endif
3332+#ifndef MEM_MOVE
3333+void *MEM_MOVE(void *out, const void *in, size_t len);
3334+#endif
3335+#else
3336+#ifndef MEM_INIT
3337+#define MEM_INIT memset
3338+#endif
3339+#ifndef MEM_CPY
3340+#define MEM_CPY memcpy
3341+#endif
3342+#ifndef MEM_MOVE
3343+#define MEM_MOVE memmove
3344+#endif
3345+#endif
3346+
3347+/**************************************
3348+* CPU Feature Detection
3349+**************************************/
3350+/*
3351+ * LZ4_FORCE_SW_BITCOUNT
3352+ * Define this parameter if your target system or compiler does not support hardware bit count
3353+ */
3354+#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
3355+# define LZ4_FORCE_SW_BITCOUNT
3356+#endif
3357+
3358+/**************************************
3359+* Compiler Options
3360+**************************************/
3361+
3362+/* LZ4_GCC_VERSION is defined into lz4.h */
3363+#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
3364+# define expect(expr,value) (__builtin_expect ((expr),(value)) )
3365+#else
3366+# define expect(expr,value) (expr)
3367+#endif
3368+
3369+#define likely(expr) expect((expr) != 0, 1)
3370+#define unlikely(expr) expect((expr) != 0, 0)
3371+
3372+
3373+/**************************************
3374+* Basic Types
3375+**************************************/
3376+#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
3377+# include <stdint.h>
3378+ typedef uint8_t BYTE;
3379+ typedef uint16_t U16;
3380+ typedef uint32_t U32;
3381+ typedef int32_t S32;
3382+ typedef uint64_t U64;
3383+#else
3384+ typedef unsigned char BYTE;
3385+ typedef unsigned short U16;
3386+ typedef unsigned int U32;
3387+ typedef signed int S32;
3388+ typedef unsigned long long U64;
3389+#endif
3390+
3391+
3392+/**************************************
3393+* Reading and writing into memory
3394+**************************************/
3395+#define STEPSIZE sizeof(size_t)
3396+
3397+unsigned LZ4_64bits(void);
3398+unsigned LZ4_isLittleEndian(void);
3399+U16 LZ4_read16(const void* memPtr);
3400+U16 LZ4_readLE16(const void* memPtr);
3401+void LZ4_writeLE16(void* memPtr, U16 value);
3402+U32 LZ4_read32(const void* memPtr);
3403+U64 LZ4_read64(const void* memPtr);
3404+size_t LZ4_read_ARCH(const void* p);
3405+
3406+void LZ4_copy4(void* dstPtr, const void* srcPtr);
3407+void LZ4_copy8(void* dstPtr, const void* srcPtr);
3408+
3409+/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
3410+void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd);
3411+
3412+
3413+/**************************************
3414+* Common Constants
3415+**************************************/
3416+#define MINMATCH 4
3417+
3418+#define COPYLENGTH 8
3419+#define LASTLITERALS 5
3420+#define MFLIMIT (COPYLENGTH+MINMATCH)
3421+static const int LZ4_minLength = (MFLIMIT+1);
3422+
3423+#define KB *(1 <<10)
3424+#define MB *(1 <<20)
3425+#define GB *(1U<<30)
3426+
3427+#define ML_BITS 4
3428+#define ML_MASK ((1U<<ML_BITS)-1)
3429+#define RUN_BITS (8-ML_BITS)
3430+#define RUN_MASK ((1U<<RUN_BITS)-1)
3431+
3432+
3433+/**************************************
3434+* Common Utils
3435+**************************************/
3436+#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
3437+
3438+
3439+/**************************************
3440+* Common functions
3441+**************************************/
3442+unsigned LZ4_NbCommonBytes (register size_t val);
3443+
3444+unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit);
3445+
3446+
3447+/**************************************
3448+* Local Constants
3449+**************************************/
3450+#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
3451+//#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
3452+#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
3453+
3454+static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
3455+static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
3456+
3457+
3458+#ifndef LZ4_COMMONDEFS_ONLY
3459+/**************************************
3460+* Local Structures and types
3461+**************************************/
3462+typedef struct {
3463+ U32 hashTable[HASH_SIZE_U32];
3464+ U32 currentOffset;
3465+ U32 initCheck;
3466+ const BYTE* dictionary;
3467+ BYTE* bufferStart; /* obsolete, used for slideInputBuffer */
3468+ U32 dictSize;
3469+} LZ4_stream_t_internal;
3470+
3471+typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
3472+typedef enum { byPtr, byU32, byU16 } tableType_t;
3473+
3474+typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
3475+typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
3476+
3477+typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
3478+typedef enum { full = 0, partial = 1 } earlyEnd_directive;
3479+
3480+
3481+/**************************************
3482+* Local Utils
3483+**************************************/
3484+int LZ4_versionNumber (void);
3485+
3486+/*
3487+LZ4_compressBound() :
3488+ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
3489+ This function is primarily useful for memory allocation purposes (destination buffer size).
3490+ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
3491+ Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
3492+ inputSize : max supported value is LZ4_MAX_INPUT_SIZE
3493+ return : maximum output size in a "worst case" scenario
3494+ or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
3495+*/
3496+int LZ4_compressBound(int inputSize);
3497+
3498+#endif
3499+
3500+
3501+#endif
3502Index: Source/lz4/lz4compress.c
3503===================================================================
3504--- Source/lz4/lz4compress.c (revision 0)
3505+++ Source/lz4/lz4compress.c (working copy)
3506@@ -0,0 +1,1096 @@
3507+/*
3508+ LZ4 - Fast LZ compression algorithm
3509+ Copyright (C) 2011-2015, Yann Collet.
3510+
3511+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
3512+
3513+ Redistribution and use in source and binary forms, with or without
3514+ modification, are permitted provided that the following conditions are
3515+ met:
3516+
3517+ * Redistributions of source code must retain the above copyright
3518+ notice, this list of conditions and the following disclaimer.
3519+ * Redistributions in binary form must reproduce the above
3520+ copyright notice, this list of conditions and the following disclaimer
3521+ in the documentation and/or other materials provided with the
3522+ distribution.
3523+
3524+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3525+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3526+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3527+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3528+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3529+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3530+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3531+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3532+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3533+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3534+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535+
3536+ You can contact the author at :
3537+ - LZ4 source repository : https://github.com/Cyan4973/lz4
3538+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
3539+*/
3540+
3541+/*
3542+ * lz4compress.c
3543+ *
3544+ * This file is a part of the LZ4 compression module for NSIS.
3545+ *
3546+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
3547+ *
3548+ * Licensed under the zlib/libpng license (the "License");
3549+ * you may not use this file except in compliance with the License.
3550+ *
3551+ * Licence details can be found in the file COPYING.
3552+ *
3553+ * This software is provided 'as-is', without any express or implied
3554+ * warranty.
3555+ */
3556+
3557+/**************************************
3558+* Tuning parameters
3559+**************************************/
3560+/*
3561+ * HEAPMODE :
3562+ * Select how default compression functions will allocate memory for their hash table,
3563+ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
3564+ */
3565+#define HEAPMODE 0
3566+
3567+/*
3568+ * ACCELERATION_DEFAULT :
3569+ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
3570+ */
3571+#define ACCELERATION_DEFAULT 1
3572+
3573+
3574+/**************************************
3575+* Includes
3576+**************************************/
3577+#include "lz4compress.h"
3578+#include "lz4hccompress.h"
3579+
3580+
3581+/**************************************
3582+* Memory routines
3583+**************************************/
3584+#include "lz4common.h"
3585+
3586+
3587+/**************************************
3588+* Compiler Options
3589+**************************************/
3590+#ifdef _MSC_VER /* Visual Studio */
3591+# define FORCE_INLINE static __forceinline
3592+# include <intrin.h>
3593+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
3594+# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
3595+#else
3596+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
3597+# if defined(__GNUC__) || defined(__clang__)
3598+# define FORCE_INLINE static inline __attribute__((always_inline))
3599+# else
3600+# define FORCE_INLINE static inline
3601+# endif
3602+# else
3603+# define FORCE_INLINE static
3604+# endif /* __STDC_VERSION__ */
3605+#endif /* _MSC_VER */
3606+
3607+
3608+#define MAXD_LOG 16
3609+#define MAXD ((1 << MAXD_LOG) - 1)
3610+
3611+
3612+#ifndef LZ4_COMMONDEFS_ONLY
3613+/**************************************
3614+* Local Utils
3615+**************************************/
3616+int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
3617+
3618+
3619+/********************************
3620+* Compression functions
3621+********************************/
3622+
3623+static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
3624+{
3625+ if (tableType == byU16)
3626+ return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
3627+ else
3628+ return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
3629+}
3630+
3631+static const U64 prime5bytes = 889523592379ULL;
3632+static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
3633+{
3634+ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
3635+ const U32 hashMask = (1<<hashLog) - 1;
3636+ return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
3637+}
3638+
3639+static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
3640+{
3641+ if (LZ4_64bits())
3642+ return LZ4_hashSequence64(sequence, tableType);
3643+ return LZ4_hashSequence((U32)sequence, tableType);
3644+}
3645+
3646+static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); }
3647+
3648+static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
3649+{
3650+ switch (tableType)
3651+ {
3652+ case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
3653+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
3654+ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
3655+ }
3656+}
3657+
3658+static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
3659+{
3660+ U32 h = LZ4_hashPosition(p, tableType);
3661+ LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
3662+}
3663+
3664+static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
3665+{
3666+ if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
3667+ if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
3668+ { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
3669+}
3670+
3671+static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
3672+{
3673+ U32 h = LZ4_hashPosition(p, tableType);
3674+ return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
3675+}
3676+
3677+FORCE_INLINE int LZ4_compress_generic(
3678+ void* const ctx,
3679+ const char* const source,
3680+ char* const dest,
3681+ const int inputSize,
3682+ const int maxOutputSize,
3683+ const limitedOutput_directive outputLimited,
3684+ const tableType_t tableType,
3685+ const dict_directive dict,
3686+ const dictIssue_directive dictIssue,
3687+ const U32 acceleration)
3688+{
3689+ LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx;
3690+
3691+ const BYTE* ip = (const BYTE*) source;
3692+ const BYTE* base;
3693+ const BYTE* lowLimit;
3694+ const BYTE* const lowRefLimit = ip - dictPtr->dictSize;
3695+ const BYTE* const dictionary = dictPtr->dictionary;
3696+ const BYTE* const dictEnd = dictionary + dictPtr->dictSize;
3697+ const size_t dictDelta = dictEnd - (const BYTE*)source;
3698+ const BYTE* anchor = (const BYTE*) source;
3699+ const BYTE* const iend = ip + inputSize;
3700+ const BYTE* const mflimit = iend - MFLIMIT;
3701+ const BYTE* const matchlimit = iend - LASTLITERALS;
3702+
3703+ BYTE* op = (BYTE*) dest;
3704+ BYTE* const olimit = op + maxOutputSize;
3705+
3706+ U32 forwardH;
3707+ size_t refDelta=0;
3708+
3709+ /* Init conditions */
3710+ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
3711+ switch(dict)
3712+ {
3713+ case noDict:
3714+ default:
3715+ base = (const BYTE*)source;
3716+ lowLimit = (const BYTE*)source;
3717+ break;
3718+ case withPrefix64k:
3719+ base = (const BYTE*)source - dictPtr->currentOffset;
3720+ lowLimit = (const BYTE*)source - dictPtr->dictSize;
3721+ break;
3722+ case usingExtDict:
3723+ base = (const BYTE*)source - dictPtr->currentOffset;
3724+ lowLimit = (const BYTE*)source;
3725+ break;
3726+ }
3727+ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
3728+ if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
3729+
3730+ /* First Byte */
3731+ LZ4_putPosition(ip, ctx, tableType, base);
3732+ ip++; forwardH = LZ4_hashPosition(ip, tableType);
3733+
3734+ /* Main Loop */
3735+ for ( ; ; )
3736+ {
3737+ const BYTE* match;
3738+ BYTE* token;
3739+ {
3740+ const BYTE* forwardIp = ip;
3741+ unsigned step = 1;
3742+ unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
3743+
3744+ /* Find a match */
3745+ do {
3746+ U32 h = forwardH;
3747+ ip = forwardIp;
3748+ forwardIp += step;
3749+ step = (searchMatchNb++ >> LZ4_skipTrigger);
3750+
3751+ if (unlikely(forwardIp > mflimit)) goto _last_literals;
3752+
3753+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
3754+ if (dict==usingExtDict)
3755+ {
3756+ if (match<(const BYTE*)source)
3757+ {
3758+ refDelta = dictDelta;
3759+ lowLimit = dictionary;
3760+ }
3761+ else
3762+ {
3763+ refDelta = 0;
3764+ lowLimit = (const BYTE*)source;
3765+ }
3766+ }
3767+ forwardH = LZ4_hashPosition(forwardIp, tableType);
3768+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
3769+
3770+ } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
3771+ || ((tableType==byU16) ? 0 : (match + MAXD < ip))
3772+ || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
3773+ }
3774+
3775+ /* Catch up */
3776+ while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
3777+
3778+ {
3779+ /* Encode Literal length */
3780+ unsigned litLength = (unsigned)(ip - anchor);
3781+ token = op++;
3782+ if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
3783+ return 0; /* Check output limit */
3784+ if (litLength>=RUN_MASK)
3785+ {
3786+ int len = (int)litLength-RUN_MASK;
3787+ *token=(RUN_MASK<<ML_BITS);
3788+ for(; len >= 255 ; len-=255) *op++ = 255;
3789+ *op++ = (BYTE)len;
3790+ }
3791+ else *token = (BYTE)(litLength<<ML_BITS);
3792+
3793+ /* Copy Literals */
3794+ LZ4_wildCopy(op, anchor, op+litLength);
3795+ op+=litLength;
3796+ }
3797+
3798+_next_match:
3799+ /* Encode Offset */
3800+ LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
3801+
3802+ /* Encode MatchLength */
3803+ {
3804+ unsigned matchLength;
3805+
3806+ if ((dict==usingExtDict) && (lowLimit==dictionary))
3807+ {
3808+ const BYTE* limit;
3809+ match += refDelta;
3810+ limit = ip + (dictEnd-match);
3811+ if (limit > matchlimit) limit = matchlimit;
3812+ matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
3813+ ip += MINMATCH + matchLength;
3814+ if (ip==limit)
3815+ {
3816+ unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit);
3817+ matchLength += more;
3818+ ip += more;
3819+ }
3820+ }
3821+ else
3822+ {
3823+ matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
3824+ ip += MINMATCH + matchLength;
3825+ }
3826+
3827+ if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
3828+ return 0; /* Check output limit */
3829+ if (matchLength>=ML_MASK)
3830+ {
3831+ *token += ML_MASK;
3832+ matchLength -= ML_MASK;
3833+ for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
3834+ if (matchLength >= 255) { matchLength-=255; *op++ = 255; }
3835+ *op++ = (BYTE)matchLength;
3836+ }
3837+ else *token += (BYTE)(matchLength);
3838+ }
3839+
3840+ anchor = ip;
3841+
3842+ /* Test end of chunk */
3843+ if (ip > mflimit) break;
3844+
3845+ /* Fill table */
3846+ LZ4_putPosition(ip-2, ctx, tableType, base);
3847+
3848+ /* Test next position */
3849+ match = LZ4_getPosition(ip, ctx, tableType, base);
3850+ if (dict==usingExtDict)
3851+ {
3852+ if (match<(const BYTE*)source)
3853+ {
3854+ refDelta = dictDelta;
3855+ lowLimit = dictionary;
3856+ }
3857+ else
3858+ {
3859+ refDelta = 0;
3860+ lowLimit = (const BYTE*)source;
3861+ }
3862+ }
3863+ LZ4_putPosition(ip, ctx, tableType, base);
3864+ if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
3865+ && (match+MAXD>=ip)
3866+ && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
3867+ { token=op++; *token=0; goto _next_match; }
3868+
3869+ /* Prepare next loop */
3870+ forwardH = LZ4_hashPosition(++ip, tableType);
3871+ }
3872+
3873+_last_literals:
3874+ /* Encode Last Literals */
3875+ {
3876+ const size_t lastRun = (size_t)(iend - anchor);
3877+ if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize))
3878+ return 0; /* Check output limit */
3879+ if (lastRun >= RUN_MASK)
3880+ {
3881+ size_t accumulator = lastRun - RUN_MASK;
3882+ *op++ = RUN_MASK << ML_BITS;
3883+ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
3884+ *op++ = (BYTE) accumulator;
3885+ }
3886+ else
3887+ {
3888+ *op++ = (BYTE)(lastRun<<ML_BITS);
3889+ }
3890+ MEM_CPY(op, anchor, lastRun);
3891+ op += lastRun;
3892+ }
3893+
3894+ /* End */
3895+ return (int) (((char*)op)-dest);
3896+}
3897+
3898+
3899+int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
3900+{
3901+ LZ4_resetStream((LZ4_stream_t*)state);
3902+ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
3903+
3904+ if (maxOutputSize >= LZ4_compressBound(inputSize))
3905+ {
3906+ if (inputSize < LZ4_64Klimit)
3907+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
3908+ else
3909+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
3910+ }
3911+ else
3912+ {
3913+ if (inputSize < LZ4_64Klimit)
3914+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
3915+ else
3916+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
3917+ }
3918+}
3919+
3920+
3921+int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
3922+{
3923+#if (HEAPMODE)
3924+ void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
3925+#else
3926+ LZ4_stream_t ctx;
3927+ void* ctxPtr = &ctx;
3928+#endif
3929+
3930+ int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
3931+
3932+#if (HEAPMODE)
3933+ FREEMEM(ctxPtr);
3934+#endif
3935+ return result;
3936+}
3937+
3938+
3939+int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
3940+{
3941+ return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
3942+}
3943+
3944+
3945+/* hidden debug function */
3946+/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
3947+int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
3948+{
3949+ LZ4_stream_t ctx;
3950+
3951+ LZ4_resetStream(&ctx);
3952+
3953+ if (inputSize < LZ4_64Klimit)
3954+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
3955+ else
3956+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
3957+}
3958+
3959+
3960+/********************************
3961+* destSize variant
3962+********************************/
3963+
3964+static int LZ4_compress_destSize_generic(
3965+ void* const ctx,
3966+ const char* const src,
3967+ char* const dst,
3968+ int* const srcSizePtr,
3969+ const int targetDstSize,
3970+ const tableType_t tableType)
3971+{
3972+ const BYTE* ip = (const BYTE*) src;
3973+ const BYTE* base = (const BYTE*) src;
3974+ const BYTE* lowLimit = (const BYTE*) src;
3975+ const BYTE* anchor = ip;
3976+ const BYTE* const iend = ip + *srcSizePtr;
3977+ const BYTE* const mflimit = iend - MFLIMIT;
3978+ const BYTE* const matchlimit = iend - LASTLITERALS;
3979+
3980+ BYTE* op = (BYTE*) dst;
3981+ BYTE* const oend = op + targetDstSize;
3982+ BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
3983+ BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
3984+ BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
3985+
3986+ U32 forwardH;
3987+
3988+
3989+ /* Init conditions */
3990+ if (targetDstSize < 1) return 0; /* Impossible to store anything */
3991+ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
3992+ if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
3993+ if (*srcSizePtr<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
3994+
3995+ /* First Byte */
3996+ *srcSizePtr = 0;
3997+ LZ4_putPosition(ip, ctx, tableType, base);
3998+ ip++; forwardH = LZ4_hashPosition(ip, tableType);
3999+
4000+ /* Main Loop */
4001+ for ( ; ; )
4002+ {
4003+ const BYTE* match;
4004+ BYTE* token;
4005+ {
4006+ const BYTE* forwardIp = ip;
4007+ unsigned step = 1;
4008+ unsigned searchMatchNb = 1 << LZ4_skipTrigger;
4009+
4010+ /* Find a match */
4011+ do {
4012+ U32 h = forwardH;
4013+ ip = forwardIp;
4014+ forwardIp += step;
4015+ step = (searchMatchNb++ >> LZ4_skipTrigger);
4016+
4017+ if (unlikely(forwardIp > mflimit))
4018+ goto _last_literals;
4019+
4020+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
4021+ forwardH = LZ4_hashPosition(forwardIp, tableType);
4022+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
4023+
4024+ } while ( ((tableType==byU16) ? 0 : (match + MAXD < ip))
4025+ || (LZ4_read32(match) != LZ4_read32(ip)) );
4026+ }
4027+
4028+ /* Catch up */
4029+ while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
4030+
4031+ {
4032+ /* Encode Literal length */
4033+ unsigned litLength = (unsigned)(ip - anchor);
4034+ token = op++;
4035+ if (op + ((litLength+240)/255) + litLength > oMaxLit)
4036+ {
4037+ /* Not enough space for a last match */
4038+ op--;
4039+ goto _last_literals;
4040+ }
4041+ if (litLength>=RUN_MASK)
4042+ {
4043+ unsigned len = litLength - RUN_MASK;
4044+ *token=(RUN_MASK<<ML_BITS);
4045+ for(; len >= 255 ; len-=255) *op++ = 255;
4046+ *op++ = (BYTE)len;
4047+ }
4048+ else *token = (BYTE)(litLength<<ML_BITS);
4049+
4050+ /* Copy Literals */
4051+ LZ4_wildCopy(op, anchor, op+litLength);
4052+ op += litLength;
4053+ }
4054+
4055+_next_match:
4056+ /* Encode Offset */
4057+ LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
4058+
4059+ /* Encode MatchLength */
4060+ {
4061+ size_t matchLength;
4062+
4063+ matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
4064+
4065+ if (op + ((matchLength+240)/255) > oMaxMatch)
4066+ {
4067+ /* Match description too long : reduce it */
4068+ matchLength = (15-1) + (oMaxMatch-op) * 255;
4069+ }
4070+ //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
4071+ ip += MINMATCH + matchLength;
4072+
4073+ if (matchLength>=ML_MASK)
4074+ {
4075+ *token += ML_MASK;
4076+ matchLength -= ML_MASK;
4077+ while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
4078+ *op++ = (BYTE)matchLength;
4079+ }
4080+ else *token += (BYTE)(matchLength);
4081+ }
4082+
4083+ anchor = ip;
4084+
4085+ /* Test end of block */
4086+ if (ip > mflimit) break;
4087+ if (op > oMaxSeq) break;
4088+
4089+ /* Fill table */
4090+ LZ4_putPosition(ip-2, ctx, tableType, base);
4091+
4092+ /* Test next position */
4093+ match = LZ4_getPosition(ip, ctx, tableType, base);
4094+ LZ4_putPosition(ip, ctx, tableType, base);
4095+ if ( (match+MAXD>=ip)
4096+ && (LZ4_read32(match)==LZ4_read32(ip)) )
4097+ { token=op++; *token=0; goto _next_match; }
4098+
4099+ /* Prepare next loop */
4100+ forwardH = LZ4_hashPosition(++ip, tableType);
4101+ }
4102+
4103+_last_literals:
4104+ /* Encode Last Literals */
4105+ {
4106+ size_t lastRunSize = (size_t)(iend - anchor);
4107+ if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)
4108+ {
4109+ /* adapt lastRunSize to fill 'dst' */
4110+ lastRunSize = (oend-op) - 1;
4111+ lastRunSize -= (lastRunSize+240)/255;
4112+ }
4113+ ip = anchor + lastRunSize;
4114+
4115+ if (lastRunSize >= RUN_MASK)
4116+ {
4117+ size_t accumulator = lastRunSize - RUN_MASK;
4118+ *op++ = RUN_MASK << ML_BITS;
4119+ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
4120+ *op++ = (BYTE) accumulator;
4121+ }
4122+ else
4123+ {
4124+ *op++ = (BYTE)(lastRunSize<<ML_BITS);
4125+ }
4126+ MEM_CPY(op, anchor, lastRunSize);
4127+ op += lastRunSize;
4128+ }
4129+
4130+ /* End */
4131+ *srcSizePtr = (int) (((const char*)ip)-src);
4132+ return (int) (((char*)op)-dst);
4133+}
4134+
4135+
4136+static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
4137+{
4138+ LZ4_resetStream((LZ4_stream_t*)state);
4139+
4140+ if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
4141+ {
4142+ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
4143+ }
4144+ else
4145+ {
4146+ if (*srcSizePtr < LZ4_64Klimit)
4147+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
4148+ else
4149+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr);
4150+ }
4151+}
4152+
4153+
4154+int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
4155+{
4156+#if (HEAPMODE)
4157+ void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
4158+#else
4159+ LZ4_stream_t ctxBody;
4160+ void* ctx = &ctxBody;
4161+#endif
4162+
4163+ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
4164+
4165+#if (HEAPMODE)
4166+ FREEMEM(ctx);
4167+#endif
4168+ return result;
4169+}
4170+
4171+
4172+
4173+/********************************
4174+* Streaming functions
4175+********************************/
4176+
4177+LZ4_stream_t* LZ4_createStream(void)
4178+{
4179+ LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
4180+ LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
4181+ LZ4_resetStream(lz4s);
4182+ return lz4s;
4183+}
4184+
4185+void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
4186+{
4187+ MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
4188+}
4189+
4190+int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
4191+{
4192+ FREEMEM(LZ4_stream);
4193+ return (0);
4194+}
4195+
4196+
4197+#define HASH_UNIT sizeof(size_t)
4198+int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
4199+{
4200+ LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
4201+ const BYTE* p = (const BYTE*)dictionary;
4202+ const BYTE* const dictEnd = p + dictSize;
4203+ const BYTE* base;
4204+
4205+ if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
4206+ LZ4_resetStream(LZ4_dict);
4207+
4208+ if (dictSize < (int)HASH_UNIT)
4209+ {
4210+ dict->dictionary = NULL;
4211+ dict->dictSize = 0;
4212+ return 0;
4213+ }
4214+
4215+ if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
4216+ dict->currentOffset += 64 KB;
4217+ base = p - dict->currentOffset;
4218+ dict->dictionary = p;
4219+ dict->dictSize = (U32)(dictEnd - p);
4220+ dict->currentOffset += dict->dictSize;
4221+
4222+ while (p <= dictEnd-HASH_UNIT)
4223+ {
4224+ LZ4_putPosition(p, dict->hashTable, byU32, base);
4225+ p+=3;
4226+ }
4227+
4228+ return dict->dictSize;
4229+}
4230+
4231+
4232+static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
4233+{
4234+ if ((LZ4_dict->currentOffset > 0x80000000) ||
4235+ ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
4236+ {
4237+ /* rescale hash table */
4238+ U32 delta = LZ4_dict->currentOffset - 64 KB;
4239+ const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
4240+ int i;
4241+ for (i=0; i<HASH_SIZE_U32; i++)
4242+ {
4243+ if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
4244+ else LZ4_dict->hashTable[i] -= delta;
4245+ }
4246+ LZ4_dict->currentOffset = 64 KB;
4247+ if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
4248+ LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
4249+ }
4250+}
4251+
4252+
4253+int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
4254+{
4255+ LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream;
4256+ const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
4257+
4258+ const BYTE* smallest = (const BYTE*) source;
4259+ if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
4260+ if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
4261+ LZ4_renormDictT(streamPtr, smallest);
4262+ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
4263+
4264+ /* Check overlapping input/dictionary space */
4265+ {
4266+ const BYTE* sourceEnd = (const BYTE*) source + inputSize;
4267+ if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))
4268+ {
4269+ streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
4270+ if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
4271+ if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
4272+ streamPtr->dictionary = dictEnd - streamPtr->dictSize;
4273+ }
4274+ }
4275+
4276+ /* prefix mode : source data follows dictionary */
4277+ if (dictEnd == (const BYTE*)source)
4278+ {
4279+ int result;
4280+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
4281+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
4282+ else
4283+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
4284+ streamPtr->dictSize += (U32)inputSize;
4285+ streamPtr->currentOffset += (U32)inputSize;
4286+ return result;
4287+ }
4288+
4289+ /* external dictionary mode */
4290+ {
4291+ int result;
4292+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
4293+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
4294+ else
4295+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
4296+ streamPtr->dictionary = (const BYTE*)source;
4297+ streamPtr->dictSize = (U32)inputSize;
4298+ streamPtr->currentOffset += (U32)inputSize;
4299+ return result;
4300+ }
4301+}
4302+
4303+
4304+/* Hidden debug function, to force external dictionary mode */
4305+int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
4306+{
4307+ LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict;
4308+ int result;
4309+ const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
4310+
4311+ const BYTE* smallest = dictEnd;
4312+ if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
4313+ LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest);
4314+
4315+ result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
4316+
4317+ streamPtr->dictionary = (const BYTE*)source;
4318+ streamPtr->dictSize = (U32)inputSize;
4319+ streamPtr->currentOffset += (U32)inputSize;
4320+
4321+ return result;
4322+}
4323+
4324+
4325+int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
4326+{
4327+ LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
4328+ const BYTE* previousDictEnd = dict->dictionary + dict->dictSize;
4329+
4330+ if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
4331+ if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
4332+
4333+ MEM_MOVE(safeBuffer, previousDictEnd - dictSize, dictSize);
4334+
4335+ dict->dictionary = (const BYTE*)safeBuffer;
4336+ dict->dictSize = (U32)dictSize;
4337+
4338+ return dictSize;
4339+}
4340+
4341+/* NSIS wrappers. */
4342+
4343+int LZ4_Init(lz4_compstream *stream, int level, int dict_size)
4344+{
4345+ int i;
4346+
4347+ for (i = 0; i < sizeof(stream->LZ4_State); i++)
4348+ *((char *)&stream->LZ4_State + i) = 0;
4349+
4350+#ifdef _LZ4_STREAM
4351+#ifdef _LZ4_RINGBUFFER
4352+ stream->LZ4_State.pInBuf = stream->LZ4_State.pRingBufBase;
4353+// LZ4_resetStream(&stream->LZ4_State.lz4Stream);
4354+#else
4355+ stream->LZ4_State.pInBuf = stream->LZ4_State.pInBufBase[0];
4356+#endif
4357+#else
4358+ #ifdef _LZ4_STREAMDICT
4359+ stream->LZ4_State.pInBuf = stream->LZ4_State.pInBufBase;
4360+ #endif
4361+#endif
4362+ stream->LZ4_State.dictSize = dict_size;
4363+
4364+ return LZ4_OK;
4365+}
4366+
4367+
4368+int LZ4_End(lz4_compstream *stream)
4369+{
4370+ return LZ4_OK;
4371+}
4372+
4373+int LZ4_Compress(lz4_compstream *stream, int finish)
4374+{
4375+#ifdef _LZ4_BLOCKONLY // working block only implementation
4376+ if (stream->LZ4_State.pInOverflow && stream->LZ4_State.recurse)
4377+ {
4378+ lz4_compstream tempStream;
4379+ tempStream.avail_in = stream->LZ4_State.inAvail;
4380+ tempStream.next_in = stream->LZ4_State.pInOverflow;
4381+ tempStream.avail_out = stream->avail_out;
4382+ tempStream.next_out = stream->next_out;
4383+ tempStream.LZ4_State.recurse = 0;
4384+
4385+ stream->LZ4_State.outBytes = LZ4_Compress(&tempStream, 0);
4386+ FREEMEM(stream->LZ4_State.pInOverflow);
4387+ stream->LZ4_State.pInOverflow = 0;
4388+ stream->LZ4_State.inAvail = 0;
4389+ stream->LZ4_State.recurse = 0;
4390+
4391+ stream->next_out += (stream->avail_out - tempStream.avail_out);
4392+ stream->avail_out = tempStream.avail_out;
4393+ }
4394+ while (stream->avail_in)
4395+ {
4396+ int i, shift, inputBytes = stream->avail_in < LZ4_BLOCK_DATA_SIZE ? stream->avail_in : LZ4_BLOCK_DATA_SIZE;
4397+ char *pAvail;
4398+
4399+ if (stream->LZ4_State.dictSize == 1 << 20)
4400+ stream->LZ4_State.outBytes = LZ4_compress_HC(stream->next_in, stream->LZ4_State.pCompBuf, inputBytes, LZ4_BLOCK_BUF_SIZE, 9);
4401+ else
4402+ stream->LZ4_State.outBytes = LZ4_compress_default(stream->next_in, stream->LZ4_State.pCompBuf, inputBytes, LZ4_BLOCK_BUF_SIZE);
4403+ if (stream->LZ4_State.outBytes <= 0)
4404+ return LZ4_DATA_ERROR;
4405+ if (stream->avail_out < (unsigned int)stream->LZ4_State.outBytes + LZ4_BLOCK_HEADER_SIZE + (finish ? LZ4_BLOCK_HEADER_SIZE : 0))
4406+ {
4407+ if (finish) return LZ4_DATA_ERROR;
4408+ if (stream->LZ4_State.pInOverflow) FREEMEM(stream->LZ4_State.pInOverflow);
4409+ stream->LZ4_State.pInOverflow = ALLOCATOR(1, stream->avail_in);
4410+ pAvail = stream->LZ4_State.pInOverflow;
4411+ ++stream->LZ4_State.recurse;
4412+ while (stream->avail_in)
4413+ *pAvail++ = *stream->next_in++, --stream->avail_in, ++stream->LZ4_State.inAvail;
4414+ return LZ4_OK;
4415+ }
4416+ stream->next_in += inputBytes;
4417+ stream->avail_in -= inputBytes;
4418+
4419+ for (i = 0, shift = 0; i < LZ4_BLOCK_HEADER_SIZE; ++i, shift += 8)
4420+ *stream->next_out++ = (unsigned char)(stream->LZ4_State.outBytes >> shift), --stream->avail_out;
4421+
4422+ pAvail = stream->LZ4_State.pCompBuf;
4423+ while (stream->LZ4_State.outBytes)
4424+ *stream->next_out++ = *pAvail++, --stream->avail_out, --stream->LZ4_State.outBytes;
4425+ }
4426+#endif
4427+
4428+
4429+#ifdef _LZ4_STREAM // working stream implementation
4430+
4431+ if (stream->LZ4_State.pInOverflow && stream->LZ4_State.recurse)
4432+ {
4433+ lz4_compstream tempStream;
4434+ LZ4_Init(&tempStream, 1, 0);
4435+ tempStream.avail_in = stream->LZ4_State.inAvail;
4436+ tempStream.next_in = stream->LZ4_State.pInOverflow;
4437+ tempStream.avail_out = stream->avail_out;
4438+ tempStream.next_out = stream->next_out;
4439+ tempStream.LZ4_State.recurse = 0;
4440+ tempStream.LZ4_State.level = stream->LZ4_State.level;
4441+ tempStream.LZ4_State.iRingIndex = stream->LZ4_State.iRingIndex;
4442+#ifdef _LZ4_RINGBUFFER
4443+ tempStream.LZ4_State.pInBuf = stream->LZ4_State.pRingBufBase;
4444+#else
4445+ tempStream.LZ4_State.pInBuf = stream->LZ4_State.pInBufBase[stream->LZ4_State.iRingIndex];
4446+#endif
4447+
4448+ stream->LZ4_State.outBytes = LZ4_Compress(&tempStream, 0);
4449+ FREEMEM(stream->LZ4_State.pInOverflow);
4450+ stream->LZ4_State.pInOverflow = 0;
4451+ stream->LZ4_State.inAvail = 0;
4452+ stream->LZ4_State.recurse = 0;
4453+
4454+ stream->next_out += (stream->avail_out - tempStream.avail_out);
4455+ stream->avail_out = tempStream.avail_out;
4456+ }
4457+ while (stream->avail_in)
4458+ {
4459+ int inputBytes = stream->avail_in < LZ4_BLOCK_DATA_SIZE ? stream->avail_in : LZ4_BLOCK_DATA_SIZE;
4460+
4461+ if (stream->avail_out < (unsigned int)stream->LZ4_State.outBytes + LZ4_BLOCK_HEADER_SIZE + finish ? LZ4_BLOCK_HEADER_SIZE : 0)
4462+ {
4463+ char *pAvail;
4464+ if (finish) return LZ4_DATA_ERROR;
4465+ if (stream->LZ4_State.pInOverflow) FREEMEM(stream->LZ4_State.pInOverflow);
4466+ stream->LZ4_State.pInOverflow = ALLOCATOR(1, stream->avail_in);
4467+ pAvail = stream->LZ4_State.pInOverflow;
4468+ stream->LZ4_State.recurse = 1;
4469+ while (stream->avail_in)
4470+ *pAvail++ = *stream->next_in++, --stream->avail_in, ++stream->LZ4_State.inAvail;
4471+ return LZ4_OK;
4472+ }
4473+ else
4474+ {
4475+ int i, shift;
4476+#ifdef _LZ4_RINGBUFFER
4477+ char* const pInBufPtr = &stream->LZ4_State.pInBuf[stream->LZ4_State.iRingIndex];
4478+#else
4479+ char* const pInBufPtr = stream->LZ4_State.pInBufBase[stream->LZ4_State.iRingIndex];
4480+#endif
4481+ for (i = 0; i < inputBytes; i++)
4482+ *(pInBufPtr + i) = *stream->next_in++, --stream->avail_in;
4483+
4484+// if (stream->LZ4_State.dictSize == 1 << 20)
4485+// stream->LZ4_State.outBytes = LZ4_compressHC_continue(&stream->LZ4_State.lz4hcStream, pInBufPtr, stream->LZ4_State.pCompBuf, inputBytes);
4486+// else
4487+ stream->LZ4_State.outBytes = LZ4_compress_fast_continue(&stream->LZ4_State.lz4Stream, pInBufPtr, stream->LZ4_State.pCompBuf, inputBytes, LZ4_BLOCK_BUF_SIZE, stream->LZ4_State.level);
4488+ if (stream->LZ4_State.outBytes <= 0)
4489+ return LZ4_DATA_ERROR;
4490+
4491+ for (i = 0, shift = 0; i < LZ4_BLOCK_HEADER_SIZE; ++i, shift += 8)
4492+ *stream->next_out++ = (unsigned char)(stream->LZ4_State.outBytes >> shift), --stream->avail_out;
4493+
4494+ for (i = 0; i < stream->LZ4_State.outBytes; i++)
4495+ *stream->next_out++ = stream->LZ4_State.pCompBuf[i], --stream->avail_out;
4496+
4497+#ifdef _LZ4_RINGBUFFER
4498+ stream->LZ4_State.iRingIndex += inputBytes;
4499+ if (stream->LZ4_State.iRingIndex >= (LZ4_RING_BUFC_SIZE - LZ4_BLOCK_DATA_SIZE))
4500+ stream->LZ4_State.iRingIndex = 0;
4501+#else
4502+ stream->LZ4_State.iRingIndex = (stream->LZ4_State.iRingIndex + 1) % 2;
4503+#endif
4504+ }
4505+ }
4506+#endif
4507+
4508+#ifdef _LZ4_STREAMDICT
4509+ if (stream->LZ4_State.pInOverflow && stream->LZ4_State.recurse)
4510+ {
4511+ lz4_compstream tempStream;
4512+ LZ4_Init(&tempStream, 1, 0);
4513+ tempStream.avail_in = stream->LZ4_State.inAvail;
4514+ tempStream.next_in = stream->LZ4_State.pInOverflow;
4515+ tempStream.avail_out = stream->avail_out;
4516+ tempStream.next_out = stream->next_out;
4517+ tempStream.LZ4_State.recurse = 0;
4518+ tempStream.LZ4_State.level = stream->LZ4_State.level;
4519+ tempStream.LZ4_State.iRingIndex = stream->LZ4_State.iRingIndex;
4520+#ifdef _LZ4_RINGBUFFER
4521+ tempStream.LZ4_State.pInBuf = stream->LZ4_State.pRingBufBase;
4522+#else
4523+ tempStream.LZ4_State.pInBuf = stream->LZ4_State.pInBufBase/*[stream->LZ4_State.iRingIndex]*/;
4524+#endif
4525+
4526+ stream->LZ4_State.outBytes = LZ4_Compress(&tempStream, 0);
4527+ FREEMEM(stream->LZ4_State.pInOverflow);
4528+ stream->LZ4_State.pInOverflow = 0;
4529+ stream->LZ4_State.inAvail = 0;
4530+ stream->LZ4_State.recurse = 0;
4531+
4532+ stream->next_out += (stream->avail_out - tempStream.avail_out);
4533+ stream->avail_out = tempStream.avail_out;
4534+ }
4535+ while (stream->avail_in)
4536+ {
4537+ int inputBytes = stream->avail_in < LZ4_BLOCK_DATA_SIZE ? stream->avail_in : LZ4_BLOCK_DATA_SIZE;
4538+
4539+ if (stream->avail_out < (unsigned int)stream->LZ4_State.outBytes + LZ4_BLOCK_HEADER_SIZE + finish ? LZ4_BLOCK_HEADER_SIZE : 0)
4540+ {
4541+ char *pAvail;
4542+ if (finish) return LZ4_DATA_ERROR;
4543+ if (stream->LZ4_State.pInOverflow) FREEMEM(stream->LZ4_State.pInOverflow);
4544+ stream->LZ4_State.pInOverflow = ALLOCATOR(1, stream->avail_in);
4545+ pAvail = stream->LZ4_State.pInOverflow;
4546+ stream->LZ4_State.recurse = 1;
4547+ while (stream->avail_in)
4548+ *pAvail++ = *stream->next_in++, --stream->avail_in, ++stream->LZ4_State.inAvail;
4549+ return LZ4_OK;
4550+ }
4551+ else
4552+ {
4553+ int i, shift;
4554+#ifdef _LZ4_RINGBUFFER
4555+ char* const pInBufPtr = &stream->LZ4_State.pInBuf[stream->LZ4_State.iRingIndex];
4556+#else
4557+ char* const pInBufPtr = stream->LZ4_State.pInBufBase/*[stream->LZ4_State.iRingIndex]*/;
4558+#endif
4559+ for (i = 0; i < inputBytes; i++)
4560+ *(pInBufPtr + i) = *stream->next_in++, --stream->avail_in;
4561+
4562+// if (stream->LZ4_State.dictSize == 1 << 20)
4563+// stream->LZ4_State.outBytes = LZ4_compressHC_continue(&stream->LZ4_State.lz4hcStream, pInBufPtr, stream->LZ4_State.pCompBuf, inputBytes);
4564+// else
4565+ stream->LZ4_State.outBytes = LZ4_compress_fast_continue(&stream->LZ4_State.lz4Stream, pInBufPtr, stream->LZ4_State.pCompBuf, inputBytes, LZ4_BLOCK_BUF_SIZE, stream->LZ4_State.level);
4566+ if (stream->LZ4_State.outBytes <= 0)
4567+ return LZ4_DATA_ERROR;
4568+
4569+ LZ4_saveDict(&stream->LZ4_State.lz4Stream, stream->LZ4_State.pDictSave, stream->LZ4_State.outBytes);
4570+
4571+ for (i = 0, shift = 0; i < LZ4_BLOCK_HEADER_SIZE; ++i, shift += 8)
4572+ *stream->next_out++ = (unsigned char)(stream->LZ4_State.outBytes >> shift), --stream->avail_out;
4573+
4574+ for (i = 0; i < stream->LZ4_State.outBytes; i++)
4575+ *stream->next_out++ = stream->LZ4_State.pCompBuf[i], --stream->avail_out;
4576+
4577+#ifdef _LZ4_RINGBUFFER
4578+ stream->LZ4_State.iRingIndex += inputBytes;
4579+ if (stream->LZ4_State.iRingIndex >= (LZ4_RING_BUFC_SIZE - LZ4_BLOCK_DATA_SIZE))
4580+ stream->LZ4_State.iRingIndex = 0;
4581+#else
4582+ stream->LZ4_State.iRingIndex = (stream->LZ4_State.iRingIndex + 1) % 2;
4583+#endif
4584+ }
4585+ }
4586+
4587+#endif
4588+
4589+ if (finish && !stream->LZ4_State.finish)
4590+ {
4591+ int i;
4592+
4593+ if (stream->avail_out < LZ4_BLOCK_HEADER_SIZE) return LZ4_DATA_ERROR;
4594+ for (i = 0; i < LZ4_BLOCK_HEADER_SIZE; ++i)
4595+ *stream->next_out++ = 0, --stream->avail_out;
4596+
4597+ stream->LZ4_State.finish = 1;
4598+ }
4599+ return LZ4_OK;
4600+}
4601+
4602+#endif /* LZ4_COMMONDEFS_ONLY */
4603Index: Source/lz4/lz4compress.h
4604===================================================================
4605--- Source/lz4/lz4compress.h (revision 0)
4606+++ Source/lz4/lz4compress.h (working copy)
4607@@ -0,0 +1,258 @@
4608+/*
4609+ LZ4 - Fast LZ compression algorithm
4610+ Header File
4611+ Copyright (C) 2011-2015, Yann Collet.
4612+
4613+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
4614+
4615+ Redistribution and use in source and binary forms, with or without
4616+ modification, are permitted provided that the following conditions are
4617+ met:
4618+
4619+ * Redistributions of source code must retain the above copyright
4620+ notice, this list of conditions and the following disclaimer.
4621+ * Redistributions in binary form must reproduce the above
4622+ copyright notice, this list of conditions and the following disclaimer
4623+ in the documentation and/or other materials provided with the
4624+ distribution.
4625+
4626+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4627+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4628+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4629+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4630+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4631+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4632+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4633+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4634+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4635+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4636+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4637+
4638+ You can contact the author at :
4639+ - LZ4 source repository : https://github.com/Cyan4973/lz4
4640+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
4641+*/
4642+
4643+/*
4644+ * lz4compress.h
4645+ *
4646+ * This file is a part of the LZ4 compression module for NSIS.
4647+ *
4648+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
4649+ *
4650+ * Licensed under the zlib/libpng license (the "License");
4651+ * you may not use this file except in compliance with the License.
4652+ *
4653+ * Licence details can be found in the file COPYING.
4654+ *
4655+ * This software is provided 'as-is', without any express or implied
4656+ * warranty.
4657+ */
4658+
4659+#ifndef __LZ4COMPRESS_H
4660+#define __LZ4COMPRESS_H
4661+
4662+#include "lz4common.h"
4663+
4664+#if defined (__cplusplus)
4665+extern "C" {
4666+#endif
4667+
4668+/*
4669+ * lz4.h provides block compression functions, and gives full buffer control to programmer.
4670+ * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
4671+ * and can let the library handle its own memory, please use lz4frame.h instead.
4672+*/
4673+
4674+/**************************************
4675+* Local Utils
4676+**************************************/
4677+int LZ4_sizeofState();
4678+
4679+
4680+/**************************************
4681+* Simple Functions
4682+**************************************/
4683+
4684+int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
4685+int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
4686+
4687+/*
4688+LZ4_compress_default() :
4689+ Compresses 'sourceSize' bytes from buffer 'source'
4690+ into already allocated 'dest' buffer of size 'maxDestSize'.
4691+ Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
4692+ It also runs faster, so it's a recommended setting.
4693+ If the function cannot compress 'source' into a more limited 'dest' budget,
4694+ compression stops *immediately*, and the function result is zero.
4695+ As a consequence, 'dest' content is not valid.
4696+ This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
4697+ sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
4698+ maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
4699+ return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
4700+ or 0 if compression fails
4701+
4702+LZ4_decompress_safe() :
4703+ compressedSize : is the precise full size of the compressed block.
4704+ maxDecompressedSize : is the size of destination buffer, which must be already allocated.
4705+ return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
4706+ If destination buffer is not large enough, decoding will stop and output an error code (<0).
4707+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
4708+ This function is protected against buffer overflow exploits, including malicious data packets.
4709+ It never writes outside output buffer, nor reads outside input buffer.
4710+*/
4711+
4712+
4713+/**************************************
4714+* Advanced Functions
4715+**************************************/
4716+//#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
4717+//#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
4718+
4719+/*
4720+LZ4_compress_fast() :
4721+ Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
4722+ The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
4723+ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
4724+ An acceleration value of "1" is the same as regular LZ4_compress_default()
4725+ Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
4726+*/
4727+int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
4728+
4729+
4730+/*
4731+LZ4_compress_fast_extState() :
4732+ Same compression function, just using an externally allocated memory space to store compression state.
4733+ Use LZ4_sizeofState() to know how much memory must be allocated,
4734+ and allocate it on 8-bytes boundaries (using malloc() typically).
4735+ Then, provide it as 'void* state' to compression function.
4736+*/
4737+int LZ4_sizeofState(void);
4738+int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
4739+
4740+
4741+/*
4742+LZ4_compress_destSize() :
4743+ Reverse the logic, by compressing as much data as possible from 'source' buffer
4744+ into already allocated buffer 'dest' of size 'targetDestSize'.
4745+ This function either compresses the entire 'source' content into 'dest' if it's large enough,
4746+ or fill 'dest' buffer completely with as much data as possible from 'source'.
4747+ *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
4748+ New value is necessarily <= old value.
4749+ return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
4750+ or 0 if compression fails
4751+*/
4752+int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
4753+
4754+
4755+/***********************************************
4756+* Streaming Compression Functions
4757+***********************************************/
4758+#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
4759+#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
4760+/*
4761+ * LZ4_stream_t
4762+ * information structure to track an LZ4 stream.
4763+ * important : init this structure content before first use !
4764+ * note : only allocated directly the structure if you are statically linking LZ4
4765+ * If you are using liblz4 as a DLL, please use below construction methods instead.
4766+ */
4767+typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
4768+
4769+/*
4770+ * LZ4_resetStream
4771+ * Use this function to init an allocated LZ4_stream_t structure
4772+ */
4773+void LZ4_resetStream (LZ4_stream_t* streamPtr);
4774+
4775+/*
4776+ * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
4777+ * LZ4_freeStream releases its memory.
4778+ * In the context of a DLL (liblz4), please use these methods rather than the static struct.
4779+ * They are more future proof, in case of a change of LZ4_stream_t size.
4780+ */
4781+LZ4_stream_t* LZ4_createStream(void);
4782+int LZ4_freeStream (LZ4_stream_t* streamPtr);
4783+
4784+/*
4785+ * LZ4_loadDict
4786+ * Use this function to load a static dictionary into LZ4_stream.
4787+ * Any previous data will be forgotten, only 'dictionary' will remain in memory.
4788+ * Loading a size of 0 is allowed.
4789+ * Return : dictionary size, in bytes (necessarily <= 64 KB)
4790+ */
4791+int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
4792+
4793+/*
4794+ * LZ4_compress_fast_continue
4795+ * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
4796+ * Important : Previous data blocks are assumed to still be present and unmodified !
4797+ * 'dst' buffer must be already allocated.
4798+ * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
4799+ * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
4800+ */
4801+int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
4802+
4803+/*
4804+ * LZ4_saveDict
4805+ * If previously compressed data block is not guaranteed to remain available at its memory location
4806+ * save it into a safer place (char* safeBuffer)
4807+ * Note : you don't need to call LZ4_loadDict() afterwards,
4808+ * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
4809+ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
4810+ */
4811+int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
4812+
4813+typedef struct _LZ4_COMPSTATE {
4814+#ifdef _LZ4_STREAM
4815+ LZ4_stream_t lz4Stream;
4816+// LZ4_streamHC_t lz4hcStream;
4817+
4818+ #ifdef _LZ4_RINGBUFFER
4819+ char pRingBufBase[LZ4_RING_BUFC_SIZE];
4820+ #else
4821+ char pInBufBase[2][LZ4_BLOCK_DATA_SIZE];
4822+ #endif
4823+#else
4824+ #ifdef _LZ4_STREAMDICT
4825+ LZ4_stream_t lz4Stream;
4826+
4827+ char pInBufBase[LZ4_BLOCK_DATA_SIZE];
4828+ char pDictSave[LZ4_BLOCK_BUF_SIZE];
4829+
4830+ #endif
4831+#endif
4832+ char *pInBuf;
4833+ char *pInOverflow; /* For overflow input data incase compression is increasing the size */
4834+ char pCompBuf[LZ4_BLOCK_BUF_SIZE];
4835+ int inAvail;
4836+ int outBytes;
4837+ int recurse;
4838+ int iRingIndex;
4839+ int dictSize;
4840+ int level;
4841+ int finish;
4842+ } LZ4_COMPSTATE;
4843+
4844+typedef struct
4845+{
4846+ /* io */
4847+ char *next_in; /* next input byte */
4848+ unsigned int avail_in; /* number of bytes available at next_in */
4849+
4850+ char *next_out; /* next output byte should be put there */
4851+ unsigned int avail_out; /* remaining free space at next_out */
4852+
4853+ LZ4_COMPSTATE LZ4_State;
4854+} lz4_compstream;
4855+
4856+int LZ4_Init(lz4_compstream *stream, int level, int dict_size);
4857+int LZ4_End(lz4_compstream *stream);
4858+int LZ4_Compress(lz4_compstream *stream, int finish);
4859+
4860+
4861+#if defined (__cplusplus)
4862+}
4863+#endif
4864+
4865+#endif //__LZ4COMPRESS_H
4866Index: Source/lz4/lz4decompress.c
4867===================================================================
4868--- Source/lz4/lz4decompress.c (revision 0)
4869+++ Source/lz4/lz4decompress.c (working copy)
4870@@ -0,0 +1,1017 @@
4871+/*
4872+ LZ4 - Fast LZ compression algorithm
4873+ Copyright (C) 2011-2015, Yann Collet.
4874+
4875+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
4876+
4877+ Redistribution and use in source and binary forms, with or without
4878+ modification, are permitted provided that the following conditions are
4879+ met:
4880+
4881+ * Redistributions of source code must retain the above copyright
4882+ notice, this list of conditions and the following disclaimer.
4883+ * Redistributions in binary form must reproduce the above
4884+ copyright notice, this list of conditions and the following disclaimer
4885+ in the documentation and/or other materials provided with the
4886+ distribution.
4887+
4888+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4889+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4890+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4891+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4892+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4893+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4894+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4895+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4896+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4897+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4898+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4899+
4900+ You can contact the author at :
4901+ - LZ4 source repository : https://github.com/Cyan4973/lz4
4902+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
4903+*/
4904+
4905+/*
4906+ * lz4decompress.c
4907+ *
4908+ * This file is a part of the LZ4 compression module for NSIS.
4909+ *
4910+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
4911+ *
4912+ * Licensed under the zlib/libpng license (the "License");
4913+ * you may not use this file except in compliance with the License.
4914+ *
4915+ * Licence details can be found in the file COPYING.
4916+ *
4917+ * This software is provided 'as-is', without any express or implied
4918+ * warranty.
4919+ */
4920+
4921+/**************************************
4922+* Includes
4923+**************************************/
4924+#include "lz4decompress.h"
4925+
4926+
4927+/**************************************
4928+* Memory routines
4929+**************************************/
4930+#include "lz4common.h"
4931+
4932+
4933+/**************************************
4934+* Compiler Options
4935+**************************************/
4936+#ifdef _MSC_VER /* Visual Studio */
4937+# define FORCE_INLINE static __forceinline
4938+# include <intrin.h>
4939+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
4940+# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
4941+#else
4942+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
4943+# if defined(__GNUC__) || defined(__clang__)
4944+# define FORCE_INLINE static inline __attribute__((always_inline))
4945+# else
4946+# define FORCE_INLINE static inline
4947+# endif
4948+# else
4949+# define FORCE_INLINE static
4950+# endif /* __STDC_VERSION__ */
4951+#endif /* _MSC_VER */
4952+
4953+enum {
4954+ LZ4D_START = 0,
4955+ LZ4D_GETLENGTHFIRST,
4956+ LZ4D_GETLENGTHSECOND,
4957+ LZ4D_GETLENGTHTHIRD,
4958+ LZ4D_COPYIN,
4959+ LZ4D_COPYINFULL,
4960+ LZ4D_COPYINPARTIAL,
4961+ LZ4D_DECOMPRESSBLOCK,
4962+ LZ4D_FLUSHOUT,
4963+ LZ4D_STREAMEND,
4964+} LZ4D_STAGE;
4965+
4966+void lz4Init(lz4_decstream *s)
4967+{
4968+ int i;
4969+
4970+ for (i = 0; i < sizeof(s->LZ4_State); i++)
4971+ *((char *)&s->LZ4_State + i) = 0;
4972+
4973+#ifdef _LZ4_STREAM
4974+ #ifdef _LZ4_RINGBUFFER
4975+ s->LZ4_State.pDecBuf = s->LZ4_State.pRingBuf;
4976+ #else
4977+ s->LZ4_State.pDecBuf = s->LZ4_State.decBuf[0];
4978+ #endif
4979+ //LZ4_setStreamDecode(&s->LZ4_State.lz4StreamDecode, NULL, 0);
4980+#else
4981+ #ifdef _LZ4_STREAMDICT
4982+ // placeholder
4983+ #endif
4984+ s->LZ4_State.pDecBuf = s->LZ4_State.decBuf;
4985+#endif
4986+}
4987+
4988+int lz4Decode(lz4_decstream *s)
4989+{
4990+ for (;;)
4991+ {
4992+ switch (s->LZ4_State.stage)
4993+ {
4994+ case LZ4D_START:
4995+ case LZ4D_GETLENGTHFIRST:
4996+ if (s->avail_in < 1)
4997+ {
4998+ s->LZ4_State.stage = LZ4D_FLUSHOUT;
4999+ break;
5000+ }
5001+ s->LZ4_State.blockLength = 0;
5002+ s->LZ4_State.blockLength = (unsigned char)*s->next_in++, --s->avail_in;
5003+ s->LZ4_State.stage = LZ4D_GETLENGTHSECOND;
5004+ case LZ4D_GETLENGTHSECOND:
5005+ if (s->avail_in < 1)
5006+ return LZ4_OK;
5007+ s->LZ4_State.blockLength |= (unsigned short)(*s->next_in++ << 8) & 0xFF00, --s->avail_in;
5008+ s->LZ4_State.stage = LZ4D_GETLENGTHTHIRD;
5009+ case LZ4D_GETLENGTHTHIRD:
5010+ if (s->avail_in < 1)
5011+ return LZ4_OK;
5012+ s->LZ4_State.blockLength |= (unsigned int)(*s->next_in++ << 16) & 0xFF0000, --s->avail_in;
5013+ s->LZ4_State.stage = LZ4D_COPYIN;
5014+ case LZ4D_COPYIN:
5015+ if (s->LZ4_State.blockLength == 0 && !s->avail_in)
5016+ {
5017+ s->LZ4_State.stage = LZ4D_STREAMEND;
5018+ break;
5019+ }
5020+ s->LZ4_State.stage = s->LZ4_State.blockLength < s->avail_in ? LZ4D_COPYINFULL : LZ4D_COPYINPARTIAL;
5021+ break;
5022+ case LZ4D_COPYINFULL:
5023+ for (s->LZ4_State.inCount = 0; s->LZ4_State.inCount < s->LZ4_State.blockLength; s->LZ4_State.inCount++)
5024+ *(s->LZ4_State.pInBuf + s->LZ4_State.inCount) = *s->next_in++, --s->avail_in;
5025+ s->LZ4_State.stage = LZ4D_DECOMPRESSBLOCK;
5026+ break;
5027+ case LZ4D_COPYINPARTIAL:
5028+ {
5029+ unsigned int i, avail = s->LZ4_State.blockLength - s->LZ4_State.inCount < s->avail_in ? s->LZ4_State.blockLength - s->LZ4_State.inCount : s->avail_in;
5030+
5031+ for (i = 0; i < avail; i++)
5032+ *(s->LZ4_State.pInBuf + s->LZ4_State.inCount + i) = *s->next_in++, --s->avail_in;
5033+ s->LZ4_State.inCount += i;
5034+ if (s->LZ4_State.inCount < s->LZ4_State.blockLength) return LZ4_OK;
5035+ s->LZ4_State.stage = LZ4D_DECOMPRESSBLOCK;
5036+ }
5037+ case LZ4D_DECOMPRESSBLOCK:
5038+#ifdef _LZ4_BLOCKONLY
5039+ s->LZ4_State.decBytes = LZ4_decompress_safe(s->LZ4_State.pInBuf, s->LZ4_State.pDecBuf, s->LZ4_State.inCount, LZ4_BLOCK_DATA_SIZE);
5040+ if (s->LZ4_State.decBytes < 0)
5041+ return LZ4_DATA_ERROR;
5042+ s->LZ4_State.inCount = 0;
5043+ s->LZ4_State.decCount = s->LZ4_State.decBytes;
5044+ s->LZ4_State.stage = LZ4D_FLUSHOUT;
5045+#endif
5046+
5047+#ifdef _LZ4_STREAM
5048+ {
5049+#ifdef _LZ4_RINGBUFFER
5050+// char* const pDecBuf = &s->LZ4_State.pRingBuf[s->LZ4_State.iRingIndex];
5051+ s->LZ4_State.pDecBuf = &s->LZ4_State.pRingBuf[s->LZ4_State.iRingIndex];
5052+#else
5053+ s->LZ4_State.pDecBuf = s->LZ4_State.decBuf[s->LZ4_State.iRingIndex];
5054+#endif
5055+
5056+ s->LZ4_State.decBytes = LZ4_decompress_safe_continue(&s->LZ4_State.lz4StreamDecode, s->LZ4_State.pInBuf, s->LZ4_State.pDecBuf, s->LZ4_State.inCount, LZ4_BLOCK_DATA_SIZE);
5057+ if (s->LZ4_State.decBytes < 0)
5058+ return LZ4_DATA_ERROR;
5059+ s->LZ4_State.inCount = 0;
5060+ s->LZ4_State.decCount = s->LZ4_State.decBytes;
5061+ s->LZ4_State.iRingIndex += s->LZ4_State.decBytes;
5062+#ifdef _LZ4_RINGBUFFER
5063+ if (s->LZ4_State.iRingIndex >= (LZ4_RING_BUFD_SIZE - LZ4_BLOCK_DATA_SIZE))
5064+ s->LZ4_State.iRingIndex = 0;
5065+#else
5066+ s->LZ4_State.iRingIndex = (s->LZ4_State.iRingIndex + 1) % 2;
5067+#endif
5068+ s->LZ4_State.stage = LZ4_FLUSHOUT;
5069+ }
5070+#endif
5071+
5072+#ifdef _LZ4_STREAMDICT
5073+
5074+ s->LZ4_State.pDecBuf = s->LZ4_State.decBuf/*[s->LZ4_State.iRingIndex]*/;
5075+
5076+ s->LZ4_State.decBytes = LZ4_decompress_safe_continue(&s->LZ4_State.lz4StreamDecode, s->LZ4_State.pInBuf, s->LZ4_State.pDecBuf, s->LZ4_State.inCount, LZ4_BLOCK_DATA_SIZE);
5077+ if (s->LZ4_State.decBytes < 0)
5078+ return LZ4_DATA_ERROR;
5079+
5080+ {
5081+ int i;
5082+
5083+ for (i = 0; i < LZ4_BLOCK_DATA_SIZE - s->LZ4_State.decBytes; ++i)
5084+ s->LZ4_State.pDictSave[i] = s->LZ4_State.pDictSave[LZ4_BLOCK_DATA_SIZE - s->LZ4_State.decBytes];
5085+
5086+ for (i = 0; i < s->LZ4_State.decBytes; ++i)
5087+ s->LZ4_State.pDictSave[i + LZ4_BLOCK_DATA_SIZE - s->LZ4_State.decBytes] = s->LZ4_State.pDecBuf[i];
5088+
5089+ LZ4_setStreamDecode(&s->LZ4_State.lz4StreamDecode, s->LZ4_State.pDictSave, LZ4_BLOCK_DATA_SIZE);
5090+ }
5091+
5092+ s->LZ4_State.inCount = 0;
5093+ s->LZ4_State.decCount = s->LZ4_State.decBytes;
5094+ s->LZ4_State.iRingIndex += s->LZ4_State.decBytes;
5095+
5096+ s->LZ4_State.stage = LZ4D_FLUSHOUT;
5097+
5098+#endif
5099+ case LZ4D_FLUSHOUT:
5100+ {
5101+ unsigned int i;
5102+
5103+ if (s->avail_out && s->LZ4_State.decCount)
5104+ {
5105+ if (s->LZ4_State.decCount > s->LZ4_State.bufCount)
5106+ {
5107+ unsigned int copyLimit = s->LZ4_State.decCount - s->LZ4_State.bufCount > s->avail_out ? s->avail_out : s->LZ4_State.decCount - s->LZ4_State.bufCount;
5108+ for (i = 0; i < copyLimit; i++)
5109+ *s->next_out++ = *(s->LZ4_State.pDecBuf + s->LZ4_State.bufCount + i), --s->avail_out;
5110+ s->LZ4_State.bufCount += i;
5111+ return LZ4_OK;
5112+ }
5113+ else
5114+ {
5115+ s->LZ4_State.decCount = 0;
5116+ s->LZ4_State.bufCount = 0;
5117+ break;
5118+ }
5119+ }
5120+ else
5121+ {
5122+ s->LZ4_State.decCount = 0;
5123+ s->LZ4_State.bufCount = 0;
5124+ s->LZ4_State.inCount = 0;
5125+ s->LZ4_State.blockLength = 0;
5126+ if (s->avail_in)
5127+ s->LZ4_State.stage = LZ4D_START;
5128+ else
5129+ return LZ4_OK;
5130+ }
5131+ }
5132+ break;
5133+ case LZ4D_STREAMEND:
5134+ return LZ4_STREAM_END;
5135+ }
5136+ }
5137+ return LZ4_OK;
5138+}
5139+
5140+
5141+#ifndef LZ4_COMMONDEFS_ONLY
5142+
5143+//#define LZ4_STATEMACHINE
5144+
5145+#ifdef LZ4_STATEMACHINE
5146+
5147+FORCE_INLINE void flushOut(lz4_decstream *s)
5148+{
5149+ while (s->avail_out && s->st.outPos)
5150+ {
5151+ *s->next_out++ = s->st.decBuf[s->st.bufCount-s->st.outPos];
5152+ s->st.outPos--;
5153+ s->avail_out--;
5154+ }
5155+}
5156+
5157+FORCE_INLINE int outByte(lz4_decstream *s, char out)
5158+{
5159+// printf("s->st.bufCount=|%d|\n", s->st.bufCount);
5160+// if (s->st.bufCount >= 65535) s->st.bufCount = 65535;
5161+ if (s->st.outPos) flushOut(s);
5162+ if (s->st.bufCount >= 65535)
5163+ {
5164+ unsigned int i;
5165+
5166+ for (i = 0; i < 65535; i++)
5167+ s->st.decBuf[i] = s->st.decBuf[i+1];
5168+
5169+ s->st.decBuf[i] = out;
5170+ }
5171+ else
5172+ {
5173+ s->st.decBuf[s->st.bufCount] = out;
5174+ s->st.bufCount++; // = s->st.bufCount >= 65535 ? 65535 : s->st.bufCount + 1;
5175+ }
5176+ s->st.outPos++;
5177+ s->st.matchPos++;
5178+
5179+ return 1;
5180+}
5181+
5182+FORCE_INLINE int loadByte(lz4_decstream *s)
5183+{
5184+ if (!s->avail_in) return 0;
5185+ s->st.shortBuf = *s->next_in++;
5186+ s->avail_in--;
5187+
5188+ return 1;
5189+}
5190+
5191+FORCE_INLINE int loadShort(lz4_decstream *s)
5192+{
5193+ if (s->avail_in < 2) return 0;
5194+ s->st.shortBuf = *s->next_in++;
5195+ s->st.shortBuf = *s->next_in++ << 8;
5196+ s->avail_in -= 2;
5197+
5198+ return 1;
5199+}
5200+
5201+FORCE_INLINE char getByte(lz4_decstream *s)
5202+{
5203+ return (char)s->st.shortBuf;
5204+}
5205+
5206+FORCE_INLINE short getShort(lz4_decstream *s)
5207+{
5208+ return s->st.shortBuf;
5209+}
5210+
5211+FORCE_INLINE char getMatchByte(lz4_decstream *s)
5212+{
5213+ s->st.matchPos--;
5214+ return s->st.decBuf[s->st.matchPos];
5215+}
5216+
5217+void trace(int stage)
5218+{
5219+ //printf("Token number=|%d|\n", stage);
5220+}
5221+
5222+/*******************************
5223+* Decompression functions
5224+*******************************/
5225+/*
5226+ * This generic decompression function cover all use cases.
5227+ * It shall be instantiated several times, using different sets of directives
5228+ * Note that it is essential this generic function is really inlined,
5229+ * in order to remove useless branches during compilation optimization.
5230+ */
5231+FORCE_INLINE int LZ4_decompress_generic(lz4_decstream *s)
5232+{
5233+ /* Local Variables */
5234+// const BYTE* ip = (const BYTE*) s->next_in;
5235+// const BYTE* const iend = ip + s->avail_in;
5236+
5237+// BYTE* op = (BYTE*) s->next_out;
5238+// BYTE* const oend = op + s->avail_out;
5239+// BYTE* cpy;
5240+// BYTE* oexit = op + targetOutputSize;
5241+// const BYTE* const lowLimit = lowPrefix - dictSize;
5242+
5243+// const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
5244+ const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
5245+ const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
5246+
5247+// const int safeDecode = (endOnInput==endOnInputSize);
5248+// const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
5249+
5250+
5251+ /* Special cases */
5252+// if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
5253+// if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
5254+// if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
5255+
5256+ if (!s->avail_in) return LZ4_STREAM_END;
5257+
5258+
5259+ /* Main Loop */
5260+ while (s->avail_in && s->avail_out)
5261+ {
5262+ //printf("s->st.bufCount=|%d|\n", s->st.bufCount);
5263+ flushOut(s);
5264+ switch (s->st.stage)
5265+ {
5266+ case LZ4_START:
5267+ case LZ4_LENGTH:
5268+ if (!loadShort(s)) return LZ4_OK;
5269+ s->st.length = getShort(s);
5270+ s->st.stage = LZ4_TOKEN;
5271+ break;
5272+
5273+ case LZ4_TOKEN:
5274+// unsigned token;
5275+// size_t length;
5276+// const BYTE* match;
5277+ trace(s->st.stage);
5278+
5279+ /* get literal length */
5280+ if (!loadByte(s)) return LZ4_OK;
5281+ s->st.token = getByte(s);
5282+ s->st.litLen = s->st.token >> ML_BITS;
5283+ s->st.stage = (s->st.litLen == RUN_MASK) ? LZ4_TOKENRUN : LZ4_LITS;
5284+ break;
5285+
5286+ case LZ4_TOKENRUN:
5287+ {
5288+ unsigned char size;
5289+ trace(s->st.stage);
5290+ do
5291+ {
5292+ if (!loadByte(s)) return LZ4_OK;
5293+ size = getByte(s);
5294+ s->st.litLen += size;
5295+ }
5296+ while (size == 255);
5297+// while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));
5298+// if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
5299+// if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
5300+ s->st.stage = LZ4_LITS;
5301+ }
5302+ case LZ4_LITS:
5303+ trace(s->st.stage);
5304+
5305+ /* copy literals */
5306+// cpy = op+length;
5307+ while (s->st.litLen)
5308+ {
5309+ if (!s->avail_out) return LZ4_OK;
5310+ if (!loadByte(s)) return LZ4_OK;
5311+ outByte(s, getByte(s));
5312+ s->st.litLen--;
5313+// LZ4_wildCopy(op, ip, cpy);
5314+// ip += length; op = cpy;
5315+ }
5316+ s->st.stage = LZ4_MOFFSET;
5317+
5318+ case LZ4_MOFFSET:
5319+ trace(s->st.stage);
5320+
5321+ /* get offset */
5322+ if (s->avail_in < 2) return LZ4_OK;
5323+ s->st.matchPos = LZ4_readLE16(s->next_in);
5324+ s->next_in += 2;
5325+ s->avail_in -= 2;
5326+ if (s->st.matchPos > 65535) return -7;
5327+ s->st.stage = LZ4_MLEN;
5328+// if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
5329+
5330+ case LZ4_MLEN:
5331+ trace(s->st.stage);
5332+
5333+ /* get matchlength */
5334+ s->st.matchLen = s->st.token & ML_MASK;
5335+ s->st.stage = (s->st.matchLen == RUN_MASK) ? LZ4_MLENRUN : LZ4_DICT;
5336+ s->st.matchLen += MINMATCH;
5337+ break;
5338+
5339+ case LZ4_MLENRUN:
5340+ {
5341+ unsigned char size;
5342+ trace(s->st.stage);
5343+ do
5344+ {
5345+ if (!loadByte(s)) return LZ4_OK;
5346+ size = getByte(s);
5347+ s->st.matchLen += size;
5348+ }
5349+ while (size == 255);
5350+// if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
5351+ s->st.stage = LZ4_DICT;
5352+ }
5353+ case LZ4_DICT:
5354+ trace(s->st.stage);
5355+
5356+ if (s->st.matchPos < s->avail_in)
5357+ {
5358+ s->st.stage = LZ4_COPYREP;
5359+ break;
5360+ }
5361+ if ((int)(s->st.bufCount - s->st.matchPos + s->st.matchLen) < s->st.bufCount)
5362+ {
5363+ s->st.stage = LZ4_DICTCOPY;
5364+ }
5365+ else
5366+// if (s->st.matchPos + s->st.matchLen >= 0)
5367+ {
5368+ s->st.stage = LZ4_DICTAPPEND;
5369+ }
5370+ break;
5371+
5372+ case LZ4_DICTCOPY:
5373+ trace(s->st.stage);
5374+
5375+ /* match can be copied as a single segment from external dictionary */
5376+// match = dictEnd - (lowPrefix-match);
5377+// MEM_MOVE(op, match, length); op += length;
5378+ while (s->st.matchLen)
5379+ {
5380+ if (!outByte(s, getMatchByte(s))) return LZ4_OK;
5381+// s->st.matchPos--;
5382+ s->st.matchLen--;
5383+ }
5384+ s->st.stage = LZ4_COPYREP;
5385+ break;
5386+
5387+ case LZ4_DICTAPPEND:
5388+ trace(s->st.stage);
5389+
5390+ while (s->st.matchLen /*s->avail_out && s->avail_in*/)
5391+ {
5392+ if (s->st.matchPos > 0)
5393+ {
5394+ if (!outByte(s, getMatchByte(s))) return LZ4_OK;
5395+ }
5396+ else
5397+ {
5398+ if (!loadByte(s)) return LZ4_OK;
5399+ if (!outByte(s, getByte(s))) return LZ4_OK;
5400+ }
5401+ s->st.matchLen--;
5402+ }
5403+ s->st.stage = LZ4_COPYREP;
5404+ break;
5405+
5406+
5407+#if 0
5408+ /* check external dictionary */
5409+ if ((dict==usingExtDict) && (match < lowPrefix))
5410+ {
5411+ if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
5412+
5413+ if (length <= (size_t)(lowPrefix-match))
5414+ {
5415+ /* match can be copied as a single segment from external dictionary */
5416+ match = dictEnd - (lowPrefix-match);
5417+ MEM_MOVE(op, match, length); op += length;
5418+ }
5419+ else
5420+ {
5421+ /* match encompass external dictionary and current segment */
5422+ size_t copySize = (size_t)(lowPrefix-match);
5423+ MEM_CPY(op, dictEnd - copySize, copySize);
5424+ op += copySize;
5425+ copySize = length - copySize;
5426+ if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
5427+ {
5428+ BYTE* const endOfMatch = op + copySize;
5429+ const BYTE* copyFrom = lowPrefix;
5430+ while (op < endOfMatch) *op++ = *copyFrom++;
5431+ }
5432+ else
5433+ {
5434+ MEM_CPY(op, lowPrefix, copySize);
5435+ op += copySize;
5436+ }
5437+ }
5438+ continue;
5439+ }
5440+#endif
5441+ case LZ4_COPYREP:
5442+ trace(s->st.stage);
5443+
5444+ /* copy repeated sequence */
5445+// cpy = op + length;
5446+ if (s->avail_out < 8) return LZ4_OK;
5447+ if (s->st.matchLen)
5448+ {
5449+ if (unlikely((s->st.bufCount-s->st.matchPos)<8))
5450+ {
5451+ const size_t dec64 = dec64table[s->st.bufCount-s->st.matchPos];
5452+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5453+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5454+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5455+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5456+ s->st.matchLen -= dec32table[s->st.bufCount-s->st.matchLen];
5457+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5458+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5459+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5460+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos--]);
5461+ s->st.matchLen += dec64;
5462+ }
5463+ else
5464+ {
5465+ unsigned int i;
5466+
5467+ for (i = 0; i < 8; i++)
5468+ outByte(s, s->st.decBuf[s->st.bufCount-(s->st.matchPos-i)]);
5469+ s->st.matchPos -= 8;
5470+ s->st.matchLen -= 8;
5471+ }
5472+ }
5473+ s->st.stage = LZ4_LASTLITS;
5474+ s->st.lastLit = 5;
5475+
5476+ case LZ4_LASTLITS:
5477+ trace(s->st.stage);
5478+
5479+// if (s->avail_out < 12) return LZ4_OK;
5480+
5481+ while (s->st.lastLit)
5482+ {
5483+ if (!s->avail_out) return LZ4_OK;
5484+// if (!loadByte(s)) return LZ4_OK;
5485+ outByte(s, s->st.decBuf[s->st.bufCount-s->st.matchPos]);
5486+ s->st.matchPos--;
5487+// s->avail_out--;
5488+ s->st.lastLit--;
5489+// LZ4_wildCopy(op, ip, cpy);
5490+// ip += length; op = cpy;
5491+ }
5492+ s->st.stage = LZ4_START;
5493+ break;
5494+
5495+#if 0
5496+ if (unlikely(cpy>oend-12))
5497+ {
5498+ if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
5499+ if (op < oend-8)
5500+ {
5501+ LZ4_wildCopy(op, match, oend-8);
5502+ match += (oend-8) - op;
5503+ op = oend-8;
5504+ }
5505+ while (op<cpy) *op++ = *match++;
5506+ }
5507+ else
5508+ LZ4_wildCopy(op, match, cpy);
5509+ op=cpy; /* correction */
5510+#endif
5511+ }
5512+ }
5513+ flushOut(s);
5514+
5515+ return LZ4_OK;
5516+
5517+#if 0
5518+ /* end of decoding */
5519+ if (endOnInput)
5520+ return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
5521+ else
5522+ return (int) (((const char*)ip)-source); /* Nb of input bytes read */
5523+
5524+ /* Overflow error detected */
5525+_output_error:
5526+ return (int) (-(((const char*)ip)-source))-1;
5527+#endif
5528+}
5529+
5530+#else
5531+
5532+
5533+/*******************************
5534+* Decompression functions
5535+*******************************/
5536+/*
5537+ * This generic decompression function cover all use cases.
5538+ * It shall be instantiated several times, using different sets of directives
5539+ * Note that it is essential this generic function is really inlined,
5540+ * in order to remove useless branches during compilation optimization.
5541+ */
5542+FORCE_INLINE int LZ4_decompress_generic(
5543+ const char* const source,
5544+ char* const dest,
5545+ int inputSize,
5546+ int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
5547+
5548+ int endOnInput, /* endOnOutputSize, endOnInputSize */
5549+ int partialDecoding, /* full, partial */
5550+ int targetOutputSize, /* only used if partialDecoding==partial */
5551+ int dict, /* noDict, withPrefix64k, usingExtDict */
5552+ const BYTE* const lowPrefix, /* == dest if dict == noDict */
5553+ const BYTE* const dictStart, /* only if dict==usingExtDict */
5554+ const size_t dictSize /* note : = 0 if noDict */
5555+ )
5556+{
5557+ /* Local Variables */
5558+ const BYTE* ip = (const BYTE*) source;
5559+ const BYTE* const iend = ip + inputSize;
5560+
5561+ BYTE* op = (BYTE*) dest;
5562+ BYTE* const oend = op + outputSize;
5563+ BYTE* cpy;
5564+ BYTE* oexit = op + targetOutputSize;
5565+ const BYTE* const lowLimit = lowPrefix - dictSize;
5566+
5567+ const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
5568+ const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
5569+ const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
5570+
5571+ const int safeDecode = (endOnInput==endOnInputSize);
5572+ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
5573+
5574+
5575+ /* Special cases */
5576+ if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
5577+ if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
5578+ if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
5579+
5580+
5581+ /* Main Loop */
5582+ while (1)
5583+ {
5584+ unsigned token;
5585+ size_t length;
5586+ const BYTE* match;
5587+
5588+ /* get literal length */
5589+ token = *ip++;
5590+ if ((length=(token>>ML_BITS)) == RUN_MASK)
5591+ {
5592+ unsigned s;
5593+ do
5594+ {
5595+ s = *ip++;
5596+ length += s;
5597+ }
5598+ while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));
5599+ if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
5600+ if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
5601+ }
5602+
5603+ /* copy literals */
5604+ cpy = op+length;
5605+ if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
5606+ || ((!endOnInput) && (cpy>oend-COPYLENGTH)))
5607+ {
5608+ if (partialDecoding)
5609+ {
5610+ if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
5611+ if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
5612+ }
5613+ else
5614+ {
5615+ if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
5616+ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
5617+ }
5618+ MEM_CPY(op, ip, length);
5619+ ip += length;
5620+ op += length;
5621+ break; /* Necessarily EOF, due to parsing restrictions */
5622+ }
5623+ LZ4_wildCopy(op, ip, cpy);
5624+ ip += length; op = cpy;
5625+
5626+ /* get offset */
5627+ match = cpy - LZ4_readLE16(ip); ip+=2;
5628+ if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
5629+
5630+ /* get matchlength */
5631+ length = token & ML_MASK;
5632+ if (length == ML_MASK)
5633+ {
5634+ unsigned s;
5635+ do
5636+ {
5637+ if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
5638+ s = *ip++;
5639+ length += s;
5640+ } while (s==255);
5641+ if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
5642+ }
5643+ length += MINMATCH;
5644+
5645+ /* check external dictionary */
5646+ if ((dict==usingExtDict) && (match < lowPrefix))
5647+ {
5648+ if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
5649+
5650+ if (length <= (size_t)(lowPrefix-match))
5651+ {
5652+ /* match can be copied as a single segment from external dictionary */
5653+ match = dictEnd - (lowPrefix-match);
5654+ MEM_MOVE(op, match, length); op += length;
5655+ }
5656+ else
5657+ {
5658+ /* match encompass external dictionary and current segment */
5659+ size_t copySize = (size_t)(lowPrefix-match);
5660+ MEM_CPY(op, dictEnd - copySize, copySize);
5661+ op += copySize;
5662+ copySize = length - copySize;
5663+ if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
5664+ {
5665+ BYTE* const endOfMatch = op + copySize;
5666+ const BYTE* copyFrom = lowPrefix;
5667+ while (op < endOfMatch) *op++ = *copyFrom++;
5668+ }
5669+ else
5670+ {
5671+ MEM_CPY(op, lowPrefix, copySize);
5672+ op += copySize;
5673+ }
5674+ }
5675+ continue;
5676+ }
5677+
5678+ /* copy repeated sequence */
5679+ cpy = op + length;
5680+ if (unlikely((op-match)<8))
5681+ {
5682+ const size_t dec64 = dec64table[op-match];
5683+ op[0] = match[0];
5684+ op[1] = match[1];
5685+ op[2] = match[2];
5686+ op[3] = match[3];
5687+ match += dec32table[op-match];
5688+ LZ4_copy4(op+4, match);
5689+ op += 8; match -= dec64;
5690+ } else { LZ4_copy8(op, match); op+=8; match+=8; }
5691+
5692+ if (unlikely(cpy>oend-12))
5693+ {
5694+ if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
5695+ if (op < oend-8)
5696+ {
5697+ LZ4_wildCopy(op, match, oend-8);
5698+ match += (oend-8) - op;
5699+ op = oend-8;
5700+ }
5701+ while (op<cpy) *op++ = *match++;
5702+ }
5703+ else
5704+ LZ4_wildCopy(op, match, cpy);
5705+ op=cpy; /* correction */
5706+ }
5707+
5708+ /* end of decoding */
5709+ if (endOnInput)
5710+ return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
5711+ else
5712+ return (int) (((const char*)ip)-source); /* Nb of input bytes read */
5713+
5714+ /* Overflow error detected */
5715+_output_error:
5716+ return (int) (-(((const char*)ip)-source))-1;
5717+}
5718+
5719+#endif
5720+
5721+
5722+
5723+#if 1
5724+int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
5725+{
5726+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
5727+}
5728+
5729+int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
5730+{
5731+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
5732+}
5733+
5734+int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
5735+{
5736+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
5737+}
5738+
5739+#endif
5740+/* streaming decompression functions */
5741+
5742+typedef struct
5743+{
5744+ const BYTE* externalDict;
5745+ size_t extDictSize;
5746+ const BYTE* prefixEnd;
5747+ size_t prefixSize;
5748+} LZ4_streamDecode_t_internal;
5749+
5750+/*
5751+ * If you prefer dynamic allocation methods,
5752+ * LZ4_createStreamDecode()
5753+ * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
5754+ */
5755+LZ4_streamDecode_t* LZ4_createStreamDecode(void)
5756+{
5757+ LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
5758+ return lz4s;
5759+}
5760+
5761+int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
5762+{
5763+ FREEMEM(LZ4_stream);
5764+ return 0;
5765+}
5766+
5767+/*
5768+ * LZ4_setStreamDecode
5769+ * Use this function to instruct where to find the dictionary
5770+ * This function is not necessary if previous data is still available where it was decoded.
5771+ * Loading a size of 0 is allowed (same effect as no dictionary).
5772+ * Return : 1 if OK, 0 if error
5773+ */
5774+int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
5775+{
5776+ LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
5777+ lz4sd->prefixSize = (size_t) dictSize;
5778+ lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
5779+ lz4sd->externalDict = NULL;
5780+ lz4sd->extDictSize = 0;
5781+ return 1;
5782+}
5783+#if 1
5784+/*
5785+*_continue() :
5786+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
5787+ Previously decoded blocks must still be available at the memory position where they were decoded.
5788+ If it's not possible, save the relevant part of decoded data into a safe buffer,
5789+ and indicate where it stands using LZ4_setStreamDecode()
5790+*/
5791+int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
5792+{
5793+ LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
5794+ int result;
5795+
5796+ if (lz4sd->prefixEnd == (BYTE*)dest)
5797+ {
5798+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
5799+ endOnInputSize, full, 0,
5800+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
5801+ if (result <= 0) return result;
5802+ lz4sd->prefixSize += result;
5803+ lz4sd->prefixEnd += result;
5804+ }
5805+ else
5806+ {
5807+ lz4sd->extDictSize = lz4sd->prefixSize;
5808+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
5809+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
5810+ endOnInputSize, full, 0,
5811+ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
5812+ if (result <= 0) return result;
5813+ lz4sd->prefixSize = result;
5814+ lz4sd->prefixEnd = (BYTE*)dest + result;
5815+ }
5816+
5817+ return result;
5818+}
5819+
5820+int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
5821+{
5822+ LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
5823+ int result;
5824+
5825+ if (lz4sd->prefixEnd == (BYTE*)dest)
5826+ {
5827+ result = LZ4_decompress_generic(source, dest, 0, originalSize,
5828+ endOnOutputSize, full, 0,
5829+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
5830+ if (result <= 0) return result;
5831+ lz4sd->prefixSize += originalSize;
5832+ lz4sd->prefixEnd += originalSize;
5833+ }
5834+ else
5835+ {
5836+ lz4sd->extDictSize = lz4sd->prefixSize;
5837+ lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
5838+ result = LZ4_decompress_generic(source, dest, 0, originalSize,
5839+ endOnOutputSize, full, 0,
5840+ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
5841+ if (result <= 0) return result;
5842+ lz4sd->prefixSize = originalSize;
5843+ lz4sd->prefixEnd = (BYTE*)dest + originalSize;
5844+ }
5845+
5846+ return result;
5847+}
5848+
5849+
5850+/*
5851+Advanced decoding functions :
5852+*_usingDict() :
5853+ These decoding functions work the same as "_continue" ones,
5854+ the dictionary must be explicitly provided within parameters
5855+*/
5856+
5857+FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
5858+{
5859+ if (dictSize==0)
5860+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
5861+ if (dictStart+dictSize == dest)
5862+ {
5863+ if (dictSize >= (int)(64 KB - 1))
5864+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
5865+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
5866+ }
5867+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
5868+}
5869+
5870+int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
5871+{
5872+ return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
5873+}
5874+
5875+int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
5876+{
5877+ return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
5878+}
5879+
5880+/* debug function */
5881+int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
5882+{
5883+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
5884+}
5885+#endif
5886+
5887+#endif /* LZ4_COMMONDEFS_ONLY */
5888Index: Source/lz4/lz4decompress.h
5889===================================================================
5890--- Source/lz4/lz4decompress.h (revision 0)
5891+++ Source/lz4/lz4decompress.h (working copy)
5892@@ -0,0 +1,269 @@
5893+/*
5894+ LZ4 - Fast LZ compression algorithm
5895+ Header File
5896+ Copyright (C) 2011-2015, Yann Collet.
5897+
5898+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5899+
5900+ Redistribution and use in source and binary forms, with or without
5901+ modification, are permitted provided that the following conditions are
5902+ met:
5903+
5904+ * Redistributions of source code must retain the above copyright
5905+ notice, this list of conditions and the following disclaimer.
5906+ * Redistributions in binary form must reproduce the above
5907+ copyright notice, this list of conditions and the following disclaimer
5908+ in the documentation and/or other materials provided with the
5909+ distribution.
5910+
5911+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5912+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5913+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5914+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5915+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5916+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5917+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5918+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5919+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5920+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5921+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5922+
5923+ You can contact the author at :
5924+ - LZ4 source repository : https://github.com/Cyan4973/lz4
5925+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
5926+*/
5927+
5928+/*
5929+ * lz4decompress.h
5930+ *
5931+ * This file is a part of the LZ4 compression module for NSIS.
5932+ *
5933+ * Copyright (C) 2016-2017 Jason Ross (JasonFriday13)
5934+ *
5935+ * Licensed under the zlib/libpng license (the "License");
5936+ * you may not use this file except in compliance with the License.
5937+ *
5938+ * Licence details can be found in the file COPYING.
5939+ *
5940+ * This software is provided 'as-is', without any express or implied
5941+ * warranty.
5942+ */
5943+
5944+#ifndef __LZ4DECOMPRESS_H
5945+#define __LZ4DECOMPRESS_H
5946+
5947+#include "lz4common.h"
5948+
5949+#if defined (__cplusplus)
5950+extern "C" {
5951+#endif
5952+
5953+/*
5954+ * lz4.h provides block compression functions, and gives full buffer control to programmer.
5955+ * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
5956+ * and can let the library handle its own memory, please use lz4frame.h instead.
5957+*/
5958+
5959+/**************************************
5960+* Simple Functions
5961+**************************************/
5962+
5963+int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
5964+
5965+/*
5966+LZ4_decompress_safe() :
5967+ compressedSize : is the precise full size of the compressed block.
5968+ maxDecompressedSize : is the size of destination buffer, which must be already allocated.
5969+ return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
5970+ If destination buffer is not large enough, decoding will stop and output an error code (<0).
5971+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
5972+ This function is protected against buffer overflow exploits, including malicious data packets.
5973+ It never writes outside output buffer, nor reads outside input buffer.
5974+*/
5975+
5976+
5977+/**************************************
5978+* Advanced Functions
5979+**************************************/
5980+
5981+/*
5982+LZ4_decompress_fast() :
5983+ originalSize : is the original and therefore uncompressed size
5984+ return : the number of bytes read from the source buffer (in other words, the compressed size)
5985+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
5986+ Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
5987+ note : This function fully respect memory boundaries for properly formed compressed data.
5988+ It is a bit faster than LZ4_decompress_safe().
5989+ However, it does not provide any protection against intentionally modified data stream (malicious input).
5990+ Use this function in trusted environment only (data to decode comes from a trusted source).
5991+*/
5992+int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
5993+
5994+/*
5995+LZ4_decompress_safe_partial() :
5996+ This function decompress a compressed block of size 'compressedSize' at position 'source'
5997+ into destination buffer 'dest' of size 'maxDecompressedSize'.
5998+ The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
5999+ reducing decompression time.
6000+ return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
6001+ Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
6002+ Always control how many bytes were decoded.
6003+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
6004+ This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
6005+*/
6006+int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
6007+
6008+
6009+/************************************************
6010+* Streaming Decompression Functions
6011+************************************************/
6012+
6013+#define LZ4_STREAMDECODESIZE_U64 4
6014+#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
6015+typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t;
6016+/*
6017+ * LZ4_streamDecode_t
6018+ * information structure to track an LZ4 stream.
6019+ * init this structure content using LZ4_setStreamDecode or memset() before first use !
6020+ *
6021+ * In the context of a DLL (liblz4) please prefer usage of construction methods below.
6022+ * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
6023+ * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
6024+ * LZ4_freeStreamDecode releases its memory.
6025+ */
6026+LZ4_streamDecode_t* LZ4_createStreamDecode(void);
6027+int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
6028+
6029+/*
6030+ * LZ4_setStreamDecode
6031+ * Use this function to instruct where to find the dictionary.
6032+ * Setting a size of 0 is allowed (same effect as reset).
6033+ * Return : 1 if OK, 0 if error
6034+ */
6035+int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
6036+
6037+/*
6038+*_continue() :
6039+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
6040+ Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
6041+ In the case of a ring buffers, decoding buffer must be either :
6042+ - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
6043+ In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
6044+ - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
6045+ maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
6046+ In which case, encoding and decoding buffers do not need to be synchronized,
6047+ and encoding ring buffer can have any size, including small ones ( < 64 KB).
6048+ - _At least_ 64 KB + 8 bytes + maxBlockSize.
6049+ In which case, encoding and decoding buffers do not need to be synchronized,
6050+ and encoding ring buffer can have any size, including larger than decoding buffer.
6051+ Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
6052+ and indicate where it is saved using LZ4_setStreamDecode()
6053+*/
6054+int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
6055+int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
6056+
6057+
6058+/*
6059+Advanced decoding functions :
6060+*_usingDict() :
6061+ These decoding functions work the same as
6062+ a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
6063+ They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
6064+*/
6065+int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
6066+int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
6067+
6068+#if 0
6069+enum
6070+{
6071+ LZ4_START = 0,
6072+ LZ4_LENGTH,
6073+ LZ4_TOKEN,
6074+ LZ4_TOKENRUN,
6075+ LZ4_LITS,
6076+ LZ4_MOFFSET,
6077+ LZ4_MLEN,
6078+ LZ4_MLENRUN,
6079+ LZ4_DICT,
6080+ LZ4_DICTCOPY,
6081+ LZ4_DICTAPPEND,
6082+ LZ4_COPYREP,
6083+ LZ4_LASTLITS,
6084+};
6085+#endif
6086+
6087+typedef struct _LZ4_DECSTATE {
6088+ char pInBuf[LZ4_BLOCK_BUF_SIZE];
6089+
6090+ unsigned int inCount;
6091+ unsigned int blockLength;
6092+#ifdef _LZ4_STREAM
6093+ LZ4_streamDecode_t lz4StreamDecode;
6094+ #ifdef _LZ4_RINGBUFFER
6095+ char pRingBuf[LZ4_RING_BUFD_SIZE];
6096+ #else
6097+ char decBuf[2][LZ4_BLOCK_DATA_SIZE];
6098+ #endif
6099+#else
6100+ #ifdef _LZ4_STREAMDICT
6101+ LZ4_streamDecode_t lz4StreamDecode;
6102+ char pDictSave[LZ4_BLOCK_DATA_SIZE];
6103+ #endif
6104+ char decBuf[LZ4_BLOCK_DATA_SIZE];
6105+#endif
6106+ char *pDecBuf;
6107+ int decBytes;
6108+ unsigned int decCount;
6109+ unsigned int bufCount;
6110+ unsigned int outPos;
6111+ unsigned int iRingIndex;
6112+
6113+ int stage;
6114+
6115+#if 0
6116+ unsigned short length;
6117+ unsigned char token;
6118+ unsigned int litLen;
6119+ unsigned short offset;
6120+ unsigned int matchLen;
6121+ unsigned int matchPos;
6122+ unsigned int matchPosActual;
6123+ unsigned short lastLit;
6124+
6125+ size_t dictSize;
6126+#endif
6127+
6128+ } LZ4_DECSTATE;
6129+
6130+
6131+typedef struct
6132+{
6133+ /* io */
6134+ unsigned char *next_in; /* next input byte */
6135+ unsigned int avail_in; /* number of bytes available at next_in */
6136+
6137+ unsigned char *next_out; /* next output byte should be put there */
6138+ unsigned int avail_out; /* remaining free space at next_out */
6139+
6140+ //LZ4_errorCode_t r;
6141+// unsigned short next_block_length;
6142+// unsigned short next_block_used;
6143+// char inBuf[65536];
6144+// char lz4DictSave[65536];
6145+// int lz4DictLength;
6146+
6147+ LZ4_DECSTATE LZ4_State;
6148+
6149+// LZ4F_decompressOptions_t dop;
6150+// LZ4F_decompressionContext_t dctx;
6151+} lz4_decstream;
6152+
6153+void lz4Init(lz4_decstream *s);
6154+int lz4Decode(lz4_decstream *s);
6155+
6156+
6157+#if defined (__cplusplus)
6158+}
6159+#endif
6160+
6161+#endif //__LZ4DECOMPRESS_H
6162Index: Source/lz4/lz4hccompress.c
6163===================================================================
6164--- Source/lz4/lz4hccompress.c (revision 0)
6165+++ Source/lz4/lz4hccompress.c (working copy)
6166@@ -0,0 +1,739 @@
6167+/*
6168+ LZ4 HC - High Compression Mode of LZ4
6169+ Copyright (C) 2011-2015, Yann Collet.
6170+
6171+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6172+
6173+ Redistribution and use in source and binary forms, with or without
6174+ modification, are permitted provided that the following conditions are
6175+ met:
6176+
6177+ * Redistributions of source code must retain the above copyright
6178+ notice, this list of conditions and the following disclaimer.
6179+ * Redistributions in binary form must reproduce the above
6180+ copyright notice, this list of conditions and the following disclaimer
6181+ in the documentation and/or other materials provided with the
6182+ distribution.
6183+
6184+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6185+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6186+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6187+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6188+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6189+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6190+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6191+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6192+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6193+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6194+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6195+
6196+ You can contact the author at :
6197+ - LZ4 source repository : https://github.com/Cyan4973/lz4
6198+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
6199+*/
6200+
6201+/*
6202+ * lz4hccompress.c
6203+ *
6204+ * This file is a part of the LZ4 compression module for NSIS.
6205+ *
6206+ * Copyright (C) 2017 Jason Ross (JasonFriday13)
6207+ *
6208+ * Licensed under the zlib/libpng license (the "License");
6209+ * you may not use this file except in compliance with the License.
6210+ *
6211+ * Licence details can be found in the file COPYING.
6212+ *
6213+ * This software is provided 'as-is', without any express or implied
6214+ * warranty.
6215+ */
6216+
6217+/**************************************
6218+* Tuning Parameter
6219+**************************************/
6220+static const int LZ4HC_compressionLevel_default = 9;
6221+
6222+
6223+/**************************************
6224+* Includes
6225+**************************************/
6226+#include "lz4common.h"
6227+#include "lz4hccompress.h"
6228+
6229+
6230+/**************************************
6231+* Local Compiler Options
6232+**************************************/
6233+#if defined(__GNUC__)
6234+# pragma GCC diagnostic ignored "-Wunused-function"
6235+#endif
6236+
6237+#if defined (__clang__)
6238+# pragma clang diagnostic ignored "-Wunused-function"
6239+#endif
6240+
6241+
6242+/**************************************
6243+* Local Constants
6244+**************************************/
6245+static const int g_maxCompressionLevel = 16;
6246+
6247+#define DICTIONARY_LOGSIZEHC 16
6248+#define MAXDHC (1<<DICTIONARY_LOGSIZEHC)
6249+#define MAXDHC_MASK (MAXDHC - 1)
6250+
6251+#define HASH_LOGHC (DICTIONARY_LOGSIZEHC-1)
6252+#define HASHTABLESIZEHC (1 << HASH_LOGHC)
6253+#define HASH_MASKHC (HASHTABLESIZEHC - 1)
6254+
6255+#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
6256+
6257+
6258+/**************************************
6259+* Local Types
6260+**************************************/
6261+typedef struct
6262+{
6263+ U32 hashTable[HASHTABLESIZEHC];
6264+ U16 chainTable[MAXDHC];
6265+ const BYTE* end; /* next block here to continue on current prefix */
6266+ const BYTE* base; /* All index relative to this position */
6267+ const BYTE* dictBase; /* alternate base for extDict */
6268+ BYTE* inputBuffer; /* deprecated */
6269+ U32 dictLimit; /* below that point, need extDict */
6270+ U32 lowLimit; /* below that point, no more dict */
6271+ U32 nextToUpdate; /* index from which to continue dictionary update */
6272+ U32 compressionLevel;
6273+} LZ4HC_Data_Structure;
6274+
6275+
6276+/**************************************
6277+* Local Macros
6278+**************************************/
6279+#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOGHC))
6280+//#define DELTANEXTU16(p) chainTable[(p) & MAXD_MASK] /* flexible, MAXD dependent */
6281+#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */
6282+
6283+static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
6284+
6285+
6286+
6287+/**************************************
6288+* HC Compression
6289+**************************************/
6290+static void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start)
6291+{
6292+ MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
6293+ MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
6294+ hc4->nextToUpdate = 64 KB;
6295+ hc4->base = start - 64 KB;
6296+ hc4->end = start;
6297+ hc4->dictBase = start - 64 KB;
6298+ hc4->dictLimit = 64 KB;
6299+ hc4->lowLimit = 64 KB;
6300+}
6301+
6302+
6303+/* Update chains up to ip (excluded) */
6304+void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
6305+{
6306+ U16* chainTable = hc4->chainTable;
6307+ U32* HashTable = hc4->hashTable;
6308+ const BYTE* const base = hc4->base;
6309+ const U32 target = (U32)(ip - base);
6310+ U32 idx = hc4->nextToUpdate;
6311+
6312+ while(idx < target)
6313+ {
6314+ U32 h = LZ4HC_hashPtr(base+idx);
6315+ size_t delta = idx - HashTable[h];
6316+ if (delta>MAXDHC) delta = MAXDHC;
6317+ DELTANEXTU16(idx) = (U16)delta;
6318+ HashTable[h] = idx;
6319+ idx++;
6320+ }
6321+
6322+ hc4->nextToUpdate = target;
6323+}
6324+
6325+
6326+int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, /* Index table will be updated */
6327+ const BYTE* ip, const BYTE* const iLimit,
6328+ const BYTE** matchpos,
6329+ const int maxNbAttempts)
6330+{
6331+ U16* const chainTable = hc4->chainTable;
6332+ U32* const HashTable = hc4->hashTable;
6333+ const BYTE* const base = hc4->base;
6334+ const BYTE* const dictBase = hc4->dictBase;
6335+ const U32 dictLimit = hc4->dictLimit;
6336+ const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
6337+ U32 matchIndex;
6338+ const BYTE* match;
6339+ int nbAttempts=maxNbAttempts;
6340+ size_t ml=0;
6341+
6342+ /* HC4 match finder */
6343+ LZ4HC_Insert(hc4, ip);
6344+ matchIndex = HashTable[LZ4HC_hashPtr(ip)];
6345+
6346+ while ((matchIndex>=lowLimit) && (nbAttempts))
6347+ {
6348+ nbAttempts--;
6349+ if (matchIndex >= dictLimit)
6350+ {
6351+ match = base + matchIndex;
6352+ if (*(match+ml) == *(ip+ml)
6353+ && (LZ4_read32(match) == LZ4_read32(ip)))
6354+ {
6355+ size_t mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
6356+ if (mlt > ml) { ml = mlt; *matchpos = match; }
6357+ }
6358+ }
6359+ else
6360+ {
6361+ match = dictBase + matchIndex;
6362+ if (LZ4_read32(match) == LZ4_read32(ip))
6363+ {
6364+ size_t mlt;
6365+ const BYTE* vLimit = ip + (dictLimit - matchIndex);
6366+ if (vLimit > iLimit) vLimit = iLimit;
6367+ mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
6368+ if ((ip+mlt == vLimit) && (vLimit < iLimit))
6369+ mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
6370+ if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
6371+ }
6372+ }
6373+ matchIndex -= DELTANEXTU16(matchIndex);
6374+ }
6375+
6376+ return (int)ml;
6377+}
6378+
6379+
6380+int LZ4HC_InsertAndGetWiderMatch (
6381+ LZ4HC_Data_Structure* hc4,
6382+ const BYTE* const ip,
6383+ const BYTE* const iLowLimit,
6384+ const BYTE* const iHighLimit,
6385+ int longest,
6386+ const BYTE** matchpos,
6387+ const BYTE** startpos,
6388+ const int maxNbAttempts)
6389+{
6390+ U16* const chainTable = hc4->chainTable;
6391+ U32* const HashTable = hc4->hashTable;
6392+ const BYTE* const base = hc4->base;
6393+ const U32 dictLimit = hc4->dictLimit;
6394+ const BYTE* const lowPrefixPtr = base + dictLimit;
6395+ const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
6396+ const BYTE* const dictBase = hc4->dictBase;
6397+ U32 matchIndex;
6398+ int nbAttempts = maxNbAttempts;
6399+ int delta = (int)(ip-iLowLimit);
6400+
6401+
6402+ /* First Match */
6403+ LZ4HC_Insert(hc4, ip);
6404+ matchIndex = HashTable[LZ4HC_hashPtr(ip)];
6405+
6406+ while ((matchIndex>=lowLimit) && (nbAttempts))
6407+ {
6408+ nbAttempts--;
6409+ if (matchIndex >= dictLimit)
6410+ {
6411+ const BYTE* matchPtr = base + matchIndex;
6412+ if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
6413+ if (LZ4_read32(matchPtr) == LZ4_read32(ip))
6414+ {
6415+ int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
6416+ int back = 0;
6417+
6418+ while ((ip+back>iLowLimit)
6419+ && (matchPtr+back > lowPrefixPtr)
6420+ && (ip[back-1] == matchPtr[back-1]))
6421+ back--;
6422+
6423+ mlt -= back;
6424+
6425+ if (mlt > longest)
6426+ {
6427+ longest = (int)mlt;
6428+ *matchpos = matchPtr+back;
6429+ *startpos = ip+back;
6430+ }
6431+ }
6432+ }
6433+ else
6434+ {
6435+ const BYTE* matchPtr = dictBase + matchIndex;
6436+ if (LZ4_read32(matchPtr) == LZ4_read32(ip))
6437+ {
6438+ size_t mlt;
6439+ int back=0;
6440+ const BYTE* vLimit = ip + (dictLimit - matchIndex);
6441+ if (vLimit > iHighLimit) vLimit = iHighLimit;
6442+ mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
6443+ if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
6444+ mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
6445+ while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
6446+ mlt -= back;
6447+ if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
6448+ }
6449+ }
6450+ matchIndex -= DELTANEXTU16(matchIndex);
6451+ }
6452+
6453+ return longest;
6454+}
6455+
6456+
6457+//typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
6458+
6459+#define LZ4HC_DEBUG 0
6460+#if LZ4HC_DEBUG
6461+static unsigned debug = 0;
6462+#endif
6463+
6464+int LZ4HC_encodeSequence (
6465+ const BYTE** ip,
6466+ BYTE** op,
6467+ const BYTE** anchor,
6468+ int matchLength,
6469+ const BYTE* const match,
6470+ limitedOutput_directive limitedOutputBuffer,
6471+ BYTE* oend)
6472+{
6473+ int length;
6474+ BYTE* token;
6475+
6476+#if LZ4HC_DEBUG
6477+ if (debug) printf("literal : %u -- match : %u -- offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
6478+#endif
6479+
6480+ /* Encode Literal length */
6481+ length = (int)(*ip - *anchor);
6482+ token = (*op)++;
6483+ if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */
6484+ if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; }
6485+ else *token = (BYTE)(length<<ML_BITS);
6486+
6487+ /* Copy Literals */
6488+ LZ4_wildCopy(*op, *anchor, (*op) + length);
6489+ *op += length;
6490+
6491+ /* Encode Offset */
6492+ LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
6493+
6494+ /* Encode MatchLength */
6495+ length = (int)(matchLength-MINMATCH);
6496+ if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */
6497+ if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }
6498+ else *token += (BYTE)(length);
6499+
6500+ /* Prepare next loop */
6501+ *ip += matchLength;
6502+ *anchor = *ip;
6503+
6504+ return 0;
6505+}
6506+
6507+
6508+static int LZ4HC_compress_generic (
6509+ void* ctxvoid,
6510+ const char* source,
6511+ char* dest,
6512+ int inputSize,
6513+ int maxOutputSize,
6514+ int compressionLevel,
6515+ limitedOutput_directive limit
6516+ )
6517+{
6518+ LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid;
6519+ const BYTE* ip = (const BYTE*) source;
6520+ const BYTE* anchor = ip;
6521+ const BYTE* const iend = ip + inputSize;
6522+ const BYTE* const mflimit = iend - MFLIMIT;
6523+ const BYTE* const matchlimit = (iend - LASTLITERALS);
6524+
6525+ BYTE* op = (BYTE*) dest;
6526+ BYTE* const oend = op + maxOutputSize;
6527+
6528+ unsigned maxNbAttempts;
6529+ int ml, ml2, ml3, ml0;
6530+ const BYTE* ref=NULL;
6531+ const BYTE* start2=NULL;
6532+ const BYTE* ref2=NULL;
6533+ const BYTE* start3=NULL;
6534+ const BYTE* ref3=NULL;
6535+ const BYTE* start0;
6536+ const BYTE* ref0;
6537+
6538+
6539+ /* init */
6540+ if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel;
6541+ if (compressionLevel < 1) compressionLevel = LZ4HC_compressionLevel_default;
6542+ maxNbAttempts = 1 << (compressionLevel-1);
6543+ ctx->end += inputSize;
6544+
6545+ ip++;
6546+
6547+ /* Main Loop */
6548+ while (ip < mflimit)
6549+ {
6550+ ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
6551+ if (!ml) { ip++; continue; }
6552+
6553+ /* saved, in case we would skip too much */
6554+ start0 = ip;
6555+ ref0 = ref;
6556+ ml0 = ml;
6557+
6558+_Search2:
6559+ if (ip+ml < mflimit)
6560+ ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts);
6561+ else ml2 = ml;
6562+
6563+ if (ml2 == ml) /* No better match */
6564+ {
6565+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
6566+ continue;
6567+ }
6568+
6569+ if (start0 < ip)
6570+ {
6571+ if (start2 < ip + ml0) /* empirical */
6572+ {
6573+ ip = start0;
6574+ ref = ref0;
6575+ ml = ml0;
6576+ }
6577+ }
6578+
6579+ /* Here, start0==ip */
6580+ if ((start2 - ip) < 3) /* First Match too small : removed */
6581+ {
6582+ ml = ml2;
6583+ ip = start2;
6584+ ref =ref2;
6585+ goto _Search2;
6586+ }
6587+
6588+_Search3:
6589+ /*
6590+ * Currently we have :
6591+ * ml2 > ml1, and
6592+ * ip1+3 <= ip2 (usually < ip1+ml1)
6593+ */
6594+ if ((start2 - ip) < OPTIMAL_ML)
6595+ {
6596+ int correction;
6597+ int new_ml = ml;
6598+ if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
6599+ if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
6600+ correction = new_ml - (int)(start2 - ip);
6601+ if (correction > 0)
6602+ {
6603+ start2 += correction;
6604+ ref2 += correction;
6605+ ml2 -= correction;
6606+ }
6607+ }
6608+ /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
6609+
6610+ if (start2 + ml2 < mflimit)
6611+ ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
6612+ else ml3 = ml2;
6613+
6614+ if (ml3 == ml2) /* No better match : 2 sequences to encode */
6615+ {
6616+ /* ip & ref are known; Now for ml */
6617+ if (start2 < ip+ml) ml = (int)(start2 - ip);
6618+ /* Now, encode 2 sequences */
6619+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
6620+ ip = start2;
6621+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
6622+ continue;
6623+ }
6624+
6625+ if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */
6626+ {
6627+ if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
6628+ {
6629+ if (start2 < ip+ml)
6630+ {
6631+ int correction = (int)(ip+ml - start2);
6632+ start2 += correction;
6633+ ref2 += correction;
6634+ ml2 -= correction;
6635+ if (ml2 < MINMATCH)
6636+ {
6637+ start2 = start3;
6638+ ref2 = ref3;
6639+ ml2 = ml3;
6640+ }
6641+ }
6642+
6643+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
6644+ ip = start3;
6645+ ref = ref3;
6646+ ml = ml3;
6647+
6648+ start0 = start2;
6649+ ref0 = ref2;
6650+ ml0 = ml2;
6651+ goto _Search2;
6652+ }
6653+
6654+ start2 = start3;
6655+ ref2 = ref3;
6656+ ml2 = ml3;
6657+ goto _Search3;
6658+ }
6659+
6660+ /*
6661+ * OK, now we have 3 ascending matches; let's write at least the first one
6662+ * ip & ref are known; Now for ml
6663+ */
6664+ if (start2 < ip+ml)
6665+ {
6666+ if ((start2 - ip) < (int)ML_MASK)
6667+ {
6668+ int correction;
6669+ if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
6670+ if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
6671+ correction = ml - (int)(start2 - ip);
6672+ if (correction > 0)
6673+ {
6674+ start2 += correction;
6675+ ref2 += correction;
6676+ ml2 -= correction;
6677+ }
6678+ }
6679+ else
6680+ {
6681+ ml = (int)(start2 - ip);
6682+ }
6683+ }
6684+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
6685+
6686+ ip = start2;
6687+ ref = ref2;
6688+ ml = ml2;
6689+
6690+ start2 = start3;
6691+ ref2 = ref3;
6692+ ml2 = ml3;
6693+
6694+ goto _Search3;
6695+ }
6696+
6697+ /* Encode Last Literals */
6698+ {
6699+ int lastRun = (int)(iend - anchor);
6700+ if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */
6701+ if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
6702+ else *op++ = (BYTE)(lastRun<<ML_BITS);
6703+ memcpy(op, anchor, iend - anchor);
6704+ op += iend-anchor;
6705+ }
6706+
6707+ /* End */
6708+ return (int) (((char*)op)-dest);
6709+}
6710+
6711+
6712+int LZ4_sizeofStateHC(void) { return sizeof(LZ4HC_Data_Structure); }
6713+
6714+int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
6715+{
6716+ if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
6717+ LZ4HC_init ((LZ4HC_Data_Structure*)state, (const BYTE*)src);
6718+ if (maxDstSize < LZ4_compressBound(srcSize))
6719+ return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
6720+ else
6721+ return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, notLimited);
6722+}
6723+
6724+int LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
6725+{
6726+ LZ4HC_Data_Structure state;
6727+ return LZ4_compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel);
6728+}
6729+
6730+
6731+
6732+/**************************************
6733+* Streaming Functions
6734+**************************************/
6735+/* allocation */
6736+LZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
6737+int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
6738+
6739+
6740+/* initialization */
6741+void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
6742+{
6743+ LZ4_STATIC_ASSERT(sizeof(LZ4HC_Data_Structure) <= sizeof(LZ4_streamHC_t)); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
6744+ ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->base = NULL;
6745+ ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->compressionLevel = (unsigned)compressionLevel;
6746+}
6747+
6748+int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
6749+{
6750+ LZ4HC_Data_Structure* ctxPtr = (LZ4HC_Data_Structure*) LZ4_streamHCPtr;
6751+ if (dictSize > 64 KB)
6752+ {
6753+ dictionary += dictSize - 64 KB;
6754+ dictSize = 64 KB;
6755+ }
6756+ LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
6757+ if (dictSize >= 4) LZ4HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));
6758+ ctxPtr->end = (const BYTE*)dictionary + dictSize;
6759+ return dictSize;
6760+}
6761+
6762+
6763+/* compression */
6764+
6765+static void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newBlock)
6766+{
6767+ if (ctxPtr->end >= ctxPtr->base + 4)
6768+ LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
6769+ /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
6770+ ctxPtr->lowLimit = ctxPtr->dictLimit;
6771+ ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
6772+ ctxPtr->dictBase = ctxPtr->base;
6773+ ctxPtr->base = newBlock - ctxPtr->dictLimit;
6774+ ctxPtr->end = newBlock;
6775+ ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
6776+}
6777+
6778+static int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr,
6779+ const char* source, char* dest,
6780+ int inputSize, int maxOutputSize, limitedOutput_directive limit)
6781+{
6782+ /* auto-init if forgotten */
6783+ if (ctxPtr->base == NULL)
6784+ LZ4HC_init (ctxPtr, (const BYTE*) source);
6785+
6786+ /* Check overflow */
6787+ if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
6788+ {
6789+ size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
6790+ if (dictSize > 64 KB) dictSize = 64 KB;
6791+
6792+ LZ4_loadDictHC((LZ4_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
6793+ }
6794+
6795+ /* Check if blocks follow each other */
6796+ if ((const BYTE*)source != ctxPtr->end)
6797+ LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
6798+
6799+ /* Check overlapping input/dictionary space */
6800+ {
6801+ const BYTE* sourceEnd = (const BYTE*) source + inputSize;
6802+ const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
6803+ const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
6804+ if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))
6805+ {
6806+ if (sourceEnd > dictEnd) sourceEnd = dictEnd;
6807+ ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
6808+ if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
6809+ }
6810+ }
6811+
6812+ return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
6813+}
6814+
6815+int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
6816+{
6817+ if (maxOutputSize < LZ4_compressBound(inputSize))
6818+ return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
6819+ else
6820+ return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, notLimited);
6821+}
6822+
6823+
6824+/* dictionary saving */
6825+
6826+int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
6827+{
6828+ LZ4HC_Data_Structure* streamPtr = (LZ4HC_Data_Structure*)LZ4_streamHCPtr;
6829+ int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
6830+ if (dictSize > 64 KB) dictSize = 64 KB;
6831+ if (dictSize < 4) dictSize = 0;
6832+ if (dictSize > prefixSize) dictSize = prefixSize;
6833+ memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
6834+ {
6835+ U32 endIndex = (U32)(streamPtr->end - streamPtr->base);
6836+ streamPtr->end = (const BYTE*)safeBuffer + dictSize;
6837+ streamPtr->base = streamPtr->end - endIndex;
6838+ streamPtr->dictLimit = endIndex - dictSize;
6839+ streamPtr->lowLimit = endIndex - dictSize;
6840+ if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
6841+ }
6842+ return dictSize;
6843+}
6844+
6845+
6846+/***********************************
6847+* Deprecated Functions
6848+***********************************/
6849+/* Deprecated compression functions */
6850+/* These functions are planned to start generate warnings by r131 approximately */
6851+int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
6852+int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
6853+int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
6854+int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
6855+int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
6856+int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
6857+int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
6858+int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
6859+int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }
6860+int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
6861+
6862+
6863+/* Deprecated streaming functions */
6864+/* These functions currently generate deprecation warnings */
6865+int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
6866+
6867+int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
6868+{
6869+ if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */
6870+ LZ4HC_init((LZ4HC_Data_Structure*)state, (const BYTE*)inputBuffer);
6871+ ((LZ4HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer;
6872+ return 0;
6873+}
6874+
6875+void* LZ4_createHC (char* inputBuffer)
6876+{
6877+ void* hc4 = ALLOCATOR(1, sizeof(LZ4HC_Data_Structure));
6878+ if (hc4 == NULL) return NULL; /* not enough memory */
6879+ LZ4HC_init ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
6880+ ((LZ4HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer;
6881+ return hc4;
6882+}
6883+
6884+int LZ4_freeHC (void* LZ4HC_Data)
6885+{
6886+ FREEMEM(LZ4HC_Data);
6887+ return (0);
6888+}
6889+
6890+int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
6891+{
6892+ return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, compressionLevel, notLimited);
6893+}
6894+
6895+int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
6896+{
6897+ return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
6898+}
6899+
6900+char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
6901+{
6902+ LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data;
6903+ int dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
6904+ return (char*)(hc4->inputBuffer + dictSize);
6905+}
6906Index: Source/lz4/lz4hccompress.h
6907===================================================================
6908--- Source/lz4/lz4hccompress.h (revision 0)
6909+++ Source/lz4/lz4hccompress.h (working copy)
6910@@ -0,0 +1,208 @@
6911+/*
6912+ LZ4 HC - High Compression Mode of LZ4
6913+ Header File
6914+ Copyright (C) 2011-2015, Yann Collet.
6915+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6916+
6917+ Redistribution and use in source and binary forms, with or without
6918+ modification, are permitted provided that the following conditions are
6919+ met:
6920+
6921+ * Redistributions of source code must retain the above copyright
6922+ notice, this list of conditions and the following disclaimer.
6923+ * Redistributions in binary form must reproduce the above
6924+ copyright notice, this list of conditions and the following disclaimer
6925+ in the documentation and/or other materials provided with the
6926+ distribution.
6927+
6928+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6929+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6930+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6931+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6932+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6933+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6934+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6935+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6936+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6937+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6938+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6939+
6940+ You can contact the author at :
6941+ - LZ4 source repository : https://github.com/Cyan4973/lz4
6942+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
6943+*/
6944+
6945+/*
6946+ * lz4hccompress.h
6947+ *
6948+ * This file is a part of the LZ4 compression module for NSIS.
6949+ *
6950+ * Copyright (C) 2017 Jason Ross (JasonFriday13)
6951+ *
6952+ * Licensed under the zlib/libpng license (the "License");
6953+ * you may not use this file except in compliance with the License.
6954+ *
6955+ * Licence details can be found in the file COPYING.
6956+ *
6957+ * This software is provided 'as-is', without any express or implied
6958+ * warranty.
6959+ */
6960+
6961+#ifndef __LZ4HCCOMPRESS_H
6962+#define __LZ4HCCOMPRESS_H
6963+
6964+#if defined (__cplusplus)
6965+extern "C" {
6966+#endif
6967+
6968+/*****************************
6969+* Includes
6970+*****************************/
6971+#include <stddef.h> /* size_t */
6972+
6973+
6974+/**************************************
6975+* Block Compression
6976+**************************************/
6977+int LZ4_compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
6978+/*
6979+LZ4_compress_HC :
6980+ Destination buffer 'dst' must be already allocated.
6981+ Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible)
6982+ Worst size evaluation is provided by function LZ4_compressBound() (see "lz4.h")
6983+ srcSize : Max supported value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
6984+ compressionLevel : Recommended values are between 4 and 9, although any value between 0 and 16 will work.
6985+ 0 means "use default value" (see lz4hc.c).
6986+ Values >16 behave the same as 16.
6987+ return : the number of bytes written into buffer 'dst'
6988+ or 0 if compression fails.
6989+*/
6990+
6991+
6992+/* Note :
6993+ Decompression functions are provided within LZ4 source code (see "lz4.h") (BSD license)
6994+*/
6995+
6996+
6997+int LZ4_sizeofStateHC(void);
6998+int LZ4_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
6999+/*
7000+LZ4_compress_HC_extStateHC() :
7001+ Use this function if you prefer to manually allocate memory for compression tables.
7002+ To know how much memory must be allocated for the compression tables, use :
7003+ int LZ4_sizeofStateHC();
7004+
7005+ Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).
7006+
7007+ The allocated memory can then be provided to the compression functions using 'void* state' parameter.
7008+ LZ4_compress_HC_extStateHC() is equivalent to previously described function.
7009+ It just uses externally allocated memory for stateHC.
7010+*/
7011+
7012+
7013+/**************************************
7014+* Streaming Compression
7015+**************************************/
7016+#define LZ4_STREAMHCSIZE 262192
7017+#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t))
7018+typedef struct { size_t table[LZ4_STREAMHCSIZE_SIZET]; } LZ4_streamHC_t;
7019+/*
7020+ LZ4_streamHC_t
7021+ This structure allows static allocation of LZ4 HC streaming state.
7022+ State must then be initialized using LZ4_resetStreamHC() before first use.
7023+
7024+ Static allocation should only be used in combination with static linking.
7025+ If you want to use LZ4 as a DLL, please use construction functions below, which are future-proof.
7026+*/
7027+
7028+
7029+LZ4_streamHC_t* LZ4_createStreamHC(void);
7030+int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
7031+/*
7032+ These functions create and release memory for LZ4 HC streaming state.
7033+ Newly created states are already initialized.
7034+ Existing state space can be re-used anytime using LZ4_resetStreamHC().
7035+ If you use LZ4 as a DLL, use these functions instead of static structure allocation,
7036+ to avoid size mismatch between different versions.
7037+*/
7038+
7039+void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
7040+int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
7041+
7042+int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);
7043+
7044+int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
7045+
7046+/*
7047+ These functions compress data in successive blocks of any size, using previous blocks as dictionary.
7048+ One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
7049+ There is an exception for ring buffers, which can be smaller 64 KB.
7050+ Such case is automatically detected and correctly handled by LZ4_compress_HC_continue().
7051+
7052+ Before starting compression, state must be properly initialized, using LZ4_resetStreamHC().
7053+ A first "fictional block" can then be designated as initial dictionary, using LZ4_loadDictHC() (Optional).
7054+
7055+ Then, use LZ4_compress_HC_continue() to compress each successive block.
7056+ It works like LZ4_compress_HC(), but use previous memory blocks as dictionary to improve compression.
7057+ Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.
7058+ As a reminder, size 'dst' buffer to handle worst cases, using LZ4_compressBound(), to ensure success of compression operation.
7059+
7060+ If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,
7061+ you must save it to a safer memory space, using LZ4_saveDictHC().
7062+ Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.
7063+*/
7064+
7065+
7066+
7067+/**************************************
7068+* Deprecated Functions
7069+**************************************/
7070+/* Deprecate Warnings */
7071+/* Should these warnings messages be a problem,
7072+ it is generally possible to disable them,
7073+ with -Wno-deprecated-declarations for gcc
7074+ or _CRT_SECURE_NO_WARNINGS in Visual for example.
7075+ You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
7076+#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
7077+# define LZ4_DEPRECATE_WARNING_DEFBLOCK
7078+# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
7079+# if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
7080+# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
7081+# elif (LZ4_GCC_VERSION >= 301)
7082+# define LZ4_DEPRECATED(message) __attribute__((deprecated))
7083+# elif defined(_MSC_VER)
7084+# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
7085+# else
7086+# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
7087+# define LZ4_DEPRECATED(message)
7088+# endif
7089+#endif // LZ4_DEPRECATE_WARNING_DEFBLOCK
7090+
7091+/* compression functions */
7092+/* these functions are planned to trigger warning messages by r131 approximately */
7093+int LZ4_compressHC (const char* source, char* dest, int inputSize);
7094+int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
7095+int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
7096+int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
7097+int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
7098+int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
7099+int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
7100+int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
7101+int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
7102+int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
7103+
7104+/* Streaming functions following the older model; should no longer be used */
7105+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") void* LZ4_createHC (char* inputBuffer);
7106+LZ4_DEPRECATED("use LZ4_saveDictHC() instead") char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
7107+LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") int LZ4_freeHC (void* LZ4HC_Data);
7108+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
7109+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
7110+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") int LZ4_sizeofStreamStateHC(void);
7111+LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") int LZ4_resetStreamStateHC(void* state, char* inputBuffer);
7112+
7113+
7114+#if defined (__cplusplus)
7115+}
7116+#endif
7117+
7118+#endif //__LZ4HCCOMPRESS_H
7119Index: Source/mmap.cpp
7120===================================================================
7121--- Source/mmap.cpp (revision 7070)
7122+++ Source/mmap.cpp (working copy)
7123@@ -119,7 +119,7 @@
7124 return 0;
7125
7126 #ifdef _WIN32
7127- m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, m_iSize, NULL);
7128+ m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, dwSize, NULL);
7129
7130 if (!m_hFileMap)
7131 return 0;
7132@@ -130,7 +130,7 @@
7133 return 1;
7134 }
7135
7136-void MMapFile::resize(int newsize)
7137+void MMapFile::resize(IGrowBuf64::size_type newsize)
7138 {
7139 release();
7140
7141@@ -168,12 +168,14 @@
7142
7143 if (m_hFile != INVALID_HANDLE_VALUE)
7144 {
7145+ DB_OFFSET off;
7146+ off.quad_part = m_iSize;
7147 m_hFileMap = CreateFileMapping(
7148 m_hFile,
7149 NULL,
7150 m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE,
7151- 0,
7152- m_iSize,
7153+ off.high_part,
7154+ off.low_part,
7155 NULL
7156 );
7157 }
7158@@ -227,17 +229,17 @@
7159 }
7160 }
7161
7162-int MMapFile::getsize() const
7163+IGrowBuf64::size_type MMapFile::getsize() const
7164 {
7165 return m_iSize;
7166 }
7167
7168-void *MMapFile::get(int offset, int size) const
7169+void *MMapFile::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7170 {
7171 return get(offset, &size);
7172 }
7173
7174-void *MMapFile::get(int offset, int *sizep) const
7175+void *MMapFile::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *sizep) const
7176 {
7177 if (!sizep)
7178 return NULL;
7179@@ -244,7 +246,7 @@
7180
7181 assert(!m_pView);
7182
7183- int size = *sizep;
7184+ IGrowBuf64::size_type size = *sizep;
7185
7186 if (!m_iSize || offset + size > m_iSize)
7187 {
7188@@ -257,11 +259,13 @@
7189 }
7190
7191 // fix offset
7192- int alignedoffset = offset - (offset % m_iAllocationGranularity);
7193+ IGrowBuf64::size_type alignedoffset = offset - (offset % m_iAllocationGranularity);
7194 size += offset - alignedoffset;
7195
7196 #ifdef _WIN32
7197- m_pView = MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, alignedoffset, size);
7198+ DB_OFFSET off;
7199+ off.quad_part = alignedoffset;
7200+ m_pView = MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, off.high_part, off.low_part, (SIZE_T)size);
7201 #else
7202 m_pView = mmap(0, size, m_bReadOnly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, m_hFileDesc, alignedoffset);
7203 m_iMappedSize = *sizep = size;
7204@@ -284,12 +288,12 @@
7205 return (void *)((char *)m_pView + offset - alignedoffset);
7206 }
7207
7208-void *MMapFile::getmore(int offset, int size) const
7209+void *MMapFile::getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7210 {
7211 void *pView;
7212 void *pViewBackup = m_pView;
7213 #ifndef _WIN32
7214- int iMappedSizeBackup = m_iMappedSize;
7215+ IGrowBuf64::size_type iMappedSizeBackup = m_iMappedSize;
7216 #endif
7217 m_pView = 0;
7218 pView = get(offset, size);
7219@@ -313,7 +317,7 @@
7220 m_pView = NULL;
7221 }
7222
7223-void MMapFile::release(void *pView, int size)
7224+void MMapFile::release(void *pView, size_t size)
7225 {
7226 if (!pView)
7227 return;
7228@@ -328,7 +332,7 @@
7229 #endif
7230 }
7231
7232-void MMapFile::flush(int num)
7233+void MMapFile::flush(size_t num)
7234 {
7235 if (m_pView)
7236 #ifdef _WIN32
7237@@ -348,23 +352,23 @@
7238 m_iSize = 0;
7239 }
7240
7241-void MMapFake::set(const char *pMem, int iSize)
7242+void MMapFake::set(const char *pMem, size_t iSize)
7243 {
7244 m_pMem = pMem;
7245 m_iSize = iSize;
7246 }
7247
7248-int MMapFake::getsize() const
7249+IGrowBuf64::size_type MMapFake::getsize() const
7250 {
7251 return m_iSize;
7252 }
7253
7254-void *MMapFake::get(int offset, int size) const
7255+void *MMapFake::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7256 {
7257 return get(offset, &size);
7258 }
7259
7260-void *MMapFake::get(int offset, int *size) const
7261+void *MMapFake::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *size) const
7262 {
7263 if (!size || (offset + *size > m_iSize))
7264 return NULL;
7265@@ -371,17 +375,17 @@
7266 return (void *)(m_pMem + offset);
7267 }
7268
7269-void *MMapFake::getmore(int offset, int size) const
7270+void *MMapFake::getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7271 {
7272 return get(offset, size);
7273 }
7274
7275-void MMapFake::resize(int n) {}
7276+void MMapFake::resize(IGrowBuf64::size_type n) {}
7277 void MMapFake::release() {}
7278-void MMapFake::release(void *p, int size) {}
7279+void MMapFake::release(void *p, size_t size) {}
7280 void MMapFake::clear() {}
7281 void MMapFake::setro(BOOL b) {}
7282-void MMapFake::flush(BOOL b) {}
7283+void MMapFake::flush(size_t b) {}
7284
7285 // =======
7286 // MMapBuf
7287@@ -398,9 +402,10 @@
7288 m_fm.release();
7289 }
7290
7291-int MMapBuf::add(const void *data, int len)
7292+IGrowBuf64::size_type MMapBuf::add(const void *data, int len)
7293 {
7294 if (len <= 0) return 0;
7295+ if (getlen() > INT_MAX) return 0;
7296 resize(getlen() + len);
7297 memcpy((char*)get(getlen() - len, len), data, len);
7298 release();
7299@@ -412,7 +417,7 @@
7300 m_fm.setro(bRO);
7301 }
7302
7303-void MMapBuf::resize(int newlen)
7304+void MMapBuf::resize(IGrowBuf64::size_type newlen)
7305 {
7306 if (!m_gb_u && newlen < (16 << 20)) // still in db mode
7307 {
7308@@ -427,15 +432,15 @@
7309 if (newlen > m_alloc)
7310 {
7311 m_alloc = newlen + (16 << 20); // add 16mb to top of mapping
7312- if (m_alloc < 0) // we've hit a signed integer overflow
7313- m_alloc = INT_MAX;
7314+ if (m_alloc > 0x7fffffffffffffff) // we've hit a signed integer overflow
7315+ m_alloc = 0x7fffffffffffffff;
7316
7317 m_fm.resize(m_alloc);
7318
7319 if (m_gb.getlen())
7320 {
7321- memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), m_gb.getlen());
7322- m_fm.flush(m_gb.getlen());
7323+ memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), (size_t)m_gb.getlen());
7324+ m_fm.flush((size_t)m_gb.getlen());
7325 m_fm.release();
7326 m_gb.resize(0);
7327 }
7328@@ -442,7 +447,7 @@
7329 }
7330 }
7331
7332-int MMapBuf::getsize() const
7333+IGrowBuf64::size_type MMapBuf::getsize() const
7334 {
7335 if (m_gb_u)
7336 return m_fm.getsize();
7337@@ -449,7 +454,7 @@
7338 return m_gb.getlen();
7339 }
7340
7341-int MMapBuf::getlen() const
7342+IGrowBuf64::size_type MMapBuf::getlen() const
7343 {
7344 if (m_gb_u)
7345 return m_used;
7346@@ -461,15 +466,15 @@
7347 return get(0, m_alloc);
7348 }
7349
7350-void *MMapBuf::get(int offset, int *sizep) const
7351+void *MMapBuf::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *sizep) const
7352 {
7353 if (!sizep)
7354 return NULL;
7355- int size = *sizep;
7356+ IGrowBuf64::size_type size = *sizep;
7357 return get(offset, size);
7358 }
7359
7360-void *MMapBuf::get(int offset, int size) const
7361+void *MMapBuf::get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7362 {
7363 if (m_gb_u)
7364 return m_fm.get(offset, size);
7365@@ -476,7 +481,7 @@
7366 return (void *) ((char *) m_gb.get() + offset);
7367 }
7368
7369-void *MMapBuf::getmore(int offset, int size) const
7370+void *MMapBuf::getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const
7371 {
7372 if (m_gb_u)
7373 return m_fm.getmore(offset, size);
7374@@ -489,7 +494,7 @@
7375 m_fm.release();
7376 }
7377
7378-void MMapBuf::release(void *pView, int size)
7379+void MMapBuf::release(void *pView, size_t size)
7380 {
7381 if (m_gb_u)
7382 m_fm.release(pView, size);
7383@@ -501,7 +506,7 @@
7384 m_fm.clear();
7385 }
7386
7387-void MMapBuf::flush(int num)
7388+void MMapBuf::flush(size_t num)
7389 {
7390 if (m_gb_u)
7391 m_fm.flush(num);
7392Index: Source/mmap.h
7393===================================================================
7394--- Source/mmap.h (revision 7070)
7395+++ Source/mmap.h (working copy)
7396@@ -20,7 +20,7 @@
7397 #define __MMAP_H_
7398
7399 #include "Platform.h"
7400-#include "growbuf.h"
7401+#include "growbuf64.h"
7402
7403 #ifndef _WIN32
7404 #include <cstdio> // for FILE*
7405@@ -27,19 +27,27 @@
7406 #include <fstream> // (some systems have FILE* in here)
7407 #endif
7408
7409+typedef union _DB_OFFSET {
7410+ struct {
7411+ UINT32 low_part;
7412+ INT32 high_part;
7413+ };
7414+ INT64 quad_part;
7415+} DB_OFFSET, *PDB_OFFSET;
7416+
7417 class IMMap
7418 {
7419 public:
7420- virtual void resize(int newlen)=0;
7421- virtual int getsize() const=0;
7422- virtual void *get(int offset, int size) const=0;
7423- virtual void *get(int offset, int *size) const=0;
7424- virtual void *getmore(int offset, int size) const=0;
7425+ virtual void resize(IGrowBuf64::size_type newlen)=0;
7426+ virtual IGrowBuf64::size_type getsize() const=0;
7427+ virtual void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const=0;
7428+ virtual void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *size) const=0;
7429+ virtual void *getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const=0;
7430 virtual void release()=0;
7431- virtual void release(void *view, int size)=0;
7432+ virtual void release(void *view, size_t size)=0;
7433 virtual void clear()=0;
7434 virtual void setro(BOOL bRO)=0;
7435- virtual void flush(int num)=0;
7436+ virtual void flush(size_t num)=0;
7437 virtual ~IMMap() {}
7438 };
7439
7440@@ -87,14 +95,14 @@
7441 * create a temporary file and use it to create a memory map. This is
7442 * what's used by MMapBuf to create a Memory Mapped Buffer.
7443 *
7444- * @param newsize The new size of the file. Limited to 32-bits.
7445+ * @param newsize The new size of the file. Limited to 63-bits.
7446 */
7447- void resize(int newsize);
7448+ void resize(IGrowBuf64::size_type newsize);
7449
7450 /**
7451 * Size of the memory map object.
7452 */
7453- int getsize() const;
7454+ IGrowBuf64::size_type getsize() const;
7455
7456 /**
7457 * Set the memory map to a particular offset in the file and return the
7458@@ -104,7 +112,7 @@
7459 * @param offset The offset from the beginning of the file.
7460 * @param size The size of the memory map window.
7461 */
7462- void *get(int offset, int size) const;
7463+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7464
7465 /**
7466 * Set the memory map to a particular offset in the file and return the
7467@@ -115,7 +123,7 @@
7468 * @param sizep [in/out] The size of the memory map window. (In non-Win32
7469 * systems, the new size is written back out.)
7470 */
7471- void *get(int offset, int *sizep) const;
7472+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *sizep) const;
7473
7474 /**
7475 * This function sets memory map and just hands you the pointer and
7476@@ -128,7 +136,7 @@
7477 * @param offset The offset from the beginning of the file.
7478 * @param size The size of the memory map window.
7479 */
7480- void *getmore(int offset, int size) const;
7481+ void *getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7482
7483 /**
7484 * Releases the memory map currently being used. Calls UnMapViewOfFile().
7485@@ -147,7 +155,7 @@
7486 * @param pView The pointer to somewhere in a MemMapped object.
7487 * @param size The size of the object. Used only in non-Win32 systems.
7488 */
7489- void release(void *pView, int size);
7490+ void release(void *pView, size_t size);
7491
7492 /**
7493 * Flushes the contents of the current memory map to disk. Set size to 0
7494@@ -155,7 +163,7 @@
7495 *
7496 * @param num The number of bytes to flush. 0 for everything.
7497 */
7498- void flush(int num);
7499+ void flush(size_t num);
7500
7501 private:
7502 #ifdef _WIN32
7503@@ -163,10 +171,10 @@
7504 #else
7505 FILE *m_hFile;
7506 int m_hFileDesc;
7507- mutable int m_iMappedSize;
7508+ mutable IGrowBuf64::size_type m_iMappedSize;
7509 #endif
7510 mutable void *m_pView;
7511- mutable int m_iSize;
7512+ mutable IGrowBuf64::size_type m_iSize;
7513 BOOL m_bReadOnly;
7514 BOOL m_bTempHandle;
7515
7516@@ -181,22 +189,22 @@
7517 public:
7518 MMapFake();
7519
7520- void set(const char *pMem, int iSize);
7521- int getsize() const;
7522- void *get(int offset, int size) const;
7523- void *get(int offset, int *size) const;
7524- void *getmore(int offset, int size) const;
7525+ void set(const char *pMem, size_t iSize);
7526+ IGrowBuf64::size_type getsize() const;
7527+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7528+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *size) const;
7529+ void *getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7530
7531- void resize(int n);
7532+ void resize(IGrowBuf64::size_type n);
7533 void release();
7534- void release(void *p, int size);
7535+ void release(void *p, size_t size);
7536 void clear();
7537 void setro(BOOL b);
7538- void flush(BOOL b);
7539+ void flush(size_t b);
7540
7541 private:
7542 const char *m_pMem;
7543- int m_iSize;
7544+ IGrowBuf64::size_type m_iSize;
7545 };
7546
7547 /**
7548@@ -208,7 +216,7 @@
7549 *
7550 * This is sort of our virtual memory manager.
7551 */
7552-class MMapBuf : public IGrowBuf, public IMMap
7553+class MMapBuf : public IGrowBuf64, public IMMap
7554 {
7555 private: // don't copy instances
7556 MMapBuf(const MMapBuf&);
7557@@ -218,26 +226,26 @@
7558 MMapBuf();
7559 virtual ~MMapBuf();
7560
7561- int add(const void *data, int len);
7562+ IGrowBuf64::size_type add(const void *data, int len);
7563 void setro(BOOL bRO);
7564- void resize(int newlen);
7565- int getsize() const;
7566- int getlen() const;
7567+ void resize(IGrowBuf64::size_type newlen);
7568+ IGrowBuf64::size_type getsize() const;
7569+ IGrowBuf64::size_type getlen() const;
7570 void *get() const;
7571- void *get(int offset, int *sizep) const;
7572- void *get(int offset, int size) const;
7573- void *getmore(int offset, int size) const;
7574+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type *sizep) const;
7575+ void *get(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7576+ void *getmore(IGrowBuf64::size_type offset, IGrowBuf64::size_type size) const;
7577 void release();
7578- void release(void *pView, int size);
7579+ void release(void *pView, size_t size);
7580 void clear();
7581- void flush(int num);
7582+ void flush(size_t num);
7583
7584 private:
7585- GrowBuf m_gb;
7586+ GrowBuf64 m_gb;
7587 MMapFile m_fm;
7588
7589 int m_gb_u;
7590- int m_alloc, m_used;
7591+ IGrowBuf64::size_type m_alloc, m_used;
7592 };
7593
7594 #endif//__MMAP_H_
7595Index: Source/script.cpp
7596===================================================================
7597--- Source/script.cpp (revision 7070)
7598+++ Source/script.cpp (working copy)
7599@@ -1711,6 +1711,58 @@
7600 my_strncpy(build_output_filename,line.gettoken_str(1),COUNTOF(build_output_filename));
7601 SCRIPT_MSG(_T("OutFile: \"%") NPRIs _T("\"\n"),build_output_filename);
7602 return PS_OK;
7603+ case TOK_SETEXOUTFILE:
7604+ case TOK_OUTFILEMODE:
7605+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7606+ {
7607+ int arg;
7608+ const TCHAR *str;
7609+ if (which_token == TOK_SETEXOUTFILE)
7610+ {
7611+ arg = line.gettoken_enum(1,_T("auto\0off\0on\0stub\0")) - 1;
7612+ warning_fl(DW_PARSE_SETEXOUTFILE_DEPRECATED, _T("SetExOutFile: is renamed to OutFileMode auto|aio|data|stub"));
7613+ }
7614+ else
7615+ {
7616+ arg = line.gettoken_enum(1,_T("auto\0aio\0data\0stub\0")) - 1;
7617+ }
7618+ switch (arg)
7619+ {
7620+ default:
7621+ case OFM_AUTO:
7622+ str = _T("auto");
7623+ break;
7624+ case OFM_AIO:
7625+ str = _T("aio");
7626+ break;
7627+ case OFM_DATA:
7628+ str = _T("data");
7629+ break;
7630+ case OFM_STUB:
7631+ str = _T("stub");
7632+ break;
7633+ }
7634+ if (arg < OFM_AUTO) PRINTHELP()
7635+#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
7636+ if (arg != OFM_AIO && build_compress_whole)
7637+ {
7638+ ERROR_MSG(_T("Error: %") NPRIs _T(" %") NPRIs _T(": solid compression can't be used with an external file.\n"), line.gettoken_str(0), str);
7639+ return PS_ERROR;
7640+ }
7641+ if (arg != build_external_file && build_compressor_set)
7642+ {
7643+ ERROR_MSG(_T("Error: %") NPRIs _T(" %") NPRIs _T(": can't change the output file mode after adding files.\n"), line.gettoken_str(0), str);
7644+ return PS_ERROR;
7645+ }
7646+#endif
7647+ build_external_file = arg;
7648+ SCRIPT_MSG(_T("OutFileMode: %") NPRIs _T("\n"),str);
7649+ }
7650+ return PS_OK;
7651+#else//!NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7652+ ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_CONFIG_EXTERNAL_FILE_SUPPORT not defined.\n"), line.gettoken_str(0));
7653+ return PS_ERROR;
7654+#endif//NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7655 case TOK_INSTDIR:
7656 {
7657 TCHAR *p = line.gettoken_str(1);
7658@@ -2393,7 +2445,21 @@
7659 if (!_tcsicmp(line.gettoken_str(a),_T("/FINAL")))
7660 build_compressor_final = true, a++;
7661 else if (!_tcsicmp(line.gettoken_str(a),_T("/SOLID")))
7662- build_compress_whole = true, a++;
7663+ {
7664+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7665+ if (build_external_file <= OFM_AUTO)
7666+ warning_fl(DW_COMP_WHOLE_IGNORE, _T("SetCompressor: ignoring /SOLID flag due to OutFileMode auto"));
7667+ else if (build_external_file == OFM_DATA)
7668+ warning_fl(DW_COMP_WHOLE_IGNORE, _T("SetCompressor: ignoring /SOLID flag due to OutFileMode data"));
7669+ else if (build_external_file == OFM_STUB)
7670+ warning_fl(DW_COMP_WHOLE_IGNORE, _T("SetCompressor: ignoring /SOLID flag due to OutFileMode stub"));
7671+ else
7672+#endif
7673+ {
7674+ build_compress_whole = true;
7675+ }
7676+ a++;
7677+ }
7678 else
7679 PRINTHELP();
7680 }
7681@@ -2404,11 +2470,12 @@
7682 PRINTHELP();
7683 }
7684
7685- int k=line.gettoken_enum(a, _T("zlib\0bzip2\0lzma\0"));
7686+ int k=line.gettoken_enum(a, _T("zlib\0bzip2\0lzma\0lz4\0"));
7687 switch (k) {
7688 case 0: compressor = &zlib_compressor; break;
7689 case 1: compressor = &bzip2_compressor; break;
7690 case 2: compressor = &lzma_compressor; break;
7691+ case 3: compressor = &lz4_compressor; break;
7692 default: PRINTHELP();
7693 }
7694
7695@@ -2549,8 +2616,8 @@
7696 ent.which=EW_WRITEUNINSTALLER;
7697 ent.offsets[0]=add_string(line.gettoken_str(1));
7698 tstring full = tstring(_T("$INSTDIR\\")) + tstring(line.gettoken_str(1));
7699- ent.offsets[3]=add_string(full.c_str());
7700- // ent.offsets[1] and ent.offsets[2] are set in CEXEBuild::uninstall_generate()
7701+ ent.offsets[4]=add_string(full.c_str());
7702+ // ent.offsets[1], ent.offsets[2], ent.offsets[3], ent.offsets[5], ent.offsets[6] are set in CEXEBuild::uninstall_generate()
7703 if (!ent.offsets[0]) PRINTHELP()
7704 SCRIPT_MSG(_T("WriteUninstaller: \"%") NPRIs _T("\"\n"),line.gettoken_str(1));
7705
7706@@ -3603,15 +3670,34 @@
7707 #endif //~ NSIS_SUPPORT_RMDIR
7708 case TOK_RESERVEFILE:
7709 case TOK_FILE:
7710+ case TOK_RESERVESTUBFILE:
7711+ case TOK_STUBFILE:
7712 #ifdef NSIS_SUPPORT_FILE
7713 {
7714 set<tstring> excluded;
7715 int a=1,attrib=0;
7716 bool fatal=true,rec=false,reserveplugin=false;
7717+ const TCHAR *which_token_str;
7718+ switch (which_token)
7719+ {
7720+ default:
7721+ case TOK_FILE:
7722+ which_token_str = _T("");
7723+ break;
7724+ case TOK_RESERVEFILE:
7725+ which_token_str = _T("Reserve");
7726+ break;
7727+ case TOK_STUBFILE:
7728+ which_token_str = _T("Stub");
7729+ break;
7730+ case TOK_RESERVESTUBFILE:
7731+ which_token_str = _T("ReserveStub");
7732+ break;
7733+ }
7734 if (!_tcsicmp(line.gettoken_str(a),_T("/nonfatal")))
7735 fatal=false, a++;
7736
7737- if (which_token == TOK_RESERVEFILE && !_tcsicmp(line.gettoken_str(a),_T("/plugin")))
7738+ if ((which_token == TOK_RESERVEFILE || which_token == TOK_RESERVESTUBFILE) && !_tcsicmp(line.gettoken_str(a),_T("/plugin")))
7739 reserveplugin=true, a++;
7740
7741 if (which_token == TOK_FILE && !_tcsicmp(line.gettoken_str(a),_T("/a")))
7742@@ -3619,7 +3705,7 @@
7743 #ifdef _WIN32
7744 attrib=1;
7745 #else
7746- warning_fl(DW_UNSUPP_STORE_FILE_ATT, _T("%") NPRIs _T("File /a is disabled for non Win32 platforms."),(which_token == TOK_FILE)?_T(""):_T("Reserve"));
7747+ warning_fl(DW_UNSUPP_STORE_FILE_ATT, _T("%") NPRIs _T("File /a is disabled for non Win32 platforms."),which_token_str);
7748 #endif
7749 a++;
7750 }
7751@@ -3627,7 +3713,7 @@
7752 {
7753 rec=true, a++;
7754 }
7755- else if (which_token == TOK_FILE && !_tcsnicmp(line.gettoken_str(a),_T("/oname="),7))
7756+ else if ((which_token == TOK_FILE || which_token == TOK_STUBFILE) && !_tcsnicmp(line.gettoken_str(a),_T("/oname="),7))
7757 {
7758 TCHAR *on=line.gettoken_str(a)+7;
7759 a++;
7760@@ -3635,7 +3721,7 @@
7761
7762 if (on[0]==_T('"'))
7763 {
7764- ERROR_MSG(_T("%") NPRIs _T("File: output name must not begin with a quote, use \"/oname=name with spaces\".\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
7765+ ERROR_MSG(_T("%") NPRIs _T("File: output name must not begin with a quote, use \"/oname=name with spaces\".\n"),which_token_str,line.gettoken_str(a));
7766 PRINTHELP();
7767 }
7768
7769@@ -3642,7 +3728,13 @@
7770 int tf=0;
7771 TCHAR *fn = line.gettoken_str(a);
7772 PATH_CONVERT(fn);
7773+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7774+ set_datablock_mode(build_external_file == OFM_STUB && which_token == TOK_STUBFILE);
7775+#endif
7776 int v=do_add_file(fn, attrib, 0, &tf, on);
7777+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7778+ set_datablock_mode(0);
7779+#endif
7780 if (v != PS_OK) return v;
7781 if (tf > 1) PRINTHELP()
7782 if (!tf)
7783@@ -3649,12 +3741,12 @@
7784 {
7785 if (fatal)
7786 {
7787- ERROR_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found.\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
7788+ ERROR_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found.\n"),which_token_str,line.gettoken_str(a));
7789 PRINTHELP()
7790 }
7791 else
7792 {
7793- warning_fl(DW_FILE_NONFATAL_NOT_FOUND, _T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),line.gettoken_str(a));
7794+ warning_fl(DW_FILE_NONFATAL_NOT_FOUND, _T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found"),which_token_str,line.gettoken_str(a));
7795
7796 // workaround for bug #1299100: add a nop opcode so relative jumps will work as expected
7797 add_entry_direct(EW_NOP);
7798@@ -3705,7 +3797,13 @@
7799 }
7800 int tf=0;
7801 TCHAR *fn = my_convert(t);
7802- int v=do_add_file(fn, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded);
7803+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7804+ set_datablock_mode(build_external_file == OFM_STUB ? (which_token == TOK_STUBFILE || which_token == TOK_RESERVESTUBFILE || reserveplugin) : 0);
7805+#endif
7806+ int v=do_add_file(fn, attrib, rec, &tf, NULL, (which_token == TOK_FILE || which_token == TOK_STUBFILE), NULL, NULL, excluded);
7807+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7808+ set_datablock_mode(0);
7809+#endif
7810 my_convert_free(fn);
7811 if (v != PS_OK) return v;
7812 if (!tf)
7813@@ -3712,12 +3810,12 @@
7814 {
7815 if (fatal)
7816 {
7817- ERROR_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found.\n"),(which_token == TOK_FILE)?_T(""):_T("Reserve"),t);
7818+ ERROR_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found.\n"),which_token_str,t);
7819 PRINTHELP();
7820 }
7821 else
7822 {
7823- warning_fl(DW_FILE_NONFATAL_NOT_FOUND, _T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found."),(which_token == TOK_FILE)?_T(""):_T("Reserve"),t);
7824+ warning_fl(DW_FILE_NONFATAL_NOT_FOUND, _T("%") NPRIs _T("File: \"%") NPRIs _T("\" -> no files found."),which_token_str,t);
7825 }
7826 }
7827 }
7828@@ -3727,6 +3825,24 @@
7829 ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_FILE not defined.\n"), line.gettoken_str(0));
7830 return PS_ERROR;
7831 #endif //~ NSIS_SUPPORT_FILE
7832+ case TOK_VERIFYEXTERNALFILE:
7833+#ifdef NSIS_SUPPORT_FILE
7834+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7835+ {
7836+ if (line.getnumtokens() > 2) PRINTHELP()
7837+ ent.which=EW_VERIFYEXTERNALFILE;
7838+ ent.offsets[0]=add_string(line.gettoken_str(1));
7839+ SCRIPT_MSG(_T("VerifyExternalFile: \"%") NPRIs _T("\"\n"),line.gettoken_str(1));
7840+ }
7841+ return add_entry(&ent);
7842+#else
7843+ ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_CONFIG_EXTERNAL_FILE_SUPPORT not defined.\n"), line.gettoken_str(0));
7844+ return PS_ERROR;
7845+#endif //~ NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7846+#else
7847+ ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_FILE not defined.\n"), line.gettoken_str(0));
7848+ return PS_ERROR;
7849+#endif //~ NSIS_SUPPORT_FILE
7850 #ifdef NSIS_SUPPORT_COPYFILES
7851 case TOK_COPYFILES:
7852 {
7853@@ -4297,9 +4413,9 @@
7854 SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T("\\%") NPRIs _T("\\%") NPRIs _T("=%") NPRIs _T("\n"),
7855 cmdname,line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
7856 ent.offsets[3]=add_string(line.gettoken_str(4));
7857- ent.offsets[4]=ent.offsets[5]=REG_SZ;
7858+ ent.offsets[5]=ent.offsets[6]=REG_SZ;
7859 if (which_token == TOK_WRITEREGEXPANDSTR)
7860- ent.offsets[5]=REG_EXPAND_SZ;
7861+ ent.offsets[6]=REG_EXPAND_SZ;
7862 }
7863 if (which_token == TOK_WRITEREGBIN || multisz || which_token == TOK_WRITEREGNONE)
7864 {
7865@@ -4315,14 +4431,26 @@
7866 SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T("\\%") NPRIs _T("\\%") NPRIs _T("=%") NPRIs _T("\n"),
7867 cmdname,line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
7868 if (multisz && !build_unicode) for (int p1=0, p2=p1; p1 < data_len; data_len--) data[p1++]=data[p2], p2+=2; // BUGBUG: Should convert each string from UTF-16 to DBCS but only exehead knows the codepage, limited to ASCII for now.
7869- ent.offsets[3]=add_db_data(data,data_len);
7870- if (ent.offsets[3] < 0) return PS_ERROR;
7871- ent.offsets[4]=REG_BINARY, ent.offsets[5]=none?REG_NONE:multisz?REG_MULTI_SZ:REG_BINARY;
7872+ crc32_t crc = 0;
7873+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7874+ set_datablock_mode(build_external_file == OFM_STUB);
7875+#endif
7876+ IGrowBuf64::size_type offset = add_db_data(data,data_len,&crc);
7877+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7878+ set_datablock_mode(0);
7879+#endif
7880+ if (offset < 0) return PS_ERROR;
7881+ DB_OFFSET off;
7882+ off.quad_part = offset;
7883+ ent.offsets[3]=off.low_part;
7884+ ent.offsets[4]=off.high_part;
7885+ ent.offsets[5]=REG_BINARY, ent.offsets[6]=none?REG_NONE:multisz?REG_MULTI_SZ:REG_BINARY;
7886+ ent.offsets[7]=FIX_ENDIAN_INT32(crc);
7887 }
7888 if (which_token == TOK_WRITEREGDWORD)
7889 {
7890 ent.offsets[3]=add_string(line.gettoken_str(4));
7891- ent.offsets[4]=ent.offsets[5]=REG_DWORD;
7892+ ent.offsets[5]=ent.offsets[6]=REG_DWORD;
7893
7894 SCRIPT_MSG(_T("WriteRegDWORD: %") NPRIs _T("\\%") NPRIs _T("\\%") NPRIs _T("=%") NPRIs _T("\n"),
7895 line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
7896@@ -5013,7 +5141,9 @@
7897 }
7898
7899 tstring dllName = get_file_name(dllPath);
7900- int data_handle = m_pPlugins->GetDllDataHandle(!!uninstall_mode, command), ret;
7901+ IGrowBuf64::size_type data_handle = m_pPlugins->GetDllDataHandle(!!uninstall_mode, command);
7902+ crc32_t crc = m_pPlugins->GetDllCRCValue(!!uninstall_mode, command);
7903+ int ret;
7904
7905 if (uninstall_mode) uninst_plugin_used = true; else plugin_used = true;
7906
7907@@ -5040,11 +5170,17 @@
7908 // times for each command in the DLL, this is actually not the case
7909 // because of CEXEBuild::datablock_optimize() that tries to discover
7910 // duplicates and reuse them.
7911- ret=do_add_file(dllPath.c_str(),0,0,&files_added,tempDLL,2,&data_handle); // 2 means no size add
7912+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7913+ set_datablock_mode(build_external_file == OFM_STUB);
7914+#endif
7915+ ret=do_add_file(dllPath.c_str(),0,0,&files_added,tempDLL,2,&data_handle,&crc); // 2 means no size add
7916+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7917+ set_datablock_mode(0);
7918+#endif
7919 if (ret != PS_OK) {
7920 return ret;
7921 }
7922- m_pPlugins->SetDllDataHandle(!!uninstall_mode, command, data_handle);
7923+ m_pPlugins->SetDllDataHandle(!!uninstall_mode, command, data_handle, crc);
7924 build_overwrite=old_build_overwrite;
7925 build_datesave=old_build_datesave;
7926 build_allowskipfiles=old_build_allowskipfiles;
7927@@ -5051,27 +5187,34 @@
7928 }
7929 else
7930 {
7931- ent.which=EW_EXTRACTFILE;
7932-
7933+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7934+ ent.which = (build_external_file == OFM_STUB) ? EW_EXTRACTSTUBFILE : EW_EXTRACTFILE;
7935+#else
7936+ ent.which = EW_EXTRACTFILE;
7937+#endif
7938 DefineInnerLangString(NLF_SKIPPED);
7939 DefineInnerLangString(NLF_ERR_DECOMPRESSING);
7940 DefineInnerLangString(NLF_ERR_WRITING);
7941 DefineInnerLangString(NLF_EXTRACT);
7942 DefineInnerLangString(NLF_CANT_WRITE);
7943+ DB_OFFSET off;
7944+ off.quad_part = data_handle;
7945
7946 ent.offsets[0]=1; // overwrite off
7947 ent.offsets[0]|=(MB_RETRYCANCEL|MB_ICONSTOP|(IDCANCEL<<21))<<3;
7948 ent.offsets[1]=add_string(tempDLL);
7949- ent.offsets[2]=data_handle;
7950- ent.offsets[3]=0xffffffff;
7951+ ent.offsets[2]=off.low_part;
7952+ ent.offsets[3]=off.high_part;
7953 ent.offsets[4]=0xffffffff;
7954- ent.offsets[5]=DefineInnerLangString(NLF_FILE_ERROR);
7955+ ent.offsets[5]=0xffffffff;
7956+ ent.offsets[6]=DefineInnerLangString(NLF_FILE_ERROR);
7957+ ent.offsets[7]=crc;
7958 if ((ret=add_entry(&ent)) != PS_OK) return ret;
7959 }
7960
7961 // SetDetailsPrint lastused
7962 ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1);
7963- if (ret != PS_OK) return ret;
7964+ if (ret != PS_OK) return (int)ret;
7965
7966 // Call the DLL
7967 tstring funcname = get_string_suffix(command, _T("::"));
7968@@ -5093,7 +5236,7 @@
7969 if (!_tcsicmp(line.gettoken_str(w), _T("/NOUNLOAD"))) nounloadmisused=1;
7970 ent.offsets[1]=0;
7971 ent.offsets[2]=0;
7972- if ((ret=add_entry(&ent)) != PS_OK) return ret;
7973+ if ((ret=add_entry(&ent)) != PS_OK) return (int)ret;
7974 SCRIPT_MSG(_T(" %") NPRIs,line.gettoken_str(i));
7975 }
7976 SCRIPT_MSG(_T("\n"));
7977@@ -5107,7 +5250,7 @@
7978 ent.offsets[2]=0;
7979 ent.offsets[3]=nounload|build_plugin_unload;
7980 ent.offsets[4]=1;
7981- if ((ret=add_entry(&ent)) != PS_OK) return ret;
7982+ if ((ret=add_entry(&ent)) != PS_OK) return (int)ret;
7983
7984 DefineInnerLangString(NLF_SYMBOL_NOT_FOUND);
7985 DefineInnerLangString(NLF_COULD_NOT_LOAD);
7986@@ -5146,10 +5289,30 @@
7987 }
7988
7989 #ifdef NSIS_SUPPORT_FILE
7990-int CEXEBuild::do_add_file(const TCHAR *lgss, int attrib, int recurse, int *total_files, const TCHAR *name_override, int generatecode, int *data_handle, const set<tstring>& excluded, const tstring& basedir, bool dir_created)
7991+int CEXEBuild::do_add_file(const TCHAR *lgss, int attrib, int recurse, int *total_files, const TCHAR *name_override, int generatecode, IGrowBuf64::size_type *data_handle, crc32_t *pcrc, const set<tstring>& excluded, const tstring& basedir, bool dir_created)
7992 {
7993 assert(!name_override || !recurse);
7994
7995+ const TCHAR *which_token_str;
7996+ if (generatecode)
7997+ {
7998+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
7999+ if (datablock_mode)
8000+ which_token_str = _T("Stub");
8001+ else
8002+#endif
8003+ which_token_str = _T("");
8004+ }
8005+ else
8006+ {
8007+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
8008+ if (datablock_mode)
8009+ which_token_str = _T("ReserveStub");
8010+ else
8011+#endif
8012+ which_token_str = _T("Reserve");
8013+ }
8014+
8015 tstring dir = get_dir_name(lgss), spec;
8016
8017 if (dir == lgss)
8018@@ -5182,7 +5345,7 @@
8019 continue;
8020
8021 if (!dir_created && generatecode) {
8022- SCRIPT_MSG(_T("%") NPRIs _T("File: Descending to: \"%") NPRIs _T("\"\n"), generatecode ? _T("") : _T("Reserve"), dir.c_str());
8023+ SCRIPT_MSG(_T("%") NPRIs _T("File: Descending to: \"%") NPRIs _T("\"\n"), which_token_str, dir.c_str());
8024
8025 if (do_add_file_create_dir(dir, basedir, attrib) != PS_OK) {
8026 return PS_ERROR;
8027@@ -5191,7 +5354,7 @@
8028 dir_created = true;
8029 }
8030
8031- if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle) != PS_OK) {
8032+ if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle, pcrc, which_token_str) != PS_OK) {
8033 return PS_ERROR;
8034 }
8035
8036@@ -5219,7 +5382,7 @@
8037 } else if (generatecode) {
8038 // always create directories that match
8039
8040- SCRIPT_MSG(_T("%") NPRIs _T("File: Descending to: \"%") NPRIs _T("\"\n"), generatecode ? _T("") : _T("Reserve"), new_spec.c_str());
8041+ SCRIPT_MSG(_T("%") NPRIs _T("File: Descending to: \"%") NPRIs _T("\"\n"), which_token_str, new_spec.c_str());
8042
8043 if (do_add_file_create_dir(dir + _T('\\') + *dirs_itr, new_dir, attrib) != PS_OK) {
8044 return PS_ERROR;
8045@@ -5229,7 +5392,7 @@
8046 }
8047
8048 const TCHAR *new_spec_c = new_spec.c_str();
8049- int res = do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, excluded, new_dir, created);
8050+ int res = do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, NULL, excluded, new_dir, created);
8051 if (res != PS_OK) {
8052 return PS_ERROR;
8053 }
8054@@ -5236,7 +5399,7 @@
8055 }
8056
8057 if (basedir == _T("")) {
8058- SCRIPT_MSG(_T("%") NPRIs _T("File: Returning to: \"%") NPRIs _T("\"\n"), generatecode ? _T("") : _T("Reserve"), dir.c_str());
8059+ SCRIPT_MSG(_T("%") NPRIs _T("File: Returning to: \"%") NPRIs _T("\"\n"), which_token_str, dir.c_str());
8060
8061 // restore $OUTDIR from $_OUTDIR [SetOutPath $_OUTDIR]
8062 if (add_entry_direct(EW_CREATEDIR, add_asciistring(_T("$_OUTDIR")), 1) != PS_OK) {
8063@@ -5247,7 +5410,7 @@
8064 return PS_OK;
8065 }
8066
8067-int CEXEBuild::add_file(const tstring& dir, const tstring& file, int attrib, const TCHAR *name_override, int generatecode, int *data_handle) {
8068+int CEXEBuild::add_file(const tstring& dir, const tstring& file, int attrib, const TCHAR *name_override, int generatecode, IGrowBuf64::size_type *data_handle, crc32_t *pcrc, const TCHAR *which_token_str) {
8069 tstring newfn_s = dir + PLATFORM_PATH_SEPARATOR_C + file;
8070 const TCHAR *newfn = newfn_s.c_str();
8071 const TCHAR *filename = file.c_str();
8072@@ -5266,7 +5429,7 @@
8073 );
8074 if (hFile == INVALID_HANDLE_VALUE)
8075 {
8076- ERROR_MSG(_T("%") NPRIs _T("File: failed opening file \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8077+ ERROR_MSG(_T("%") NPRIs _T("File: failed opening file \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8078 return PS_ERROR;
8079 }
8080 MANAGE_WITH(hFile, CloseHandle);
8081@@ -5274,7 +5437,7 @@
8082 len = GetFileSize(hFile, NULL);
8083 if (len && !mmap.setfile(hFile, len))
8084 {
8085- ERROR_MSG(_T("%") NPRIs _T("File: failed creating mmap of \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8086+ ERROR_MSG(_T("%") NPRIs _T("File: failed creating mmap of \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8087 return PS_ERROR;
8088 }
8089 #else // !_WIN32
8090@@ -5281,7 +5444,7 @@
8091 int fd = OPEN(newfn, O_RDONLY);
8092 if (fd == -1)
8093 {
8094- ERROR_MSG(_T("%") NPRIs _T("File: failed opening file \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8095+ ERROR_MSG(_T("%") NPRIs _T("File: failed opening file \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8096 return PS_ERROR;
8097 }
8098 MANAGE_WITH(fd, close); // Will auto-close(2) fd
8099@@ -5288,13 +5451,13 @@
8100
8101 struct stat s;
8102 if (fstat(fd, &s)) {
8103- ERROR_MSG(_T("%") NPRIs _T("File: failed stating file \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8104+ ERROR_MSG(_T("%") NPRIs _T("File: failed stating file \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8105 return PS_ERROR;
8106 }
8107 len = (DWORD) s.st_size;
8108 if (len && !mmap.setfile(fd, len))
8109 {
8110- ERROR_MSG(_T("%") NPRIs _T("File: failed creating mmap of \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8111+ ERROR_MSG(_T("%") NPRIs _T("File: failed creating mmap of \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8112 return PS_ERROR;
8113 }
8114 #endif // ~_WIN32
8115@@ -5301,18 +5464,21 @@
8116
8117 if (generatecode&1)
8118 section_add_size_kb((len+1023)/1024);
8119- if (name_override) SCRIPT_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\"->\"%") NPRIs _T("\""),generatecode?_T(""):_T("Reserve"),filename,name_override);
8120- else SCRIPT_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\""),generatecode?_T(""):_T("Reserve"),filename);
8121+ if (name_override) SCRIPT_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\"->\"%") NPRIs _T("\""),which_token_str,filename,name_override);
8122+ else SCRIPT_MSG(_T("%") NPRIs _T("File: \"%") NPRIs _T("\""),which_token_str,filename);
8123 if (!build_compress_whole)
8124 if (build_compress) SCRIPT_MSG(_T(" [compress]"));
8125 fflush(stdout);
8126 TCHAR buf[1024];
8127- int last_build_datablock_used=getcurdbsize();
8128+ IGrowBuf64::size_type last_build_datablock_used=getcurdbsize();
8129 entry ent={0,};
8130 if (generatecode)
8131 {
8132+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
8133+ ent.which=datablock_mode?EW_EXTRACTSTUBFILE:EW_EXTRACTFILE;
8134+#else
8135 ent.which=EW_EXTRACTFILE;
8136-
8137+#endif
8138 DefineInnerLangString(NLF_SKIPPED);
8139 DefineInnerLangString(NLF_ERR_DECOMPRESSING);
8140 DefineInnerLangString(NLF_ERR_WRITING);
8141@@ -5338,23 +5504,62 @@
8142 ent.offsets[1]=add_string(buf);
8143 }
8144 }
8145- ent.offsets[2]=add_db_data(&mmap);
8146-
8147+ crc32_t crc = 0;
8148+ IGrowBuf64::size_type db_offset = add_db_data(&mmap, &crc);
8149 mmap.clear();
8150+ if (db_offset < 0) return PS_ERROR;
8151+ DB_OFFSET off;
8152+ off.quad_part = db_offset;
8153
8154- if (ent.offsets[2] < 0)
8155- return PS_ERROR;
8156+ ent.offsets[2]=off.low_part;
8157+ ent.offsets[3]=off.high_part;
8158+ ent.offsets[7]=FIX_ENDIAN_INT32(crc);
8159
8160+ if (pcrc)
8161+ *pcrc = ent.offsets[7];
8162+
8163 if (data_handle)
8164- *data_handle=ent.offsets[2];
8165+ *data_handle = db_offset;
8166
8167 {
8168- DWORD s=getcurdbsize()-last_build_datablock_used;
8169+ DWORD s=truncate_cast(DWORD, (UINT64)(getcurdbsize()-last_build_datablock_used));
8170 if (s) s-=4;
8171 if (s != len)
8172 SCRIPT_MSG(_T(" %d/%d bytes\n"),s,len);
8173 else
8174 SCRIPT_MSG(_T(" %d bytes\n"),len);
8175+
8176+#ifdef NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
8177+ if (build_external_file != OFM_AIO)
8178+ {
8179+ if (getcurdbsize() > IGrowBuf64::getlimit())
8180+ {
8181+ ERROR_MSG(_T("%") NPRIs _T("File: failed to add file, datablock bigger than external file output limit (8EB).\n"),which_token_str);
8182+ return PS_ERROR;
8183+ }
8184+ }
8185+ else
8186+#endif//NSIS_CONFIG_EXTERNAL_FILE_SUPPORT
8187+ {
8188+#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
8189+ if (build_compress_whole)
8190+ {
8191+ if (getcurdbsize() > 0x7fffffff)
8192+ {
8193+ ERROR_MSG(_T("%") NPRIs _T("File: failed to add file, exehead datablock bigger than file output limit (2GB).\n"),which_token_str);
8194+ return PS_ERROR;
8195+ }
8196+ }
8197+ else
8198+#endif
8199+ {
8200+ if (getcurdbsize() > 0xffffffff)
8201+ {
8202+ ERROR_MSG(_T("%") NPRIs _T("File: failed to add file, exehead datablock bigger than file output limit (4GB).\n"),which_token_str);
8203+ return PS_ERROR;
8204+ }
8205+ }
8206+ }
8207 }
8208
8209 if (generatecode)
8210@@ -5367,7 +5572,7 @@
8211 {
8212 PULONGLONG fti = (PULONGLONG) &ft;
8213 *fti -= *fti % 20000000; // FAT write time has a resolution of 2 seconds
8214- ent.offsets[3]=ft.dwLowDateTime, ent.offsets[4]=ft.dwHighDateTime;
8215+ ent.offsets[4]=ft.dwLowDateTime, ent.offsets[5]=ft.dwHighDateTime;
8216 }
8217 #else
8218 struct stat st;
8219@@ -5375,18 +5580,18 @@
8220 {
8221 unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
8222 ll -= ll % 20000000; // FAT write time has a resolution of 2 seconds
8223- ent.offsets[3] = (int) ll, ent.offsets[4] = (int) (ll >> 32);
8224+ ent.offsets[4] = (int) ll, ent.offsets[5] = (int) (ll >> 32);
8225 }
8226 #endif
8227 else
8228 {
8229- ERROR_MSG(_T("%") NPRIs _T("File: failed getting file date from \"%") NPRIs _T("\"\n"),generatecode?_T(""):_T("Reserve"),newfn);
8230+ ERROR_MSG(_T("%") NPRIs _T("File: failed getting file date from \"%") NPRIs _T("\"\n"),which_token_str,newfn);
8231 return PS_ERROR;
8232 }
8233 }
8234 else
8235 {
8236- ent.offsets[3]=0xffffffff, ent.offsets[4]=0xffffffff;
8237+ ent.offsets[4]=0xffffffff, ent.offsets[5]=0xffffffff;
8238 }
8239
8240 // overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits
8241@@ -5402,7 +5607,7 @@
8242 mb |= IDCANCEL << 21; // default for silent installers
8243 }
8244 ent.offsets[0] |= mb << 3;
8245- ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
8246+ ent.offsets[6] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
8247 }
8248
8249 if (generatecode)
8250@@ -5421,6 +5626,8 @@
8251 ent.offsets[3]=0;
8252 ent.offsets[4]=0;
8253 ent.offsets[5]=0;
8254+ ent.offsets[6]=0;
8255+ ent.offsets[7]=0;
8256
8257 if (INVALID_FILE_ATTRIBUTES != (DWORD)ent.offsets[1])
8258 {
8259Index: Source/tokens.cpp
8260===================================================================
8261--- Source/tokens.cpp (revision 7070)
8262+++ Source/tokens.cpp (working copy)
8263@@ -88,9 +88,11 @@
8264 {TOK_FINDFIRST,_T("FindFirst"),3,0,_T("$(user_var: handle output) $(user_var: filename output) filespec"),TP_CODE},
8265 {TOK_FINDNEXT,_T("FindNext"),2,0,_T("$(user_var: handle input) $(user_var: filename output)"),TP_CODE},
8266 {TOK_FILE,_T("File"),1,-1,_T("[/nonfatal] [/a] ([/r] [/x filespec [...]] filespec [...] |\n /oname=outfile one_file_only)"),TP_CODE},
8267+{TOK_STUBFILE,_T("StubFile"),1,-1,_T("[/nonfatal] [/a] ([/r] [/x filespec [...]] filespec [...] |\n /oname=outfile one_file_only)"),TP_CODE},
8268 {TOK_FILEBUFSIZE,_T("FileBufSize"),1,0,_T("buf_size_mb"),TP_ALL},
8269 {TOK_FLUSHINI,_T("FlushINI"),1,0,_T("ini_file"),TP_CODE},
8270 {TOK_RESERVEFILE,_T("ReserveFile"),1,-1,_T("[/nonfatal] [/r] [/x filespec [...]] file [file...] | [/nonfatal] /plugin file.dll"),TP_ALL},
8271+{TOK_RESERVESTUBFILE,_T("ReserveStubFile"),1,-1,_T("[/nonfatal] [/r] [/x filespec [...]] file [file...] | [/nonfatal] /plugin file.dll"),TP_ALL},
8272 {TOK_FILECLOSE,_T("FileClose"),1,0,_T("$(user_var: handle input)"),TP_CODE},
8273 {TOK_FILEERRORTEXT,_T("FileErrorText"),0,2,_T("[text (can contain $0)] [text without ignore (can contain $0)]"),TP_GLOBAL},
8274 {TOK_FILEOPEN,_T("FileOpen"),3,0,_T("$(user_var: handle output) filename openmode\n openmode=r|w|a"),TP_CODE},
8275@@ -149,6 +151,9 @@
8276 {TOK_NOP,_T("Nop"),0,0,_T(""),TP_CODE},
8277 {TOK_NAME,_T("Name"),1,1,_T("installer_name [installer_name_doubled_ampersands]"),TP_GLOBAL},
8278 {TOK_OUTFILE,_T("OutFile"),1,0,_T("install_output.exe"),TP_GLOBAL},
8279+{TOK_OUTFILEMODE,_T("OutFileMode"),1,0,_T("auto|aio|data|stub"),TP_GLOBAL},
8280+{TOK_SETEXOUTFILE,_T("SetExOutFile"),1,0,_T("auto|off|on|stub"),TP_GLOBAL},
8281+{TOK_VERIFYEXTERNALFILE,_T("VerifyExternalFile"),0,1,_T("[$(user_var: filename input)]"),TP_CODE},
8282 #ifdef NSIS_SUPPORT_CODECALLBACKS
8283 {TOK_PAGE,_T("Page"),1,4,_T("((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles|uninstConfirm) [pre_function] [show_function] [leave_function])) [/ENABLECANCEL]"),TP_GLOBAL},
8284 #else
8285Index: Source/tokens.h
8286===================================================================
8287--- Source/tokens.h (revision 7070)
8288+++ Source/tokens.h (working copy)
8289@@ -42,6 +42,8 @@
8290 TOK_SILENTUNINST,
8291 TOK_INSTTYPE,
8292 TOK_OUTFILE,
8293+ TOK_OUTFILEMODE,
8294+ TOK_SETEXOUTFILE,
8295 TOK_INSTDIR,
8296 TOK_INSTALLDIRREGKEY,
8297 TOK_UNINSTALLEXENAME,
8298@@ -73,6 +75,7 @@
8299 TOK_SETFONT,
8300 TOK_LOADNLF,
8301 TOK_RESERVEFILE,
8302+ TOK_RESERVESTUBFILE,
8303 TOK_ALLOWSKIPFILES,
8304 TOK_DEFVAR,
8305 TOK_VI_ADDKEY,
8306@@ -204,6 +207,8 @@
8307 TOK_DELETE,
8308 TOK_RMDIR,
8309 TOK_FILE,
8310+ TOK_STUBFILE,
8311+ TOK_VERIFYEXTERNALFILE,
8312 TOK_COPYFILES,
8313 TOK_SETFILEATTRIBUTES,
8314 TOK_SLEEP,
8315Index: Source/util.cpp
8316===================================================================
8317--- Source/util.cpp (revision 7070)
8318+++ Source/util.cpp (working copy)
8319@@ -663,6 +663,82 @@
8320 return f;
8321 }
8322
8323+#ifdef WIN32
8324+ #define _myseek64 _lseeki64
8325+#else
8326+ #define _myseek64 lseek64
8327+ // _fileno isn't always available, so use the old function
8328+ #ifndef _fileno
8329+ #define _fileno fileno
8330+ #endif
8331+#endif
8332+#define seek64_helper(f, o, w) _myseek64((_fileno(f)), (o), (w))
8333+#define tell64_helper(f) seek64_helper((f), 0, SEEK_CUR)
8334+int myfgetsetpos(FILE *stream)
8335+{
8336+ fpos_t pos;
8337+ return ((fgetpos(stream, &pos) == 0) && (fsetpos(stream, &pos) == 0));
8338+}
8339+
8340+INT64 mytell64(FILE *stream)
8341+{
8342+ return (myfgetsetpos(stream)) ? tell64_helper(stream) : -1;
8343+}
8344+int myseek64(FILE *stream, INT64 offset, int origin)
8345+{
8346+ return (myfgetsetpos(stream)) ? ((seek64_helper(stream, offset, origin) == -1LL) ? -1 : 0) : -1;
8347+}
8348+
8349+FileWriter::FileWriter()
8350+{
8351+ fp = 0;
8352+}
8353+FileWriter::~FileWriter()
8354+{
8355+ Fclose();
8356+}
8357+FILE* FileWriter::GetHandle()
8358+{
8359+ return fp;
8360+}
8361+bool FileWriter::Fopen(TCHAR *filename)
8362+{
8363+ fp = FOPEN(filename,("w+b"));
8364+ return !!fp;
8365+}
8366+void FileWriter::Fclose()
8367+{
8368+ if (fp) Fflush(), fclose(fp), fp = 0;
8369+}
8370+long FileWriter::Ftell()
8371+{
8372+ return ftell(fp);
8373+}
8374+INT64 FileWriter::Ftell64()
8375+{
8376+ return mytell64(fp);
8377+}
8378+int FileWriter::Fseek(int pos, int origin)
8379+{
8380+ return fseek(fp, pos, origin);
8381+}
8382+int FileWriter::Fseek64(INT64 pos, int origin)
8383+{
8384+ return myseek64(fp, pos, origin);
8385+}
8386+size_t FileWriter::Fread(void *ptr, size_t size, size_t nmemb)
8387+{
8388+ return fread(ptr, size, nmemb, fp);
8389+}
8390+size_t FileWriter::Fwrite(const void *ptr, size_t size, size_t nmemb)
8391+{
8392+ return fwrite(ptr, size, nmemb, fp);
8393+}
8394+void FileWriter::Fflush()
8395+{
8396+ fflush(fp);
8397+}
8398+
8399 #if (defined(_MSC_VER) && (_MSC_VER >= 1200)) || defined(__MINGW32__)
8400 #include <io.h>
8401 static UINT64 get_file_size64(FILE *f)
8402Index: Source/util.h
8403===================================================================
8404--- Source/util.h (revision 7070)
8405+++ Source/util.h (working copy)
8406@@ -285,6 +285,26 @@
8407 void close_file_view(FILEVIEW&mmfv);
8408 char* create_file_view_readonly(const TCHAR *filepath, FILEVIEW&mmfv);
8409
8410+class FileWriter
8411+{
8412+public:
8413+ FileWriter();
8414+ ~FileWriter();
8415+ FILE* GetHandle();
8416+ bool Fopen(TCHAR *filename);
8417+ void Fclose();
8418+ long Ftell();
8419+ INT64 Ftell64();
8420+ int Fseek(int offset, int origin);
8421+ int Fseek64(INT64 offset, int origin);
8422+ size_t Fread(void *ptr, size_t size, size_t nmemb);
8423+ size_t Fwrite(const void *ptr, size_t size, size_t nmemb);
8424+ void Fflush();
8425+
8426+private:
8427+ FILE *fp;
8428+};
8429+
8430 // round a value up to be a multiple of 512
8431 // assumption: T is an int type
8432 template <class T> inline T align_to_512(const T x) { return (x+511) & ~511; }
8433Index: Source/writer.cpp
8434===================================================================
8435--- Source/writer.cpp (revision 7070)
8436+++ Source/writer.cpp (working copy)
8437@@ -19,6 +19,7 @@
8438 #include "exehead/config.h"
8439 #include "writer.h"
8440 #include "growbuf.h"
8441+#include "growbuf64.h"
8442 #include "util.h"
8443 #include <string.h>
8444 #include <stdlib.h>
8445@@ -27,7 +28,7 @@
8446
8447 void writer_sink::write_byte(const unsigned char b)
8448 {
8449- write_data(&b, 1);
8450+ write_data(&b, (UINT32)1);
8451 }
8452
8453 void writer_sink::write_short(const short s)
8454@@ -79,7 +80,7 @@
8455 char *wb = new char[size];
8456 memset(wb, 0, size);
8457 WideCharToMultiByte(CP_ACP, 0, s, -1, wb, (int)size, NULL, NULL);
8458- write_data(wb, size);
8459+ write_data(wb, (UINT32)size);
8460 delete [] wb;
8461 }
8462 #else
8463@@ -94,35 +95,36 @@
8464
8465 void writer_sink::write_growbuf(const IGrowBuf *b)
8466 {
8467- write_data(b->get(), b->getlen());
8468+ write_data(b->get(), (UINT32)b->getlen());
8469 }
8470
8471+void writer_sink::write_growbuf64(const IGrowBuf64 *b)
8472+{
8473+ write_data(b->get(), (UINT32)b->getlen());
8474+}
8475+
8476 namespace hlp {
8477 template<class T> static inline bool issigned() { return T(-1) < T(0); }
8478 template<class T> static inline bool issigned(const T&t) { return issigned<T>(); }
8479 }
8480
8481-void growbuf_writer_sink::write_data(const void *data, const size_t size)
8482+void growbuf_writer_sink::write_data(const void *data, const UINT32 size)
8483 {
8484- // TODO: Replace all of this with a simple call when GrowBuf is changed to use size_t
8485- if (sizeof(size) == sizeof(sink_type::size_type) && hlp::issigned(size) == hlp::issigned<sink_type::size_type>())
8486- {
8487- m_buf->add(data, truncate_cast(sink_type::size_type, size));
8488- }
8489- else
8490- {
8491- size_t left = size;
8492- sink_type::size_type cbmaxadd = INT_MAX, cb;
8493- for (char *p = (char *) data; left; p += cb, left -= cb)
8494- {
8495- cb = left >= (size_t) cbmaxadd ? cbmaxadd : (sink_type::size_type) left;
8496- m_buf->add(p, cb);
8497- }
8498- }
8499+ m_buf->add(data, (sink_type::size_type)size);
8500 }
8501
8502-void file_writer_sink::write_data(const void *data, const size_t size)
8503+void growbuf64_writer_sink::write_data(const void *data, const UINT32 size)
8504 {
8505+ m_buf->add(data, size);
8506+}
8507+
8508+/*void growbuf64_writer_sink::write_data(const void *data, const UINT64 size)
8509+{
8510+ m_buf->add(data, (size_t)size);
8511+}
8512+*/
8513+void file_writer_sink::write_data(const void *data, const UINT32 size)
8514+{
8515 if (fwrite(data, 1, size, m_fp) != size)
8516 {
8517 throw std::runtime_error("error writing");
8518@@ -132,7 +134,7 @@
8519 #ifdef NSIS_CONFIG_CRC_SUPPORT
8520 #include "crc32.h"
8521
8522-void crc_writer_sink::write_data(const void *data, const size_t size)
8523+void crc_writer_sink::write_data(const void *data, const UINT32 size)
8524 {
8525 *m_crc = CRC32(*m_crc, (const unsigned char *) data, size);
8526 }
8527Index: Source/writer.h
8528===================================================================
8529--- Source/writer.h (revision 7070)
8530+++ Source/writer.h (working copy)
8531@@ -21,6 +21,7 @@
8532
8533 #include "exehead/config.h"
8534 #include "growbuf.h"
8535+#include "growbuf64.h"
8536 #include "crc32.h"
8537 #include <stdio.h>
8538 #include "tchar.h"
8539@@ -47,8 +48,10 @@
8540 virtual void write_int_array(const int i[], const size_t len);
8541 virtual void write_string(const TCHAR *s, size_t size);
8542 virtual void write_growbuf(const IGrowBuf *b);
8543+ virtual void write_growbuf64(const IGrowBuf64 *b);
8544
8545- virtual void write_data(const void *data, const size_t size) = 0;
8546+ virtual void write_data(const void *data, const UINT32 size) = 0;
8547+ //virtual void write_data(const void *data, const UINT64 size);
8548 virtual const writer_target_info& get_target_info() const { return m_ti; }
8549 protected:
8550 writer_target_info m_ti;
8551@@ -69,7 +72,7 @@
8552 typedef IGrowBuf sink_type;
8553 growbuf_writer_sink(sink_type *buf, const writer_target_info&ti) : writer_sink(ti), m_buf(buf) { }
8554
8555- virtual void write_data(const void *data, const size_t size);
8556+ virtual void write_data(const void *data, const UINT32 size);
8557
8558 private:
8559 sink_type *m_buf;
8560@@ -76,11 +79,24 @@
8561
8562 };
8563
8564+class growbuf64_writer_sink : public writer_sink {
8565+public:
8566+ typedef IGrowBuf64 sink_type;
8567+ growbuf64_writer_sink(sink_type *buf, const writer_target_info&ti) : writer_sink(ti), m_buf(buf) { }
8568+
8569+ virtual void write_data(const void *data, const UINT32 size);
8570+// virtual void write_data(const void *data, const UINT64 size);
8571+
8572+private:
8573+ sink_type *m_buf;
8574+
8575+};
8576+
8577 class file_writer_sink : public writer_sink {
8578 public:
8579 file_writer_sink(FILE *fp, const writer_target_info&ti) : writer_sink(ti), m_fp(fp) {}
8580
8581- virtual void write_data(const void *data, const size_t size);
8582+ virtual void write_data(const void *data, const UINT32 size);
8583
8584 private:
8585 FILE *m_fp;
8586@@ -92,7 +108,7 @@
8587 public:
8588 crc_writer_sink(crc32_t *crc) : writer_sink(writer_target_info()), m_crc(crc) {}
8589
8590- virtual void write_data(const void *data, const size_t size);
8591+ virtual void write_data(const void *data, const UINT32 size);
8592
8593 private:
8594 crc32_t *m_crc;
8595Index: Source/xxhash.c
8596===================================================================
8597--- Source/xxhash.c (revision 0)
8598+++ Source/xxhash.c (working copy)
8599@@ -0,0 +1,1066 @@
8600+/*
8601+* xxHash - Fast Hash algorithm
8602+* Copyright (C) 2012-2016, Yann Collet
8603+*
8604+* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8605+*
8606+* Redistribution and use in source and binary forms, with or without
8607+* modification, are permitted provided that the following conditions are
8608+* met:
8609+*
8610+* * Redistributions of source code must retain the above copyright
8611+* notice, this list of conditions and the following disclaimer.
8612+* * Redistributions in binary form must reproduce the above
8613+* copyright notice, this list of conditions and the following disclaimer
8614+* in the documentation and/or other materials provided with the
8615+* distribution.
8616+*
8617+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8618+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
8619+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8620+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8621+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8622+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
8623+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
8624+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
8625+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
8626+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
8627+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8628+*
8629+* You can contact the author at :
8630+* - xxHash homepage: http://www.xxhash.com
8631+* - xxHash source repository : https://github.com/Cyan4973/xxHash
8632+*/
8633+
8634+/*
8635+ * xxhash.c
8636+ *
8637+ * This file is a part of the external hash module for NSIS.
8638+ *
8639+ * Copyright (C) 2019 Jason Ross (JasonFriday13)
8640+ *
8641+ * Licensed under the zlib/libpng license (the "License");
8642+ * you may not use this file except in compliance with the License.
8643+ *
8644+ * Licence details can be found in the file COPYING.
8645+ *
8646+ * This software is provided 'as-is', without any express or implied
8647+ * warranty.
8648+ */
8649+
8650+/* *************************************
8651+* Tuning parameters
8652+***************************************/
8653+/*!XXH_FORCE_MEMORY_ACCESS :
8654+ * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
8655+ * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
8656+ * The below switch allow to select different access method for improved performance.
8657+ * Method 0 (default) : use `memcpy()`. Safe and portable.
8658+ * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
8659+ * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
8660+ * Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
8661+ * It can generate buggy code on targets which do not support unaligned memory accesses.
8662+ * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
8663+ * See http://stackoverflow.com/a/32095106/646947 for details.
8664+ * Prefer these methods in priority order (0 > 1 > 2)
8665+ */
8666+#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
8667+# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
8668+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
8669+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
8670+# define XXH_FORCE_MEMORY_ACCESS 2
8671+# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \
8672+ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
8673+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
8674+ || defined(__ARM_ARCH_7S__) ))
8675+# define XXH_FORCE_MEMORY_ACCESS 1
8676+# endif
8677+#endif
8678+
8679+/*!XXH_ACCEPT_NULL_INPUT_POINTER :
8680+ * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault.
8681+ * When this macro is enabled, xxHash actively checks input for null pointer.
8682+ * It it is, result for null input pointers is the same as a null-length input.
8683+ */
8684+#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */
8685+# define XXH_ACCEPT_NULL_INPUT_POINTER 0
8686+#endif
8687+
8688+/*!XXH_FORCE_ALIGN_CHECK :
8689+ * This is a minor performance trick, only useful with lots of very small keys.
8690+ * It means : check for aligned/unaligned input.
8691+ * The check costs one initial branch per hash;
8692+ * set it to 0 when the input is guaranteed to be aligned,
8693+ * or when alignment doesn't matter for performance.
8694+ */
8695+#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
8696+# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
8697+# define XXH_FORCE_ALIGN_CHECK 0
8698+# else
8699+# define XXH_FORCE_ALIGN_CHECK 1
8700+# endif
8701+#endif
8702+
8703+
8704+/* *************************************
8705+* Compiler Specific Options
8706+***************************************/
8707+#ifdef _MSC_VER /* Visual Studio */
8708+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
8709+# define XXH_FORCE_INLINE static __forceinline
8710+#else
8711+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
8712+# ifdef __GNUC__
8713+# define XXH_FORCE_INLINE static inline __attribute__((always_inline))
8714+# else
8715+# define XXH_FORCE_INLINE static inline
8716+# endif
8717+# else
8718+# define XXH_FORCE_INLINE static
8719+# endif /* __STDC_VERSION__ */
8720+#endif
8721+
8722+
8723+/* *************************************
8724+* Includes & Memory related functions
8725+***************************************/
8726+/*! Modify the local functions below should you wish to use some other memory routines
8727+* for malloc(), free() */
8728+#include "xxhash.h"
8729+
8730+#ifdef EXEHEAD
8731+static void* XXH_malloc(size_t s) { return GlobalAlloc(GPTR, s); }
8732+static void XXH_free (void* p) { GlobalFree(p); }
8733+static void* XXH_memcpy(void* dest, const void* src, size_t size)
8734+{
8735+ char *c_out=(char*)dest;
8736+ char *c_in=(char *)src;
8737+ while (size-- > 0)
8738+ {
8739+ *c_out++=*c_in++;
8740+ }
8741+ return dest;
8742+}
8743+static void* XXH_memset(void* dest, int value, size_t size)
8744+{
8745+ char *p=(char*)dest;
8746+ while (size-- > 0)
8747+ {
8748+ *p++=value;
8749+ }
8750+ return dest;
8751+}
8752+#else
8753+static void* XXH_malloc(size_t s) { return malloc(s); }
8754+static void XXH_free (void* p) { free(p); }
8755+/*! and for memcpy() */
8756+#include <string.h>
8757+static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
8758+static void* XXH_memset(void* dest, int value, size_t size) { return memset(dest, value, size); }
8759+#endif
8760+
8761+
8762+
8763+/* *************************************
8764+* Basic Types
8765+***************************************/
8766+#ifndef MEM_MODULE
8767+# if !defined (__VMS) \
8768+ && (defined (__cplusplus) \
8769+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
8770+# include <stdint.h>
8771+ typedef uint8_t BYTE;
8772+ typedef uint16_t U16;
8773+ typedef uint32_t U32;
8774+# else
8775+ typedef unsigned char BYTE;
8776+ typedef unsigned short U16;
8777+ typedef unsigned int U32;
8778+# endif
8779+#endif
8780+
8781+
8782+/* === Memory access === */
8783+
8784+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
8785+
8786+/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
8787+static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
8788+
8789+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
8790+
8791+/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
8792+/* currently only defined for gcc and icc */
8793+typedef union { U32 u32; } __attribute__((packed)) unalign;
8794+static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
8795+
8796+#else
8797+
8798+/* portable and safe solution. Generally efficient.
8799+ * see : http://stackoverflow.com/a/32095106/646947
8800+ */
8801+static U32 XXH_read32(const void* memPtr)
8802+{
8803+ U32 val;
8804+ XXH_memcpy(&val, memPtr, sizeof(val));
8805+ return val;
8806+}
8807+#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
8808+
8809+
8810+/* === Endianess === */
8811+typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
8812+
8813+/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
8814+#ifndef XXH_CPU_LITTLE_ENDIAN
8815+static int XXH_isLittleEndian(void)
8816+{
8817+ const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
8818+ return one.c[0];
8819+}
8820+# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
8821+#endif
8822+
8823+
8824+
8825+
8826+/* ****************************************
8827+* Compiler-specific Functions and Macros
8828+******************************************/
8829+#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
8830+
8831+/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
8832+#if defined(_MSC_VER)
8833+# define XXH_rotl32(x,r) _rotl(x,r)
8834+# define XXH_rotl64(x,r) _rotl64(x,r)
8835+#else
8836+# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
8837+# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
8838+#endif
8839+
8840+#if 0
8841+#if defined(_MSC_VER) /* Visual Studio */
8842+# define XXH_swap32 _byteswap_ulong
8843+#elif XXH_GCC_VERSION >= 403
8844+# define XXH_swap32 __builtin_bswap32
8845+#else
8846+static U32 XXH_swap32 (U32 x)
8847+{
8848+ return ((x << 24) & 0xff000000 ) |
8849+ ((x << 8) & 0x00ff0000 ) |
8850+ ((x >> 8) & 0x0000ff00 ) |
8851+ ((x >> 24) & 0x000000ff );
8852+}
8853+#endif
8854+#endif
8855+
8856+static U32 XXH_swap32 (U32 x)
8857+{
8858+ return ((x << 24) & 0xff000000 ) |
8859+ ((x << 8) & 0x00ff0000 ) |
8860+ ((x >> 8) & 0x0000ff00 ) |
8861+ ((x >> 24) & 0x000000ff );
8862+}
8863+
8864+/* ***************************
8865+* Memory reads
8866+*****************************/
8867+typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
8868+
8869+XXH_FORCE_INLINE U32 XXH_readLE32(const void* ptr)
8870+{
8871+ return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
8872+}
8873+
8874+static U32 XXH_readBE32(const void* ptr)
8875+{
8876+ return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
8877+}
8878+
8879+XXH_FORCE_INLINE U32
8880+XXH_readLE32_align(const void* ptr, XXH_alignment align)
8881+{
8882+ if (align==XXH_unaligned) {
8883+ return XXH_readLE32(ptr);
8884+ } else {
8885+ return XXH_CPU_LITTLE_ENDIAN ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
8886+ }
8887+}
8888+
8889+
8890+/* *************************************
8891+* Macros
8892+***************************************/
8893+#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */
8894+XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
8895+
8896+
8897+/* *******************************************************************
8898+* 32-bit hash functions
8899+*********************************************************************/
8900+static const U32 PRIME32_1 = 2654435761U; /* 0b10011110001101110111100110110001 */
8901+static const U32 PRIME32_2 = 2246822519U; /* 0b10000101111010111100101001110111 */
8902+static const U32 PRIME32_3 = 3266489917U; /* 0b11000010101100101010111000111101 */
8903+static const U32 PRIME32_4 = 668265263U; /* 0b00100111110101001110101100101111 */
8904+static const U32 PRIME32_5 = 374761393U; /* 0b00010110010101100110011110110001 */
8905+
8906+static U32 XXH32_round(U32 acc, U32 input)
8907+{
8908+ acc += input * PRIME32_2;
8909+ acc = XXH_rotl32(acc, 13);
8910+ acc *= PRIME32_1;
8911+#if defined(__GNUC__) && defined(__SSE4_1__) && !defined(XXH_ENABLE_AUTOVECTORIZE)
8912+ /* UGLY HACK:
8913+ * This inline assembly hack forces acc into a normal register. This is the
8914+ * only thing that prevents GCC and Clang from autovectorizing the XXH32 loop
8915+ * (pragmas and attributes don't work for some resason) without globally
8916+ * disabling SSE4.1.
8917+ *
8918+ * The reason we want to avoid vectorization is because despite working on
8919+ * 4 integers at a time, there are multiple factors slowing XXH32 down on
8920+ * SSE4:
8921+ * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on newer chips!)
8922+ * making it slightly slower to multiply four integers at once compared to four
8923+ * integers independently. Even when pmulld was fastest, Sandy/Ivy Bridge, it is
8924+ * still not worth it to go into SSE just to multiply unless doing a long operation.
8925+ *
8926+ * - Four instructions are required to rotate,
8927+ * movqda tmp, v // not required with VEX encoding
8928+ * pslld tmp, 13 // tmp <<= 13
8929+ * psrld v, 19 // x >>= 19
8930+ * por v, tmp // x |= tmp
8931+ * compared to one for scalar:
8932+ * roll v, 13 // reliably fast across the board
8933+ * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason
8934+ *
8935+ * - Instruction level parallelism is actually more beneficial here because the
8936+ * SIMD actually serializes this operation: While v1 is rotating, v2 can load data,
8937+ * while v3 can multiply. SSE forces them to operate together.
8938+ *
8939+ * How this hack works:
8940+ * __asm__("" // Declare an assembly block but don't declare any instructions
8941+ * : // However, as an Input/Output Operand,
8942+ * "+r" // constrain a read/write operand (+) as a general purpose register (r).
8943+ * (acc) // and set acc as the operand
8944+ * );
8945+ *
8946+ * Because of the 'r', the compiler has promised that seed will be in a
8947+ * general purpose register and the '+' says that it will be 'read/write',
8948+ * so it has to assume it has changed. It is like volatile without all the
8949+ * loads and stores.
8950+ *
8951+ * Since the argument has to be in a normal register (not an SSE register),
8952+ * each time XXH32_round is called, it is impossible to vectorize. */
8953+ __asm__("" : "+r" (acc));
8954+#endif
8955+ return acc;
8956+}
8957+
8958+/* mix all bits */
8959+static U32 XXH32_avalanche(U32 h32)
8960+{
8961+ h32 ^= h32 >> 15;
8962+ h32 *= PRIME32_2;
8963+ h32 ^= h32 >> 13;
8964+ h32 *= PRIME32_3;
8965+ h32 ^= h32 >> 16;
8966+ return(h32);
8967+}
8968+
8969+#define XXH_get32bits(p) XXH_readLE32_align(p, align)
8970+
8971+static U32
8972+XXH32_finalize(U32 h32, const void* ptr, size_t len, XXH_alignment align)
8973+
8974+{
8975+ const BYTE* p = (const BYTE*)ptr;
8976+
8977+#define PROCESS1 \
8978+ h32 += (*p++) * PRIME32_5; \
8979+ h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
8980+
8981+#define PROCESS4 \
8982+ h32 += XXH_get32bits(p) * PRIME32_3; \
8983+ p+=4; \
8984+ h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
8985+
8986+ switch(len&15) /* or switch(bEnd - p) */
8987+ {
8988+ case 12: PROCESS4;
8989+ /* fallthrough */
8990+ case 8: PROCESS4;
8991+ /* fallthrough */
8992+ case 4: PROCESS4;
8993+ return XXH32_avalanche(h32);
8994+
8995+ case 13: PROCESS4;
8996+ /* fallthrough */
8997+ case 9: PROCESS4;
8998+ /* fallthrough */
8999+ case 5: PROCESS4;
9000+ PROCESS1;
9001+ return XXH32_avalanche(h32);
9002+
9003+ case 14: PROCESS4;
9004+ /* fallthrough */
9005+ case 10: PROCESS4;
9006+ /* fallthrough */
9007+ case 6: PROCESS4;
9008+ PROCESS1;
9009+ PROCESS1;
9010+ return XXH32_avalanche(h32);
9011+
9012+ case 15: PROCESS4;
9013+ /* fallthrough */
9014+ case 11: PROCESS4;
9015+ /* fallthrough */
9016+ case 7: PROCESS4;
9017+ /* fallthrough */
9018+ case 3: PROCESS1;
9019+ /* fallthrough */
9020+ case 2: PROCESS1;
9021+ /* fallthrough */
9022+ case 1: PROCESS1;
9023+ /* fallthrough */
9024+ case 0: return XXH32_avalanche(h32);
9025+ }
9026+// assert(0);
9027+ return h32; /* reaching this point is deemed impossible */
9028+}
9029+
9030+XXH_FORCE_INLINE U32
9031+XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_alignment align)
9032+{
9033+ const BYTE* p = (const BYTE*)input;
9034+ const BYTE* bEnd = p + len;
9035+ U32 h32;
9036+
9037+#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
9038+ if (p==NULL) {
9039+ len=0;
9040+ bEnd=p=(const BYTE*)(size_t)16;
9041+ }
9042+#endif
9043+
9044+ if (len>=16) {
9045+ const BYTE* const limit = bEnd - 15;
9046+ U32 v1 = seed + PRIME32_1 + PRIME32_2;
9047+ U32 v2 = seed + PRIME32_2;
9048+ U32 v3 = seed + 0;
9049+ U32 v4 = seed - PRIME32_1;
9050+
9051+ do {
9052+ v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
9053+ v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
9054+ v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
9055+ v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
9056+ } while (p < limit);
9057+
9058+ h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7)
9059+ + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
9060+ } else {
9061+ h32 = seed + PRIME32_5;
9062+ }
9063+
9064+ h32 += (U32)len;
9065+
9066+ return XXH32_finalize(h32, p, len&15, align);
9067+}
9068+
9069+
9070+XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
9071+{
9072+#if 0
9073+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
9074+ XXH32_state_t state;
9075+ XXH32_reset(&state, seed);
9076+ XXH32_update(&state, input, len);
9077+ return XXH32_digest(&state);
9078+
9079+#else
9080+
9081+ if (XXH_FORCE_ALIGN_CHECK) {
9082+ if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
9083+ return XXH32_endian_align(input, len, seed, XXH_aligned);
9084+ } }
9085+
9086+ return XXH32_endian_align(input, len, seed, XXH_unaligned);
9087+#endif
9088+}
9089+
9090+
9091+
9092+/*====== Hash streaming ======*/
9093+
9094+XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
9095+{
9096+ return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
9097+}
9098+XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
9099+{
9100+ XXH_free(statePtr);
9101+ return XXH_OK;
9102+}
9103+
9104+XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
9105+{
9106+ XXH_memcpy(dstState, srcState, sizeof(*dstState));
9107+}
9108+
9109+XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
9110+{
9111+ XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
9112+ XXH_memset(&state, 0, sizeof(state));
9113+ state.v1 = seed + PRIME32_1 + PRIME32_2;
9114+ state.v2 = seed + PRIME32_2;
9115+ state.v3 = seed + 0;
9116+ state.v4 = seed - PRIME32_1;
9117+ /* do not write into reserved, planned to be removed in a future version */
9118+ XXH_memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved));
9119+ return XXH_OK;
9120+}
9121+
9122+
9123+XXH_PUBLIC_API XXH_errorcode
9124+XXH32_update(XXH32_state_t* state, const void* input, size_t len)
9125+{
9126+ if (input==NULL)
9127+#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
9128+ return XXH_OK;
9129+#else
9130+ return XXH_ERROR;
9131+#endif
9132+
9133+ { const BYTE* p = (const BYTE*)input;
9134+ const BYTE* const bEnd = p + len;
9135+
9136+ state->total_len_32 += (XXH32_hash_t)len;
9137+ state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));
9138+
9139+ if (state->memsize + len < 16) { /* fill in tmp buffer */
9140+ XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
9141+ state->memsize += (XXH32_hash_t)len;
9142+ return XXH_OK;
9143+ }
9144+
9145+ if (state->memsize) { /* some data left from previous update */
9146+ XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
9147+ { const U32* p32 = state->mem32;
9148+ state->v1 = XXH32_round(state->v1, XXH_readLE32(p32)); p32++;
9149+ state->v2 = XXH32_round(state->v2, XXH_readLE32(p32)); p32++;
9150+ state->v3 = XXH32_round(state->v3, XXH_readLE32(p32)); p32++;
9151+ state->v4 = XXH32_round(state->v4, XXH_readLE32(p32));
9152+ }
9153+ p += 16-state->memsize;
9154+ state->memsize = 0;
9155+ }
9156+
9157+ if (p <= bEnd-16) {
9158+ const BYTE* const limit = bEnd - 16;
9159+ U32 v1 = state->v1;
9160+ U32 v2 = state->v2;
9161+ U32 v3 = state->v3;
9162+ U32 v4 = state->v4;
9163+
9164+ do {
9165+ v1 = XXH32_round(v1, XXH_readLE32(p)); p+=4;
9166+ v2 = XXH32_round(v2, XXH_readLE32(p)); p+=4;
9167+ v3 = XXH32_round(v3, XXH_readLE32(p)); p+=4;
9168+ v4 = XXH32_round(v4, XXH_readLE32(p)); p+=4;
9169+ } while (p<=limit);
9170+
9171+ state->v1 = v1;
9172+ state->v2 = v2;
9173+ state->v3 = v3;
9174+ state->v4 = v4;
9175+ }
9176+
9177+ if (p < bEnd) {
9178+ XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
9179+ state->memsize = (unsigned)(bEnd-p);
9180+ }
9181+ }
9182+
9183+ return XXH_OK;
9184+}
9185+
9186+
9187+XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state)
9188+{
9189+ U32 h32;
9190+
9191+ if (state->large_len) {
9192+ h32 = XXH_rotl32(state->v1, 1)
9193+ + XXH_rotl32(state->v2, 7)
9194+ + XXH_rotl32(state->v3, 12)
9195+ + XXH_rotl32(state->v4, 18);
9196+ } else {
9197+ h32 = state->v3 /* == seed */ + PRIME32_5;
9198+ }
9199+
9200+ h32 += state->total_len_32;
9201+
9202+ return XXH32_finalize(h32, state->mem32, state->memsize, XXH_aligned);
9203+}
9204+
9205+
9206+/*====== Canonical representation ======*/
9207+
9208+/*! Default XXH result types are basic unsigned 32 and 64 bits.
9209+* The canonical representation follows human-readable write convention, aka big-endian (large digits first).
9210+* These functions allow transformation of hash result into and from its canonical format.
9211+* This way, hash values can be written into a file or buffer, remaining comparable across different systems.
9212+*/
9213+
9214+XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
9215+{
9216+ XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
9217+ if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
9218+ XXH_memcpy(dst, &hash, sizeof(*dst));
9219+}
9220+
9221+XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
9222+{
9223+ return XXH_readBE32(src);
9224+}
9225+
9226+
9227+#if 0
9228+/*#ifndef XXH_NO_LONG_LONG*/
9229+
9230+/* *******************************************************************
9231+* 64-bit hash functions
9232+*********************************************************************/
9233+
9234+/*====== Memory access ======*/
9235+
9236+#ifndef MEM_MODULE
9237+# define MEM_MODULE
9238+# if !defined (__VMS) \
9239+ && (defined (__cplusplus) \
9240+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
9241+# include <stdint.h>
9242+ typedef uint64_t U64;
9243+# else
9244+ /* if compiler doesn't support unsigned long long, replace by another 64-bit type */
9245+ typedef unsigned long long U64;
9246+# endif
9247+#endif
9248+
9249+
9250+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
9251+
9252+/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
9253+static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
9254+
9255+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
9256+
9257+/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
9258+/* currently only defined for gcc and icc */
9259+typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64;
9260+static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; }
9261+
9262+#else
9263+
9264+/* portable and safe solution. Generally efficient.
9265+ * see : http://stackoverflow.com/a/32095106/646947
9266+ */
9267+
9268+static U64 XXH_read64(const void* memPtr)
9269+{
9270+ U64 val;
9271+ XXH_memcpy(&val, memPtr, sizeof(val));
9272+ return val;
9273+}
9274+
9275+#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
9276+
9277+#if defined(_MSC_VER) /* Visual Studio */
9278+# define XXH_swap64 _byteswap_uint64
9279+#elif XXH_GCC_VERSION >= 403
9280+# define XXH_swap64 __builtin_bswap64
9281+#else
9282+static U64 XXH_swap64 (U64 x)
9283+{
9284+ return ((x << 56) & 0xff00000000000000ULL) |
9285+ ((x << 40) & 0x00ff000000000000ULL) |
9286+ ((x << 24) & 0x0000ff0000000000ULL) |
9287+ ((x << 8) & 0x000000ff00000000ULL) |
9288+ ((x >> 8) & 0x00000000ff000000ULL) |
9289+ ((x >> 24) & 0x0000000000ff0000ULL) |
9290+ ((x >> 40) & 0x000000000000ff00ULL) |
9291+ ((x >> 56) & 0x00000000000000ffULL);
9292+}
9293+#endif
9294+
9295+XXH_FORCE_INLINE U64 XXH_readLE64(const void* ptr)
9296+{
9297+ return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
9298+}
9299+
9300+static U64 XXH_readBE64(const void* ptr)
9301+{
9302+ return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
9303+}
9304+
9305+XXH_FORCE_INLINE U64
9306+XXH_readLE64_align(const void* ptr, XXH_alignment align)
9307+{
9308+ if (align==XXH_unaligned)
9309+ return XXH_readLE64(ptr);
9310+ else
9311+ return XXH_CPU_LITTLE_ENDIAN ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
9312+}
9313+
9314+
9315+/*====== xxh64 ======*/
9316+
9317+static const U64 PRIME64_1 = 11400714785074694791ULL; /* 0b1001111000110111011110011011000110000101111010111100101010000111 */
9318+static const U64 PRIME64_2 = 14029467366897019727ULL; /* 0b1100001010110010101011100011110100100111110101001110101101001111 */
9319+static const U64 PRIME64_3 = 1609587929392839161ULL; /* 0b0001011001010110011001111011000110011110001101110111100111111001 */
9320+static const U64 PRIME64_4 = 9650029242287828579ULL; /* 0b1000010111101011110010100111011111000010101100101010111001100011 */
9321+static const U64 PRIME64_5 = 2870177450012600261ULL; /* 0b0010011111010100111010110010111100010110010101100110011111000101 */
9322+
9323+static U64 XXH64_round(U64 acc, U64 input)
9324+{
9325+ acc += input * PRIME64_2;
9326+ acc = XXH_rotl64(acc, 31);
9327+ acc *= PRIME64_1;
9328+ return acc;
9329+}
9330+
9331+static U64 XXH64_mergeRound(U64 acc, U64 val)
9332+{
9333+ val = XXH64_round(0, val);
9334+ acc ^= val;
9335+ acc = acc * PRIME64_1 + PRIME64_4;
9336+ return acc;
9337+}
9338+
9339+static U64 XXH64_avalanche(U64 h64)
9340+{
9341+ h64 ^= h64 >> 33;
9342+ h64 *= PRIME64_2;
9343+ h64 ^= h64 >> 29;
9344+ h64 *= PRIME64_3;
9345+ h64 ^= h64 >> 32;
9346+ return h64;
9347+}
9348+
9349+
9350+#define XXH_get64bits(p) XXH_readLE64_align(p, align)
9351+
9352+static U64
9353+XXH64_finalize(U64 h64, const void* ptr, size_t len, XXH_alignment align)
9354+{
9355+ const BYTE* p = (const BYTE*)ptr;
9356+
9357+#define PROCESS1_64 \
9358+ h64 ^= (*p++) * PRIME64_5; \
9359+ h64 = XXH_rotl64(h64, 11) * PRIME64_1;
9360+
9361+#define PROCESS4_64 \
9362+ h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; \
9363+ p+=4; \
9364+ h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
9365+
9366+#define PROCESS8_64 { \
9367+ U64 const k1 = XXH64_round(0, XXH_get64bits(p)); \
9368+ p+=8; \
9369+ h64 ^= k1; \
9370+ h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \
9371+}
9372+
9373+ switch(len&31) {
9374+ case 24: PROCESS8_64;
9375+ /* fallthrough */
9376+ case 16: PROCESS8_64;
9377+ /* fallthrough */
9378+ case 8: PROCESS8_64;
9379+ return XXH64_avalanche(h64);
9380+
9381+ case 28: PROCESS8_64;
9382+ /* fallthrough */
9383+ case 20: PROCESS8_64;
9384+ /* fallthrough */
9385+ case 12: PROCESS8_64;
9386+ /* fallthrough */
9387+ case 4: PROCESS4_64;
9388+ return XXH64_avalanche(h64);
9389+
9390+ case 25: PROCESS8_64;
9391+ /* fallthrough */
9392+ case 17: PROCESS8_64;
9393+ /* fallthrough */
9394+ case 9: PROCESS8_64;
9395+ PROCESS1_64;
9396+ return XXH64_avalanche(h64);
9397+
9398+ case 29: PROCESS8_64;
9399+ /* fallthrough */
9400+ case 21: PROCESS8_64;
9401+ /* fallthrough */
9402+ case 13: PROCESS8_64;
9403+ /* fallthrough */
9404+ case 5: PROCESS4_64;
9405+ PROCESS1_64;
9406+ return XXH64_avalanche(h64);
9407+
9408+ case 26: PROCESS8_64;
9409+ /* fallthrough */
9410+ case 18: PROCESS8_64;
9411+ /* fallthrough */
9412+ case 10: PROCESS8_64;
9413+ PROCESS1_64;
9414+ PROCESS1_64;
9415+ return XXH64_avalanche(h64);
9416+
9417+ case 30: PROCESS8_64;
9418+ /* fallthrough */
9419+ case 22: PROCESS8_64;
9420+ /* fallthrough */
9421+ case 14: PROCESS8_64;
9422+ /* fallthrough */
9423+ case 6: PROCESS4_64;
9424+ PROCESS1_64;
9425+ PROCESS1_64;
9426+ return XXH64_avalanche(h64);
9427+
9428+ case 27: PROCESS8_64;
9429+ /* fallthrough */
9430+ case 19: PROCESS8_64;
9431+ /* fallthrough */
9432+ case 11: PROCESS8_64;
9433+ PROCESS1_64;
9434+ PROCESS1_64;
9435+ PROCESS1_64;
9436+ return XXH64_avalanche(h64);
9437+
9438+ case 31: PROCESS8_64;
9439+ /* fallthrough */
9440+ case 23: PROCESS8_64;
9441+ /* fallthrough */
9442+ case 15: PROCESS8_64;
9443+ /* fallthrough */
9444+ case 7: PROCESS4_64;
9445+ /* fallthrough */
9446+ case 3: PROCESS1_64;
9447+ /* fallthrough */
9448+ case 2: PROCESS1_64;
9449+ /* fallthrough */
9450+ case 1: PROCESS1_64;
9451+ /* fallthrough */
9452+ case 0: return XXH64_avalanche(h64);
9453+ }
9454+
9455+ /* impossible to reach */
9456+ assert(0);
9457+ return 0; /* unreachable, but some compilers complain without it */
9458+}
9459+
9460+XXH_FORCE_INLINE U64
9461+XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_alignment align)
9462+{
9463+ const BYTE* p = (const BYTE*)input;
9464+ const BYTE* bEnd = p + len;
9465+ U64 h64;
9466+
9467+#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
9468+ if (p==NULL) {
9469+ len=0;
9470+ bEnd=p=(const BYTE*)(size_t)32;
9471+ }
9472+#endif
9473+
9474+ if (len>=32) {
9475+ const BYTE* const limit = bEnd - 32;
9476+ U64 v1 = seed + PRIME64_1 + PRIME64_2;
9477+ U64 v2 = seed + PRIME64_2;
9478+ U64 v3 = seed + 0;
9479+ U64 v4 = seed - PRIME64_1;
9480+
9481+ do {
9482+ v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
9483+ v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
9484+ v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
9485+ v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
9486+ } while (p<=limit);
9487+
9488+ h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
9489+ h64 = XXH64_mergeRound(h64, v1);
9490+ h64 = XXH64_mergeRound(h64, v2);
9491+ h64 = XXH64_mergeRound(h64, v3);
9492+ h64 = XXH64_mergeRound(h64, v4);
9493+
9494+ } else {
9495+ h64 = seed + PRIME64_5;
9496+ }
9497+
9498+ h64 += (U64) len;
9499+
9500+ return XXH64_finalize(h64, p, len, align);
9501+}
9502+
9503+
9504+XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
9505+{
9506+#if 0
9507+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
9508+ XXH64_state_t state;
9509+ XXH64_reset(&state, seed);
9510+ XXH64_update(&state, input, len);
9511+ return XXH64_digest(&state);
9512+
9513+#else
9514+
9515+ if (XXH_FORCE_ALIGN_CHECK) {
9516+ if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
9517+ return XXH64_endian_align(input, len, seed, XXH_aligned);
9518+ } }
9519+
9520+ return XXH64_endian_align(input, len, seed, XXH_unaligned);
9521+
9522+#endif
9523+}
9524+
9525+/*====== Hash Streaming ======*/
9526+
9527+XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
9528+{
9529+ return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
9530+}
9531+XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
9532+{
9533+ XXH_free(statePtr);
9534+ return XXH_OK;
9535+}
9536+
9537+XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState)
9538+{
9539+ XXH_memcpy(dstState, srcState, sizeof(*dstState));
9540+}
9541+
9542+XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
9543+{
9544+ XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
9545+ XXH_memset(&state, 0, sizeof(state));
9546+ state.v1 = seed + PRIME64_1 + PRIME64_2;
9547+ state.v2 = seed + PRIME64_2;
9548+ state.v3 = seed + 0;
9549+ state.v4 = seed - PRIME64_1;
9550+ /* do not write into reserved, planned to be removed in a future version */
9551+ XXH_memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved));
9552+ return XXH_OK;
9553+}
9554+
9555+XXH_PUBLIC_API XXH_errorcode
9556+XXH64_update (XXH64_state_t* state, const void* input, size_t len)
9557+{
9558+ if (input==NULL)
9559+#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
9560+ return XXH_OK;
9561+#else
9562+ return XXH_ERROR;
9563+#endif
9564+
9565+ { const BYTE* p = (const BYTE*)input;
9566+ const BYTE* const bEnd = p + len;
9567+
9568+ state->total_len += len;
9569+
9570+ if (state->memsize + len < 32) { /* fill in tmp buffer */
9571+ XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
9572+ state->memsize += (U32)len;
9573+ return XXH_OK;
9574+ }
9575+
9576+ if (state->memsize) { /* tmp buffer is full */
9577+ XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
9578+ state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0));
9579+ state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1));
9580+ state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2));
9581+ state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3));
9582+ p += 32-state->memsize;
9583+ state->memsize = 0;
9584+ }
9585+
9586+ if (p+32 <= bEnd) {
9587+ const BYTE* const limit = bEnd - 32;
9588+ U64 v1 = state->v1;
9589+ U64 v2 = state->v2;
9590+ U64 v3 = state->v3;
9591+ U64 v4 = state->v4;
9592+
9593+ do {
9594+ v1 = XXH64_round(v1, XXH_readLE64(p)); p+=8;
9595+ v2 = XXH64_round(v2, XXH_readLE64(p)); p+=8;
9596+ v3 = XXH64_round(v3, XXH_readLE64(p)); p+=8;
9597+ v4 = XXH64_round(v4, XXH_readLE64(p)); p+=8;
9598+ } while (p<=limit);
9599+
9600+ state->v1 = v1;
9601+ state->v2 = v2;
9602+ state->v3 = v3;
9603+ state->v4 = v4;
9604+ }
9605+
9606+ if (p < bEnd) {
9607+ XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
9608+ state->memsize = (unsigned)(bEnd-p);
9609+ }
9610+ }
9611+
9612+ return XXH_OK;
9613+}
9614+
9615+
9616+XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state)
9617+{
9618+ U64 h64;
9619+
9620+ if (state->total_len >= 32) {
9621+ U64 const v1 = state->v1;
9622+ U64 const v2 = state->v2;
9623+ U64 const v3 = state->v3;
9624+ U64 const v4 = state->v4;
9625+
9626+ h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
9627+ h64 = XXH64_mergeRound(h64, v1);
9628+ h64 = XXH64_mergeRound(h64, v2);
9629+ h64 = XXH64_mergeRound(h64, v3);
9630+ h64 = XXH64_mergeRound(h64, v4);
9631+ } else {
9632+ h64 = state->v3 /*seed*/ + PRIME64_5;
9633+ }
9634+
9635+ h64 += (U64) state->total_len;
9636+
9637+ return XXH64_finalize(h64, state->mem64, (size_t)state->total_len, XXH_aligned);
9638+}
9639+
9640+
9641+/*====== Canonical representation ======*/
9642+
9643+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
9644+{
9645+ XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
9646+ if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
9647+ XXH_memcpy(dst, &hash, sizeof(*dst));
9648+}
9649+
9650+XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
9651+{
9652+ return XXH_readBE64(src);
9653+}
9654+
9655+
9656+
9657+/* *********************************************************************
9658+* XXH3
9659+* New generation hash designed for speed on small keys and vectorization
9660+************************************************************************ */
9661+
9662+/*#include "xxh3.h"*/
9663+
9664+
9665+#endif /* XXH_NO_LONG_LONG */
9666Index: Source/xxhash.h
9667===================================================================
9668--- Source/xxhash.h (revision 0)
9669+++ Source/xxhash.h (working copy)
9670@@ -0,0 +1,443 @@
9671+/*
9672+ xxHash - Extremely Fast Hash algorithm
9673+ Header File
9674+ Copyright (C) 2012-2016, Yann Collet.
9675+
9676+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
9677+
9678+ Redistribution and use in source and binary forms, with or without
9679+ modification, are permitted provided that the following conditions are
9680+ met:
9681+
9682+ * Redistributions of source code must retain the above copyright
9683+ notice, this list of conditions and the following disclaimer.
9684+ * Redistributions in binary form must reproduce the above
9685+ copyright notice, this list of conditions and the following disclaimer
9686+ in the documentation and/or other materials provided with the
9687+ distribution.
9688+
9689+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9690+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9691+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
9692+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9693+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9694+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9695+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9696+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9697+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9698+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
9699+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9700+
9701+ You can contact the author at :
9702+ - xxHash source repository : https://github.com/Cyan4973/xxHash
9703+*/
9704+
9705+/* Notice extracted from xxHash homepage :
9706+
9707+xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
9708+It also successfully passes all tests from the SMHasher suite.
9709+
9710+Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
9711+
9712+Name Speed Q.Score Author
9713+xxHash 5.4 GB/s 10
9714+CrapWow 3.2 GB/s 2 Andrew
9715+MumurHash 3a 2.7 GB/s 10 Austin Appleby
9716+SpookyHash 2.0 GB/s 10 Bob Jenkins
9717+SBox 1.4 GB/s 9 Bret Mulvey
9718+Lookup3 1.2 GB/s 9 Bob Jenkins
9719+SuperFastHash 1.2 GB/s 1 Paul Hsieh
9720+CityHash64 1.05 GB/s 10 Pike & Alakuijala
9721+FNV 0.55 GB/s 5 Fowler, Noll, Vo
9722+CRC32 0.43 GB/s 9
9723+MD5-32 0.33 GB/s 10 Ronald L. Rivest
9724+SHA1-32 0.28 GB/s 10
9725+
9726+Q.Score is a measure of quality of the hash function.
9727+It depends on successfully passing SMHasher test set.
9728+10 is a perfect score.
9729+
9730+A 64-bit version, named XXH64, is available since r35.
9731+It offers much better speed, but for 64-bit applications only.
9732+Name Speed on 64 bits Speed on 32 bits
9733+XXH64 13.8 GB/s 1.9 GB/s
9734+XXH32 6.8 GB/s 6.0 GB/s
9735+*/
9736+
9737+/*
9738+ * xxhash.h
9739+ *
9740+ * This file is a part of the external hash module for NSIS.
9741+ *
9742+ * Copyright (C) 2019 Jason Ross (JasonFriday13)
9743+ *
9744+ * Licensed under the zlib/libpng license (the "License");
9745+ * you may not use this file except in compliance with the License.
9746+ *
9747+ * Licence details can be found in the file COPYING.
9748+ *
9749+ * This software is provided 'as-is', without any express or implied
9750+ * warranty.
9751+ */
9752+
9753+#ifndef XXHASH_H_5627135585666179
9754+#define XXHASH_H_5627135585666179 1
9755+
9756+#if defined (__cplusplus)
9757+extern "C" {
9758+#endif
9759+
9760+
9761+/* ****************************
9762+* Definitions
9763+******************************/
9764+#include <stddef.h> /* size_t */
9765+typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
9766+
9767+
9768+/* ****************************
9769+ * API modifier
9770+ ******************************/
9771+#define XXH_PUBLIC_API /* do nothing */
9772+#define XXH_STATIC_LINKING_ONLY
9773+
9774+/*! XXH_NAMESPACE, aka Namespace Emulation :
9775+ *
9776+ * If you want to include _and expose_ xxHash functions from within your own library,
9777+ * but also want to avoid symbol collisions with other libraries which may also include xxHash,
9778+ *
9779+ * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
9780+ * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
9781+ *
9782+ * Note that no change is required within the calling program as long as it includes `xxhash.h` :
9783+ * regular symbol name will be automatically translated by this header.
9784+ */
9785+#ifdef XXH_NAMESPACE
9786+# define XXH_CAT(A,B) A##B
9787+# define XXH_NAME2(A,B) XXH_CAT(A,B)
9788+# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
9789+# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
9790+# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
9791+# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
9792+# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
9793+# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
9794+# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
9795+# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
9796+# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
9797+# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
9798+# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
9799+# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
9800+# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
9801+# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
9802+# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
9803+# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
9804+# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
9805+# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
9806+# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
9807+#endif
9808+
9809+
9810+/* *************************************
9811+* Version
9812+***************************************/
9813+#define XXH_VERSION_MAJOR 0
9814+#define XXH_VERSION_MINOR 7
9815+#define XXH_VERSION_RELEASE 0
9816+#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
9817+XXH_PUBLIC_API unsigned XXH_versionNumber (void);
9818+
9819+#include "Platform.h"
9820+
9821+/*-**********************************************************************
9822+* 32-bit hash
9823+************************************************************************/
9824+typedef UINT32 XXH32_hash_t;
9825+
9826+
9827+#ifndef XXH_NO_LONG_LONG
9828+/*-**********************************************************************
9829+* 64-bit hash
9830+************************************************************************/
9831+typedef UINT64 XXH64_hash_t;
9832+#endif
9833+
9834+
9835+
9836+#ifdef XXH_STATIC_LINKING_ONLY
9837+
9838+/* ================================================================================================
9839+ This section contains declarations which are not guaranteed to remain stable.
9840+ They may change in future versions, becoming incompatible with a different version of the library.
9841+ These declarations should only be used with static linking.
9842+ Never use them in association with dynamic linking !
9843+=================================================================================================== */
9844+
9845+/* These definitions are only present to allow
9846+ * static allocation of XXH state, on stack or in a struct for example.
9847+ * Never **ever** use members directly. */
9848+
9849+#if !defined (__VMS) \
9850+ && (defined (__cplusplus) \
9851+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
9852+
9853+struct XXH32_state_s {
9854+ UINT32 total_len_32;
9855+ UINT32 large_len;
9856+ UINT32 v1;
9857+ UINT32 v2;
9858+ UINT32 v3;
9859+ UINT32 v4;
9860+ UINT32 mem32[4];
9861+ UINT32 memsize;
9862+ UINT32 reserved; /* never read nor write, might be removed in a future version */
9863+}; /* typedef'd to XXH32_state_t */
9864+
9865+struct XXH64_state_s {
9866+ UINT64 total_len;
9867+ UINT64 v1;
9868+ UINT64 v2;
9869+ UINT64 v3;
9870+ UINT64 v4;
9871+ UINT64 mem64[4];
9872+ UINT32 memsize;
9873+ UINT32 reserved[2]; /* never read nor write, might be removed in a future version */
9874+}; /* typedef'd to XXH64_state_t */
9875+
9876+# else
9877+
9878+struct XXH32_state_s {
9879+ XXH32_hash_t total_len_32;
9880+ XXH32_hash_t large_len;
9881+ XXH32_hash_t v1;
9882+ XXH32_hash_t v2;
9883+ XXH32_hash_t v3;
9884+ XXH32_hash_t v4;
9885+ XXH32_hash_t mem32[4];
9886+ XXH32_hash_t memsize;
9887+ XXH32_hash_t reserved; /* never read nor write, might be removed in a future version */
9888+}; /* typedef'd to XXH32_state_t */
9889+
9890+# ifndef XXH_NO_LONG_LONG /* remove 64-bit support */
9891+struct XXH64_state_s {
9892+ XXH64_hash_t total_len;
9893+ XXH64_hash_t v1;
9894+ XXH64_hash_t v2;
9895+ XXH64_hash_t v3;
9896+ XXH64_hash_t v4;
9897+ XXH64_hash_t mem64[4];
9898+ XXH32_hash_t memsize;
9899+ XXH32_hash_t reserved[2]; /* never read nor write, might be removed in a future version */
9900+}; /* typedef'd to XXH64_state_t */
9901+# endif
9902+
9903+# endif
9904+
9905+
9906+
9907+/*-**********************************************************************
9908+* 32-bit hash
9909+************************************************************************/
9910+
9911+/*! XXH32() :
9912+ Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input".
9913+ The memory between input & input+length must be valid (allocated and read-accessible).
9914+ "seed" can be used to alter the result predictably.
9915+ Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */
9916+XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
9917+
9918+/*====== Streaming ======*/
9919+typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
9920+XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
9921+XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
9922+XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);
9923+
9924+XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
9925+XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
9926+XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
9927+
9928+/*
9929+ * Streaming functions generate the xxHash of an input provided in multiple segments.
9930+ * Note that, for small input, they are slower than single-call functions, due to state management.
9931+ * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized.
9932+ *
9933+ * XXH state must first be allocated, using XXH*_createState() .
9934+ *
9935+ * Start a new hash by initializing state with a seed, using XXH*_reset().
9936+ *
9937+ * Then, feed the hash state by calling XXH*_update() as many times as necessary.
9938+ * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
9939+ *
9940+ * Finally, a hash value can be produced anytime, by using XXH*_digest().
9941+ * This function returns the nn-bits hash as an int or long long.
9942+ *
9943+ * It's still possible to continue inserting input into the hash state after a digest,
9944+ * and generate some new hashes later on, by calling again XXH*_digest().
9945+ *
9946+ * When done, free XXH state space if it was allocated dynamically.
9947+ */
9948+
9949+/*====== Canonical representation ======*/
9950+
9951+typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
9952+XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
9953+XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
9954+
9955+/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
9956+ * The canonical representation uses human-readable write convention, aka big-endian (large digits first).
9957+ * These functions allow transformation of hash result into and from its canonical format.
9958+ * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
9959+ */
9960+
9961+
9962+
9963+
9964+#ifndef XXH_NO_LONG_LONG
9965+/*-**********************************************************************
9966+* 64-bit hash
9967+************************************************************************/
9968+
9969+/*! XXH64() :
9970+ Calculate the 64-bit hash of sequence of length "len" stored at memory address "input".
9971+ "seed" can be used to alter the result predictably.
9972+ This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark).
9973+*/
9974+XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
9975+
9976+/*====== Streaming ======*/
9977+typedef struct XXH64_state_s XXH64_state_t;
9978+XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
9979+XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
9980+XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state);
9981+
9982+XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
9983+XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
9984+XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
9985+
9986+/*====== Canonical representation ======*/
9987+typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
9988+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
9989+XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
9990+
9991+
9992+#endif /* XXH_NO_LONG_LONG */
9993+
9994+
9995+/*-**********************************************************************
9996+* XXH3
9997+* New experimental hash
9998+************************************************************************/
9999+#ifndef XXH_NO_LONG_LONG
10000+
10001+
10002+/* ============================================
10003+ * XXH3 is a new hash algorithm,
10004+ * featuring vastly improved speed performance
10005+ * for both small and large inputs.
10006+ * A full speed analysis will be published,
10007+ * it requires a lot more space than this comment can handle.
10008+ * In general, expect XXH3 to run about ~2x faster on large inputs,
10009+ * and >3x faster on small ones, though exact difference depend on platform.
10010+ *
10011+ * The algorithm is portable, will generate the same hash on all platforms.
10012+ * It benefits greatly from vectorization units, but does not require it.
10013+ *
10014+ * XXH3 offers 2 variants, _64bits and _128bits.
10015+ * When only 64 bits are needed, prefer calling the _64bits variant :
10016+ * it reduces the amount of mixing, resulting in faster speed on small inputs.
10017+ * It's also generally simpler to manipulate a scalar type than a struct.
10018+ * Note : the low 64-bit field of the _128bits variant is the same as _64bits result.
10019+ *
10020+ * The XXH3 algorithm is still considered experimental.
10021+ * It's possible to use it for ephemeral data, but avoid storing long-term values for later re-use.
10022+ * While labelled experimental, the produced result can still change between versions.
10023+ *
10024+ * The API currently supports one-shot hashing only.
10025+ * The full version will include streaming capability, and canonical representation
10026+ * Long term optional feature may include custom secret keys, and secret key generation.
10027+ *
10028+ * There are still a number of opened questions that community can influence during the experimental period.
10029+ * I'm trying to list a few of them below, though don't consider this list as complete.
10030+ *
10031+ * - 128-bits output type : currently defined as a structure of 2 64-bits fields.
10032+ * That's because 128-bit values do not exist in C standard.
10033+ * Note that it means that, at byte level, result is not identical depending on endianess.
10034+ * However, at field level, they are identical on all platforms.
10035+ * The canonical representation will solve the issue of identical byte-level representation across platforms,
10036+ * which is necessary for serialization.
10037+ * Would there be a better representation for a 128-bit hash result ?
10038+ * Are the names of the inner 64-bit fields important ? Should they be changed ?
10039+ *
10040+ * - Canonical representation : for the 64-bit variant, canonical representation is the same as XXH64() (aka big-endian).
10041+ * What should it be for the 128-bit variant ?
10042+ * Since it's no longer a scalar value, big-endian representation is no longer an obvious choice.
10043+ * One possibility : represent it as the concatenation of two 64-bits canonical representation (aka 2x big-endian)
10044+ * Another one : represent it in the same order as natural order in the struct for little-endian platforms.
10045+ * Less consistent with existing convention for XXH32/XXH64, but may be more natural for little-endian platforms.
10046+ *
10047+ * - Associated functions for 128-bit hash : simple things, such as checking if 2 hashes are equal, become more difficult with struct.
10048+ * Granted, it's not terribly difficult to create a comparator, but it's still a workload.
10049+ * Would it be beneficial to declare and define a comparator function for XXH128_hash_t ?
10050+ * Are there other operations on XXH128_hash_t which would be desirable ?
10051+ *
10052+ * - Variant compatibility : The low 64-bit field of the _128bits variant is the same as the result of _64bits.
10053+ * This is not a compulsory behavior. It just felt that it "wouldn't hurt", and might even help in some (unidentified) cases.
10054+ * But it might influence the design of XXH128_hash_t, in ways which may block other possibilities.
10055+ * Good idea, bad idea ?
10056+ *
10057+ * - Seed type for 128-bits variant : currently, it's a single 64-bit value, like the 64-bit variant.
10058+ * It could be argued that it's more logical to offer a 128-bit seed input parameter for a 128-bit hash.
10059+ * Although it's also more difficult to use, since it requires to declare and pass a structure instead of a value.
10060+ * It would either replace current choice, or add a new one.
10061+ * Farmhash, for example, offers both variants (the 128-bits seed variant is called `doubleSeed`).
10062+ * If both 64-bit and 128-bit seeds are possible, which variant should be called XXH128 ?
10063+ *
10064+ * - Result for len==0 : Currently, the result of hashing a zero-length input is the seed.
10065+ * This mimics the behavior of a crc : in which case, a seed is effectively an accumulator, so it's not updated if input is empty.
10066+ * Consequently, by default, when no seed specified, it returns zero. That part seems okay (it used to be a request for XXH32/XXH64).
10067+ * But is it still fine to return the seed when the seed is non-zero ?
10068+ * Are there use case which would depend on this behavior, or would prefer a mixing of the seed ?
10069+ */
10070+
10071+#ifdef XXH_NAMESPACE
10072+# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128)
10073+# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits)
10074+# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed)
10075+# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits)
10076+# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed)
10077+#endif
10078+
10079+
10080+typedef struct {
10081+ XXH64_hash_t low64;
10082+ XXH64_hash_t high64;
10083+} XXH128_hash_t;
10084+
10085+XXH_PUBLIC_API XXH128_hash_t XXH128(const void* data, size_t len, unsigned long long seed);
10086+
10087+/* note : variants without seed produce same result as variant with seed == 0 */
10088+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* data, size_t len);
10089+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, unsigned long long seed);
10090+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* data, size_t len);
10091+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(const void* data, size_t len, unsigned long long seed); /* == XXH128() */
10092+
10093+
10094+#endif /* XXH_NO_LONG_LONG */
10095+
10096+
10097+/*-**********************************************************************
10098+* XXH_INLINE_ALL
10099+************************************************************************/
10100+#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
10101+# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
10102+#endif
10103+
10104+
10105+
10106+#endif /* XXH_STATIC_LINKING_ONLY */
10107+
10108+
10109+#if defined (__cplusplus)
10110+}
10111+#endif
10112+
10113+#endif /* XXHASH_H_5627135585666179 */