Files
Aaru/Aaru.Compression/XZ.cs

111 lines
4.5 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using SharpCompress.Compressors.Xz;
// ReSharper disable UnusedMember.Global
namespace Aaru.Compression;
public static partial class XZ
{
public enum CheckType : uint
{
None = 0,
Crc32 = 1,
Crc64 = 4,
Sha256 = 10
}
/// <summary>
/// AARU_EXPORT int32_t AARU_CALL AARU_xz_decode_buffer(uint8_t * dst_buffer, size_t *dst_size, const uint8_t
/// *src_buffer, size_t src_size)
/// </summary>
/// <param name="dst_buffer">Buffer to write the decompressed data to</param>
/// <param name="dst_size">Size of the destination buffer, total bytes written on finish</param>
/// <param name="src_buffer">Buffer that contains the compressed data</param>
/// <param name="src_size">Size of the source buffer</param>
/// <returns></returns>
[LibraryImport("libAaru.Compression.Native", SetLastError = true)]
private static partial int AARU_xz_decode_buffer(byte[] dst_buffer, ref nuint dst_size, byte[] src_buffer,
nuint src_size);
/// <summary>
/// AARU_EXPORT int32_t AARU_CALL AARU_xz_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t
/// *src_buffer, size_t src_size,uint32_t preset, uint32_t checkType)
/// </summary>
/// <param name="dst_buffer">Buffer to write the decompressed data to</param>
/// <param name="dst_size">Size of the destination buffer</param>
/// <param name="src_buffer">Buffer that contains the compressed data</param>
/// <param name="src_size">Size of the source buffer</param>
/// <param name="level">Compression level</param>
/// <param name="checkType">Checksum to use</param>
/// <returns>The size of the compressed data, or -1 on error.</returns>
[LibraryImport("libAaru.Compression.Native", SetLastError = true)]
private static partial int AARU_xz_encode_buffer(byte[] dst_buffer, ref nuint dst_size, byte[] src_buffer,
nuint src_size, uint level, CheckType checkType);
/// <summary>Decodes a buffer compressed with XZ</summary>
/// <param name="source">Encoded buffer</param>
/// <param name="destination">Buffer where to write the decoded data</param>
/// <returns>The number of decoded bytes, or -1 on error</returns>
public static int DecodeBuffer(byte[] source, byte[] destination)
{
if(Native.IsSupported)
{
var dstSize = (nuint)destination.Length;
int res = AARU_xz_decode_buffer(destination, ref dstSize, source, (nuint)source.Length);
if(res == 0) return (int)dstSize;
}
// Managed fallback using SharpCompress
return DecodeBufferManaged(source, destination);
}
/// <summary>Decodes a buffer compressed with XZ using managed code</summary>
/// <param name="source">Encoded buffer</param>
/// <param name="destination">Buffer where to write the decoded data</param>
/// <returns>The number of decoded bytes, or -1 on error</returns>
static int DecodeBufferManaged(byte[] source, byte[] destination)
{
try
{
using var inputStream = new MemoryStream(source);
using var xzStream = new XZStream(inputStream);
using var outputStream = new MemoryStream();
xzStream.CopyTo(outputStream);
byte[] result = outputStream.ToArray();
if(result.Length > destination.Length) return -1;
Array.Copy(result, destination, result.Length);
return result.Length;
}
catch
{
return -1;
}
}
/// <summary>Compresses a buffer using XZ</summary>
/// <param name="source">Data to compress</param>
/// <param name="destination">Buffer to store the compressed data</param>
/// <param name="level">Compression level (0-9)</param>
/// <param name="checkType">Checksum type to use for integrity verification</param>
/// <returns>The size of the compressed data, or -1 on error</returns>
public static int EncodeBuffer(byte[] source, byte[] destination, uint level, CheckType checkType)
{
if(!Native.IsSupported) return -1;
var dstSize = (nuint)destination.Length;
int res = AARU_xz_encode_buffer(destination, ref dstSize, source, (nuint)source.Length, level, checkType);
if(res != 0) return -1;
return (int)dstSize;
}
}