diff --git a/Makefile b/Makefile
index 7a6d461..b3d1b72 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
# args
MT := 1
STATIC_CPP := 0
+STATIC_C := 0
# used clang?
CL := 0
# build with -m32?
@@ -71,7 +72,11 @@ else
endif
ifeq ($(MINS),0)
else
- TINY_LINK += -Wl,--gc-sections,--as-needed
+ TINY_LINK += -s -Wl,--gc-sections,--as-needed
+endif
+ifeq ($(STATIC_C),0)
+else
+ TINY_LINK += -static
endif
ifeq ($(CL),1)
CXX := clang++
diff --git a/README.md b/README.md
index cb12574..a080d56 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# [tinyuz](https://github.com/sisong/tinyuz)
-[](https://github.com/sisong/tinyuz/releases)
+# [tinyuz]
+[](https://github.com/sisong/tinyuz/releases)
[](https://github.com/sisong/tinyuz/blob/master/LICENSE)
[](https://github.com/sisong/tinyuz/pulls)
[](https://github.com/sisong/tinyuz/issues)
@@ -8,17 +8,27 @@
**tinyuz** is a lossless compression algorithm, designed for embedded systems,MCU, NB-IoT, etc., with better compression ratios.
Which is characterized by a very small decompress code(ROM or flash occupancy);
-The stream decompresser compiled by Mbed Studio is 856 bytes(can define to 758 bytes),
-and the memory decompresser is 424 bytes(can define to unsafe mode 298 bytes).
+The stream decompresser compiled by Mbed Studio is 626 bytes(can define to 468 bytes),
+and the memory decompresser is 424 bytes(can define to 298 bytes).
At the same time, the stream decompress memory(RAM occupancy) can also be very small,
RAM size = dictionary size(>=1Byte, specified when compress) + cache size(>=2Byte, specified when decompress).
Tip: The smaller the dictionary, the lower the compression ratio; while the smaller cache only affects the decompress speed.
-( other decompresser compiled by Mbed Studio: zlib v1.2.12 stream decompresser >~10k; lzma v22.01 stream decompresser ~6k; minilzo v2.10 memory decompresser 868 bytes(unsafe mode 628 bytes). )
+( other decompresser compiled by Mbed Studio: [zlib] v1.3.1 stream decompresser >~10k; [lzma] v22.01 stream decompresser ~6k; [miniLZO] v2.10 memory decompresser 868 bytes(unsafe mode 628 bytes). )
Large data are supported, both compress and decompress support streaming.
The compress and decompress speed is related to the characteristics of the input data and parameter settings;
On modern CPUs, compress speed is slower by about 0.4MB/S--2MB/S, and decompress speed is faster by about 180MB/S--300MB/S.
+[tinyuz]: https://github.com/sisong/tinyuz
+[HPatchLite]: https://github.com/sisong/HPatchLite
+[zlib]: https://github.com/madler/zlib
+[lzma]: https://www.7-zip.org/sdk.html
+[QuickLZ]: http://www.quicklz.com/order.html
+[tamp]: https://github.com/BrianPugh/tamp
+[heatshrink]: https://github.com/atomicobject/heatshrink
+[FastLZ]: https://github.com/ariya/fastlz
+[miniLZO]: http://www.oberhumer.com/opensource/lzo
+
---
## Releases/Binaries
[Download from latest release](https://github.com/sisong/tinyuz/releases) : Command line app for Windows, Linux, MacOS.
@@ -76,35 +86,45 @@ can also decompress at once in memory:
tuz_TResult tuz_decompress_mem(const tuz_byte* in_code,tuz_size_t code_size,tuz_byte* out_data,tuz_size_t* data_size);
```
+---
+## Porting decompress algorithm to embedded devices:
+* Add or copy the entire directory `tinyuz/decompress/` to your project;
+* Add a reference to the `tuz_dec.h` header file where the decompress algorithm is needed, and call the decompress functions declared in this file.
+
---
## test compression ratio:
ratio: compressedSize/uncompressedSize
-zlib v1.2.11: test with compress level 9, windowBits -15
-tinyuz v0.9.2: test with multiple different dictSizes 32MB,1MB,32KB,5KB,1KB,255B,79B,24B
- ('tuz -32m' means: tinyuz -c-32m)
+[tinyuz] v1.1.0: test with multiple different dictSize 1MB,32KB,4KB,1KB,255B
+('tuz -32k' means: tinyuz -c-32k)
+[zlib] v1.3.1 test with compress level 9, windowBits -15(i.e. dictSize 32KB)
+[QuickLZ] v1.5.0 test compress with default setting QLZ_COMPRESSION_LEVEL=3, QLZ_STREAMING_BUFFER=1048576
+[tamp] v1.7.0 test compress with windowBits 15 & 12(i.e. dictSize 32KB & 4KB)
+[heatshrink] v0.4.1 test compress with windowBits 12(i.e. dictSize 4KB), lookahead_sz2=6
+[FastLZ] v0.5.0 test with compress level 2
+[miniLZO] v2.10 test with `lzo1x_1_compress` function, wrkmem used default `LZO1X_1_MEM_COMPRESS=16k*sizeof(void*)` size
"aMCU.bin" is a firmware file of MCU device;
-"aMCU.bin.diff" is a uncompressed differential file between two versions of firmware files (created by [HPatchLite](https://github.com/sisong/HPatchLite));
+"aMCU.bin.diff" is a uncompressed differential file between two versions of firmware files (created by [HPatchLite]);
"A10.jpg"--"world95.txt" download from http://www.maximumcompression.com/data/files/index.html
"enwik8" download from https://data.deepai.org/enwik8.zip
"silesia.tar" download from https://sun.aei.polsl.pl//~sdeor/index.php?page=silesia
-||zlib -9|tuz -32m|tuz -1m|tuz -32k|tuz -5k|tuz -1k|tuz -255|tuz -79|tuz -24|
-|:----|----:|----:|----:|----:|----:|----:|----:|----:|----:|
-|aMCU.bin|46.54%|45.80%|45.80%|45.98%|49.16%|54.29%|60.61%|68.03%|77.95%|
-|aMCU.bin.diff|5.29%|5.75%|5.75%|5.75%|5.95%|6.35%|6.89%|7.85%|9.54%|
-|A10.jpg|99.88%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|
-|AcroRd32.exe|44.88%|42.01%|42.12%|43.80%|46.53%|51.48%|58.29%|67.57%|78.81%|
-|english.dic|25.83%|28.62%|28.65%|29.20%|29.98%|31.25%|33.49%|36.53%|39.93%|
-|FlashMX.pdf|84.76%|86.08%|85.34%|85.81%|87.34%|88.31%|89.90%|92.05%|96.83%|
-|FP.LOG|6.46%|4.95%|5.26%|7.36%|9.99%|12.67%|19.27%|99.25%|100.00%|
-|MSO97.DLL|57.94%|53.54%|54.12%|56.96%|59.80%|64.38%|70.62%|78.36%|87.73%|
-|ohs.doc|24.05%|20.65%|21.03%|24.50%|26.85%|31.08%|37.50%|69.31%|82.85%|
-|rafale.bmp|30.23%|30.30%|30.40%|32.66%|35.51%|40.81%|43.52%|47.70%|54.42%|
-|vcfiu.hlp|20.41%|17.71%|17.79%|20.39%|24.24%|27.46%|32.39%|49.01%|69.64%|
-|world95.txt|28.87%|22.88%|23.44%|30.79%|47.15%|54.96%|65.23%|78.53%|97.20%|
-|enwik8|36.45%|30.09%|33.22%|38.36%|43.96%|51.53%|63.38%|79.63%|96.78%|
-|silesia.tar|31.98%|28.41%|29.66%|33.27%|38.21%|44.45%|52.58%|63.62%|78.49%|
+|test file|tuz 1m|tuz 32k|tuz 4k|tuz 1k|tuz 255|zlib 32k|QuickLZ|tamp 32k|tamp 4k|heatshrink 4k|FastLZ|miniLZO
+|:----|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|
+aMCU.bin|45.80%|45.98%|49.64%|54.29%|60.61%|46.54%|54.49%|57.87%|56.11%|58.52%|62.21%|61.33%
+aMCU.bin.diff|5.75%|5.75%|5.99%|6.35%|6.89%|5.29%|9.52%|18.91%|16.78%|9.26%|12.50%|14.21%
+A10.jpg|99.99%|99.99%|99.99%|99.99%|99.99%|99.88%|100.00%|107.79%|108.27%|112.16%|102.91%|100.38%
+AcroRd32.exe|42.12%|43.80%|46.99%|51.48%|58.29%|44.88%|52.07%|55.86%|54.17%|56.15%|61.22%|61.44%
+english.dic|28.65%|29.20%|30.10%|31.25%|33.49%|25.83%|35.50%|39.81%|36.64%|36.82%|40.86%|43.82%
+FlashMX.pdf|85.34%|85.81%|87.46%|88.31%|89.90%|84.76%|100.00%|92.92%|93.40%|96.60%|89.57%|91.73%
+FP.LOG|5.26%|7.36%|10.34%|12.67%|19.27%|6.46%|8.59%|20.95%|21.51%|14.12%|11.97%|13.01%
+MSO97.DLL|54.12%|56.96%|60.23%|64.38%|70.62%|57.94%|65.65%|67.75%|65.78%|70.49%|74.80%|75.57%
+ohs.doc|21.03%|24.50%|27.14%|31.08%|37.50%|24.05%|25.72%|38.34%|38.15%|33.51%|28.31%|30.41%
+rafale.bmp|30.40%|32.66%|35.80%|40.81%|43.52%|30.23%|42.06%|37.38%|39.72%|40.30%|52.63%|55.41%
+vcfiu.hlp|17.79%|20.39%|24.51%|27.46%|32.39%|20.41%|24.88%|32.77%|33.87%|30.42%|32.36%|34.10%
+world95.txt|23.44%|30.79%|48.07%|54.96%|65.23%|28.87%|35.17%|38.18%|51.30%|54.32%|52.04%|51.56%
+enwik8|33.22%|38.36%|44.81%|51.53%|63.38%|36.45%|44.79%|44.48%|48.04%|50.41%|54.52%|55.79%
+silesia.tar|29.66%|33.27%|38.99%|44.45%|52.58%|31.98%|38.60%|42.77%|45.09%|44.27%|47.25%|47.50%
---
## Contact
diff --git a/README_cn.md b/README_cn.md
index 9bf0557..3e0f175 100644
--- a/README_cn.md
+++ b/README_cn.md
@@ -1,5 +1,5 @@
-# [tinyuz](https://github.com/sisong/tinyuz)
-[](https://github.com/sisong/tinyuz/releases)
+# [tinyuz]
+[](https://github.com/sisong/tinyuz/releases)
[](https://github.com/sisong/tinyuz/blob/master/LICENSE)
[](https://github.com/sisong/tinyuz/pulls)
[](https://github.com/sisong/tinyuz/issues)
@@ -8,14 +8,24 @@
**tinyuz** 是一个无损压缩算法,为超小型嵌入式设备(MCU、NB-IoT等)设计,保持还不错的压缩率。
特色是编译后的解压缩代码(ROM或flash占用)非常的小;
-流模式解压用 Mbed Studio 编译后为 856 字节(可以调整宏定义后到 758 字节);
-而内存模式解压为 424 字节(可以调整宏定义后到非安全模式 298 字节)。
-(其他解压器用 Mbed Studio 编译后大小参考: zlib v1.2.12 流模式解压 约大于10k; lzma v22.01 流模式解压 约6k; minilzo v2.10 内存模式解压为 868 字节(非安全模式 628 字节)。)
+流模式解压用 Mbed Studio 编译后为 626 字节(可以调整宏定义后可以到 468 字节);
+而内存模式解压为 424 字节(可以调整宏定义后可以到 298 字节)。
+(其他解压器用 Mbed Studio 编译后大小参考: [zlib] v1.3.1 流模式解压 约大于10k; [lzma] v22.01 流模式解压 约6k; [miniLZO] v2.10 内存模式解压为 868 字节(非安全模式 628 字节)。)
同时,流模式解压时内存(RAM占用)也可以非常的小,RAM大小= 字典大小(>=1Byte,压缩时指定) + 缓冲区大小(>=2Byte,解压缩时指定)。
提示:字典越小压缩率越低,而缓冲区较小时只影响解压缩速度。
支持处理巨大的数据,压缩和解压缩时都支持流式处理。
压缩和解压缩速度与数据特性和参数设置有关;在现代 CPU 上,压缩时比较慢约 0.4MB/S--2MB/S,解压缩较快约 180MB/S--300MB/S。
+[tinyuz]: https://github.com/sisong/tinyuz
+[HPatchLite]: https://github.com/sisong/HPatchLite
+[zlib]: https://github.com/madler/zlib
+[lzma]: https://www.7-zip.org/sdk.html
+[QuickLZ]: http://www.quicklz.com/order.html
+[tamp]: https://github.com/BrianPugh/tamp
+[heatshrink]: https://github.com/atomicobject/heatshrink
+[FastLZ]: https://github.com/ariya/fastlz
+[miniLZO]: http://www.oberhumer.com/opensource/lzo
+
---
## 二进制发布包
[从 release 下载](https://github.com/sisong/tinyuz/releases) : 分别运行在 Windows、Linux、MacOS操作系统的命令行程序。
@@ -73,35 +83,45 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
tuz_TResult tuz_decompress_mem(const tuz_byte* in_code,tuz_size_t code_size,tuz_byte* out_data,tuz_size_t* data_size);
```
+---
+## 移植解压算法到嵌入式设备:
+* 将 `tinyuz/decompress/` 整个目录添加或拷贝到你的项目工程中;
+* 在需要使用解压缩算法的地方添加 `tuz_dec.h` 头文件的引用,并调用该文件中声明的解压缩函数。
+
---
## 压缩率测试:
压缩率: 压缩后大小/压缩前大小
-zlib v1.2.11: 测试时设置压缩水平为9, 窗口比特大小设置为-15
-tinyuz v0.9.2: 测试时设置多个不同的字典大小 32MB,1MB,32KB,5KB,1KB,255B,79B,24B
- (表中'tuz -32m' 表示: tinyuz -c-32m)
+[tinyuz] v1.1.0 测试时字典大小分别设置为 1MB,32KB,4KB,1KB,255B
+(表中'tuz -32k' 表示: tinyuz -c-32k)
+[zlib] v1.3.1 测试时设置压缩水平为9, 窗口比特大小设置为-15(即字典大小32KB)
+[QuickLZ] v1.5.0 测试时使用默认设置QLZ_COMPRESSION_LEVEL=3, QLZ_STREAMING_BUFFER=1048576
+[tamp] v1.7.0 测试时窗口比特大小分别设置为15和12(即字典大小32KB和4KB)
+[heatshrink] v0.4.1 测试时窗口比特大小设置为12(即字典大小4KB), lookahead_sz2=6
+[FastLZ] v0.5.0 测试时设置压缩水平为2
+[miniLZO] v2.10 测试时`lzo1x_1_compress`函数, wrkmem使用了默认的`LZO1X_1_MEM_COMPRESS=16k*sizeof(void*)`大小
"aMCU.bin" 是一个MCU设备的固件文件;
-"aMCU.bin.diff" 是用两个不同版本的固件文件来创建的一个未压缩的补丁文件(用 [HPatchLite](https://github.com/sisong/HPatchLite) 所创建);
+"aMCU.bin.diff" 是用两个不同版本的固件文件来创建的一个未压缩的补丁文件(用 [HPatchLite] 所创建);
"A10.jpg"--"world95.txt" 从 http://www.maximumcompression.com/data/files/index.html 下载
"enwik8" 从 https://data.deepai.org/enwik8.zip 下载
"silesia.tar" 从 https://sun.aei.polsl.pl//~sdeor/index.php?page=silesia 下载
-||zlib -9|tuz -32m|tuz -1m|tuz -32k|tuz -5k|tuz -1k|tuz -255|tuz -79|tuz -24|
-|:----|----:|----:|----:|----:|----:|----:|----:|----:|----:|
-|aMCU.bin|46.54%|45.80%|45.80%|45.98%|49.16%|54.29%|60.61%|68.03%|77.95%|
-|aMCU.bin.diff|5.29%|5.75%|5.75%|5.75%|5.95%|6.35%|6.89%|7.85%|9.54%|
-|A10.jpg|99.88%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|99.99%|
-|AcroRd32.exe|44.88%|42.01%|42.12%|43.80%|46.53%|51.48%|58.29%|67.57%|78.81%|
-|english.dic|25.83%|28.62%|28.65%|29.20%|29.98%|31.25%|33.49%|36.53%|39.93%|
-|FlashMX.pdf|84.76%|86.08%|85.34%|85.81%|87.34%|88.31%|89.90%|92.05%|96.83%|
-|FP.LOG|6.46%|4.95%|5.26%|7.36%|9.99%|12.67%|19.27%|99.25%|100.00%|
-|MSO97.DLL|57.94%|53.54%|54.12%|56.96%|59.80%|64.38%|70.62%|78.36%|87.73%|
-|ohs.doc|24.05%|20.65%|21.03%|24.50%|26.85%|31.08%|37.50%|69.31%|82.85%|
-|rafale.bmp|30.23%|30.30%|30.40%|32.66%|35.51%|40.81%|43.52%|47.70%|54.42%|
-|vcfiu.hlp|20.41%|17.71%|17.79%|20.39%|24.24%|27.46%|32.39%|49.01%|69.64%|
-|world95.txt|28.87%|22.88%|23.44%|30.79%|47.15%|54.96%|65.23%|78.53%|97.20%|
-|enwik8|36.45%|30.09%|33.22%|38.36%|43.96%|51.53%|63.38%|79.63%|96.78%|
-|silesia.tar|31.98%|28.41%|29.66%|33.27%|38.21%|44.45%|52.58%|63.62%|78.49%|
+|test file|tuz 1m|tuz 32k|tuz 4k|tuz 1k|tuz 255|zlib 32k|QuickLZ|tamp 32k|tamp 4k|heatshrink 4k|FastLZ|miniLZO
+|:----|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|----:|
+aMCU.bin|45.80%|45.98%|49.64%|54.29%|60.61%|46.54%|54.49%|57.87%|56.11%|58.52%|62.21%|61.33%
+aMCU.bin.diff|5.75%|5.75%|5.99%|6.35%|6.89%|5.29%|9.52%|18.91%|16.78%|9.26%|12.50%|14.21%
+A10.jpg|99.99%|99.99%|99.99%|99.99%|99.99%|99.88%|100.00%|107.79%|108.27%|112.16%|102.91%|100.38%
+AcroRd32.exe|42.12%|43.80%|46.99%|51.48%|58.29%|44.88%|52.07%|55.86%|54.17%|56.15%|61.22%|61.44%
+english.dic|28.65%|29.20%|30.10%|31.25%|33.49%|25.83%|35.50%|39.81%|36.64%|36.82%|40.86%|43.82%
+FlashMX.pdf|85.34%|85.81%|87.46%|88.31%|89.90%|84.76%|100.00%|92.92%|93.40%|96.60%|89.57%|91.73%
+FP.LOG|5.26%|7.36%|10.34%|12.67%|19.27%|6.46%|8.59%|20.95%|21.51%|14.12%|11.97%|13.01%
+MSO97.DLL|54.12%|56.96%|60.23%|64.38%|70.62%|57.94%|65.65%|67.75%|65.78%|70.49%|74.80%|75.57%
+ohs.doc|21.03%|24.50%|27.14%|31.08%|37.50%|24.05%|25.72%|38.34%|38.15%|33.51%|28.31%|30.41%
+rafale.bmp|30.40%|32.66%|35.80%|40.81%|43.52%|30.23%|42.06%|37.38%|39.72%|40.30%|52.63%|55.41%
+vcfiu.hlp|17.79%|20.39%|24.51%|27.46%|32.39%|20.41%|24.88%|32.77%|33.87%|30.42%|32.36%|34.10%
+world95.txt|23.44%|30.79%|48.07%|54.96%|65.23%|28.87%|35.17%|38.18%|51.30%|54.32%|52.04%|51.56%
+enwik8|33.22%|38.36%|44.81%|51.53%|63.38%|36.45%|44.79%|44.48%|48.04%|50.41%|54.52%|55.79%
+silesia.tar|29.66%|33.27%|38.99%|44.45%|52.58%|31.98%|38.60%|42.77%|45.09%|44.27%|47.25%|47.50%
---
## 联系
diff --git a/builds/codeblocks/tinyuz.cbp b/builds/codeblocks/tinyuz.cbp
deleted file mode 100644
index 9f53211..0000000
--- a/builds/codeblocks/tinyuz.cbp
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/builds/vc/libtinyuz.vcxproj b/builds/vc/libtinyuz.vcxproj
index 5285ca5..3dec80c 100644
--- a/builds/vc/libtinyuz.vcxproj
+++ b/builds/vc/libtinyuz.vcxproj
@@ -1,6 +1,10 @@
+
+ Debug
+ ARM64
+
Debug
Win32
@@ -9,6 +13,10 @@
Debug
x64
+
+ Release
+ ARM64
+
Release
Win32
@@ -47,7 +55,6 @@
v4.0
ManagedCProj
tinyuz
- 10.0
@@ -64,6 +71,13 @@
Unicode
v143
+
+ StaticLibrary
+ true
+ false
+ Unicode
+ v143
+
StaticLibrary
false
@@ -80,6 +94,14 @@
true
v143
+
+ StaticLibrary
+ false
+ false
+ Unicode
+ true
+ v143
+
@@ -89,12 +111,18 @@
+
+
+
+
+
+
true
@@ -102,12 +130,18 @@
true
+
+ true
+
false
false
+
+ false
+
Level3
@@ -140,6 +174,22 @@
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;%(PreprocessorDefinitions)
+ NotUsing
+ MultiThreadedDebug
+
+
+
+
+ true
+
+
+
+
Level3
@@ -172,6 +222,22 @@
+
+
+ Level3
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ NotUsing
+ true
+ MultiThreaded
+
+
+
+
+ true
+
+
+
+
diff --git a/builds/vc/speedTest.vcxproj b/builds/vc/speedTest.vcxproj
index 4f97e00..73d508d 100644
--- a/builds/vc/speedTest.vcxproj
+++ b/builds/vc/speedTest.vcxproj
@@ -1,6 +1,10 @@
+
+ Debug
+ ARM64
+
Debug
Win32
@@ -9,6 +13,10 @@
Debug
x64
+
+ Release
+ ARM64
+
Release
Win32
@@ -33,7 +41,6 @@
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}
Win32Proj
speedTest
- 10.0
@@ -48,6 +55,12 @@
Unicode
v143
+
+ Application
+ true
+ Unicode
+ v143
+
Application
false
@@ -62,6 +75,13 @@
Unicode
v143
+
+ Application
+ false
+ true
+ Unicode
+ v143
+
@@ -71,12 +91,18 @@
+
+
+
+
+
+
true
@@ -86,6 +112,10 @@
true
..\..\..\zlib;$(IncludePath)
+
+ true
+ ..\..\..\zlib;$(IncludePath)
+
false
..\..\..\zlib;$(IncludePath)
@@ -94,6 +124,10 @@
false
..\..\..\zlib;$(IncludePath)
+
+ false
+ ..\..\..\zlib;$(IncludePath)
+
NotUsing
@@ -126,6 +160,22 @@
true
+
+
+ NotUsing
+ Level3
+ Disabled
+ WIN32;_DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+
+
+
+
+
+
+ true
+
+
Level3
@@ -144,6 +194,7 @@
true
true
true
+ UseLinkTimeCodeGeneration
@@ -164,6 +215,28 @@
true
true
true
+ UseLinkTimeCodeGeneration
+
+
+
+
+ Level3
+ NotUsing
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreaded
+
+
+
+
+
+
+ true
+ true
+ true
+ UseLinkTimeCodeGeneration
diff --git a/builds/vc/tinyuz.sln b/builds/vc/tinyuz.sln
index d735acd..5ddcbf8 100644
--- a/builds/vc/tinyuz.sln
+++ b/builds/vc/tinyuz.sln
@@ -17,48 +17,70 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyuz", "tinyuz.vcxproj",
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
+ Release|ARM64 = Release|ARM64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|ARM64.Build.0 = Debug|ARM64
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|Win32.ActiveCfg = Debug|Win32
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|Win32.Build.0 = Debug|Win32
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|x64.ActiveCfg = Debug|x64
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Debug|x64.Build.0 = Debug|x64
+ {6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|ARM64.Build.0 = Release|ARM64
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|Win32.ActiveCfg = Release|Win32
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|Win32.Build.0 = Release|Win32
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|x64.ActiveCfg = Release|x64
{6609E1CF-8DAE-41E9-BC20-1574E49EC91B}.Release|x64.Build.0 = Release|x64
+ {EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|ARM64.Build.0 = Debug|ARM64
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|Win32.ActiveCfg = Debug|Win32
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|Win32.Build.0 = Debug|Win32
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|x64.ActiveCfg = Debug|x64
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Debug|x64.Build.0 = Debug|x64
+ {EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|ARM64.ActiveCfg = Release|ARM64
+ {EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|ARM64.Build.0 = Release|ARM64
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|Win32.ActiveCfg = Release|Win32
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|Win32.Build.0 = Release|Win32
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|x64.ActiveCfg = Release|x64
{EF8D668D-DF30-4CC6-AFAC-929D951BC8E7}.Release|x64.Build.0 = Release|x64
+ {2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|ARM64.Build.0 = Debug|ARM64
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|Win32.ActiveCfg = Debug|Win32
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|Win32.Build.0 = Debug|Win32
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|x64.ActiveCfg = Debug|x64
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Debug|x64.Build.0 = Debug|x64
+ {2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|ARM64.Build.0 = Release|ARM64
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|Win32.ActiveCfg = Release|Win32
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|Win32.Build.0 = Release|Win32
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|x64.ActiveCfg = Release|x64
{2668A815-C1D0-48AD-A4AE-FE1ADB90B1FF}.Release|x64.Build.0 = Release|x64
+ {35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|ARM64.Build.0 = Debug|ARM64
{35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|Win32.ActiveCfg = Debug|Win32
{35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|Win32.Build.0 = Debug|Win32
{35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|x64.ActiveCfg = Debug|x64
{35ED7715-6B17-4225-8171-C954968D8F8C}.Debug|x64.Build.0 = Debug|x64
+ {35ED7715-6B17-4225-8171-C954968D8F8C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {35ED7715-6B17-4225-8171-C954968D8F8C}.Release|ARM64.Build.0 = Release|ARM64
{35ED7715-6B17-4225-8171-C954968D8F8C}.Release|Win32.ActiveCfg = Release|Win32
{35ED7715-6B17-4225-8171-C954968D8F8C}.Release|Win32.Build.0 = Release|Win32
{35ED7715-6B17-4225-8171-C954968D8F8C}.Release|x64.ActiveCfg = Release|x64
{35ED7715-6B17-4225-8171-C954968D8F8C}.Release|x64.Build.0 = Release|x64
+ {981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|ARM64.Build.0 = Debug|ARM64
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|Win32.ActiveCfg = Debug|Win32
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|Win32.Build.0 = Debug|Win32
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|x64.ActiveCfg = Debug|x64
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Debug|x64.Build.0 = Debug|x64
+ {981B8BF9-84DD-4DF9-990B-0428808E770E}.Release|ARM64.ActiveCfg = Release|ARM64
+ {981B8BF9-84DD-4DF9-990B-0428808E770E}.Release|ARM64.Build.0 = Release|ARM64
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Release|Win32.ActiveCfg = Release|Win32
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Release|Win32.Build.0 = Release|Win32
{981B8BF9-84DD-4DF9-990B-0428808E770E}.Release|x64.ActiveCfg = Release|x64
diff --git a/builds/vc/tinyuz.vcxproj b/builds/vc/tinyuz.vcxproj
index 1109c03..b138af9 100644
--- a/builds/vc/tinyuz.vcxproj
+++ b/builds/vc/tinyuz.vcxproj
@@ -1,6 +1,10 @@
+
+ Debug
+ ARM64
+
Debug
Win32
@@ -9,6 +13,10 @@
Debug
x64
+
+ Release
+ ARM64
+
Release
Win32
@@ -21,7 +29,6 @@
{981B8BF9-84DD-4DF9-990B-0428808E770E}
tinyuz
- 10.0
@@ -36,6 +43,12 @@
Unicode
v143
+
+ Application
+ true
+ Unicode
+ v143
+
Application
false
@@ -50,6 +63,13 @@
Unicode
v143
+
+ Application
+ false
+ true
+ Unicode
+ v143
+
@@ -59,12 +79,18 @@
+
+
+
+
+
+
@@ -93,6 +119,19 @@
..\..\..\HDiffPatch\builds\vc\longPathAware.exe.manifest %(AdditionalManifestFiles)
+
+
+ Level3
+ Disabled
+ MultiThreadedDebug
+
+
+ true
+
+
+ ..\..\..\HDiffPatch\builds\vc\longPathAware.exe.manifest %(AdditionalManifestFiles)
+
+
Level3
@@ -129,6 +168,24 @@
..\..\..\HDiffPatch\builds\vc\longPathAware.exe.manifest %(AdditionalManifestFiles)
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ MultiThreaded
+
+
+ false
+ true
+ true
+ UseLinkTimeCodeGeneration
+
+
+ ..\..\..\HDiffPatch\builds\vc\longPathAware.exe.manifest %(AdditionalManifestFiles)
+
+
{6609e1cf-8dae-41e9-bc20-1574e49ec91b}
diff --git a/builds/vc/unitTest.vcxproj b/builds/vc/unitTest.vcxproj
index e5af9a9..38e78b5 100644
--- a/builds/vc/unitTest.vcxproj
+++ b/builds/vc/unitTest.vcxproj
@@ -1,6 +1,10 @@
+
+ Debug
+ ARM64
+
Debug
Win32
@@ -9,6 +13,10 @@
Debug
x64
+
+ Release
+ ARM64
+
Release
Win32
@@ -31,7 +39,6 @@
v4.0
ManagedCProj
unitTest
- 10.0
@@ -48,6 +55,13 @@
Unicode
v143
+
+ Application
+ true
+ false
+ Unicode
+ v143
+
Application
false
@@ -64,6 +78,14 @@
true
v143
+
+ Application
+ false
+ false
+ Unicode
+ true
+ v143
+
@@ -73,12 +95,18 @@
+
+
+
+
+
+
true
@@ -86,12 +114,18 @@
true
+
+ true
+
false
false
+
+ false
+
Level3
@@ -124,6 +158,22 @@
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;%(PreprocessorDefinitions)
+ NotUsing
+
+
+ MultiThreadedDebug
+
+
+ true
+
+
+
+
Level3
@@ -154,6 +204,21 @@
+
+
+ Level3
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ NotUsing
+
+
+ MultiThreaded
+
+
+ true
+
+
+
+
diff --git a/compress/tuz_enc_private/tuz_enc_code.cpp b/compress/tuz_enc_private/tuz_enc_code.cpp
index 6f27c43..a5c1967 100644
--- a/compress/tuz_enc_private/tuz_enc_code.cpp
+++ b/compress/tuz_enc_private/tuz_enc_code.cpp
@@ -160,13 +160,13 @@ size_t TTuzCode::_getSavedDictLenBit(size_t len)const{
}
void TTuzCode::outDict(size_t match_len,size_t dict_pos){
outType(tuz_codeType_dict);
- size_t saved_dict_pos=dict_pos+1; //0 for ctrl
+ const size_t saved_dict_pos=dict_pos+1; //0 for ctrl
if (saved_dict_pos>_dict_size_max) _dict_size_max=saved_dict_pos;
const size_t isSamePos=(_dictPos_back==saved_dict_pos)?1:0;
const size_t isSavedSamePos=(isSamePos&&_isHaveData_back)?1:0;
size_t len=match_len-tuz_kMinDictMatchLen;
if (!isSavedSamePos){
- if (saved_dict_pos>tuz_kBigPosForLen) { checkv(match_len>=3); --len; }
+ if (saved_dict_pos>tuz_kBigPosForLen) { checkv(match_len>=tuz_kMinDictMatchLen+1); --len; }
//if (saved_dict_pos>((1<<17)+(1<<15)+(1<<13)+(1<<11)+(1<<9)+(1<<7)-1)) { checkv(match_len>=4); --len; }
}
outDictLen(len);
@@ -200,7 +200,7 @@ void TTuzCode::outDict(size_t match_len,size_t dict_pos){
mdict_offs=dict_pos;
#endif
_isHaveData_back=false;
- _dictPos_back=dict_pos+1;
+ _dictPos_back=saved_dict_pos;
}
void TTuzCode::outCtrl_streamEnd(){
diff --git a/compress/tuz_enc_private/tuz_enc_match.cpp b/compress/tuz_enc_private/tuz_enc_match.cpp
index d60e45a..9ad01bb 100644
--- a/compress/tuz_enc_private/tuz_enc_match.cpp
+++ b/compress/tuz_enc_private/tuz_enc_match.cpp
@@ -6,14 +6,11 @@
#include "tuz_enc_match.h"
#include "tuz_enc_code.h"
namespace _tuz_private{
-
- typedef TMatch::TInt TInt;
- typedef TMatch::TUInt TUInt;
- typedef TMatch::TLCPInt TLCPInt;
+
const TUInt kNullCostValue=~(TUInt)0;
#define _k_kBMatchStep 512 // skip by a big match
- static TInt _sstr_eqLen(const tuz_byte* ss_end,size_t maxSaveLength,
+ static inline TInt _sstr_eqLen(const tuz_byte* ss_end,size_t maxSaveLength,
const tuz_byte* matchedString,const tuz_byte* curString){
TInt eqLen=0;
while ((curString& cost){
}
}
-void TMatch::_getCostByLiteralLen(const tuz_byte* cur0,std::vector& cost){
+
+
+ #define _MatchedAtBy_byLiteralLen(isSamePos){ \
+ const size_t saveDictCost=coder.getSavedDictPosBit(dict_pos,isHaveData); \
+ const size_t curSaveCost=cost[curi-1]+saveDictCost; \
+ assert(curSaveCost(match_len,dict_pos); \
+ const size_t ni=curi+match_len-1; \
+ const size_t cost_ni=cost[ni]; \
+ if (dictCost& cost){
+ const size_t back_pos=dictPos[curi-1];
+ const size_t isHaveData=((matchLen[curi-1]==0)&&(curi>1))?1:0;
+
+ if (isHaveData&&(back_pos==dict_pos)){ //same pos match
+ _MatchedAtBy_byLiteralLen(true);
+ }else{
+ _MatchedAtBy_byLiteralLen(false);
+ }
+ }
+
+void TMatch::_getCostByLiteralLen(std::vector& cost){
size_t costSize=cost.size();
size_t unmatched_len=0;
size_t unmatched_fill0_i=0;
@@ -193,37 +216,45 @@ void TMatch::_getCostByLiteralLen(const tuz_byte* cur0,std::vector& cost)
unmatched_fill0_i=i;
}
++i;
- }
+ }
}
-void TMatch::_getCost(const tuz_byte* cur0){
- std::vector cost;
- size_t costSize=(sstring.src_end-cur0)+1;
+
+ static void _restoreMatch(size_t costSize,TPosInt* dictPos,TLCPInt* matchLen){
+ size_t i_inc=costSize;
+ while (i_inc>0) {
+ size_t i=i_inc-1;
+ TLCPInt mlen=matchLen[i];
+ if (mlen>0){
+ dictPos[i-mlen+1]=dictPos[i];
+ matchLen[i-mlen+1]=mlen;
+ i_inc-=mlen;
+ }else{
+ --i_inc;
+ }
+ }
+ }
+void TMatch::_initCost(std::vector& cost,size_t costSize){
+ cost.clear();
+ matchLen.clear();
cost.resize(costSize,kNullCostValue);
- dictPos.resize(costSize);
matchLen.resize(costSize,0);
+ dictPos.clear();
+ dictPos.resize(costSize,~(size_t)0);
cost[0]=0;
dictPos[0]=0;
matchLen[0]=0;
-
- _getCostByMatch(cur0,cost);
-
- size_t i_inc=costSize;
- while (i_inc>0) {
- size_t i=i_inc-1;
- TLCPInt mlen=matchLen[i];
- if (mlen>0){
- dictPos[i-mlen+1]=dictPos[i];
- matchLen[i-mlen+1]=mlen;
- if (props.isNeedLiteralLine)
- cost[i-mlen+1]=cost[i];
- i_inc-=mlen;
- }else{
- --i_inc;
- }
- }
+}
+void TMatch::_getCost(const tuz_byte* cur0){
+ std::vector cost;
+ const size_t costSize=(sstring.src_end-cur0)+1;
+ _initCost(cost,costSize);
+ _getCostByMatch(cur0,cost);
+ sstring.clearMem();
+ _restoreMatch(costSize,dictPos.data(),matchLen.data());
+
if (props.isNeedLiteralLine)
- _getCostByLiteralLen(cur0,cost);
+ _getCostByLiteralLen(cost);
}
bool TMatch::match(const tuz_byte** out_matched,size_t* out_match_len,
@@ -241,4 +272,4 @@ bool TMatch::match(const tuz_byte** out_matched,size_t* out_match_len,
}
}
-}
+}//namespace _tuz_private
diff --git a/compress/tuz_enc_private/tuz_enc_match.h b/compress/tuz_enc_private/tuz_enc_match.h
index d4e2ede..76618f3 100644
--- a/compress/tuz_enc_private/tuz_enc_match.h
+++ b/compress/tuz_enc_private/tuz_enc_match.h
@@ -7,8 +7,18 @@
#define _tuz_enc_match_h
#include "tuz_sstring.h"
namespace _tuz_private{
+
struct TTuzCode;
+ typedef TSuffixString::TInt TInt;
+ typedef uint32_t TUInt;
+ typedef TSuffixString::TLCPInt TLCPInt;
+ #if (tuz_kMaxOfDictSize>=(1<<16))
+ typedef TUInt TPosInt;
+ #else
+ typedef TLCPInt TPosInt;
+ #endif
+
struct TMatch{
explicit TMatch(const tuz_byte* data,const tuz_byte* data_end,
const TTuzCode& _coder,const tuz_TCompressProps& _props)
@@ -16,25 +26,20 @@ namespace _tuz_private{
props(_props){ }
bool match(const tuz_byte** out_matched,size_t* out_match_len,
const tuz_byte* cur);
- typedef TSuffixString::TInt TInt;
- typedef uint32_t TUInt;
- typedef TSuffixString::TLCPInt TLCPInt;
private:
TSuffixString sstring;
const TTuzCode& coder;
const tuz_TCompressProps& props;
- #if (tuz_kMaxOfDictSize>=(1<<16))
- typedef TUInt TPosInt;
- #else
- typedef TLCPInt TPosInt;
- #endif
std::vector dictPos;
std::vector matchLen;
void _cost_match(const TInt curString,const size_t curi,
size_t* out_maxMatchLen,std::vector& cost);
+ void _initCost(std::vector& cost,size_t costSize);
void _getCost(const tuz_byte* cur0);
void _getCostByMatch(const tuz_byte* cur0,std::vector& cost);
- void _getCostByLiteralLen(const tuz_byte* cur0,std::vector& cost);
+ void _cost_match_byLiteralLen(const size_t match_len,const size_t dict_pos,
+ const size_t curi,std::vector& cost);
+ void _getCostByLiteralLen(std::vector& cost);
};
}
diff --git a/compress/tuz_enc_private/tuz_sstring.cpp b/compress/tuz_enc_private/tuz_sstring.cpp
index b96bd34..d516cdd 100644
--- a/compress/tuz_enc_private/tuz_sstring.cpp
+++ b/compress/tuz_enc_private/tuz_sstring.cpp
@@ -44,4 +44,15 @@ void TSuffixString::_init(TLCPInt maxLCPValue){
_LCP_create_withR(src,(TInt)SA.size(),SA.data(),R.data(),LCP.data(),maxLCPValue);
}
+ template
+ static void _clearVector(std::vector& v){
+ std::vector _tmp;
+ v.swap(_tmp);
+ }
+void TSuffixString::clearMem(){
+ _clearVector(SA);
+ _clearVector(R);
+ _clearVector(LCP);
+}
+
}
diff --git a/compress/tuz_enc_private/tuz_sstring.h b/compress/tuz_enc_private/tuz_sstring.h
index 70a3753..40b5e26 100644
--- a/compress/tuz_enc_private/tuz_sstring.h
+++ b/compress/tuz_enc_private/tuz_sstring.h
@@ -21,6 +21,7 @@ namespace _tuz_private{
std::vector LCP; // lcp(i,i+1), longest common prefix between adjacent sstring
size_t threadNum;
inline size_t size()const { return src_end-src; }
+ void clearMem();
private:
void _init(TLCPInt maxLCPValue);
};
diff --git a/decompress/tuz_dec.c b/decompress/tuz_dec.c
index 005505f..32ed962 100644
--- a/decompress/tuz_dec.c
+++ b/decompress/tuz_dec.c
@@ -1,29 +1,15 @@
// tuz_dec.c
/*
The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
+ Copyright (c) 2012-2025 HouSisong All Rights Reserved.
*/
#include "tuz_dec.h"
#include "tuz_types_private.h"
-#if _IS_USED_C_MEMCPY
-# include // memcpy
-#endif
#if (_IS_RUN_MEM_SAFE_CHECK)
# define __RUN_MEM_SAFE_CHECK
#endif
-#define _memmove_order memmove_order
-#if (!(_IS_USED_C_MEMCPY))
-# define _memcpy memmove_order
-#else
-# define _memcpy memcpy
- tuz_force_inline
-#endif
- static void memmove_order(tuz_byte* dst,const tuz_byte* src,tuz_size_t len){
- while (len--) *dst++=*src++;
- }
-
//low to high bitmap: xx?xx?xx?xx? ...
#define _def_unpack_len(self,readBit,_read_lowbits){ \
tuz_length_t v=0; \
@@ -120,63 +106,6 @@ static tuz_force_inline tuz_size_t _cache_unpack_dict_pos(tuz_TStream* self){
return ((result&((1<<7)-1))|(_cache_unpack_pos_len(self)<<7))+(1<<7);
}
-
-static void _update_dict(tuz_TStream *self,const tuz_byte* out_data,const tuz_byte* cur_out_data) {
- // [ dict buf ]|[ out buf ]
- // |dict_cur dict_size|out_data cur_out_data]
- // [ out buf ]
- // [ out buf ]
- const tuz_size_t out_len=(tuz_size_t)(cur_out_data-out_data);
- const tuz_size_t dict_size=self->_dict.dict_size;
- tuz_byte* dict=self->_dict.dict_buf;
- if (self->_state.dictType_pos_inc>=out_len){
- self->_state.dictType_pos_inc-=out_len;
- }else{
- self->_state.dictType_pos-=(tuz_size_t)(out_len-self->_state.dictType_pos_inc);
- self->_state.dictType_pos_inc=0;
- }
- if (out_len>=dict_size){
- _memcpy(dict,cur_out_data-dict_size,dict_size);
- self->_dict.dict_cur=0;
- }else{
- tuz_size_t dict_cur=self->_dict.dict_cur;
- const tuz_size_t sub_len=dict_size-dict_cur;
- if (out_len<=sub_len){
- _memcpy(dict+dict_cur,out_data,out_len);
- }else{
- _memcpy(dict+dict_cur,out_data,sub_len);
- _memcpy(dict,out_data+sub_len,out_len-sub_len);
- }
- self->_dict.dict_cur=(out_len<=sub_len)?
- (out_len+dict_cur):(out_len-sub_len);
- }
-}
-
-static tuz_size_t _copy_from_dict(tuz_TStream *self,tuz_byte* cur_out_data,tuz_size_t dsize) {
- // [ dict buf ]
- // dict_cur+dictType_pos| <-- len --> |
- // dict_cur+dictType_pos| <-- len --> |
- // dict_cur+dictType_pos| <-- len --> |
- tuz_size_t len,pos;
- len=self->_dict.dict_size-self->_state.dictType_pos;
- len=(len_state.dictType_len_state.dictType_len:len;
- pos=self->_dict.dict_size-self->_dict.dict_cur;
- if (self->_state.dictType_pos_dict.dict_cur+self->_state.dictType_pos;
- else
- pos=self->_state.dictType_pos-pos;
- if (len<=(self->_dict.dict_size-pos)){
- _memcpy(cur_out_data,self->_dict.dict_buf+pos,len);
- }else{
- tuz_size_t part_len=self->_dict.dict_size-pos;
- _memcpy(cur_out_data,self->_dict.dict_buf+pos,part_len);
- _memcpy(cur_out_data+part_len,self->_dict.dict_buf,len-part_len);
- }
- return len;
-}
-
-
tuz_size_t tuz_TStream_read_dict_size(tuz_TInputStreamHandle inputStream,tuz_TInputStream_read read_code){
tuz_size_t v=tuz_kDictSizeSavedBytes;
tuz_byte saved[tuz_kDictSizeSavedBytes];
@@ -218,9 +147,8 @@ tuz_TResult tuz_TStream_open(tuz_TStream* self,tuz_TInputStreamHandle inputStrea
self->_dict.dict_buf=dict_and_cache;
self->_state.dictType_pos=0;
- self->_state.dictType_pos_inc=0;
self->_state.dict_pos_back=1;
- self->_state.dictType_len=0;
+ self->_state.dictType_len=0;
#if tuz_isNeedLiteralLine
self->_state.literalType_len=0;
#endif
@@ -230,34 +158,38 @@ tuz_TResult tuz_TStream_open(tuz_TStream* self,tuz_TInputStreamHandle inputStrea
return tuz_OK;
}
-tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,tuz_size_t* data_size){
- tuz_byte* cur_out_data=out_data;
- tuz_size_t dsize=*data_size;
+
+static tuz_force_inline tuz_byte _dict_read_byte(tuz_TStream* self){
+ // [ dict buf ]
+ // dict_cur+dictType_pos|
+ // dict_cur+dictType_pos|
+ tuz_size_t index_pos=self->_dict.dict_cur+self->_state.dictType_pos;
+ index_pos-=(self->_state.dictType_pos<(tuz_size_t)(self->_dict.dict_size-self->_dict.dict_cur))?0:self->_dict.dict_size;
+ return self->_dict.dict_buf[index_pos];
+}
+
+static tuz_try_inline void _dict_write_byte(tuz_TStream* self,tuz_byte bdata){
+ // [ dict buf ]
+ // |dict_cur dict_cur+dict_size|
+ tuz_size_t index_pos=self->_dict.dict_cur;
+ self->_dict.dict_buf[index_pos++]=bdata;
+ self->_dict.dict_cur=(index_pos_dict.dict_size)?index_pos:0;
+}
+
+tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* cur_out_data,tuz_size_t* data_size){
+ tuz_byte* const out_data_end=cur_out_data+(*data_size);
#ifdef __RUN_MEM_SAFE_CHECK
- const tuz_BOOL isNeedOut=(dsize>0);
+ const tuz_BOOL isNeedOut=(cur_out_data_state.dictType_len){ //copy from dict or out_data
- copyDict_process:
- if (dsize){
- // [ dict buf ]|[ out buf | ]
- // |dict_cur dict_size|out_data cur_out_data| <-- dsize -->|
- // dictType_pos| <-- dictType_len --> |
- // dictType_pos| <-- dictType_len --> |
- // dictType_pos| <- dictType_len -> |
- tuz_size_t len;
- if (self->_state.dictType_pos_dict.dict_size){
- len=_copy_from_dict(self,cur_out_data,dsize);
- self->_state.dictType_pos+=len;
- }else{
- len=(self->_state.dictType_len_state.dictType_len:dsize;
- _memmove_order(cur_out_data,out_data+self->_state.dictType_pos_inc,len);
- self->_state.dictType_pos_inc+=len;
- }
- self->_state.dictType_len-=len;
- cur_out_data+=len;
- dsize-=len;
+ //copyDict_process:
+ if (cur_out_data_state.dictType_len--;
goto copyDict_cmp_process;
}else{
break;
@@ -265,15 +197,14 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
}
#if tuz_isNeedLiteralLine
- copyLiteral_cmp_process:
+ copyLiteral_cmp_process:
if (self->_state.literalType_len){
- copyLiteral_process:
- if (dsize){
- tuz_length_t cpyLen=(self->_state.literalType_len_state.literalType_len:dsize;
- self->_state.literalType_len-=cpyLen;
- dsize-=cpyLen;
- while (cpyLen--)
- *cur_out_data++=_cache_read_1byte(&self->_code_cache);
+ //copyLiteral_process:
+ if (cur_out_data_code_cache);
+ _dict_write_byte(self,bdata);
+ *cur_out_data++=bdata;
+ self->_state.literalType_len--;
goto copyLiteral_cmp_process;
}else{
break;
@@ -295,27 +226,20 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
self->_state.isHaveData_back=tuz_FALSE;
if (saved_dict_pos){
- const tuz_size_t outed_size=(tuz_size_t)(cur_out_data-out_data);
self->_state.dict_pos_back=saved_dict_pos;
self->_state.dictType_len=saved_len+tuz_kMinDictMatchLen;
saved_dict_pos=(self->_dict.dict_size-saved_dict_pos);
#ifdef __RUN_MEM_SAFE_CHECK
if (saved_dict_pos>=self->_dict.dict_size) return tuz_DICT_POS_ERROR;
#endif
- if (outed_size_dict.dict_size-saved_dict_pos){
- self->_state.dictType_pos=outed_size+saved_dict_pos;
- self->_state.dictType_pos_inc=0;
- }else{
- self->_state.dictType_pos=self->_dict.dict_size;
- self->_state.dictType_pos_inc=outed_size+saved_dict_pos-self->_dict.dict_size;
- }
- goto copyDict_process;
+ self->_state.dictType_pos=saved_dict_pos;
+ continue; // goto copyDict_process;
}else{ // ctrlType
#if tuz_isNeedLiteralLine
if (tuz_ctrlType_literalLine==saved_len){
self->_state.isHaveData_back=tuz_TRUE;
self->_state.literalType_len=_cache_unpack_pos_len(self)+tuz_kMinLiteralLen;
- goto copyLiteral_process;
+ continue; // goto copyLiteral_process;
}
#endif
@@ -324,7 +248,7 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
if (tuz_ctrlType_clipEnd==saved_len){ //clip end
goto type_process;
}else if (tuz_ctrlType_streamEnd==saved_len){ //stream end
- *data_size=(tuz_size_t)(cur_out_data-out_data);
+ (*data_size)-=(tuz_size_t)(out_data_end-cur_out_data);
return tuz_STREAM_END;
}else{
return _cache_success_finish(&self->_code_cache)?
@@ -332,10 +256,11 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
}
}
}else{
- if (dsize){
+ if (cur_out_data_code_cache);
+ _dict_write_byte(self,bdata);
+ *cur_out_data++=bdata;
self->_state.isHaveData_back=tuz_TRUE;
- *cur_out_data++=_cache_read_1byte(&self->_code_cache);
- --dsize;
goto type_process;
}else{
_cache_push_1bit(self,tuz_codeType_data);
@@ -347,9 +272,7 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
//return_process:
{
- assert(dsize==0);
- if (out_data!=cur_out_data)
- _update_dict(self,out_data,cur_out_data);
+ assert(cur_out_data==out_data_end);
if (!_cache_success_finish(&self->_code_cache))
return tuz_READ_CODE_ERROR;
@@ -361,7 +284,6 @@ tuz_TResult tuz_TStream_decompress_partial(tuz_TStream* self,tuz_byte* out_data,
}
}
-
//---------------------------------------------------------------------------------------------
typedef struct _mem_TStream{
diff --git a/decompress/tuz_dec.h b/decompress/tuz_dec.h
index ae8feb0..ddc3e6f 100644
--- a/decompress/tuz_dec.h
+++ b/decompress/tuz_dec.h
@@ -1,7 +1,7 @@
// tuz_dec.h
/*
The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
+ Copyright (c) 2012-2025 HouSisong All Rights Reserved.
*/
#ifndef _tuz_dec_h
#define _tuz_dec_h
@@ -28,8 +28,8 @@ typedef enum tuz_TResult{
//-----------------------------------------------------------------------------------------------------------------
-// decompress step by step: compiled by Mbed Studio is 856 bytes
-// if set tuz_isNeedLiteralLine=0 & _IS_RUN_MEM_SAFE_CHECK=0, compiled by Mbed Studio is 758 bytes
+// decompress step by step: compiled by Mbed Studio is 626 bytes
+// if set tuz_isNeedLiteralLine=0 & _IS_RUN_MEM_SAFE_CHECK=0, compiled by Mbed Studio is 468 bytes
typedef struct tuz_TStream{
_tuz_TInputCache _code_cache;
diff --git a/decompress/tuz_types.h b/decompress/tuz_types.h
index 1c069c9..191f126 100644
--- a/decompress/tuz_types.h
+++ b/decompress/tuz_types.h
@@ -11,7 +11,7 @@
#endif
#ifndef tuz_isNeedLiteralLine // optimize incompressible data for improve compression ratio
-//if tuz_isNeedLiteralLine==0 when decompress, must also be set to 0 when compress, can reduce 80 bytes
+//if tuz_isNeedLiteralLine==0 when decompress, must also be set to 0 when compress, can reduce 54 bytes
# define tuz_isNeedLiteralLine 1
#endif
@@ -26,9 +26,6 @@
# define tuz_FALSE hpi_FALSE
# define tuz_TRUE hpi_TRUE
# define tuz_size_t hpi_size_t //memory size type
-# define tuz_inline hpi_inline
-# define tuz_force_inline hpi_force_inline
-# define tuz_try_inline hpi_try_inline
# define tuz_TInputStreamHandle hpi_TInputStreamHandle
# define tuz_TInputStream_read hpi_TInputStream_read
#endif
@@ -100,7 +97,6 @@ extern "C" {
#endif
#ifndef tuz_try_inline
-//# define tuz_try_inline tuz_inline
# define tuz_try_inline
#endif
@@ -108,10 +104,6 @@ extern "C" {
# define _IS_RUN_MEM_SAFE_CHECK 1
#endif
-#ifndef _IS_USED_C_MEMCPY // use memcpy() in ?
-# define _IS_USED_C_MEMCPY 1
-#endif
-
#ifndef tuz_kMaxOfDictSize
# define tuz_kMaxOfDictSize __tuz_kMaxOfDictSize_MAX
//# define tuz_kMaxOfDictSize ((1<<24)-1) //3 bytes
@@ -161,7 +153,6 @@ typedef struct _tuz_TDict{
} _tuz_TDict;
typedef struct _tuz_TState{
tuz_size_t dictType_pos;
- tuz_size_t dictType_pos_inc;
tuz_size_t dict_pos_back;
tuz_length_t dictType_len;
#if tuz_isNeedLiteralLine
diff --git a/speed_test.cpp b/speed_test.cpp
index 7e3d0e2..5f01235 100644
--- a/speed_test.cpp
+++ b/speed_test.cpp
@@ -2,7 +2,7 @@
// for tinyuz
/*
The MIT License (MIT)
- Copyright (c) 2012-2022 HouSisong All Rights Reserved.
+ Copyright (c) 2012-2025 HouSisong All Rights Reserved.
*/
#include
#include
@@ -14,6 +14,10 @@
#include "decompress/tuz_dec.h"
#include "compress/tuz_enc.h"
#include "zlib.h"
+#define _IS_NEED_TEST_OTHERS 0
+#if (_IS_NEED_TEST_OTHERS)
+#include "test_others.h"
+#endif
#ifdef min
# undef min
@@ -22,8 +26,10 @@
std::string TEST_FILE_DIR;
tuz_BOOL isDictSizeTest=0;
-static const tuz_size_t tDictSizes[]={24,79,255,1<<10,5<<10,32<<10,1<<20,32<<20};
-static const char* tDictSizes_tag[]={"24","79","255","1k","5k","32k","1m","32m"};
+int threadTest=1;
+static const tuz_size_t tDictSizes[]={255,1<<10,4<<10,32<<10,1<<20};
+static const char* tDictSizes_tag[]={"255","1k","4k","32k","1m"};
+static std::string tTestPrograms;
void readFile(std::vector& data,const char* fileName){
FILE * file=fopen(fileName, "rb");
@@ -71,8 +77,8 @@ double testDecodeProc(T_decompress proc_decompress,unsigned char* out_data,unsig
do {
for (int i=0; i<10; ++i){
bool ret=proc_decompress(out_data,out_data_end,zip_code,zip_code_end);
- ++testDecompressCount;
if (!ret) throw "error result!";
+ ++testDecompressCount;
if (isDictSizeTest) break;
}
time2=clock_s();
@@ -89,6 +95,7 @@ double testEncodeProc(T_compress proc_compress,std::vector& compr
double time1=clock_s();
do{
dstCodeSize=proc_compress(&compressedCode[0],&compressedCode[0]+compressedCode.size(),src,src_end);
+ if (dstCodeSize<=0) throw "error result!";
++testCompressCount;
}while ((clock_s()-time1)& compr
return compressTime_s;
}
-TTestResult testProc(const char* srcFileName,T_compress proc_compress,const char* proc_compress_Name,
+TTestResult testProc(const char* srcFileName,T_compress proc_compress,
T_decompress proc_decompress,const char* proc_decompress_Name){
std::string testFilePath=TEST_FILE_DIR; testFilePath.append(srcFileName);
std::vector oldData; readFile(oldData,testFilePath.c_str());
@@ -132,15 +139,15 @@ TTestResult testProc(const char* srcFileName,T_compress proc_compress,const char
static void outResult(const TTestResult& rt){
const bool isSimpleView=isDictSizeTest;
+ static tuz_BOOL isOutedTag=0;
if (isSimpleView){
- static tuz_BOOL isOutedTag=0;
if (!isOutedTag){
isOutedTag=1;
- printf("|zlib -9");
- for (int i=(sizeof(tDictSizes)/sizeof(tDictSizes[0])-1);i>=0; --i) {
- std::string tag=std::string("tuz -")+tDictSizes_tag[i];
- printf("|%s",tag.c_str());
- }
+ std::string str="test file";
+ for (int i=(sizeof(tDictSizes)/sizeof(tDictSizes[0])-1);i>=0; --i)
+ str+=std::string("|tuz ")+tDictSizes_tag[i];
+ str+=tTestPrograms;
+ printf(str.c_str());
}
static std::string srcFileName_back;
@@ -150,16 +157,20 @@ static void outResult(const TTestResult& rt){
}
printf("|%.2f%%",rt.zipSize*100.0/rt.srcSize);
}else{//default view
+ if (!isOutedTag){
+ isOutedTag=1;
+ printf("test file|size|program|C M/S|D M/S|C size|C ratio\n");
+ }
printf("%s|%d|%s|",rt.srcFileName.c_str(),rt.srcSize,rt.procName.c_str());
printf("%.2f|%.0f|",rt.srcSize/rt.compressTime_s/1024/1024,rt.srcSize/rt.decompressTime_s/1024/1024);
- printf("%.2f|%.0f|",rt.zipSize/rt.compressTime_s/1024/1024,rt.zipSize/rt.decompressTime_s/1024/1024);
+ //printf("%.2f|%.0f|",rt.zipSize/rt.compressTime_s/1024/1024,rt.zipSize/rt.decompressTime_s/1024/1024);
printf("%d|%.2f%%\n",rt.zipSize,rt.zipSize*100.0/rt.srcSize);
}
}
////
-int zlib_windowBits = 0;
+int zlib_windowBits = -15;
int zlib_level = 9;
int zlib_compress(unsigned char* out_data,unsigned char* out_data_end,
@@ -248,7 +259,7 @@ int _test_tuz_compress(unsigned char* out_data,unsigned char* out_data_end,
mem_as_hStreamInput(&in_stream,src,src_end);
tuz_TCompressProps props=tuz_kDefaultCompressProps;
props.dictSize=_tuz_kDictSize;
- props.threadNum=8;
+ props.threadNum=threadTest;
//props.maxSaveLength=255;
hpatch_StreamPos_t codeSize=tuz_compress(&out_stream,&in_stream,&props);
return (int)codeSize;
@@ -318,23 +329,32 @@ bool _test_tuz_decompress_mem(unsigned char* out_data,unsigned char* out_data_en
}
static void testFile(const char* srcFileName){
- //zlib_level=6;
- //outResult(testProc(srcFileName, zlib_compress, "", zlib_decompress, " zlib -6"));
- zlib_level=9;
-
+ tTestPrograms="|zlib 32k";
+ tTestPrograms+=(_IS_NEED_TEST_OTHERS?"|QuickLZ|tamp 32k|tamp 4k|heatshrink 4k|FastLZ|miniLZO":"");
if (!isDictSizeTest) {
- outResult(testProc(srcFileName,zlib_compress ,"",zlib_decompress ," zlib -9"));
- outResult(testProc(srcFileName,_test_tuz_compress,"",_test_tuz_decompress_stream,"tinyuz_stream"));
- outResult(testProc(srcFileName,_test_tuz_compress,"",_test_tuz_decompress_mem ," tinyuz_mem"));
+ outResult(testProc(srcFileName,_test_tuz_compress ,_test_tuz_decompress_stream ," tinyuz_stream"));
+ outResult(testProc(srcFileName,_test_tuz_compress ,_test_tuz_decompress_mem ," tinyuz_mem"));
}else{
- zlib_windowBits=-15;
- outResult(testProc(srcFileName,zlib_compress ,"",zlib_decompress ,"zlib -9"));
for (int i=(sizeof(tDictSizes)/sizeof(tDictSizes[0])-1);i>=0; --i) {
- std::string tag=std::string("tinyuz -c-")+tDictSizes_tag[i];
_tuz_kDictSize=tDictSizes[i];
- outResult(testProc(srcFileName,_test_tuz_compress,"",_test_tuz_decompress_stream,tag.c_str()));
+ outResult(testProc(srcFileName,_test_tuz_compress,_test_tuz_decompress_stream,(std::string("tuz ")+tDictSizes_tag[i]).c_str()));
}
}
+
+ outResult(testProc(srcFileName,zlib_compress ,zlib_decompress ," zlib 32k"));
+ #if (_IS_NEED_TEST_OTHERS)
+ outResult(testProc(srcFileName,quicklz_compress ,quicklz_decompress ," QuickLZ"));
+ tamp_windowBits=15; outResult(testProc(srcFileName,tamp_compress ,tamp_decompress ," tamp 32k"));
+ tamp_windowBits=12; outResult(testProc(srcFileName,tamp_compress ,tamp_decompress ," tamp 4k"));
+//tamp_windowBits=10; outResult(testProc(srcFileName,tamp_compress ,tamp_decompress ," tamp 1k"));
+//tamp_windowBits=8; outResult(testProc(srcFileName,tamp_compress ,tamp_decompress ," tamp 256"));
+//hs_windowBits=15;outResult(testProc(srcFileName,heatshrink_compress,heatshrink_decompress,"heatshrink 32k"));// test fail when hs_windowBits=15
+hs_windowBits=12;outResult(testProc(srcFileName,heatshrink_compress,heatshrink_decompress," heatshrink 4k"));
+//hs_windowBits=10;outResult(testProc(srcFileName,heatshrink_compress,heatshrink_decompress," heatshrink 1k"));
+//hs_windowBits=8; outResult(testProc(srcFileName,heatshrink_compress,heatshrink_decompress,"heatshrink 256"));
+ outResult(testProc(srcFileName,_fastlz_compress ,_fastlz_decompress ," FastLZ"));
+ outResult(testProc(srcFileName,minilzo_compress ,minilzo_decompress ," miniLZO"));
+ #endif
}
int main(int argc, const char * argv[]){
@@ -342,7 +362,8 @@ int main(int argc, const char * argv[]){
std::cout << "speed_test \"testFile\"\n";
return -1;
}
- isDictSizeTest=0;
+ isDictSizeTest=1;
+ threadTest=16;
const int testDictBit=15;
zlib_windowBits=-testDictBit;
_tuz_kDictSize = (1 << testDictBit);
@@ -380,7 +401,7 @@ int main(int argc, const char * argv[]){
//testFile("enwik9");
//*/
- std::cout << "done!\n";
+ std::cout << "\ndone!\n";
return 0;
}
diff --git a/test_others.h b/test_others.h
new file mode 100644
index 0000000..d161f2e
--- /dev/null
+++ b/test_others.h
@@ -0,0 +1,207 @@
+//test_others.h
+#ifndef tinyuz_test_others_h
+#define tinyuz_test_others_h
+
+
+#include "../minilzo/minilzo.h"
+// GNU GENERAL PUBLIC LICENSE Version 2
+
+#define HEAP_ALLOC(var,size) \
+ lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
+
+int minilzo_compress(unsigned char* out_data,unsigned char* out_data_end,
+ const unsigned char* src,const unsigned char* src_end){
+ HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
+ lzo_uint dst_len=out_data_end-out_data;
+ int ret=lzo1x_1_compress(src,src_end-src,out_data,&dst_len,wrkmem);
+ if (ret!=LZO_E_OK)
+ return 0;
+ return dst_len;
+}
+
+bool minilzo_decompress(unsigned char* out_data,unsigned char* out_data_end,
+ const unsigned char* zip_code,const unsigned char* zip_code_end){
+ lzo_uint dst_len=out_data_end-out_data;
+ int ret=lzo1x_decompress_safe(zip_code,zip_code_end-zip_code,out_data,&dst_len,0);
+ return (ret==LZO_E_OK);
+}
+
+
+
+#include "../quicklz/src/quicklz.h"
+// GNU GENERAL PUBLIC LICENSE Version 2
+
+int quicklz_compress(unsigned char* out_data,unsigned char* out_data_end,
+ const unsigned char* src,const unsigned char* src_end){
+ qlz_state_compress *state_compress = (qlz_state_compress *)malloc(sizeof(qlz_state_compress));
+ int c=qlz_compress(src,(char*)out_data,src_end-src, state_compress);
+ free(state_compress);
+ return c;
+}
+
+bool quicklz_decompress(unsigned char* out_data,unsigned char* out_data_end,
+ const unsigned char* zip_code,const unsigned char* zip_code_end){
+ qlz_state_decompress *state_decompress = (qlz_state_decompress *)malloc(sizeof(qlz_state_decompress));
+ if (zip_code_end-zip_code<9) return false;
+ int dc = qlz_size_decompressed((const char*)zip_code);
+ int c = qlz_size_compressed((const char*)zip_code);
+ if (out_data_end-out_datatamp_decompressor_decompress(&d,out_data,out_data_end-out_data,
+ &output_size,zip_code,zip_code_end-zip_code,&input_size))
+ return false;
+ free(buf);
+ return true;
+}
+
+#endif //tinyuz_test_others_h
\ No newline at end of file