diff --git a/src/FastLZMA2Net/CompressStream.cs b/src/FastLZMA2Net/CompressStream.cs
index fdcd7c2..d7d9662 100644
--- a/src/FastLZMA2Net/CompressStream.cs
+++ b/src/FastLZMA2Net/CompressStream.cs
@@ -2,7 +2,10 @@
namespace FastLZMA2Net
{
- public class CompressStream : Stream, IDisposable
+ ///
+ /// Streaming Fast LZMA2 compress
+ ///
+ public class CompressStream : Stream
{
private readonly int bufferSize;
private byte[] outputBufferArray;
@@ -15,6 +18,10 @@ public class CompressStream : Stream, IDisposable
public override bool CanRead => _innerStream != null && _innerStream.CanRead;
public override bool CanWrite => false;
public override bool CanSeek => false;
+
+ ///
+ /// Can't determine decompressed data size
+ ///
public override long Length => throw new NotSupportedException();
public override long Position
@@ -22,41 +29,65 @@ public override long Position
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
-
+ ///
+ /// Compress Level [1..10]
+ ///
public int CompressLevel
{
get => (int)GetParameter(FL2Parameter.CompressionLevel);
set => SetParameter(FL2Parameter.CompressionLevel, (nuint)value);
}
+ ///
+ /// Levels 1..10 Setting to 1 switches to an alternate cLevel table.
+ ///
public int HighCompressLevel
{
get => (int)GetParameter(FL2Parameter.HighCompression);
set => SetParameter(FL2Parameter.HighCompression, (nuint)value);
}
+ ///
+ /// Dictionary size with FL2.DictSizeMin & FL2.DictSizeMax
+ ///
public int DictionarySize
{
get => (int)GetParameter(FL2Parameter.DictionarySize);
set => SetParameter(FL2Parameter.DictionarySize, (nuint)value);
}
-
+ ///
+ /// Match finder will resolve string matches up to this length.
+ /// If a longer match exists further back in the input, it will not be found.
+ /// Default = 42
+ ///
public int SearchDepth
{
get => (int)GetParameter(FL2Parameter.SearchDepth);
set => SetParameter(FL2Parameter.SearchDepth, (nuint)value);
}
-
+ ///
+ /// Only useful for strategies >= opt.
+ /// Length of match considered "good enough" to stop search.
+ /// Larger values make compression stronger and slower.
+ /// Default = 48
+ ///
public int FastLength
{
get => (int)GetParameter(FL2Parameter.FastLength);
set => SetParameter(FL2Parameter.FastLength, (nuint)value);
}
- public CompressStream(Stream innerStream, uint nbThreads = 0, int outBufferSize = 64 * 1024 * 1024)
+ ///
+ /// Initialize streaming compress context
+ ///
+ /// compressed data store
+ /// thread use, auto = 0
+ /// Native interop buffer size, default = 64M
+ ///
+ public CompressStream(Stream dstStream, uint nbThreads = 0, int outBufferSize = 64 * 1024 * 1024)
{
bufferSize = outBufferSize;
- _innerStream = innerStream;
+ _innerStream = dstStream;
_context = NativeMethods.FL2_createCStreamMt(nbThreads, 1);
var code = NativeMethods.FL2_initCStream(_context, 0);
if (FL2Exception.IsError(code))
@@ -75,26 +106,54 @@ public CompressStream(Stream innerStream, uint nbThreads = 0, int outBufferSize
};
}
+ ///
+ /// Append raw data to streaming, won't close compress stream
+ ///
+ /// Extra data
+ /// Start index in buffer
+ /// How many bytes to append
public void Append(byte[] buffer, int offset, int count)
{
Append(buffer.AsSpan(offset, count));
}
+ ///
+ /// Append raw data to streaming, won't close compress stream
+ ///
+ /// Extra data
public void Append(ReadOnlySpan buffer)
{
CompressCore(buffer, true);
}
+ ///
+ /// Start compression and finish stream.
+ ///
+ /// Raw data
+ /// Start index in buffer
+ /// How many bytes to append
public override void Write(byte[] buffer, int offset, int count)
{
Write(buffer.AsSpan(offset, count));
}
+ ///
+ /// Start compression and finish stream.
+ ///
+ /// Raw data
public override void Write(ReadOnlySpan buffer)
{
CompressCore(buffer, false);
}
+ ///
+ /// Start compression and finish stream asynchronized.
+ ///
+ /// Raw data
+ /// Start index in buffer
+ /// How many bytes to append
+ ///
+ ///
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
Memory bufferMemory = buffer.AsMemory(offset, count);
@@ -102,6 +161,12 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc
return;
}
+ ///
+ /// Start compression and finish stream asynchronized.
+ ///
+ /// Raw data
+ ///
+ ///
public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default)
{
await new ValueTask(CompressCore(buffer.Span, false, cancellationToken)).ConfigureAwait(false);
@@ -121,7 +186,7 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
};
nuint code;
- //push source data& receive part of compressed data
+ //push source data & receive part of compressed data
do
{
outBuffer.pos = 0;
@@ -150,12 +215,9 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
code = NativeMethods.FL2_copyCStreamOutput(_context, ref outBuffer);
if (FL2Exception.IsError(code))
{
- if (FL2Exception.IsError(code))
+ if (FL2Exception.GetErrorCode(code) != FL2ErrorCode.Buffer)
{
- if (FL2Exception.GetErrorCode(code) != FL2ErrorCode.Buffer)
- {
- throw new FL2Exception(code);
- }
+ throw new FL2Exception(code);
}
}
_innerStream.Write(outputBufferArray, 0, (int)outBuffer.pos);
@@ -166,7 +228,7 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
return 0;
}
- // receive all remaining compressed data
+ // receive all remaining compressed data for safety
do
{
outBuffer.pos = 0;
@@ -174,12 +236,9 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
code = NativeMethods.FL2_flushStream(_context, ref outBuffer);
if (FL2Exception.IsError(code))
{
- if (FL2Exception.IsError(code))
+ if (FL2Exception.GetErrorCode(code) != FL2ErrorCode.Buffer)
{
- if (FL2Exception.GetErrorCode(code) != FL2ErrorCode.Buffer)
- {
- throw new FL2Exception(code);
- }
+ throw new FL2Exception(code);
}
}
_innerStream.Write(outputBufferArray, 0, (int)outBuffer.pos);
@@ -190,7 +249,7 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
return 0;
}
- //Write compress checksum
+ //Write compress checksum if not appending mode
if (!Appending)
{
code = NativeMethods.FL2_endStream(_context, ref outBuffer);
@@ -216,24 +275,77 @@ private unsafe int CompressCore(ReadOnlySpan buffer, bool Appending, Cance
return 0;
}
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override void SetLength(long value) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
public override int Read(Span buffer) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override int ReadByte() => throw new NotSupportedException();
-
- public override void Close() => Dispose(true);
-
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
- => throw new NotSupportedException();
-
+ => throw new NotSupportedException();
+
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
+ ///
+ /// Close streaming progress
+ ///
+ public override void Close() => Dispose(true);
+
+ ///
+ /// Write Checksum in the end. finish compress progress.
+ ///
+ ///
public override void Flush()
{
var code = NativeMethods.FL2_endStream(_context, ref outBuffer);
@@ -253,6 +365,14 @@ public override void Flush()
}
}
+
+ ///
+ /// Set detail compress parameter
+ ///
+ /// Parameter Enum
+ ///
+ /// Error Code
+ ///
public nuint SetParameter(FL2Parameter param, nuint value)
{
nuint code = NativeMethods.FL2_CStream_setParameter(_context, param, value);
@@ -263,6 +383,12 @@ public nuint SetParameter(FL2Parameter param, nuint value)
return code;
}
+ ///
+ /// Get detail compress parameter
+ ///
+ /// Parameter Enum
+ /// Parameter Value
+ ///
public nuint GetParameter(FL2Parameter param)
{
var code = NativeMethods.FL2_CStream_getParameter(_context, param);
@@ -277,7 +403,7 @@ protected override void Dispose(bool disposing)
{
if (!disposed)
{
- _innerStream.Flush();
+ Flush();
if (disposing)
{
outputBufferHandle.Free();
diff --git a/src/FastLZMA2Net/Compressor.cs b/src/FastLZMA2Net/Compressor.cs
index 5e0cc4c..b639fd7 100644
--- a/src/FastLZMA2Net/Compressor.cs
+++ b/src/FastLZMA2Net/Compressor.cs
@@ -1,65 +1,104 @@
using System.IO.MemoryMappedFiles;
+using System.Text.RegularExpressions;
namespace FastLZMA2Net
{
- //FL2CompressContext
+ ///
+ /// Fast LZMA2 Compress Context
+ ///
public partial class Compressor : IDisposable
{
private readonly nint _CContext;
private bool disposed = false;
private bool disposedValue;
+ ///
+ /// Thread use of the context
+ ///
public uint ThreadCount => NativeMethods.FL2_getCCtxThreadCount(_CContext);
+
+ ///
+ /// Dictionary size property
+ ///
public byte DictSizeProperty => NativeMethods.FL2_getCCtxDictProp(_CContext);
+ ///
+ /// Compress Level [1..10]
+ ///
public int CompressLevel
{
get => (int)GetParameter(FL2Parameter.CompressionLevel);
set => SetParameter(FL2Parameter.CompressionLevel, (nuint)value);
}
+ ///
+ /// Levels 1..10 Setting to 1 switches to an alternate cLevel table.
+ ///
public int HighCompressLevel
{
get => (int)GetParameter(FL2Parameter.HighCompression);
set => SetParameter(FL2Parameter.HighCompression, (nuint)value);
}
+ ///
+ /// Dictionary size with FL2.DictSizeMin & FL2.DictSizeMax
+ ///
public int DictionarySize
{
get => (int)GetParameter(FL2Parameter.DictionarySize);
set => SetParameter(FL2Parameter.DictionarySize, (nuint)value);
}
+ ///
+ /// Match finder will resolve string matches up to this length.
+ /// If a longer match exists further back in the input, it will not be found.
+ /// Default = 42
+ ///
public int SearchDepth
{
get => (int)GetParameter(FL2Parameter.SearchDepth);
set => SetParameter(FL2Parameter.SearchDepth, (nuint)value);
}
+ ///
+ /// Only useful for strategies >= opt.
+ /// Length of match considered "good enough" to stop search.
+ /// Larger values make compression stronger and slower.
+ /// Default = 48
+ ///
public int FastLength
{
get => (int)GetParameter(FL2Parameter.FastLength);
set => SetParameter(FL2Parameter.FastLength, (nuint)value);
}
+ ///
+ /// Initialize new compress context
+ ///
+ /// How many thread use. auto = 0
+ /// default = 6
public Compressor(uint nbThreads = 0, int compressLevel = 6)
{
- if (nbThreads == 1)
- {
- _CContext = NativeMethods.FL2_createCCtx();
- }
- else
- {
- _CContext = NativeMethods.FL2_createCCtxMt(nbThreads);
- }
+ _CContext = NativeMethods.FL2_createCCtxMt(nbThreads);
CompressLevel = (int)compressLevel;
}
+ ///
+ /// Compress data asynchronized
+ ///
+ /// Data byte array
+ /// Bytes Compressed
public Task CompressAsync(byte[] src)
{
- return CompressAsync(src, 0);
+ return CompressAsync(src, CompressLevel);
}
+ ///
+ /// Compress data asynchronized
+ ///
+ /// Data byte array
+ /// compress level
+ /// Bytes Compressed
public Task CompressAsync(byte[] src, int compressLevel)
{
return Task.Run(() => Compress(src, compressLevel));
@@ -70,12 +109,16 @@ public byte[] Compress(byte[] src)
return Compress(src, 0);
}
+ ///
+ /// Compress data with compress level setting
+ ///
+ /// Data byte array
+ /// compress level
+ /// Bytes Compressed
+ ///
public byte[] Compress(byte[] src, int compressLevel)
{
- if (src is null)
- {
- throw new ArgumentNullException(nameof(src));
- }
+ ArgumentNullException.ThrowIfNull(src);
byte[] buffer = new byte[FL2.FindCompressBound(src)];
nuint code = NativeMethods.FL2_compressCCtx(_CContext, buffer, (nuint)buffer.Length, src, (nuint)src.Length, compressLevel);
@@ -86,15 +129,18 @@ public byte[] Compress(byte[] src, int compressLevel)
return buffer[..(int)code];
}
+ ///
+ /// Compress file using direct file access. No memory copy overhead.
+ ///
+ /// source file path
+ /// output file path
+ /// Bytes Compressed
+ ///
public unsafe nuint Compress(string srcPath, string dstPath)
{
nuint code;
FileInfo sourceFile = new FileInfo(srcPath);
FileInfo destFile = new FileInfo(dstPath);
- if (sourceFile.Length >= 0x7FFFFFFF)
- {
- throw new ArgumentOutOfRangeException(nameof(srcPath), "File is too large");
- }
if (destFile.Exists)
{
destFile.Delete();
@@ -123,6 +169,13 @@ public unsafe nuint Compress(string srcPath, string dstPath)
return code;
}
+ ///
+ /// Set detail compress parameter
+ ///
+ /// Parameter Enum
+ ///
+ /// Error Code
+ ///
public nuint SetParameter(FL2Parameter param, nuint value)
{
nuint code = NativeMethods.FL2_CCtx_setParameter(_CContext, param, value);
@@ -133,6 +186,12 @@ public nuint SetParameter(FL2Parameter param, nuint value)
return code;
}
+ ///
+ /// Get detail compress parameter
+ ///
+ /// Parameter Enum
+ /// Parameter Value
+ ///
public nuint GetParameter(FL2Parameter param)
{
var code = NativeMethods.FL2_CCtx_getParameter(_CContext, param);
diff --git a/src/FastLZMA2Net/DecompressStream.cs b/src/FastLZMA2Net/DecompressStream.cs
index da1f680..aef5bae 100644
--- a/src/FastLZMA2Net/DecompressStream.cs
+++ b/src/FastLZMA2Net/DecompressStream.cs
@@ -2,7 +2,10 @@
namespace FastLZMA2Net
{
- public class DecompressStream : Stream, IDisposable
+ ///
+ /// Streaming decompress context
+ ///
+ public class DecompressStream : Stream
{
private readonly int bufferSize = 16 * 1024 * 1024;
private byte[] inputBufferArray;
@@ -14,6 +17,10 @@ public class DecompressStream : Stream, IDisposable
public override bool CanRead => _innerStream != null && _innerStream.CanRead;
public override bool CanWrite => false;
public override bool CanSeek => false;
+
+ ///
+ /// Can't determine data size
+ ///
public override long Length => throw new NotSupportedException();
public override long Position
@@ -22,10 +29,17 @@ public override long Position
set => throw new NotSupportedException();
}
- public DecompressStream(Stream innerStream, uint nbThreads = 0, int inBufferSize = 16 * 1024 * 1024)
+ ///
+ /// Initialize streaming decompress context
+ ///
+ /// compressed data store
+ ///
+ /// Native interop buffer size, default = 64M
+ ///
+ public DecompressStream(Stream srcStream, uint nbThreads = 0, int inBufferSize = 64 * 1024 * 1024)
{
bufferSize = inBufferSize;
- _innerStream = innerStream;
+ _innerStream = srcStream;
if (nbThreads == 1)
{
@@ -53,13 +67,18 @@ public DecompressStream(Stream innerStream, uint nbThreads = 0, int inBufferSize
};
}
- public override void Flush()
- {
- _innerStream.Flush();
- }
+ ///
+ /// Copy decompressed data to destination stream
+ ///
+ ///
public new void CopyTo(Stream destination) => CopyTo(destination, 256 * 1024 * 1024);
+ ///
+ /// Copy decompressed data to destination stream
+ ///
+ ///
+ /// Default = 256M
public override void CopyTo(Stream destination, int bufferSize = 256 * 1024 * 1024)
{
byte[] outBufferArray = new byte[bufferSize];
@@ -72,24 +91,53 @@ public override void CopyTo(Stream destination, int bufferSize = 256 * 1024 * 10
} while (bytesRead != 0);
}
+ ///
+ /// How many data has been decompressed
+ ///
public ulong Progress => NativeMethods.FL2_getDStreamProgress(_context);
+ ///
+ /// Read decompressed data
+ ///
+ /// buffer array to receive data
+ /// Start index in buffer
+ /// How many bytes to append
+ /// How many bytes read.
public override int Read(byte[] buffer, int offset, int count)
{
return Read(buffer.AsSpan(offset, count));
}
+ ///
+ /// Read decompressed data
+ ///
+ /// buffer array to receive data
+ /// How many bytes read.
public override int Read(Span buffer)
{
return DecompressCore(buffer);
}
+ ///
+ /// Read decompressed data asynchronized
+ ///
+ /// buffer array to receive data
+ /// Start index in buffer
+ /// How many bytes to append
+ ///
+ /// How many bytes read.
public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
Memory bufferMemory = buffer.AsMemory(offset, count);
return ReadAsync(buffer, cancellationToken).AsTask();
}
+ ///
+ /// Read decompressed data asynchronized
+ ///
+ /// buffer array to receive data
+ ///
+ /// How many bytes read.
public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default)
{
_innerStream.ReadAsync(new byte[10], 0, 0);
@@ -144,27 +192,78 @@ private unsafe int DecompressCore(Span buffer, CancellationToken cancellat
}
}
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override void SetLength(long value) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override void Write(ReadOnlySpan buffer) => throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override int ReadByte() => throw new NotSupportedException();
-
- public override void Close() => Dispose(true);
-
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
=> throw new NotSupportedException();
+ ///
+ /// Not support
+ ///
+ ///
+ ///
+ ///
+ ///
public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default)
=> throw new NotSupportedException();
-
+ ///
+ /// Not support
+ ///
+ ///
+ ///
public override void WriteByte(byte value)
=> throw new NotSupportedException();
+ public override void Close() => Dispose(true);
+ public override void Flush()
+ {
+ _innerStream.Flush();
+ }
protected override void Dispose(bool disposing)
{
if (!disposed)
diff --git a/src/FastLZMA2Net/Decompressor.cs b/src/FastLZMA2Net/Decompressor.cs
index 00ce708..185327d 100644
--- a/src/FastLZMA2Net/Decompressor.cs
+++ b/src/FastLZMA2Net/Decompressor.cs
@@ -1,12 +1,21 @@
namespace FastLZMA2Net
{
+ ///
+ /// Fast LZMA2 Decompress Context
+ ///
public partial class Decompressor : IDisposable
{
private readonly nint _DContext;
private bool disposedValue;
-
+ ///
+ /// Thread use of the context
+ ///
public uint ThreadCount => NativeMethods.FL2_getDCtxThreadCount(_DContext);
+ ///
+ /// Initialize new decompress context
+ ///
+ ///
public Decompressor(uint nbThreads = 0)
{
if (nbThreads == 1)
@@ -19,11 +28,21 @@ public Decompressor(uint nbThreads = 0)
}
}
+ ///
+ /// Initial new context with specific dict size property
+ ///
+ /// dictSizeProperty
public void Init(byte prop)
{
NativeMethods.FL2_initDCtx(_DContext, prop);
}
+ ///
+ /// Decompress
+ ///
+ /// Fast LZMA2 data
+ /// Raw data
+ ///
public byte[] Decompress(byte[] data)
{
nuint decompressedSize = FL2.FindDecompressedSize(data);
diff --git a/src/FastLZMA2Net/FastLZMA2Net.csproj b/src/FastLZMA2Net/FastLZMA2Net.csproj
index 5f6aaa7..c28ae54 100644
--- a/src/FastLZMA2Net/FastLZMA2Net.csproj
+++ b/src/FastLZMA2Net/FastLZMA2Net.csproj
@@ -8,15 +8,15 @@
true
True
x64;x86;AnyCPU
- 0.3.0
- alpha
+ 0.6.0
+ beta
$(VersionPrefix)-$(VersionSuffix)
FastLZMA2Net
False
FastLZMA2Net
KingsZNHONE
Copyright © KingsZNHONE 2024-present
- fast lzma2 compression
+ lzma2;compression
README.md
https://github.com/kingsznhone/FastLZMA2Net
LICENSE
@@ -25,6 +25,7 @@
snupkg
latest-all
logo.png
+ https://github.com/kingsznhone/FastLZMA2Net