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-10-19 01:47:14 +02:00
|
|
|
|
public static byte[] SCompress(byte[] b, int level = 19)
|
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];
|
|
|
|
|
|
2023-05-28 21:06:34 +02:00
|
|
|
|
var userDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SwitchToolbox");
|
|
|
|
|
if (!Directory.Exists(userDir))
|
|
|
|
|
Directory.CreateDirectory(userDir);
|
|
|
|
|
|
2023-05-28 22:11:41 +02:00
|
|
|
|
//Create folder for TOTK contents if it does not exist
|
|
|
|
|
if (!Directory.Exists(Path.Combine(userDir, "TOTK")))
|
|
|
|
|
Directory.CreateDirectory(Path.Combine(userDir, "TOTK"));
|
|
|
|
|
|
2023-05-28 21:06:34 +02:00
|
|
|
|
string folder = Path.Combine(userDir, "TOTK", "ZstdDictionaries");
|
|
|
|
|
|
2023-05-28 22:15:19 +02:00
|
|
|
|
if (!Directory.Exists(folder))
|
|
|
|
|
Directory.CreateDirectory(folder);
|
2023-05-28 22:11:41 +02:00
|
|
|
|
|
|
|
|
|
void TransferZDic(string path)
|
2023-05-28 21:06:34 +02:00
|
|
|
|
{
|
2023-05-28 22:11:41 +02:00
|
|
|
|
//Check if old directory contains the file and move it
|
|
|
|
|
string fileOld = Path.Combine(Runtime.ExecutableDir, "Lib", "ZstdDictionaries", path);
|
|
|
|
|
string fileNew = Path.Combine(folder, path);
|
|
|
|
|
if (!File.Exists(fileNew) && File.Exists(fileOld))
|
|
|
|
|
{
|
|
|
|
|
File.Move(fileOld, fileNew);
|
|
|
|
|
}
|
2023-05-28 21:06:34 +02:00
|
|
|
|
}
|
2023-05-28 22:11:41 +02:00
|
|
|
|
TransferZDic("bcett.byml.zsdic");
|
|
|
|
|
TransferZDic("pack.zsdic");
|
|
|
|
|
TransferZDic("zs.zsdic");
|
2023-05-28 21:06:34 +02:00
|
|
|
|
|
2023-05-14 21:37:14 +02:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|