2019-09-16 01:13:01 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Compression;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Toolbox.Library.IO;
|
2023-05-14 21:37:14 +02:00
|
|
|
|
using ICSharpCode.SharpZipLib.Zip;
|
2019-09-16 01:13:01 +02:00
|
|
|
|
|
|
|
|
|
namespace Toolbox.Library
|
|
|
|
|
{
|
|
|
|
|
public class Zstb : ICompressionFormat
|
|
|
|
|
{
|
|
|
|
|
public string[] Description { get; set; } = new string[] { "ZSTD" };
|
2021-12-09 02:46:42 +01:00
|
|
|
|
public string[] Extension { get; set; } = new string[] { "*.zstd", "*.zst", };
|
2019-09-16 01:13:01 +02:00
|
|
|
|
|
|
|
|
|
public override string ToString() { return "ZSTD"; }
|
|
|
|
|
|
2023-05-14 21:37:14 +02:00
|
|
|
|
static string fileNameTemp = "";
|
|
|
|
|
|
2023-05-21 19:17:25 +02:00
|
|
|
|
public void Init(string fileName) { fileNameTemp = fileName; }
|
|
|
|
|
|
2019-09-16 01:13:01 +02:00
|
|
|
|
public bool Identify(Stream stream, string fileName)
|
|
|
|
|
{
|
2023-05-14 21:37:14 +02:00
|
|
|
|
//Small hack to check current file name
|
|
|
|
|
fileNameTemp = fileName;
|
2019-09-16 01:13:01 +02:00
|
|
|
|
using (var reader = new FileReader(stream, true))
|
|
|
|
|
{
|
|
|
|
|
uint magic = reader.ReadUInt32();
|
2020-03-17 22:08:24 +01:00
|
|
|
|
reader.Position = 0;
|
2019-09-16 01:13:01 +02:00
|
|
|
|
return magic == 0x28B52FFD || magic == 0xFD2FB528;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool CanCompress { get; } = true;
|
|
|
|
|
|
|
|
|
|
public Stream Decompress(Stream stream)
|
|
|
|
|
{
|
|
|
|
|
return new MemoryStream(SDecompress(stream.ToArray()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Stream Compress(Stream stream)
|
|
|
|
|
{
|
|
|
|
|
return new MemoryStream(SCompress(stream.ToArray()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] SDecompress(byte[] b)
|
|
|
|
|
{
|
2023-05-14 21:37:14 +02:00
|
|
|
|
var options = new ZstdNet.DecompressionOptions(GetExternalDictionaries());
|
|
|
|
|
using (var decompressor = new ZstdNet.Decompressor(options))
|
|
|
|
|
{
|
|
|
|
|
return decompressor.Unwrap(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] SDecompress(byte[] b, byte[] dict)
|
|
|
|
|
{
|
|
|
|
|
var options = new ZstdNet.DecompressionOptions(dict);
|
|
|
|
|
using (var decompressor = new ZstdNet.Decompressor(options))
|
2019-09-16 01:13:01 +02:00
|
|
|
|
{
|
|
|
|
|
return decompressor.Unwrap(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-14 21:37:14 +02:00
|
|
|
|
|
2019-09-16 01:13:01 +02:00
|
|
|
|
public static byte[] SDecompress(byte[] b, int MaxDecompressedSize)
|
|
|
|
|
{
|
2023-05-14 21:37:14 +02:00
|
|
|
|
var options = new ZstdNet.DecompressionOptions(GetExternalDictionaries());
|
|
|
|
|
using (var decompressor = new ZstdNet.Decompressor(options))
|
2019-09-16 01:13:01 +02:00
|
|
|
|
{
|
|
|
|
|
return decompressor.Unwrap(b, MaxDecompressedSize);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-28 01:33:14 +02:00
|
|
|
|
public static byte[] SCompress(byte[] b, int level = 5)
|
2019-09-16 01:13:01 +02:00
|
|
|
|
{
|
2023-05-28 01:33:14 +02:00
|
|
|
|
using (var compressor = new ZstdNet.Compressor(new ZstdNet.CompressionOptions(level)))
|
2019-09-16 01:13:01 +02:00
|
|
|
|
{
|
|
|
|
|
return compressor.Wrap(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-14 21:37:14 +02:00
|
|
|
|
|
|
|
|
|
static byte[] GetExternalDictionaries()
|
|
|
|
|
{
|
|
|
|
|
byte[] dictionary = new byte[0];
|
|
|
|
|
|
|
|
|
|
string folder = Path.Combine(Runtime.ExecutableDir, "Lib", "ZstdDictionaries");
|
|
|
|
|
if (Directory.Exists(folder))
|
|
|
|
|
{
|
|
|
|
|
void CheckZDic(string fileName, string expectedExtension)
|
|
|
|
|
{
|
|
|
|
|
//Dictionary already set
|
|
|
|
|
if (dictionary.Length != 0) return;
|
|
|
|
|
|
|
|
|
|
string zDictPath = Path.Combine(folder, fileName);
|
|
|
|
|
//Then check if the input file uses the expected extension
|
|
|
|
|
if (File.Exists(zDictPath) && fileNameTemp.EndsWith(expectedExtension))
|
|
|
|
|
dictionary = File.ReadAllBytes(zDictPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Order matters, zs must go last
|
|
|
|
|
CheckZDic("bcett.byml.zsdic", "bcett.byml.zs" );
|
|
|
|
|
CheckZDic("pack.zsdic", "pack.zs" );
|
|
|
|
|
CheckZDic("zs.zsdic", ".zs" );
|
|
|
|
|
}
|
|
|
|
|
return dictionary;
|
|
|
|
|
}
|
2019-09-16 01:13:01 +02:00
|
|
|
|
}
|
|
|
|
|
}
|